Skip to content

Commit 3b24b50

Browse files
committed
bigint with ec
1 parent 8e60521 commit 3b24b50

File tree

2 files changed

+62
-8
lines changed

2 files changed

+62
-8
lines changed

include/jsoncons/reflect/json_conv_traits.hpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,11 +1442,12 @@ has_can_convert = ext_traits::is_detected<traits_can_convert_t, Json, T>;
14421442
switch (j.type())
14431443
{
14441444
case json_type::string_value:
1445-
if (!jsoncons::utility::is_base10(j.as_string_view().data(), j.as_string_view().length()))
1446-
{
1447-
return result_type(jsoncons::unexpect, conv_errc::not_bigint);
1448-
}
1449-
return result_type(basic_bigint<Allocator>::parse(j.as_string_view().data(), j.as_string_view().length()));
1445+
{
1446+
auto sv = j.as_string_view();
1447+
std::error_code ec;
1448+
auto val = basic_bigint<Allocator>::parse(sv.data(), sv.length(), ec);
1449+
return ec? result_type(jsoncons::unexpect, conv_errc::not_bigint) : result_type(std::move(val));
1450+
}
14501451
case json_type::half_value:
14511452
case json_type::double_value:
14521453
{
@@ -1727,7 +1728,9 @@ namespace variant_detail
17271728
case semantic_tag::epoch_milli:
17281729
{
17291730
auto sv = j.as_string_view();
1730-
bigint n = bigint::parse(sv.data(), sv.length());
1731+
std::error_code ec;
1732+
auto n = bigint::parse(sv.data(), sv.length(), ec);
1733+
if (ec) {return result_type(jsoncons::unexpect, conv_errc::not_epoch);}
17311734
if (n != 0)
17321735
{
17331736
n = n / millis_in_second;
@@ -1737,7 +1740,9 @@ namespace variant_detail
17371740
case semantic_tag::epoch_nano:
17381741
{
17391742
auto sv = j.as_string_view();
1740-
bigint n = bigint::parse(sv.data(), sv.length());
1743+
std::error_code ec;
1744+
auto n = bigint::parse(sv.data(), sv.length(), ec);
1745+
if (ec) {return result_type(jsoncons::unexpect, conv_errc::not_epoch);}
17411746
if (n != 0)
17421747
{
17431748
n = n / nanos_in_second;
@@ -1839,7 +1844,10 @@ namespace variant_detail
18391844
{
18401845
return result_type(unexpect, conv_errc::not_epoch);
18411846
}
1842-
bigint n = bigint::parse((*res).data(), (*res).length());
1847+
auto sv = *res;
1848+
std::error_code ec;
1849+
auto n = bigint::parse(sv.data(), sv.length(), ec);
1850+
if (ec) {return result_type(jsoncons::unexpect, conv_errc::not_epoch);}
18431851
if (n != 0)
18441852
{
18451853
n = n / nanos_in_milli;

include/jsoncons/utility/bigint.hpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <limits> // std::numeric_limits
1818
#include <memory> // std::allocator
1919
#include <string> // std::string
20+
#include <system_error>
2021
#include <type_traits> // std::enable_if
2122
#include <vector> // std::vector
2223

@@ -381,6 +382,12 @@ class basic_bigint : protected detail::basic_bigint_base<Allocator>
381382
return parse(s, std::char_traits<CharT>::length(s));
382383
}
383384

385+
template <typename CharT>
386+
static basic_bigint<Allocator> parse(const CharT* s, std::error_code& ec)
387+
{
388+
return parse(s, std::char_traits<CharT>::length(s), ec);
389+
}
390+
384391
template <typename CharT>
385392
static basic_bigint<Allocator> parse(const CharT* data, size_type length)
386393
{
@@ -418,6 +425,45 @@ class basic_bigint : protected detail::basic_bigint_base<Allocator>
418425
return v;
419426
}
420427

428+
template <typename CharT>
429+
static basic_bigint<Allocator> parse(const CharT* data, size_type length, std::error_code& ec)
430+
{
431+
ec.clear();
432+
bool neg;
433+
if (*data == '-')
434+
{
435+
neg = true;
436+
data++;
437+
--length;
438+
}
439+
else
440+
{
441+
neg = false;
442+
}
443+
444+
basic_bigint<Allocator> v = 0;
445+
for (size_type i = 0; i < length; i++)
446+
{
447+
CharT c = data[i];
448+
switch (c)
449+
{
450+
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
451+
v = (v * 10u) + (uint64_t)(c - '0');
452+
break;
453+
default:
454+
ec = std::make_error_code(std::errc::invalid_argument);
455+
return basic_bigint<Allocator>{};
456+
}
457+
}
458+
459+
if (neg)
460+
{
461+
v.common_stor_.is_negative_ = true;
462+
}
463+
464+
return v;
465+
}
466+
421467
template <typename CharT>
422468
static basic_bigint<Allocator> parse_radix(const CharT* data, size_type length, uint8_t radix)
423469
{

0 commit comments

Comments
 (0)