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.
Files changed (155) hide show
  1. checksums.yaml +7 -0
  2. data/ext/jsoncons/extconf.rb +43 -0
  3. data/ext/jsoncons/jsoncons.cpp +161 -0
  4. data/ext/jsoncons/jsoncons.h +10 -0
  5. data/jsoncons.gemspec +44 -0
  6. data/lib/jsoncons/jsoncons/examples/input/address-book.json +13 -0
  7. data/lib/jsoncons/jsoncons/examples/input/books.json +28 -0
  8. data/lib/jsoncons/jsoncons/examples/input/countries.json +7 -0
  9. data/lib/jsoncons/jsoncons/examples/input/employees.json +30 -0
  10. data/lib/jsoncons/jsoncons/examples/input/jsonschema/name.json +15 -0
  11. data/lib/jsoncons/jsoncons/examples/input/multiple-json-objects.json +3 -0
  12. data/lib/jsoncons/jsoncons/examples/input/sales.csv +6 -0
  13. data/lib/jsoncons/jsoncons/examples/input/store.json +28 -0
  14. data/lib/jsoncons/jsoncons/examples/input/tasks.csv +6 -0
  15. data/lib/jsoncons/jsoncons/include/jsoncons/allocator_holder.hpp +38 -0
  16. data/lib/jsoncons/jsoncons/include/jsoncons/basic_json.hpp +5905 -0
  17. data/lib/jsoncons/jsoncons/include/jsoncons/bigint.hpp +1611 -0
  18. data/lib/jsoncons/jsoncons/include/jsoncons/byte_string.hpp +820 -0
  19. data/lib/jsoncons/jsoncons/include/jsoncons/config/binary_config.hpp +226 -0
  20. data/lib/jsoncons/jsoncons/include/jsoncons/config/compiler_support.hpp +375 -0
  21. data/lib/jsoncons/jsoncons/include/jsoncons/config/jsoncons_config.hpp +309 -0
  22. data/lib/jsoncons/jsoncons/include/jsoncons/config/version.hpp +40 -0
  23. data/lib/jsoncons/jsoncons/include/jsoncons/conv_error.hpp +218 -0
  24. data/lib/jsoncons/jsoncons/include/jsoncons/decode_json.hpp +209 -0
  25. data/lib/jsoncons/jsoncons/include/jsoncons/decode_traits.hpp +651 -0
  26. data/lib/jsoncons/jsoncons/include/jsoncons/detail/endian.hpp +44 -0
  27. data/lib/jsoncons/jsoncons/include/jsoncons/detail/grisu3.hpp +312 -0
  28. data/lib/jsoncons/jsoncons/include/jsoncons/detail/optional.hpp +483 -0
  29. data/lib/jsoncons/jsoncons/include/jsoncons/detail/parse_number.hpp +1133 -0
  30. data/lib/jsoncons/jsoncons/include/jsoncons/detail/span.hpp +188 -0
  31. data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_view.hpp +537 -0
  32. data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_wrapper.hpp +370 -0
  33. data/lib/jsoncons/jsoncons/include/jsoncons/detail/write_number.hpp +567 -0
  34. data/lib/jsoncons/jsoncons/include/jsoncons/encode_json.hpp +315 -0
  35. data/lib/jsoncons/jsoncons/include/jsoncons/encode_traits.hpp +378 -0
  36. data/lib/jsoncons/jsoncons/include/jsoncons/json.hpp +18 -0
  37. data/lib/jsoncons/jsoncons/include/jsoncons/json_array.hpp +324 -0
  38. data/lib/jsoncons/jsoncons/include/jsoncons/json_content_handler.hpp +12 -0
  39. data/lib/jsoncons/jsoncons/include/jsoncons/json_cursor.hpp +448 -0
  40. data/lib/jsoncons/jsoncons/include/jsoncons/json_decoder.hpp +420 -0
  41. data/lib/jsoncons/jsoncons/include/jsoncons/json_encoder.hpp +1587 -0
  42. data/lib/jsoncons/jsoncons/include/jsoncons/json_error.hpp +156 -0
  43. data/lib/jsoncons/jsoncons/include/jsoncons/json_exception.hpp +241 -0
  44. data/lib/jsoncons/jsoncons/include/jsoncons/json_filter.hpp +653 -0
  45. data/lib/jsoncons/jsoncons/include/jsoncons/json_fwd.hpp +23 -0
  46. data/lib/jsoncons/jsoncons/include/jsoncons/json_object.hpp +1772 -0
  47. data/lib/jsoncons/jsoncons/include/jsoncons/json_options.hpp +862 -0
  48. data/lib/jsoncons/jsoncons/include/jsoncons/json_parser.hpp +2900 -0
  49. data/lib/jsoncons/jsoncons/include/jsoncons/json_reader.hpp +731 -0
  50. data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros.hpp +1072 -0
  51. data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros_deprecated.hpp +144 -0
  52. data/lib/jsoncons/jsoncons/include/jsoncons/json_type.hpp +206 -0
  53. data/lib/jsoncons/jsoncons/include/jsoncons/json_type_traits.hpp +1830 -0
  54. data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor.hpp +1560 -0
  55. data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor2.hpp +2079 -0
  56. data/lib/jsoncons/jsoncons/include/jsoncons/pretty_print.hpp +89 -0
  57. data/lib/jsoncons/jsoncons/include/jsoncons/ser_context.hpp +62 -0
  58. data/lib/jsoncons/jsoncons/include/jsoncons/sink.hpp +289 -0
  59. data/lib/jsoncons/jsoncons/include/jsoncons/source.hpp +777 -0
  60. data/lib/jsoncons/jsoncons/include/jsoncons/source_adaptor.hpp +148 -0
  61. data/lib/jsoncons/jsoncons/include/jsoncons/staj2_cursor.hpp +1189 -0
  62. data/lib/jsoncons/jsoncons/include/jsoncons/staj_cursor.hpp +1254 -0
  63. data/lib/jsoncons/jsoncons/include/jsoncons/staj_iterator.hpp +449 -0
  64. data/lib/jsoncons/jsoncons/include/jsoncons/tag_type.hpp +245 -0
  65. data/lib/jsoncons/jsoncons/include/jsoncons/text_source_adaptor.hpp +144 -0
  66. data/lib/jsoncons/jsoncons/include/jsoncons/traits_extension.hpp +884 -0
  67. data/lib/jsoncons/jsoncons/include/jsoncons/typed_array_view.hpp +250 -0
  68. data/lib/jsoncons/jsoncons/include/jsoncons/unicode_traits.hpp +1330 -0
  69. data/lib/jsoncons/jsoncons/include/jsoncons/uri.hpp +635 -0
  70. data/lib/jsoncons/jsoncons/include/jsoncons/value_converter.hpp +340 -0
  71. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson.hpp +23 -0
  72. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_cursor.hpp +320 -0
  73. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_decimal128.hpp +865 -0
  74. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_encoder.hpp +585 -0
  75. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_error.hpp +103 -0
  76. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_oid.hpp +245 -0
  77. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_options.hpp +75 -0
  78. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_parser.hpp +645 -0
  79. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_reader.hpp +92 -0
  80. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_type.hpp +44 -0
  81. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/decode_bson.hpp +201 -0
  82. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/encode_bson.hpp +144 -0
  83. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor.hpp +26 -0
  84. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor.hpp +351 -0
  85. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor2.hpp +265 -0
  86. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_detail.hpp +93 -0
  87. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_encoder.hpp +1766 -0
  88. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_error.hpp +105 -0
  89. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_options.hpp +113 -0
  90. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_parser.hpp +1942 -0
  91. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_reader.hpp +116 -0
  92. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/decode_cbor.hpp +203 -0
  93. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/encode_cbor.hpp +151 -0
  94. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv.hpp +17 -0
  95. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_cursor.hpp +358 -0
  96. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_encoder.hpp +954 -0
  97. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_error.hpp +85 -0
  98. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_options.hpp +973 -0
  99. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_parser.hpp +2099 -0
  100. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_reader.hpp +348 -0
  101. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_serializer.hpp +12 -0
  102. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/decode_csv.hpp +208 -0
  103. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/encode_csv.hpp +122 -0
  104. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath.hpp +5215 -0
  105. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath_error.hpp +215 -0
  106. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch.hpp +579 -0
  107. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch_error.hpp +121 -0
  108. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/expression.hpp +3329 -0
  109. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/flatten.hpp +432 -0
  110. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_location.hpp +445 -0
  111. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_query.hpp +115 -0
  112. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath.hpp +13 -0
  113. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_error.hpp +240 -0
  114. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_expression.hpp +2612 -0
  115. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_selector.hpp +1322 -0
  116. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer.hpp +1577 -0
  117. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer_error.hpp +119 -0
  118. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/format_validator.hpp +968 -0
  119. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/json_validator.hpp +120 -0
  120. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema.hpp +13 -0
  121. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_error.hpp +105 -0
  122. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_version.hpp +18 -0
  123. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator.hpp +1745 -0
  124. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator_factory.hpp +556 -0
  125. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_draft7.hpp +198 -0
  126. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_location.hpp +200 -0
  127. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_version.hpp +35 -0
  128. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/subschema.hpp +144 -0
  129. data/lib/jsoncons/jsoncons/include/jsoncons_ext/mergepatch/mergepatch.hpp +103 -0
  130. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/decode_msgpack.hpp +202 -0
  131. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/encode_msgpack.hpp +142 -0
  132. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack.hpp +24 -0
  133. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor.hpp +343 -0
  134. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor2.hpp +259 -0
  135. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_encoder.hpp +753 -0
  136. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_error.hpp +94 -0
  137. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_options.hpp +74 -0
  138. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_parser.hpp +748 -0
  139. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_reader.hpp +116 -0
  140. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_type.hpp +63 -0
  141. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/decode_ubjson.hpp +201 -0
  142. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/encode_ubjson.hpp +142 -0
  143. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson.hpp +23 -0
  144. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_cursor.hpp +307 -0
  145. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_encoder.hpp +502 -0
  146. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_error.hpp +100 -0
  147. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_options.hpp +87 -0
  148. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_parser.hpp +880 -0
  149. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_reader.hpp +92 -0
  150. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_type.hpp +43 -0
  151. data/lib/jsoncons/version.rb +5 -0
  152. data/lib/jsoncons.rb +33 -0
  153. data/test/jsoncons_test.rb +108 -0
  154. data/test/test_helper.rb +7 -0
  155. 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