jsoncons 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/jsoncons/extconf.rb +43 -0
- data/ext/jsoncons/jsoncons.cpp +161 -0
- data/ext/jsoncons/jsoncons.h +10 -0
- data/jsoncons.gemspec +44 -0
- data/lib/jsoncons/jsoncons/examples/input/address-book.json +13 -0
- data/lib/jsoncons/jsoncons/examples/input/books.json +28 -0
- data/lib/jsoncons/jsoncons/examples/input/countries.json +7 -0
- data/lib/jsoncons/jsoncons/examples/input/employees.json +30 -0
- data/lib/jsoncons/jsoncons/examples/input/jsonschema/name.json +15 -0
- data/lib/jsoncons/jsoncons/examples/input/multiple-json-objects.json +3 -0
- data/lib/jsoncons/jsoncons/examples/input/sales.csv +6 -0
- data/lib/jsoncons/jsoncons/examples/input/store.json +28 -0
- data/lib/jsoncons/jsoncons/examples/input/tasks.csv +6 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/allocator_holder.hpp +38 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/basic_json.hpp +5905 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/bigint.hpp +1611 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/byte_string.hpp +820 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/binary_config.hpp +226 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/compiler_support.hpp +375 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/jsoncons_config.hpp +309 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/version.hpp +40 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/conv_error.hpp +218 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/decode_json.hpp +209 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/decode_traits.hpp +651 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/endian.hpp +44 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/grisu3.hpp +312 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/optional.hpp +483 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/parse_number.hpp +1133 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/span.hpp +188 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_view.hpp +537 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_wrapper.hpp +370 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/write_number.hpp +567 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/encode_json.hpp +315 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/encode_traits.hpp +378 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json.hpp +18 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_array.hpp +324 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_content_handler.hpp +12 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_cursor.hpp +448 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_decoder.hpp +420 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_encoder.hpp +1587 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_error.hpp +156 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_exception.hpp +241 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_filter.hpp +653 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_fwd.hpp +23 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_object.hpp +1772 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_options.hpp +862 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_parser.hpp +2900 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_reader.hpp +731 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros.hpp +1072 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros_deprecated.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_type.hpp +206 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_type_traits.hpp +1830 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor.hpp +1560 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor2.hpp +2079 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/pretty_print.hpp +89 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/ser_context.hpp +62 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/sink.hpp +289 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/source.hpp +777 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/source_adaptor.hpp +148 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/staj2_cursor.hpp +1189 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/staj_cursor.hpp +1254 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/staj_iterator.hpp +449 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/tag_type.hpp +245 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/text_source_adaptor.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/traits_extension.hpp +884 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/typed_array_view.hpp +250 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/unicode_traits.hpp +1330 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/uri.hpp +635 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/value_converter.hpp +340 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson.hpp +23 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_cursor.hpp +320 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_decimal128.hpp +865 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_encoder.hpp +585 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_error.hpp +103 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_oid.hpp +245 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_options.hpp +75 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_parser.hpp +645 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_reader.hpp +92 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_type.hpp +44 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/decode_bson.hpp +201 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/encode_bson.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor.hpp +26 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor.hpp +351 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor2.hpp +265 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_detail.hpp +93 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_encoder.hpp +1766 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_error.hpp +105 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_options.hpp +113 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_parser.hpp +1942 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_reader.hpp +116 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/decode_cbor.hpp +203 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/encode_cbor.hpp +151 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv.hpp +17 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_cursor.hpp +358 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_encoder.hpp +954 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_error.hpp +85 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_options.hpp +973 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_parser.hpp +2099 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_reader.hpp +348 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_serializer.hpp +12 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/decode_csv.hpp +208 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/encode_csv.hpp +122 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath.hpp +5215 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath_error.hpp +215 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch.hpp +579 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch_error.hpp +121 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/expression.hpp +3329 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/flatten.hpp +432 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_location.hpp +445 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_query.hpp +115 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath.hpp +13 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_error.hpp +240 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_expression.hpp +2612 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_selector.hpp +1322 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer.hpp +1577 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer_error.hpp +119 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/format_validator.hpp +968 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/json_validator.hpp +120 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema.hpp +13 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_error.hpp +105 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_version.hpp +18 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator.hpp +1745 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator_factory.hpp +556 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_draft7.hpp +198 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_location.hpp +200 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_version.hpp +35 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/subschema.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/mergepatch/mergepatch.hpp +103 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/decode_msgpack.hpp +202 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/encode_msgpack.hpp +142 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack.hpp +24 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor.hpp +343 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor2.hpp +259 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_encoder.hpp +753 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_error.hpp +94 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_options.hpp +74 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_parser.hpp +748 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_reader.hpp +116 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_type.hpp +63 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/decode_ubjson.hpp +201 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/encode_ubjson.hpp +142 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson.hpp +23 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_cursor.hpp +307 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_encoder.hpp +502 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_error.hpp +100 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_options.hpp +87 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_parser.hpp +880 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_reader.hpp +92 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_type.hpp +43 -0
- data/lib/jsoncons/version.rb +5 -0
- data/lib/jsoncons.rb +33 -0
- data/test/jsoncons_test.rb +108 -0
- data/test/test_helper.rb +7 -0
- metadata +268 -0
|
@@ -0,0 +1,1133 @@
|
|
|
1
|
+
// Copyright 2013 Daniel Parker
|
|
2
|
+
// Distributed under the Boost license, Version 1.0.
|
|
3
|
+
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
4
|
+
|
|
5
|
+
// See https://github.com/danielaparker/jsoncons for latest version
|
|
6
|
+
|
|
7
|
+
#ifndef JSONCONS_DETAIL_PARSE_NUMBER_HPP
|
|
8
|
+
#define JSONCONS_DETAIL_PARSE_NUMBER_HPP
|
|
9
|
+
|
|
10
|
+
#include <system_error>
|
|
11
|
+
#include <stdexcept>
|
|
12
|
+
#include <string>
|
|
13
|
+
#include <vector>
|
|
14
|
+
#include <locale>
|
|
15
|
+
#include <string>
|
|
16
|
+
#include <limits> // std::numeric_limits
|
|
17
|
+
#include <type_traits> // std::enable_if
|
|
18
|
+
#include <exception>
|
|
19
|
+
#include <jsoncons/config/jsoncons_config.hpp>
|
|
20
|
+
#include <jsoncons/json_exception.hpp>
|
|
21
|
+
#include <cctype>
|
|
22
|
+
|
|
23
|
+
namespace jsoncons { namespace detail {
|
|
24
|
+
|
|
25
|
+
enum class to_integer_errc : uint8_t {success=0, overflow, invalid_digit, invalid_number};
|
|
26
|
+
|
|
27
|
+
class to_integer_error_category_impl
|
|
28
|
+
: public std::error_category
|
|
29
|
+
{
|
|
30
|
+
public:
|
|
31
|
+
const char* name() const noexcept override
|
|
32
|
+
{
|
|
33
|
+
return "jsoncons/to_integer_unchecked";
|
|
34
|
+
}
|
|
35
|
+
std::string message(int ev) const override
|
|
36
|
+
{
|
|
37
|
+
switch (static_cast<to_integer_errc>(ev))
|
|
38
|
+
{
|
|
39
|
+
case to_integer_errc::overflow:
|
|
40
|
+
return "Integer overflow";
|
|
41
|
+
case to_integer_errc::invalid_digit:
|
|
42
|
+
return "Invalid digit";
|
|
43
|
+
case to_integer_errc::invalid_number:
|
|
44
|
+
return "Invalid number";
|
|
45
|
+
default:
|
|
46
|
+
return "Unknown to_integer_unchecked error";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
inline
|
|
52
|
+
const std::error_category& to_integer_error_category()
|
|
53
|
+
{
|
|
54
|
+
static to_integer_error_category_impl instance;
|
|
55
|
+
return instance;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
inline
|
|
59
|
+
std::error_code make_error_code(to_integer_errc e)
|
|
60
|
+
{
|
|
61
|
+
return std::error_code(static_cast<int>(e),to_integer_error_category());
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
} // namespace detail
|
|
65
|
+
} // namespace jsoncons
|
|
66
|
+
|
|
67
|
+
namespace std {
|
|
68
|
+
template<>
|
|
69
|
+
struct is_error_code_enum<jsoncons::detail::to_integer_errc> : public true_type
|
|
70
|
+
{
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
namespace jsoncons { namespace detail {
|
|
75
|
+
|
|
76
|
+
template <class T,class CharT>
|
|
77
|
+
struct to_integer_result
|
|
78
|
+
{
|
|
79
|
+
const CharT* ptr;
|
|
80
|
+
to_integer_errc ec;
|
|
81
|
+
constexpr to_integer_result(const CharT* ptr_)
|
|
82
|
+
: ptr(ptr_), ec(to_integer_errc())
|
|
83
|
+
{
|
|
84
|
+
}
|
|
85
|
+
constexpr to_integer_result(const CharT* ptr_, to_integer_errc ec_)
|
|
86
|
+
: ptr(ptr_), ec(ec_)
|
|
87
|
+
{
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
to_integer_result(const to_integer_result&) = default;
|
|
91
|
+
|
|
92
|
+
to_integer_result& operator=(const to_integer_result&) = default;
|
|
93
|
+
|
|
94
|
+
constexpr explicit operator bool() const noexcept
|
|
95
|
+
{
|
|
96
|
+
return ec == to_integer_errc();
|
|
97
|
+
}
|
|
98
|
+
std::error_code error_code() const
|
|
99
|
+
{
|
|
100
|
+
return make_error_code(ec);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
enum class integer_chars_format : uint8_t {decimal=1,hex};
|
|
105
|
+
enum class integer_chars_state {initial,minus,integer,binary,octal,decimal,base16};
|
|
106
|
+
|
|
107
|
+
template <class CharT>
|
|
108
|
+
bool is_base10(const CharT* s, std::size_t length)
|
|
109
|
+
{
|
|
110
|
+
integer_chars_state state = integer_chars_state::initial;
|
|
111
|
+
|
|
112
|
+
const CharT* end = s + length;
|
|
113
|
+
for (;s < end; ++s)
|
|
114
|
+
{
|
|
115
|
+
switch(state)
|
|
116
|
+
{
|
|
117
|
+
case integer_chars_state::initial:
|
|
118
|
+
{
|
|
119
|
+
switch(*s)
|
|
120
|
+
{
|
|
121
|
+
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
|
|
122
|
+
state = integer_chars_state::decimal;
|
|
123
|
+
break;
|
|
124
|
+
case '-':
|
|
125
|
+
state = integer_chars_state::minus;
|
|
126
|
+
break;
|
|
127
|
+
default:
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
case integer_chars_state::minus:
|
|
133
|
+
{
|
|
134
|
+
switch(*s)
|
|
135
|
+
{
|
|
136
|
+
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
|
|
137
|
+
state = integer_chars_state::decimal;
|
|
138
|
+
break;
|
|
139
|
+
default:
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
case integer_chars_state::decimal:
|
|
145
|
+
{
|
|
146
|
+
switch(*s)
|
|
147
|
+
{
|
|
148
|
+
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
|
|
149
|
+
break;
|
|
150
|
+
default:
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
default:
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return state == integer_chars_state::decimal ? true : false;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
template <class T, class CharT>
|
|
163
|
+
typename std::enable_if<traits_extension::integer_limits<T>::is_specialized && !traits_extension::integer_limits<T>::is_signed,to_integer_result<T,CharT>>::type
|
|
164
|
+
to_integer_decimal(const CharT* s, std::size_t length, T& n)
|
|
165
|
+
{
|
|
166
|
+
n = 0;
|
|
167
|
+
|
|
168
|
+
integer_chars_state state = integer_chars_state::initial;
|
|
169
|
+
|
|
170
|
+
const CharT* end = s + length;
|
|
171
|
+
while (s < end)
|
|
172
|
+
{
|
|
173
|
+
switch(state)
|
|
174
|
+
{
|
|
175
|
+
case integer_chars_state::initial:
|
|
176
|
+
{
|
|
177
|
+
switch(*s)
|
|
178
|
+
{
|
|
179
|
+
case '0':
|
|
180
|
+
if (++s == end)
|
|
181
|
+
{
|
|
182
|
+
return (++s == end) ? to_integer_result<T,CharT>(s) : to_integer_result<T, CharT>(s, to_integer_errc());
|
|
183
|
+
}
|
|
184
|
+
else
|
|
185
|
+
{
|
|
186
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_digit);
|
|
187
|
+
}
|
|
188
|
+
case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9': // Must be decimal
|
|
189
|
+
state = integer_chars_state::decimal;
|
|
190
|
+
break;
|
|
191
|
+
default:
|
|
192
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_digit);
|
|
193
|
+
}
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
case integer_chars_state::decimal:
|
|
197
|
+
{
|
|
198
|
+
static constexpr T max_value = (traits_extension::integer_limits<T>::max)();
|
|
199
|
+
static constexpr T max_value_div_10 = max_value / 10;
|
|
200
|
+
for (; s < end; ++s)
|
|
201
|
+
{
|
|
202
|
+
T x = 0;
|
|
203
|
+
switch(*s)
|
|
204
|
+
{
|
|
205
|
+
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
|
|
206
|
+
x = static_cast<T>(*s) - static_cast<T>('0');
|
|
207
|
+
break;
|
|
208
|
+
default:
|
|
209
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_digit);
|
|
210
|
+
}
|
|
211
|
+
if (n > max_value_div_10)
|
|
212
|
+
{
|
|
213
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
214
|
+
}
|
|
215
|
+
n = n * 10;
|
|
216
|
+
if (n > max_value - x)
|
|
217
|
+
{
|
|
218
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
219
|
+
}
|
|
220
|
+
n += x;
|
|
221
|
+
}
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
default:
|
|
225
|
+
JSONCONS_UNREACHABLE();
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return (state == integer_chars_state::initial) ? to_integer_result<T,CharT>(s, to_integer_errc::invalid_number) : to_integer_result<T,CharT>(s, to_integer_errc());
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
template <class T, class CharT>
|
|
233
|
+
typename std::enable_if<traits_extension::integer_limits<T>::is_specialized && traits_extension::integer_limits<T>::is_signed,to_integer_result<T,CharT>>::type
|
|
234
|
+
to_integer_decimal(const CharT* s, std::size_t length, T& n)
|
|
235
|
+
{
|
|
236
|
+
n = 0;
|
|
237
|
+
|
|
238
|
+
if (length == 0)
|
|
239
|
+
{
|
|
240
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_number);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
bool is_negative = *s == '-' ? true : false;
|
|
244
|
+
if (is_negative)
|
|
245
|
+
{
|
|
246
|
+
++s;
|
|
247
|
+
--length;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
using U = typename traits_extension::make_unsigned<T>::type;
|
|
251
|
+
|
|
252
|
+
U u;
|
|
253
|
+
auto ru = to_integer_decimal(s, length, u);
|
|
254
|
+
if (ru.ec != to_integer_errc())
|
|
255
|
+
{
|
|
256
|
+
return to_integer_result<T,CharT>(ru.ptr, ru.ec);
|
|
257
|
+
}
|
|
258
|
+
if (is_negative)
|
|
259
|
+
{
|
|
260
|
+
if (u > static_cast<U>(-((traits_extension::integer_limits<T>::lowest)()+T(1))) + U(1))
|
|
261
|
+
{
|
|
262
|
+
return to_integer_result<T,CharT>(ru.ptr, to_integer_errc::overflow);
|
|
263
|
+
}
|
|
264
|
+
else
|
|
265
|
+
{
|
|
266
|
+
n = static_cast<T>(U(0) - u);
|
|
267
|
+
return to_integer_result<T,CharT>(ru.ptr, to_integer_errc());
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
else
|
|
271
|
+
{
|
|
272
|
+
if (u > static_cast<U>((traits_extension::integer_limits<T>::max)()))
|
|
273
|
+
{
|
|
274
|
+
return to_integer_result<T,CharT>(ru.ptr, to_integer_errc::overflow);
|
|
275
|
+
}
|
|
276
|
+
else
|
|
277
|
+
{
|
|
278
|
+
n = static_cast<T>(u);
|
|
279
|
+
return to_integer_result<T,CharT>(ru.ptr, to_integer_errc());
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
template <class T, class CharT>
|
|
285
|
+
typename std::enable_if<traits_extension::integer_limits<T>::is_specialized && !traits_extension::integer_limits<T>::is_signed,to_integer_result<T,CharT>>::type
|
|
286
|
+
to_integer_base16(const CharT* s, std::size_t length, T& n)
|
|
287
|
+
{
|
|
288
|
+
n = 0;
|
|
289
|
+
|
|
290
|
+
integer_chars_state state = integer_chars_state::initial;
|
|
291
|
+
|
|
292
|
+
const CharT* end = s + length;
|
|
293
|
+
while (s < end)
|
|
294
|
+
{
|
|
295
|
+
switch(state)
|
|
296
|
+
{
|
|
297
|
+
case integer_chars_state::initial:
|
|
298
|
+
{
|
|
299
|
+
switch(*s)
|
|
300
|
+
{
|
|
301
|
+
case '0':
|
|
302
|
+
if (++s == end)
|
|
303
|
+
{
|
|
304
|
+
return (++s == end) ? to_integer_result<T,CharT>(s) : to_integer_result<T, CharT>(s, to_integer_errc());
|
|
305
|
+
}
|
|
306
|
+
else
|
|
307
|
+
{
|
|
308
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_digit);
|
|
309
|
+
}
|
|
310
|
+
case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9': // Must be base16
|
|
311
|
+
case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
|
|
312
|
+
case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
|
|
313
|
+
state = integer_chars_state::base16;
|
|
314
|
+
break;
|
|
315
|
+
default:
|
|
316
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_digit);
|
|
317
|
+
}
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
case integer_chars_state::base16:
|
|
321
|
+
{
|
|
322
|
+
static constexpr T max_value = (traits_extension::integer_limits<T>::max)();
|
|
323
|
+
static constexpr T max_value_div_16 = max_value / 16;
|
|
324
|
+
for (; s < end; ++s)
|
|
325
|
+
{
|
|
326
|
+
CharT c = *s;
|
|
327
|
+
T x = 0;
|
|
328
|
+
switch(*s)
|
|
329
|
+
{
|
|
330
|
+
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
|
|
331
|
+
x = c - '0';
|
|
332
|
+
break;
|
|
333
|
+
case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
|
|
334
|
+
x = c - ('a' - 10);
|
|
335
|
+
break;
|
|
336
|
+
case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
|
|
337
|
+
x = c - ('A' - 10);
|
|
338
|
+
break;
|
|
339
|
+
default:
|
|
340
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_digit);
|
|
341
|
+
}
|
|
342
|
+
if (n > max_value_div_16)
|
|
343
|
+
{
|
|
344
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
345
|
+
}
|
|
346
|
+
n = n * 16;
|
|
347
|
+
if (n > max_value - x)
|
|
348
|
+
{
|
|
349
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
350
|
+
}
|
|
351
|
+
n += x;
|
|
352
|
+
}
|
|
353
|
+
break;
|
|
354
|
+
}
|
|
355
|
+
default:
|
|
356
|
+
JSONCONS_UNREACHABLE();
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return (state == integer_chars_state::initial) ? to_integer_result<T,CharT>(s, to_integer_errc::invalid_number) : to_integer_result<T,CharT>(s, to_integer_errc());
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
template <class T, class CharT>
|
|
364
|
+
typename std::enable_if<traits_extension::integer_limits<T>::is_specialized && traits_extension::integer_limits<T>::is_signed,to_integer_result<T,CharT>>::type
|
|
365
|
+
to_integer_base16(const CharT* s, std::size_t length, T& n)
|
|
366
|
+
{
|
|
367
|
+
n = 0;
|
|
368
|
+
|
|
369
|
+
if (length == 0)
|
|
370
|
+
{
|
|
371
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_number);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
bool is_negative = *s == '-' ? true : false;
|
|
375
|
+
if (is_negative)
|
|
376
|
+
{
|
|
377
|
+
++s;
|
|
378
|
+
--length;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
using U = typename traits_extension::make_unsigned<T>::type;
|
|
382
|
+
|
|
383
|
+
U u;
|
|
384
|
+
auto ru = to_integer_base16(s, length, u);
|
|
385
|
+
if (ru.ec != to_integer_errc())
|
|
386
|
+
{
|
|
387
|
+
return to_integer_result<T,CharT>(ru.ptr, ru.ec);
|
|
388
|
+
}
|
|
389
|
+
if (is_negative)
|
|
390
|
+
{
|
|
391
|
+
if (u > static_cast<U>(-((traits_extension::integer_limits<T>::lowest)()+T(1))) + U(1))
|
|
392
|
+
{
|
|
393
|
+
return to_integer_result<T,CharT>(ru.ptr, to_integer_errc::overflow);
|
|
394
|
+
}
|
|
395
|
+
else
|
|
396
|
+
{
|
|
397
|
+
n = static_cast<T>(U(0) - u);
|
|
398
|
+
return to_integer_result<T,CharT>(ru.ptr, to_integer_errc());
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
else
|
|
402
|
+
{
|
|
403
|
+
if (u > static_cast<U>((traits_extension::integer_limits<T>::max)()))
|
|
404
|
+
{
|
|
405
|
+
return to_integer_result<T,CharT>(ru.ptr, to_integer_errc::overflow);
|
|
406
|
+
}
|
|
407
|
+
else
|
|
408
|
+
{
|
|
409
|
+
n = static_cast<T>(u);
|
|
410
|
+
return to_integer_result<T,CharT>(ru.ptr, to_integer_errc());
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
template <class T, class CharT>
|
|
416
|
+
typename std::enable_if<traits_extension::integer_limits<T>::is_specialized && !traits_extension::integer_limits<T>::is_signed,to_integer_result<T,CharT>>::type
|
|
417
|
+
to_integer(const CharT* s, std::size_t length, T& n)
|
|
418
|
+
{
|
|
419
|
+
n = 0;
|
|
420
|
+
|
|
421
|
+
integer_chars_state state = integer_chars_state::initial;
|
|
422
|
+
|
|
423
|
+
const CharT* end = s + length;
|
|
424
|
+
while (s < end)
|
|
425
|
+
{
|
|
426
|
+
switch(state)
|
|
427
|
+
{
|
|
428
|
+
case integer_chars_state::initial:
|
|
429
|
+
{
|
|
430
|
+
switch(*s)
|
|
431
|
+
{
|
|
432
|
+
case '0':
|
|
433
|
+
state = integer_chars_state::integer; // Could be binary, octal, hex
|
|
434
|
+
++s;
|
|
435
|
+
break;
|
|
436
|
+
case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9': // Must be decimal
|
|
437
|
+
state = integer_chars_state::decimal;
|
|
438
|
+
break;
|
|
439
|
+
default:
|
|
440
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_digit);
|
|
441
|
+
}
|
|
442
|
+
break;
|
|
443
|
+
}
|
|
444
|
+
case integer_chars_state::integer:
|
|
445
|
+
{
|
|
446
|
+
switch(*s)
|
|
447
|
+
{
|
|
448
|
+
case 'b':case 'B':
|
|
449
|
+
{
|
|
450
|
+
state = integer_chars_state::binary;
|
|
451
|
+
++s;
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
case 'x':case 'X':
|
|
455
|
+
{
|
|
456
|
+
state = integer_chars_state::base16;
|
|
457
|
+
++s;
|
|
458
|
+
break;
|
|
459
|
+
}
|
|
460
|
+
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
|
|
461
|
+
{
|
|
462
|
+
state = integer_chars_state::octal;
|
|
463
|
+
break;
|
|
464
|
+
}
|
|
465
|
+
default:
|
|
466
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_digit);
|
|
467
|
+
}
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
case integer_chars_state::binary:
|
|
471
|
+
{
|
|
472
|
+
static constexpr T max_value = (traits_extension::integer_limits<T>::max)();
|
|
473
|
+
static constexpr T max_value_div_2 = max_value / 2;
|
|
474
|
+
for (; s < end; ++s)
|
|
475
|
+
{
|
|
476
|
+
T x = 0;
|
|
477
|
+
switch(*s)
|
|
478
|
+
{
|
|
479
|
+
case '0':case '1':
|
|
480
|
+
x = static_cast<T>(*s) - static_cast<T>('0');
|
|
481
|
+
break;
|
|
482
|
+
default:
|
|
483
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_digit);
|
|
484
|
+
}
|
|
485
|
+
if (n > max_value_div_2)
|
|
486
|
+
{
|
|
487
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
488
|
+
}
|
|
489
|
+
n = n * 2;
|
|
490
|
+
if (n > max_value - x)
|
|
491
|
+
{
|
|
492
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
493
|
+
}
|
|
494
|
+
n += x;
|
|
495
|
+
}
|
|
496
|
+
break;
|
|
497
|
+
}
|
|
498
|
+
case integer_chars_state::octal:
|
|
499
|
+
{
|
|
500
|
+
static constexpr T max_value = (traits_extension::integer_limits<T>::max)();
|
|
501
|
+
static constexpr T max_value_div_8 = max_value / 8;
|
|
502
|
+
for (; s < end; ++s)
|
|
503
|
+
{
|
|
504
|
+
T x = 0;
|
|
505
|
+
switch(*s)
|
|
506
|
+
{
|
|
507
|
+
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':
|
|
508
|
+
x = static_cast<T>(*s) - static_cast<T>('0');
|
|
509
|
+
break;
|
|
510
|
+
default:
|
|
511
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_digit);
|
|
512
|
+
}
|
|
513
|
+
if (n > max_value_div_8)
|
|
514
|
+
{
|
|
515
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
516
|
+
}
|
|
517
|
+
n = n * 8;
|
|
518
|
+
if (n > max_value - x)
|
|
519
|
+
{
|
|
520
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
521
|
+
}
|
|
522
|
+
n += x;
|
|
523
|
+
}
|
|
524
|
+
break;
|
|
525
|
+
}
|
|
526
|
+
case integer_chars_state::decimal:
|
|
527
|
+
{
|
|
528
|
+
static constexpr T max_value = (traits_extension::integer_limits<T>::max)();
|
|
529
|
+
static constexpr T max_value_div_10 = max_value / 10;
|
|
530
|
+
for (; s < end; ++s)
|
|
531
|
+
{
|
|
532
|
+
T x = 0;
|
|
533
|
+
switch(*s)
|
|
534
|
+
{
|
|
535
|
+
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
|
|
536
|
+
x = static_cast<T>(*s) - static_cast<T>('0');
|
|
537
|
+
break;
|
|
538
|
+
default:
|
|
539
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_digit);
|
|
540
|
+
}
|
|
541
|
+
if (n > max_value_div_10)
|
|
542
|
+
{
|
|
543
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
544
|
+
}
|
|
545
|
+
n = n * 10;
|
|
546
|
+
if (n > max_value - x)
|
|
547
|
+
{
|
|
548
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
549
|
+
}
|
|
550
|
+
n += x;
|
|
551
|
+
}
|
|
552
|
+
break;
|
|
553
|
+
}
|
|
554
|
+
case integer_chars_state::base16:
|
|
555
|
+
{
|
|
556
|
+
static constexpr T max_value = (traits_extension::integer_limits<T>::max)();
|
|
557
|
+
static constexpr T max_value_div_16 = max_value / 16;
|
|
558
|
+
for (; s < end; ++s)
|
|
559
|
+
{
|
|
560
|
+
CharT c = *s;
|
|
561
|
+
T x = 0;
|
|
562
|
+
switch (c)
|
|
563
|
+
{
|
|
564
|
+
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
|
|
565
|
+
x = c - '0';
|
|
566
|
+
break;
|
|
567
|
+
case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
|
|
568
|
+
x = c - ('a' - 10);
|
|
569
|
+
break;
|
|
570
|
+
case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
|
|
571
|
+
x = c - ('A' - 10);
|
|
572
|
+
break;
|
|
573
|
+
default:
|
|
574
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_digit);
|
|
575
|
+
}
|
|
576
|
+
if (n > max_value_div_16)
|
|
577
|
+
{
|
|
578
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
579
|
+
}
|
|
580
|
+
n = n * 16;
|
|
581
|
+
if (n > max_value - x)
|
|
582
|
+
{
|
|
583
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
n += x;
|
|
587
|
+
}
|
|
588
|
+
break;
|
|
589
|
+
}
|
|
590
|
+
default:
|
|
591
|
+
JSONCONS_UNREACHABLE();
|
|
592
|
+
break;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return (state == integer_chars_state::initial) ? to_integer_result<T,CharT>(s, to_integer_errc::invalid_number) : to_integer_result<T,CharT>(s, to_integer_errc());
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
template <class T, class CharT>
|
|
599
|
+
typename std::enable_if<traits_extension::integer_limits<T>::is_specialized && traits_extension::integer_limits<T>::is_signed,to_integer_result<T,CharT>>::type
|
|
600
|
+
to_integer(const CharT* s, std::size_t length, T& n)
|
|
601
|
+
{
|
|
602
|
+
n = 0;
|
|
603
|
+
|
|
604
|
+
if (length == 0)
|
|
605
|
+
{
|
|
606
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_number);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
bool is_negative = *s == '-' ? true : false;
|
|
610
|
+
if (is_negative)
|
|
611
|
+
{
|
|
612
|
+
++s;
|
|
613
|
+
--length;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
using U = typename traits_extension::make_unsigned<T>::type;
|
|
617
|
+
|
|
618
|
+
U u;
|
|
619
|
+
auto ru = to_integer(s, length, u);
|
|
620
|
+
if (ru.ec != to_integer_errc())
|
|
621
|
+
{
|
|
622
|
+
return to_integer_result<T,CharT>(ru.ptr, ru.ec);
|
|
623
|
+
}
|
|
624
|
+
if (is_negative)
|
|
625
|
+
{
|
|
626
|
+
if (u > static_cast<U>(-((traits_extension::integer_limits<T>::lowest)()+T(1))) + U(1))
|
|
627
|
+
{
|
|
628
|
+
return to_integer_result<T,CharT>(ru.ptr, to_integer_errc::overflow);
|
|
629
|
+
}
|
|
630
|
+
else
|
|
631
|
+
{
|
|
632
|
+
n = static_cast<T>(U(0) - u);
|
|
633
|
+
return to_integer_result<T,CharT>(ru.ptr, to_integer_errc());
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
else
|
|
637
|
+
{
|
|
638
|
+
if (u > static_cast<U>((traits_extension::integer_limits<T>::max)()))
|
|
639
|
+
{
|
|
640
|
+
return to_integer_result<T,CharT>(ru.ptr, to_integer_errc::overflow);
|
|
641
|
+
}
|
|
642
|
+
else
|
|
643
|
+
{
|
|
644
|
+
n = static_cast<T>(u);
|
|
645
|
+
return to_integer_result<T,CharT>(ru.ptr, to_integer_errc());
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
template <class T, class CharT>
|
|
651
|
+
typename std::enable_if<traits_extension::integer_limits<T>::is_specialized,to_integer_result<T,CharT>>::type
|
|
652
|
+
to_integer(const CharT* s, T& n)
|
|
653
|
+
{
|
|
654
|
+
return to_integer<T,CharT>(s, std::char_traits<CharT>::length(s), n);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// Precondition: s satisfies
|
|
658
|
+
|
|
659
|
+
// digit
|
|
660
|
+
// digit1-digits
|
|
661
|
+
// - digit
|
|
662
|
+
// - digit1-digits
|
|
663
|
+
|
|
664
|
+
template <class T, class CharT>
|
|
665
|
+
typename std::enable_if<traits_extension::integer_limits<T>::is_specialized && !traits_extension::integer_limits<T>::is_signed,to_integer_result<T,CharT>>::type
|
|
666
|
+
to_integer_unchecked(const CharT* s, std::size_t length, T& n)
|
|
667
|
+
{
|
|
668
|
+
static_assert(traits_extension::integer_limits<T>::is_specialized, "Integer type not specialized");
|
|
669
|
+
JSONCONS_ASSERT(length > 0);
|
|
670
|
+
|
|
671
|
+
n = 0;
|
|
672
|
+
const CharT* end = s + length;
|
|
673
|
+
if (*s == '-')
|
|
674
|
+
{
|
|
675
|
+
static constexpr T min_value = (traits_extension::integer_limits<T>::lowest)();
|
|
676
|
+
static constexpr T min_value_div_10 = min_value / 10;
|
|
677
|
+
++s;
|
|
678
|
+
for (; s < end; ++s)
|
|
679
|
+
{
|
|
680
|
+
T x = (T)*s - (T)('0');
|
|
681
|
+
if (n < min_value_div_10)
|
|
682
|
+
{
|
|
683
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
684
|
+
}
|
|
685
|
+
n = n * 10;
|
|
686
|
+
if (n < min_value + x)
|
|
687
|
+
{
|
|
688
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
n -= x;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
else
|
|
695
|
+
{
|
|
696
|
+
static constexpr T max_value = (traits_extension::integer_limits<T>::max)();
|
|
697
|
+
static constexpr T max_value_div_10 = max_value / 10;
|
|
698
|
+
for (; s < end; ++s)
|
|
699
|
+
{
|
|
700
|
+
T x = static_cast<T>(*s) - static_cast<T>('0');
|
|
701
|
+
if (n > max_value_div_10)
|
|
702
|
+
{
|
|
703
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
704
|
+
}
|
|
705
|
+
n = n * 10;
|
|
706
|
+
if (n > max_value - x)
|
|
707
|
+
{
|
|
708
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
n += x;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
return to_integer_result<T,CharT>(s, to_integer_errc());
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// Precondition: s satisfies
|
|
719
|
+
|
|
720
|
+
// digit
|
|
721
|
+
// digit1-digits
|
|
722
|
+
// - digit
|
|
723
|
+
// - digit1-digits
|
|
724
|
+
|
|
725
|
+
template <class T, class CharT>
|
|
726
|
+
typename std::enable_if<traits_extension::integer_limits<T>::is_specialized && traits_extension::integer_limits<T>::is_signed,to_integer_result<T,CharT>>::type
|
|
727
|
+
to_integer_unchecked(const CharT* s, std::size_t length, T& n)
|
|
728
|
+
{
|
|
729
|
+
static_assert(traits_extension::integer_limits<T>::is_specialized, "Integer type not specialized");
|
|
730
|
+
JSONCONS_ASSERT(length > 0);
|
|
731
|
+
|
|
732
|
+
n = 0;
|
|
733
|
+
|
|
734
|
+
const CharT* end = s + length;
|
|
735
|
+
if (*s == '-')
|
|
736
|
+
{
|
|
737
|
+
static constexpr T min_value = (traits_extension::integer_limits<T>::lowest)();
|
|
738
|
+
static constexpr T min_value_div_10 = min_value / 10;
|
|
739
|
+
++s;
|
|
740
|
+
for (; s < end; ++s)
|
|
741
|
+
{
|
|
742
|
+
T x = (T)*s - (T)('0');
|
|
743
|
+
if (n < min_value_div_10)
|
|
744
|
+
{
|
|
745
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
746
|
+
}
|
|
747
|
+
n = n * 10;
|
|
748
|
+
if (n < min_value + x)
|
|
749
|
+
{
|
|
750
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
n -= x;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
else
|
|
757
|
+
{
|
|
758
|
+
static constexpr T max_value = (traits_extension::integer_limits<T>::max)();
|
|
759
|
+
static constexpr T max_value_div_10 = max_value / 10;
|
|
760
|
+
for (; s < end; ++s)
|
|
761
|
+
{
|
|
762
|
+
T x = static_cast<T>(*s) - static_cast<T>('0');
|
|
763
|
+
if (n > max_value_div_10)
|
|
764
|
+
{
|
|
765
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
766
|
+
}
|
|
767
|
+
n = n * 10;
|
|
768
|
+
if (n > max_value - x)
|
|
769
|
+
{
|
|
770
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
n += x;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
return to_integer_result<T,CharT>(s, to_integer_errc());
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// base16_to_integer
|
|
781
|
+
|
|
782
|
+
template <class T, class CharT>
|
|
783
|
+
typename std::enable_if<traits_extension::integer_limits<T>::is_specialized && traits_extension::integer_limits<T>::is_signed,to_integer_result<T,CharT>>::type
|
|
784
|
+
base16_to_integer(const CharT* s, std::size_t length, T& n)
|
|
785
|
+
{
|
|
786
|
+
static_assert(traits_extension::integer_limits<T>::is_specialized, "Integer type not specialized");
|
|
787
|
+
JSONCONS_ASSERT(length > 0);
|
|
788
|
+
|
|
789
|
+
n = 0;
|
|
790
|
+
|
|
791
|
+
const CharT* end = s + length;
|
|
792
|
+
if (*s == '-')
|
|
793
|
+
{
|
|
794
|
+
static constexpr T min_value = (traits_extension::integer_limits<T>::lowest)();
|
|
795
|
+
static constexpr T min_value_div_16 = min_value / 16;
|
|
796
|
+
++s;
|
|
797
|
+
for (; s < end; ++s)
|
|
798
|
+
{
|
|
799
|
+
CharT c = *s;
|
|
800
|
+
T x = 0;
|
|
801
|
+
switch (c)
|
|
802
|
+
{
|
|
803
|
+
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
|
|
804
|
+
x = c - '0';
|
|
805
|
+
break;
|
|
806
|
+
case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
|
|
807
|
+
x = c - ('a' - 10);
|
|
808
|
+
break;
|
|
809
|
+
case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
|
|
810
|
+
x = c - ('A' - 10);
|
|
811
|
+
break;
|
|
812
|
+
default:
|
|
813
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_digit);
|
|
814
|
+
}
|
|
815
|
+
if (n < min_value_div_16)
|
|
816
|
+
{
|
|
817
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
818
|
+
}
|
|
819
|
+
n = n * 16;
|
|
820
|
+
if (n < min_value + x)
|
|
821
|
+
{
|
|
822
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
823
|
+
}
|
|
824
|
+
n -= x;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
else
|
|
828
|
+
{
|
|
829
|
+
static constexpr T max_value = (traits_extension::integer_limits<T>::max)();
|
|
830
|
+
static constexpr T max_value_div_16 = max_value / 16;
|
|
831
|
+
for (; s < end; ++s)
|
|
832
|
+
{
|
|
833
|
+
CharT c = *s;
|
|
834
|
+
T x = 0;
|
|
835
|
+
switch (c)
|
|
836
|
+
{
|
|
837
|
+
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
|
|
838
|
+
x = c - '0';
|
|
839
|
+
break;
|
|
840
|
+
case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
|
|
841
|
+
x = c - ('a' - 10);
|
|
842
|
+
break;
|
|
843
|
+
case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
|
|
844
|
+
x = c - ('A' - 10);
|
|
845
|
+
break;
|
|
846
|
+
default:
|
|
847
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_digit);
|
|
848
|
+
}
|
|
849
|
+
if (n > max_value_div_16)
|
|
850
|
+
{
|
|
851
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
852
|
+
}
|
|
853
|
+
n = n * 16;
|
|
854
|
+
if (n > max_value - x)
|
|
855
|
+
{
|
|
856
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
n += x;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
return to_integer_result<T,CharT>(s, to_integer_errc());
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
template <class T, class CharT>
|
|
867
|
+
typename std::enable_if<traits_extension::integer_limits<T>::is_specialized && !traits_extension::integer_limits<T>::is_signed,to_integer_result<T,CharT>>::type
|
|
868
|
+
base16_to_integer(const CharT* s, std::size_t length, T& n)
|
|
869
|
+
{
|
|
870
|
+
static_assert(traits_extension::integer_limits<T>::is_specialized, "Integer type not specialized");
|
|
871
|
+
JSONCONS_ASSERT(length > 0);
|
|
872
|
+
|
|
873
|
+
n = 0;
|
|
874
|
+
const CharT* end = s + length;
|
|
875
|
+
|
|
876
|
+
static constexpr T max_value = (traits_extension::integer_limits<T>::max)();
|
|
877
|
+
static constexpr T max_value_div_16 = max_value / 16;
|
|
878
|
+
for (; s < end; ++s)
|
|
879
|
+
{
|
|
880
|
+
CharT c = *s;
|
|
881
|
+
T x = *s;
|
|
882
|
+
switch (c)
|
|
883
|
+
{
|
|
884
|
+
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
|
|
885
|
+
x = c - '0';
|
|
886
|
+
break;
|
|
887
|
+
case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
|
|
888
|
+
x = c - ('a' - 10);
|
|
889
|
+
break;
|
|
890
|
+
case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
|
|
891
|
+
x = c - ('A' - 10);
|
|
892
|
+
break;
|
|
893
|
+
default:
|
|
894
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::invalid_digit);
|
|
895
|
+
}
|
|
896
|
+
if (n > max_value_div_16)
|
|
897
|
+
{
|
|
898
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
899
|
+
}
|
|
900
|
+
n = n * 16;
|
|
901
|
+
if (n > max_value - x)
|
|
902
|
+
{
|
|
903
|
+
return to_integer_result<T,CharT>(s, to_integer_errc::overflow);
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
n += x;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
return to_integer_result<T,CharT>(s, to_integer_errc());
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
|
|
913
|
+
#if defined(JSONCONS_HAS_STD_FROM_CHARS) && JSONCONS_HAS_STD_FROM_CHARS
|
|
914
|
+
|
|
915
|
+
class chars_to
|
|
916
|
+
{
|
|
917
|
+
public:
|
|
918
|
+
|
|
919
|
+
char get_decimal_point() const
|
|
920
|
+
{
|
|
921
|
+
return '.';
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
template <class CharT>
|
|
925
|
+
typename std::enable_if<std::is_same<CharT,char>::value,double>::type
|
|
926
|
+
operator()(const CharT* s, std::size_t len) const
|
|
927
|
+
{
|
|
928
|
+
double val = 0;
|
|
929
|
+
const auto res = std::from_chars(s, s+len, val);
|
|
930
|
+
if (res.ec != std::errc())
|
|
931
|
+
{
|
|
932
|
+
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("Convert chars to double failed"));
|
|
933
|
+
}
|
|
934
|
+
return val;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
template <class CharT>
|
|
938
|
+
typename std::enable_if<std::is_same<CharT,wchar_t>::value,double>::type
|
|
939
|
+
operator()(const CharT* s, std::size_t len) const
|
|
940
|
+
{
|
|
941
|
+
std::string input(len,'0');
|
|
942
|
+
for (size_t i = 0; i < len; ++i)
|
|
943
|
+
{
|
|
944
|
+
input[i] = static_cast<char>(s[i]);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
double val = 0;
|
|
948
|
+
const auto res = std::from_chars(input.data(), input.data() + len, val);
|
|
949
|
+
if (res.ec != std::errc())
|
|
950
|
+
{
|
|
951
|
+
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("Convert chars to double failed"));
|
|
952
|
+
}
|
|
953
|
+
return val;
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
#elif defined(JSONCONS_HAS_MSC_STRTOD_L)
|
|
957
|
+
|
|
958
|
+
class chars_to
|
|
959
|
+
{
|
|
960
|
+
private:
|
|
961
|
+
_locale_t locale_;
|
|
962
|
+
public:
|
|
963
|
+
chars_to()
|
|
964
|
+
{
|
|
965
|
+
locale_ = _create_locale(LC_NUMERIC, "C");
|
|
966
|
+
}
|
|
967
|
+
~chars_to() noexcept
|
|
968
|
+
{
|
|
969
|
+
_free_locale(locale_);
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
chars_to(const chars_to&)
|
|
973
|
+
{
|
|
974
|
+
locale_ = _create_locale(LC_NUMERIC, "C");
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
chars_to& operator=(const chars_to&)
|
|
978
|
+
{
|
|
979
|
+
// Don't assign locale
|
|
980
|
+
return *this;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
char get_decimal_point() const
|
|
984
|
+
{
|
|
985
|
+
return '.';
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
template <class CharT>
|
|
989
|
+
typename std::enable_if<std::is_same<CharT,char>::value,double>::type
|
|
990
|
+
operator()(const CharT* s, std::size_t) const
|
|
991
|
+
{
|
|
992
|
+
CharT *end = nullptr;
|
|
993
|
+
double val = _strtod_l(s, &end, locale_);
|
|
994
|
+
if (s == end)
|
|
995
|
+
{
|
|
996
|
+
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("Convert string to double failed"));
|
|
997
|
+
}
|
|
998
|
+
return val;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
template <class CharT>
|
|
1002
|
+
typename std::enable_if<std::is_same<CharT,wchar_t>::value,double>::type
|
|
1003
|
+
operator()(const CharT* s, std::size_t) const
|
|
1004
|
+
{
|
|
1005
|
+
CharT *end = nullptr;
|
|
1006
|
+
double val = _wcstod_l(s, &end, locale_);
|
|
1007
|
+
if (s == end)
|
|
1008
|
+
{
|
|
1009
|
+
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("Convert string to double failed"));
|
|
1010
|
+
}
|
|
1011
|
+
return val;
|
|
1012
|
+
}
|
|
1013
|
+
};
|
|
1014
|
+
|
|
1015
|
+
#elif defined(JSONCONS_HAS_STRTOLD_L)
|
|
1016
|
+
|
|
1017
|
+
class chars_to
|
|
1018
|
+
{
|
|
1019
|
+
private:
|
|
1020
|
+
locale_t locale_;
|
|
1021
|
+
public:
|
|
1022
|
+
chars_to()
|
|
1023
|
+
{
|
|
1024
|
+
locale_ = newlocale(LC_ALL_MASK, "C", (locale_t) 0);
|
|
1025
|
+
}
|
|
1026
|
+
~chars_to() noexcept
|
|
1027
|
+
{
|
|
1028
|
+
freelocale(locale_);
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
chars_to(const chars_to&)
|
|
1032
|
+
{
|
|
1033
|
+
locale_ = newlocale(LC_ALL_MASK, "C", (locale_t) 0);
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
chars_to& operator=(const chars_to&)
|
|
1037
|
+
{
|
|
1038
|
+
return *this;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
char get_decimal_point() const
|
|
1042
|
+
{
|
|
1043
|
+
return '.';
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
template <class CharT>
|
|
1047
|
+
typename std::enable_if<std::is_same<CharT,char>::value,double>::type
|
|
1048
|
+
operator()(const CharT* s, std::size_t) const
|
|
1049
|
+
{
|
|
1050
|
+
char *end = nullptr;
|
|
1051
|
+
double val = strtold_l(s, &end, locale_);
|
|
1052
|
+
if (s == end)
|
|
1053
|
+
{
|
|
1054
|
+
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("Convert string to double failed"));
|
|
1055
|
+
}
|
|
1056
|
+
return val;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
template <class CharT>
|
|
1060
|
+
typename std::enable_if<std::is_same<CharT,wchar_t>::value,double>::type
|
|
1061
|
+
operator()(const CharT* s, std::size_t) const
|
|
1062
|
+
{
|
|
1063
|
+
CharT *end = nullptr;
|
|
1064
|
+
double val = wcstold_l(s, &end, locale_);
|
|
1065
|
+
if (s == end)
|
|
1066
|
+
{
|
|
1067
|
+
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("Convert string to double failed"));
|
|
1068
|
+
}
|
|
1069
|
+
return val;
|
|
1070
|
+
}
|
|
1071
|
+
};
|
|
1072
|
+
|
|
1073
|
+
#else
|
|
1074
|
+
class chars_to
|
|
1075
|
+
{
|
|
1076
|
+
private:
|
|
1077
|
+
std::vector<char> buffer_;
|
|
1078
|
+
char decimal_point_;
|
|
1079
|
+
public:
|
|
1080
|
+
chars_to()
|
|
1081
|
+
: buffer_()
|
|
1082
|
+
{
|
|
1083
|
+
struct lconv * lc = localeconv();
|
|
1084
|
+
if (lc != nullptr && lc->decimal_point[0] != 0)
|
|
1085
|
+
{
|
|
1086
|
+
decimal_point_ = lc->decimal_point[0];
|
|
1087
|
+
}
|
|
1088
|
+
else
|
|
1089
|
+
{
|
|
1090
|
+
decimal_point_ = '.';
|
|
1091
|
+
}
|
|
1092
|
+
buffer_.reserve(100);
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
chars_to(const chars_to&) = default;
|
|
1096
|
+
chars_to& operator=(const chars_to&) = default;
|
|
1097
|
+
|
|
1098
|
+
char get_decimal_point() const
|
|
1099
|
+
{
|
|
1100
|
+
return decimal_point_;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
template <class CharT>
|
|
1104
|
+
typename std::enable_if<std::is_same<CharT,char>::value,double>::type
|
|
1105
|
+
operator()(const CharT* s, std::size_t /*length*/) const
|
|
1106
|
+
{
|
|
1107
|
+
CharT *end = nullptr;
|
|
1108
|
+
double val = strtod(s, &end);
|
|
1109
|
+
if (s == end)
|
|
1110
|
+
{
|
|
1111
|
+
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("Convert string to double failed"));
|
|
1112
|
+
}
|
|
1113
|
+
return val;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
template <class CharT>
|
|
1117
|
+
typename std::enable_if<std::is_same<CharT,wchar_t>::value,double>::type
|
|
1118
|
+
operator()(const CharT* s, std::size_t /*length*/) const
|
|
1119
|
+
{
|
|
1120
|
+
CharT *end = nullptr;
|
|
1121
|
+
double val = wcstod(s, &end);
|
|
1122
|
+
if (s == end)
|
|
1123
|
+
{
|
|
1124
|
+
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("Convert string to double failed"));
|
|
1125
|
+
}
|
|
1126
|
+
return val;
|
|
1127
|
+
}
|
|
1128
|
+
};
|
|
1129
|
+
#endif
|
|
1130
|
+
|
|
1131
|
+
}}
|
|
1132
|
+
|
|
1133
|
+
#endif
|