Skip to content

Commit a181387

Browse files
committed
bigint::parse -> to_bigint
1 parent fa234bb commit a181387

File tree

10 files changed

+234
-132
lines changed

10 files changed

+234
-132
lines changed

doc/ref/corelib/bigint_chars_format.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ int main()
2323
{
2424
std::string s = "-18446744073709551617";
2525
26-
json j(bigint::parse(s.c_str()));
26+
json j(bigint(s.c_str()));
2727
2828
std::cout << "(1) " << print(j) << "\n\n";
2929

doc/ref/corelib/bignum_format_kind.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ int main()
2626
{
2727
std::string s = "-18446744073709551617";
2828
29-
json j(bigint::parse(s.c_str()));
29+
json j(bigint(s.c_str()));
3030
3131
std::cout << "(1) " << print(j) << "\n\n";
3232

examples_boost/serialization_examples.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ void bignum_serialization_examples1()
343343
{
344344
std::string s = "-18446744073709551617";
345345

346-
json j(bigint::parse(s.c_str()));
346+
json j(bigint(s.c_str()));
347347

348348
std::cout << "(default) ";
349349
j.dump(std::cout);

include/jsoncons/json_encoder.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@ namespace detail {
983983
}
984984
case bignum_format_kind::base64:
985985
{
986-
bigint n = bigint::parse(sv.data(), sv.length());
986+
bigint n(sv.data(), sv.length());
987987
bool is_neg = n < 0;
988988
if (is_neg)
989989
{
@@ -1006,7 +1006,7 @@ namespace detail {
10061006
}
10071007
case bignum_format_kind::base64url:
10081008
{
1009-
bigint n = bigint::parse(sv.data(), sv.length());
1009+
bigint n(sv.data(), sv.length());
10101010
bool is_neg = n < 0;
10111011
if (is_neg)
10121012
{
@@ -1303,7 +1303,7 @@ namespace detail {
13031303
}
13041304
case bignum_format_kind::base64:
13051305
{
1306-
bigint n = bigint::parse(sv.data(), sv.length());
1306+
bigint n(sv.data(), sv.length());
13071307
bool is_neg = n < 0;
13081308
if (is_neg)
13091309
{
@@ -1324,7 +1324,7 @@ namespace detail {
13241324
}
13251325
case bignum_format_kind::base64url:
13261326
{
1327-
bigint n = bigint::parse(sv.data(), sv.length());
1327+
bigint n(sv.data(), sv.length());
13281328
bool is_neg = n < 0;
13291329
if (is_neg)
13301330
{

include/jsoncons/utility/bigint.hpp

Lines changed: 167 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <jsoncons/config/jsoncons_config.hpp>
2626
#include <jsoncons/conversion_result.hpp>
2727
#include <jsoncons/utility/more_type_traits.hpp>
28+
#include <jsoncons/utility/read_number.hpp>
2829

2930
namespace jsoncons {
3031

@@ -576,6 +577,17 @@ struct to_bigint_result
576577
}
577578
};
578579

580+
template <typename Allocator>
581+
class basic_bigint;
582+
583+
template <typename CharT, typename Allocator>
584+
utility::to_number_result<CharT> to_bigint(const CharT* data, std::size_t length,
585+
basic_bigint<Allocator>& value, const Allocator& alloc);
586+
587+
template <typename CharT>
588+
utility::to_number_result<CharT> to_bigint(const CharT* data, std::size_t length,
589+
basic_bigint<std::allocator<uint64_t>>& value);
590+
579591
/*
580592
This implementation is based on Chapter 2 and Appendix A of
581593
Ammeraal, L. (1996) Algorithms and Data Structures in C++,
@@ -630,7 +642,22 @@ class basic_bigint
630642
basic_bigint(const CharT* s, const Allocator& alloc = Allocator())
631643
: storage_(alloc)
632644
{
633-
*this = parse(s, std::char_traits<CharT>::length(s), alloc);
645+
auto r = jsoncons::to_bigint(s, std::char_traits<CharT>::length(s), *this, alloc);
646+
if (r.ec != std::errc{})
647+
{
648+
JSONCONS_THROW(std::system_error((int)r.ec, std::system_category()));
649+
}
650+
}
651+
652+
template <typename CharT>
653+
basic_bigint(const CharT* s, size_type length, const Allocator& alloc = Allocator())
654+
: storage_(alloc)
655+
{
656+
auto r = jsoncons::to_bigint(s, length, *this, alloc);
657+
if (r.ec != std::errc{})
658+
{
659+
JSONCONS_THROW(std::system_error((int)r.ec, std::system_category()));
660+
}
634661
}
635662

636663
basic_bigint(const basic_bigint& other)
@@ -661,9 +688,13 @@ class basic_bigint
661688
}
662689

663690
template <typename StringViewLike,typename=typename std::enable_if<ext_traits::is_string_or_string_view<StringViewLike>::value>::type>
664-
basic_bigint(const StringViewLike& sv)
691+
basic_bigint(const StringViewLike& s)
665692
{
666-
*this = parse(sv.data(), sv.size());
693+
auto r = jsoncons::to_bigint(s.data(), s.size(), *this);
694+
if (r.ec != std::errc{})
695+
{
696+
JSONCONS_THROW(std::system_error((int)r.ec, std::system_category()));
697+
}
667698
}
668699

669700
~basic_bigint() noexcept
@@ -697,48 +728,47 @@ class basic_bigint
697728
}
698729

699730
template <typename CharT>
700-
static basic_bigint<Allocator> parse(const std::basic_string<CharT>& s)
731+
static utility::to_number_result<CharT> parse(const std::basic_string<CharT>& s, basic_bigint<Allocator>& value)
701732
{
702-
return parse(s.data(), s.size());
733+
return parse<CharT>(s.data(), s.size(), value);
703734
}
704735

705736
template <typename CharT>
706-
static basic_bigint<Allocator> parse(const CharT* s)
737+
static utility::to_number_result<CharT> parse(const CharT* s, basic_bigint<Allocator>& value)
707738
{
708-
return parse(s, std::char_traits<CharT>::length(s));
709-
}
710-
711-
template <typename CharT>
712-
static basic_bigint<Allocator> parse(const CharT* s, std::error_code& ec)
713-
{
714-
return parse(s, std::char_traits<CharT>::length(s), ec);
739+
auto r = parse(s, std::char_traits<CharT>::length(s), value);
740+
if (r.ec != std::errc{})
741+
{
742+
JSONCONS_THROW(std::system_error((int)r.ec, std::system_category()));
743+
}
715744
}
716745

717746
template <typename CharT>
718-
static basic_bigint<Allocator> parse(const CharT* data, size_type length, const Allocator& alloc = Allocator())
747+
static utility::to_number_result<CharT> parse(const CharT* data, size_type length,
748+
basic_bigint<Allocator>& value, const Allocator& alloc = Allocator())
719749
{
720750
if (JSONCONS_UNLIKELY(length == 0))
721751
{
722-
JSONCONS_THROW(std::runtime_error(std::string("Invalid argument")));
752+
return utility::to_number_result<CharT>(data, std::errc::invalid_argument);
723753
}
724754

725755
if (*data == '-')
726756
{
727-
return parse(data+1, length-1, true, alloc);
757+
return parse(data+1, length-1, true, value, alloc);
728758
}
729759
else
730760
{
731-
return parse(data, length, false, alloc);
761+
return parse(data, length, false, value, alloc);
732762
}
733763
}
734764

735765
template <typename CharT>
736-
static basic_bigint<Allocator> parse(const CharT* data, size_type length,
737-
bool neg, const Allocator& alloc = Allocator())
766+
static utility::to_number_result<CharT> parse(const CharT* data, size_type length,
767+
bool neg, basic_bigint<Allocator>& value, const Allocator& alloc = Allocator())
738768
{
739769
if (JSONCONS_UNLIKELY(length == 0))
740770
{
741-
JSONCONS_THROW(std::runtime_error(std::string("Invalid argument")));
771+
return utility::to_number_result<CharT>(data, std::errc::invalid_argument);
742772
}
743773

744774
const CharT* last = data + length;
@@ -750,7 +780,8 @@ class basic_bigint
750780
}
751781
if (p == last)
752782
{
753-
return basic_bigint{0, alloc};
783+
value = std::move(basic_bigint{0, alloc});
784+
return utility::to_number_result<CharT>(last, std::errc{});
754785
}
755786
size_type num_digits = last - data;
756787
size_type num_words;
@@ -775,7 +806,7 @@ class basic_bigint
775806
v = (v * 10u) + (word_type)(c - '0');
776807
break;
777808
default:
778-
JSONCONS_THROW(std::runtime_error(std::string("Invalid digit ") + "\'" + (char)c + "\'"));
809+
return utility::to_number_result<CharT>(data+i, std::errc::invalid_argument);
779810
}
780811
}
781812

@@ -790,46 +821,8 @@ class basic_bigint
790821
v.set_negative(true);
791822
}
792823

793-
return v;
794-
}
795-
796-
template <typename CharT>
797-
static basic_bigint<Allocator> parse(const CharT* data, size_type length, std::error_code& ec)
798-
{
799-
ec.clear();
800-
bool neg;
801-
if (*data == '-')
802-
{
803-
neg = true;
804-
data++;
805-
--length;
806-
}
807-
else
808-
{
809-
neg = false;
810-
}
811-
812-
basic_bigint<Allocator> v = 0;
813-
for (size_type i = 0; i < length; i++)
814-
{
815-
CharT c = data[i];
816-
switch (c)
817-
{
818-
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
819-
v = (v * 10u) + (word_type)(c - '0');
820-
break;
821-
default:
822-
ec = std::make_error_code(std::errc::invalid_argument);
823-
return basic_bigint<Allocator>{};
824-
}
825-
}
826-
827-
if (neg)
828-
{
829-
v.set_negative(true);
830-
}
831-
832-
return v;
824+
value = std::move(v);
825+
return utility::to_number_result<CharT>(last, std::errc{});
833826
}
834827

835828
template <typename CharT>
@@ -1966,13 +1959,13 @@ class basic_bigint
19661959
}
19671960

19681961
template <typename CharT>
1969-
friend to_bigint_result<CharT> to_bigint(const CharT* s, basic_bigint& val, int radix = 10)
1962+
friend to_bigint_result<CharT> to_bigint(const CharT* s, basic_bigint& val, int radix)
19701963
{
19711964
return to_bigint(s, std::char_traits<CharT>::length(s), val, radix);
19721965
}
19731966

19741967
template <typename CharT>
1975-
friend to_bigint_result<CharT> to_bigint(const CharT* s, size_type length, basic_bigint& val, int radix = 10)
1968+
friend to_bigint_result<CharT> to_bigint(const CharT* s, size_type length, basic_bigint& val, int radix)
19761969
{
19771970
if (!(radix >= 2 && radix <= 16))
19781971
{
@@ -2075,7 +2068,116 @@ basic_bigint<Allocator> bsqrt(const basic_bigint<Allocator>& a)
20752068
return x < q ? x : q;
20762069
}
20772070

2078-
using bigint = basic_bigint<std::allocator<uint8_t>>;
2071+
template <typename CharT, typename Allocator>
2072+
utility::to_number_result<CharT> to_bigint(const CharT* data, std::size_t length,
2073+
basic_bigint<Allocator>& value, const Allocator& alloc)
2074+
{
2075+
if (JSONCONS_UNLIKELY(length == 0))
2076+
{
2077+
return utility::to_number_result<CharT>(data, std::errc::invalid_argument);
2078+
}
2079+
2080+
if (*data == '-')
2081+
{
2082+
return to_bigint(data+1, length-1, true, value, alloc);
2083+
}
2084+
else
2085+
{
2086+
return to_bigint(data, length, false, value, alloc);
2087+
}
2088+
}
2089+
2090+
template <typename CharT>
2091+
utility::to_number_result<CharT> to_bigint(const CharT* s, basic_bigint<std::allocator<uint64_t>>& value)
2092+
{
2093+
return to_bigint(s, std::char_traits<CharT>::length(s), value);
2094+
}
2095+
2096+
template <typename CharT>
2097+
utility::to_number_result<CharT> to_bigint(const CharT* data, std::size_t length,
2098+
basic_bigint<std::allocator<uint64_t>>& value)
2099+
{
2100+
if (JSONCONS_UNLIKELY(length == 0))
2101+
{
2102+
return utility::to_number_result<CharT>(data, std::errc::invalid_argument);
2103+
}
2104+
2105+
if (*data == '-')
2106+
{
2107+
return to_bigint(data+1, length-1, true, value, std::allocator<uint64_t>{});
2108+
}
2109+
else
2110+
{
2111+
return to_bigint(data, length, false, value, std::allocator<uint64_t>{});
2112+
}
2113+
}
2114+
2115+
template <typename CharT, typename Allocator>
2116+
utility::to_number_result<CharT> to_bigint(const CharT* data, std::size_t length,
2117+
bool neg, basic_bigint<Allocator>& value, const Allocator& alloc)
2118+
{
2119+
if (JSONCONS_UNLIKELY(length == 0))
2120+
{
2121+
return utility::to_number_result<CharT>(data, std::errc::invalid_argument);
2122+
}
2123+
2124+
using word_type = typename basic_bigint<Allocator>::word_type;
2125+
2126+
const CharT* last = data + length;
2127+
const CharT* p = data;
2128+
2129+
while (p < last && *p == '0')
2130+
{
2131+
++p;
2132+
}
2133+
if (p == last)
2134+
{
2135+
value = std::move(basic_bigint<Allocator>{0, alloc});
2136+
return utility::to_number_result<CharT>(last, std::errc{});
2137+
}
2138+
std::size_t num_digits = last - data;
2139+
std::size_t num_words;
2140+
if (length < 10)
2141+
{
2142+
num_words = 1;
2143+
}
2144+
else
2145+
{
2146+
std::size_t num_bits = (std::size_t)(((num_digits*detail::bits_per_digit[10]) >> 10) + 1);
2147+
num_words = (num_bits+63) >> 6;
2148+
}
2149+
2150+
basic_bigint<Allocator> v(0, alloc);
2151+
v.reserve(num_words);
2152+
for (std::size_t i = 0; i < length; i++)
2153+
{
2154+
CharT c = data[i];
2155+
switch (c)
2156+
{
2157+
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
2158+
v = (v * 10u) + (word_type)(c - '0');
2159+
break;
2160+
default:
2161+
return utility::to_number_result<CharT>(data+i, std::errc::invalid_argument);
2162+
}
2163+
}
2164+
2165+
//auto view = v.get_storage_view();
2166+
//if (num_words != view.size())
2167+
//{
2168+
// std::cout << "Unexpected num_words! num_words: " << num_words << ", " << num_words << ", size: " << view.size() << "\n";
2169+
//}
2170+
2171+
if (neg)
2172+
{
2173+
v.set_negative(true);
2174+
}
2175+
2176+
value = std::move(v);
2177+
return utility::to_number_result<CharT>(last, std::errc{});
2178+
}
2179+
2180+
using bigint = basic_bigint<std::allocator<uint64_t>>;
20792181

20802182
} // namespace jsoncons
20812183

0 commit comments

Comments
 (0)