jsoncons 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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