Line data Source code
1 : /*
2 : __ _____ _____ _____
3 : __| | __| | | | JSON for Modern C++
4 : | | |__ | | | | | | version 3.10.5
5 : |_____|_____|_____|_|___| https://github.com/nlohmann/json
6 :
7 : Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 : SPDX-License-Identifier: MIT
9 : Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
10 :
11 : Permission is hereby granted, free of charge, to any person obtaining a copy
12 : of this software and associated documentation files (the "Software"), to deal
13 : in the Software without restriction, including without limitation the rights
14 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 : copies of the Software, and to permit persons to whom the Software is
16 : furnished to do so, subject to the following conditions:
17 :
18 : The above copyright notice and this permission notice shall be included in all
19 : copies or substantial portions of the Software.
20 :
21 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 : SOFTWARE.
28 : */
29 :
30 : /****************************************************************************\
31 : * Note on documentation: The source files contain links to the online *
32 : * documentation of the public API at https://json.nlohmann.me. This URL *
33 : * contains the most recent documentation and should also be applicable to *
34 : * previous versions; documentation for deprecated functions is not *
35 : * removed, but marked deprecated. See "Generate documentation" section in *
36 : * file doc/README.md. *
37 : \****************************************************************************/
38 :
39 : #ifndef INCLUDE_NLOHMANN_JSON_HPP_
40 : #define INCLUDE_NLOHMANN_JSON_HPP_
41 :
42 : #define NLOHMANN_JSON_VERSION_MAJOR 3
43 : #define NLOHMANN_JSON_VERSION_MINOR 10
44 : #define NLOHMANN_JSON_VERSION_PATCH 5
45 :
46 : #include <algorithm> // all_of, find, for_each
47 : #include <cstddef> // nullptr_t, ptrdiff_t, size_t
48 : #include <functional> // hash, less
49 : #include <initializer_list> // initializer_list
50 : #ifndef JSON_NO_IO
51 : #include <iosfwd> // istream, ostream
52 : #endif // JSON_NO_IO
53 : #include <iterator> // random_access_iterator_tag
54 : #include <memory> // unique_ptr
55 : #include <numeric> // accumulate
56 : #include <string> // string, stoi, to_string
57 : #include <utility> // declval, forward, move, pair, swap
58 : #include <vector> // vector
59 :
60 : // #include <nlohmann/adl_serializer.hpp>
61 :
62 :
63 : #include <type_traits>
64 : #include <utility>
65 :
66 : // #include <nlohmann/detail/conversions/from_json.hpp>
67 :
68 :
69 : #include <algorithm> // transform
70 : #include <array> // array
71 : #include <forward_list> // forward_list
72 : #include <iterator> // inserter, front_inserter, end
73 : #include <map> // map
74 : #include <string> // string
75 : #include <tuple> // tuple, make_tuple
76 : #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
77 : #include <unordered_map> // unordered_map
78 : #include <utility> // pair, declval
79 : #include <valarray> // valarray
80 :
81 : // #include <nlohmann/detail/exceptions.hpp>
82 :
83 :
84 : #include <exception> // exception
85 : #include <stdexcept> // runtime_error
86 : #include <string> // to_string
87 : #include <vector> // vector
88 :
89 : // #include <nlohmann/detail/value_t.hpp>
90 :
91 :
92 : #include <array> // array
93 : #include <cstddef> // size_t
94 : #include <cstdint> // uint8_t
95 : #include <string> // string
96 :
97 : namespace nlohmann
98 : {
99 : namespace detail
100 : {
101 : ///////////////////////////
102 : // JSON type enumeration //
103 : ///////////////////////////
104 :
105 : /*!
106 : @brief the JSON type enumeration
107 :
108 : This enumeration collects the different JSON types. It is internally used to
109 : distinguish the stored values, and the functions @ref basic_json::is_null(),
110 : @ref basic_json::is_object(), @ref basic_json::is_array(),
111 : @ref basic_json::is_string(), @ref basic_json::is_boolean(),
112 : @ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
113 : @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
114 : @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
115 : @ref basic_json::is_structured() rely on it.
116 :
117 : @note There are three enumeration entries (number_integer, number_unsigned, and
118 : number_float), because the library distinguishes these three types for numbers:
119 : @ref basic_json::number_unsigned_t is used for unsigned integers,
120 : @ref basic_json::number_integer_t is used for signed integers, and
121 : @ref basic_json::number_float_t is used for floating-point numbers or to
122 : approximate integers which do not fit in the limits of their respective type.
123 :
124 : @sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
125 : value with the default value for a given type
126 :
127 : @since version 1.0.0
128 : */
129 : enum class value_t : std::uint8_t
130 : {
131 : null, ///< null value
132 : object, ///< object (unordered set of name/value pairs)
133 : array, ///< array (ordered collection of values)
134 : string, ///< string value
135 : boolean, ///< boolean value
136 : number_integer, ///< number value (signed integer)
137 : number_unsigned, ///< number value (unsigned integer)
138 : number_float, ///< number value (floating-point)
139 : binary, ///< binary array (ordered collection of bytes)
140 : discarded ///< discarded by the parser callback function
141 : };
142 :
143 : /*!
144 : @brief comparison operator for JSON types
145 :
146 : Returns an ordering that is similar to Python:
147 : - order: null < boolean < number < object < array < string < binary
148 : - furthermore, each type is not smaller than itself
149 : - discarded values are not comparable
150 : - binary is represented as a b"" string in python and directly comparable to a
151 : string; however, making a binary array directly comparable with a string would
152 : be surprising behavior in a JSON file.
153 :
154 : @since version 1.0.0
155 : */
156 : inline bool operator<(const value_t lhs, const value_t rhs) noexcept
157 : {
158 : static constexpr std::array<std::uint8_t, 9> order = {{
159 : 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
160 : 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
161 : 6 /* binary */
162 : }
163 : };
164 :
165 0 : const auto l_index = static_cast<std::size_t>(lhs);
166 0 : const auto r_index = static_cast<std::size_t>(rhs);
167 0 : return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
168 : }
169 : } // namespace detail
170 : } // namespace nlohmann
171 :
172 : // #include <nlohmann/detail/string_escape.hpp>
173 :
174 :
175 : #include <string>
176 : // #include <nlohmann/detail/macro_scope.hpp>
177 :
178 :
179 : #include <utility> // declval, pair
180 : // #include <nlohmann/thirdparty/hedley/hedley.hpp>
181 :
182 :
183 : /* Hedley - https://nemequ.github.io/hedley
184 : * Created by Evan Nemerson <evan@nemerson.com>
185 : *
186 : * To the extent possible under law, the author(s) have dedicated all
187 : * copyright and related and neighboring rights to this software to
188 : * the public domain worldwide. This software is distributed without
189 : * any warranty.
190 : *
191 : * For details, see <http://creativecommons.org/publicdomain/zero/1.0/>.
192 : * SPDX-License-Identifier: CC0-1.0
193 : */
194 :
195 : #if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
196 : #if defined(JSON_HEDLEY_VERSION)
197 : #undef JSON_HEDLEY_VERSION
198 : #endif
199 : #define JSON_HEDLEY_VERSION 15
200 :
201 : #if defined(JSON_HEDLEY_STRINGIFY_EX)
202 : #undef JSON_HEDLEY_STRINGIFY_EX
203 : #endif
204 : #define JSON_HEDLEY_STRINGIFY_EX(x) #x
205 :
206 : #if defined(JSON_HEDLEY_STRINGIFY)
207 : #undef JSON_HEDLEY_STRINGIFY
208 : #endif
209 : #define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
210 :
211 : #if defined(JSON_HEDLEY_CONCAT_EX)
212 : #undef JSON_HEDLEY_CONCAT_EX
213 : #endif
214 : #define JSON_HEDLEY_CONCAT_EX(a,b) a##b
215 :
216 : #if defined(JSON_HEDLEY_CONCAT)
217 : #undef JSON_HEDLEY_CONCAT
218 : #endif
219 : #define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
220 :
221 : #if defined(JSON_HEDLEY_CONCAT3_EX)
222 : #undef JSON_HEDLEY_CONCAT3_EX
223 : #endif
224 : #define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
225 :
226 : #if defined(JSON_HEDLEY_CONCAT3)
227 : #undef JSON_HEDLEY_CONCAT3
228 : #endif
229 : #define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
230 :
231 : #if defined(JSON_HEDLEY_VERSION_ENCODE)
232 : #undef JSON_HEDLEY_VERSION_ENCODE
233 : #endif
234 : #define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
235 :
236 : #if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
237 : #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
238 : #endif
239 : #define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
240 :
241 : #if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
242 : #undef JSON_HEDLEY_VERSION_DECODE_MINOR
243 : #endif
244 : #define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
245 :
246 : #if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
247 : #undef JSON_HEDLEY_VERSION_DECODE_REVISION
248 : #endif
249 : #define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
250 :
251 : #if defined(JSON_HEDLEY_GNUC_VERSION)
252 : #undef JSON_HEDLEY_GNUC_VERSION
253 : #endif
254 : #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
255 : #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
256 : #elif defined(__GNUC__)
257 : #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
258 : #endif
259 :
260 : #if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
261 : #undef JSON_HEDLEY_GNUC_VERSION_CHECK
262 : #endif
263 : #if defined(JSON_HEDLEY_GNUC_VERSION)
264 : #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
265 : #else
266 : #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
267 : #endif
268 :
269 : #if defined(JSON_HEDLEY_MSVC_VERSION)
270 : #undef JSON_HEDLEY_MSVC_VERSION
271 : #endif
272 : #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
273 : #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
274 : #elif defined(_MSC_FULL_VER) && !defined(__ICL)
275 : #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
276 : #elif defined(_MSC_VER) && !defined(__ICL)
277 : #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
278 : #endif
279 :
280 : #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
281 : #undef JSON_HEDLEY_MSVC_VERSION_CHECK
282 : #endif
283 : #if !defined(JSON_HEDLEY_MSVC_VERSION)
284 : #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
285 : #elif defined(_MSC_VER) && (_MSC_VER >= 1400)
286 : #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
287 : #elif defined(_MSC_VER) && (_MSC_VER >= 1200)
288 : #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
289 : #else
290 : #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
291 : #endif
292 :
293 : #if defined(JSON_HEDLEY_INTEL_VERSION)
294 : #undef JSON_HEDLEY_INTEL_VERSION
295 : #endif
296 : #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
297 : #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
298 : #elif defined(__INTEL_COMPILER) && !defined(__ICL)
299 : #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
300 : #endif
301 :
302 : #if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
303 : #undef JSON_HEDLEY_INTEL_VERSION_CHECK
304 : #endif
305 : #if defined(JSON_HEDLEY_INTEL_VERSION)
306 : #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
307 : #else
308 : #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
309 : #endif
310 :
311 : #if defined(JSON_HEDLEY_INTEL_CL_VERSION)
312 : #undef JSON_HEDLEY_INTEL_CL_VERSION
313 : #endif
314 : #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
315 : #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
316 : #endif
317 :
318 : #if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
319 : #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
320 : #endif
321 : #if defined(JSON_HEDLEY_INTEL_CL_VERSION)
322 : #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
323 : #else
324 : #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
325 : #endif
326 :
327 : #if defined(JSON_HEDLEY_PGI_VERSION)
328 : #undef JSON_HEDLEY_PGI_VERSION
329 : #endif
330 : #if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
331 : #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
332 : #endif
333 :
334 : #if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
335 : #undef JSON_HEDLEY_PGI_VERSION_CHECK
336 : #endif
337 : #if defined(JSON_HEDLEY_PGI_VERSION)
338 : #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
339 : #else
340 : #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
341 : #endif
342 :
343 : #if defined(JSON_HEDLEY_SUNPRO_VERSION)
344 : #undef JSON_HEDLEY_SUNPRO_VERSION
345 : #endif
346 : #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
347 : #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
348 : #elif defined(__SUNPRO_C)
349 : #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
350 : #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
351 : #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
352 : #elif defined(__SUNPRO_CC)
353 : #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
354 : #endif
355 :
356 : #if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
357 : #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
358 : #endif
359 : #if defined(JSON_HEDLEY_SUNPRO_VERSION)
360 : #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
361 : #else
362 : #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
363 : #endif
364 :
365 : #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
366 : #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
367 : #endif
368 : #if defined(__EMSCRIPTEN__)
369 : #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
370 : #endif
371 :
372 : #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
373 : #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
374 : #endif
375 : #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
376 : #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
377 : #else
378 : #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
379 : #endif
380 :
381 : #if defined(JSON_HEDLEY_ARM_VERSION)
382 : #undef JSON_HEDLEY_ARM_VERSION
383 : #endif
384 : #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
385 : #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
386 : #elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
387 : #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
388 : #endif
389 :
390 : #if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
391 : #undef JSON_HEDLEY_ARM_VERSION_CHECK
392 : #endif
393 : #if defined(JSON_HEDLEY_ARM_VERSION)
394 : #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
395 : #else
396 : #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
397 : #endif
398 :
399 : #if defined(JSON_HEDLEY_IBM_VERSION)
400 : #undef JSON_HEDLEY_IBM_VERSION
401 : #endif
402 : #if defined(__ibmxl__)
403 : #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
404 : #elif defined(__xlC__) && defined(__xlC_ver__)
405 : #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
406 : #elif defined(__xlC__)
407 : #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
408 : #endif
409 :
410 : #if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
411 : #undef JSON_HEDLEY_IBM_VERSION_CHECK
412 : #endif
413 : #if defined(JSON_HEDLEY_IBM_VERSION)
414 : #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
415 : #else
416 : #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
417 : #endif
418 :
419 : #if defined(JSON_HEDLEY_TI_VERSION)
420 : #undef JSON_HEDLEY_TI_VERSION
421 : #endif
422 : #if \
423 : defined(__TI_COMPILER_VERSION__) && \
424 : ( \
425 : defined(__TMS470__) || defined(__TI_ARM__) || \
426 : defined(__MSP430__) || \
427 : defined(__TMS320C2000__) \
428 : )
429 : #if (__TI_COMPILER_VERSION__ >= 16000000)
430 : #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
431 : #endif
432 : #endif
433 :
434 : #if defined(JSON_HEDLEY_TI_VERSION_CHECK)
435 : #undef JSON_HEDLEY_TI_VERSION_CHECK
436 : #endif
437 : #if defined(JSON_HEDLEY_TI_VERSION)
438 : #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
439 : #else
440 : #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
441 : #endif
442 :
443 : #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
444 : #undef JSON_HEDLEY_TI_CL2000_VERSION
445 : #endif
446 : #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
447 : #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
448 : #endif
449 :
450 : #if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
451 : #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
452 : #endif
453 : #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
454 : #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
455 : #else
456 : #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
457 : #endif
458 :
459 : #if defined(JSON_HEDLEY_TI_CL430_VERSION)
460 : #undef JSON_HEDLEY_TI_CL430_VERSION
461 : #endif
462 : #if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
463 : #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
464 : #endif
465 :
466 : #if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
467 : #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
468 : #endif
469 : #if defined(JSON_HEDLEY_TI_CL430_VERSION)
470 : #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
471 : #else
472 : #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
473 : #endif
474 :
475 : #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
476 : #undef JSON_HEDLEY_TI_ARMCL_VERSION
477 : #endif
478 : #if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
479 : #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
480 : #endif
481 :
482 : #if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
483 : #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
484 : #endif
485 : #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
486 : #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
487 : #else
488 : #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
489 : #endif
490 :
491 : #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
492 : #undef JSON_HEDLEY_TI_CL6X_VERSION
493 : #endif
494 : #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
495 : #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
496 : #endif
497 :
498 : #if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
499 : #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
500 : #endif
501 : #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
502 : #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
503 : #else
504 : #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
505 : #endif
506 :
507 : #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
508 : #undef JSON_HEDLEY_TI_CL7X_VERSION
509 : #endif
510 : #if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
511 : #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
512 : #endif
513 :
514 : #if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
515 : #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
516 : #endif
517 : #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
518 : #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
519 : #else
520 : #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
521 : #endif
522 :
523 : #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
524 : #undef JSON_HEDLEY_TI_CLPRU_VERSION
525 : #endif
526 : #if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
527 : #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
528 : #endif
529 :
530 : #if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
531 : #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
532 : #endif
533 : #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
534 : #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
535 : #else
536 : #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
537 : #endif
538 :
539 : #if defined(JSON_HEDLEY_CRAY_VERSION)
540 : #undef JSON_HEDLEY_CRAY_VERSION
541 : #endif
542 : #if defined(_CRAYC)
543 : #if defined(_RELEASE_PATCHLEVEL)
544 : #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
545 : #else
546 : #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
547 : #endif
548 : #endif
549 :
550 : #if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
551 : #undef JSON_HEDLEY_CRAY_VERSION_CHECK
552 : #endif
553 : #if defined(JSON_HEDLEY_CRAY_VERSION)
554 : #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
555 : #else
556 : #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
557 : #endif
558 :
559 : #if defined(JSON_HEDLEY_IAR_VERSION)
560 : #undef JSON_HEDLEY_IAR_VERSION
561 : #endif
562 : #if defined(__IAR_SYSTEMS_ICC__)
563 : #if __VER__ > 1000
564 : #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
565 : #else
566 : #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
567 : #endif
568 : #endif
569 :
570 : #if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
571 : #undef JSON_HEDLEY_IAR_VERSION_CHECK
572 : #endif
573 : #if defined(JSON_HEDLEY_IAR_VERSION)
574 : #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
575 : #else
576 : #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
577 : #endif
578 :
579 : #if defined(JSON_HEDLEY_TINYC_VERSION)
580 : #undef JSON_HEDLEY_TINYC_VERSION
581 : #endif
582 : #if defined(__TINYC__)
583 : #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
584 : #endif
585 :
586 : #if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
587 : #undef JSON_HEDLEY_TINYC_VERSION_CHECK
588 : #endif
589 : #if defined(JSON_HEDLEY_TINYC_VERSION)
590 : #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
591 : #else
592 : #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
593 : #endif
594 :
595 : #if defined(JSON_HEDLEY_DMC_VERSION)
596 : #undef JSON_HEDLEY_DMC_VERSION
597 : #endif
598 : #if defined(__DMC__)
599 : #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
600 : #endif
601 :
602 : #if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
603 : #undef JSON_HEDLEY_DMC_VERSION_CHECK
604 : #endif
605 : #if defined(JSON_HEDLEY_DMC_VERSION)
606 : #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
607 : #else
608 : #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
609 : #endif
610 :
611 : #if defined(JSON_HEDLEY_COMPCERT_VERSION)
612 : #undef JSON_HEDLEY_COMPCERT_VERSION
613 : #endif
614 : #if defined(__COMPCERT_VERSION__)
615 : #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
616 : #endif
617 :
618 : #if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
619 : #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
620 : #endif
621 : #if defined(JSON_HEDLEY_COMPCERT_VERSION)
622 : #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
623 : #else
624 : #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
625 : #endif
626 :
627 : #if defined(JSON_HEDLEY_PELLES_VERSION)
628 : #undef JSON_HEDLEY_PELLES_VERSION
629 : #endif
630 : #if defined(__POCC__)
631 : #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
632 : #endif
633 :
634 : #if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
635 : #undef JSON_HEDLEY_PELLES_VERSION_CHECK
636 : #endif
637 : #if defined(JSON_HEDLEY_PELLES_VERSION)
638 : #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
639 : #else
640 : #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
641 : #endif
642 :
643 : #if defined(JSON_HEDLEY_MCST_LCC_VERSION)
644 : #undef JSON_HEDLEY_MCST_LCC_VERSION
645 : #endif
646 : #if defined(__LCC__) && defined(__LCC_MINOR__)
647 : #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
648 : #endif
649 :
650 : #if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
651 : #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
652 : #endif
653 : #if defined(JSON_HEDLEY_MCST_LCC_VERSION)
654 : #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
655 : #else
656 : #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
657 : #endif
658 :
659 : #if defined(JSON_HEDLEY_GCC_VERSION)
660 : #undef JSON_HEDLEY_GCC_VERSION
661 : #endif
662 : #if \
663 : defined(JSON_HEDLEY_GNUC_VERSION) && \
664 : !defined(__clang__) && \
665 : !defined(JSON_HEDLEY_INTEL_VERSION) && \
666 : !defined(JSON_HEDLEY_PGI_VERSION) && \
667 : !defined(JSON_HEDLEY_ARM_VERSION) && \
668 : !defined(JSON_HEDLEY_CRAY_VERSION) && \
669 : !defined(JSON_HEDLEY_TI_VERSION) && \
670 : !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
671 : !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
672 : !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
673 : !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
674 : !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
675 : !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
676 : !defined(__COMPCERT__) && \
677 : !defined(JSON_HEDLEY_MCST_LCC_VERSION)
678 : #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
679 : #endif
680 :
681 : #if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
682 : #undef JSON_HEDLEY_GCC_VERSION_CHECK
683 : #endif
684 : #if defined(JSON_HEDLEY_GCC_VERSION)
685 : #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
686 : #else
687 : #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
688 : #endif
689 :
690 : #if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
691 : #undef JSON_HEDLEY_HAS_ATTRIBUTE
692 : #endif
693 : #if \
694 : defined(__has_attribute) && \
695 : ( \
696 : (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
697 : )
698 : # define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
699 : #else
700 : # define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
701 : #endif
702 :
703 : #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
704 : #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
705 : #endif
706 : #if defined(__has_attribute)
707 : #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
708 : #else
709 : #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
710 : #endif
711 :
712 : #if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
713 : #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
714 : #endif
715 : #if defined(__has_attribute)
716 : #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
717 : #else
718 : #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
719 : #endif
720 :
721 : #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
722 : #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
723 : #endif
724 : #if \
725 : defined(__has_cpp_attribute) && \
726 : defined(__cplusplus) && \
727 : (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
728 : #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
729 : #else
730 : #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
731 : #endif
732 :
733 : #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
734 : #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
735 : #endif
736 : #if !defined(__cplusplus) || !defined(__has_cpp_attribute)
737 : #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
738 : #elif \
739 : !defined(JSON_HEDLEY_PGI_VERSION) && \
740 : !defined(JSON_HEDLEY_IAR_VERSION) && \
741 : (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
742 : (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
743 : #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
744 : #else
745 : #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
746 : #endif
747 :
748 : #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
749 : #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
750 : #endif
751 : #if defined(__has_cpp_attribute) && defined(__cplusplus)
752 : #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
753 : #else
754 : #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
755 : #endif
756 :
757 : #if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
758 : #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
759 : #endif
760 : #if defined(__has_cpp_attribute) && defined(__cplusplus)
761 : #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
762 : #else
763 : #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
764 : #endif
765 :
766 : #if defined(JSON_HEDLEY_HAS_BUILTIN)
767 : #undef JSON_HEDLEY_HAS_BUILTIN
768 : #endif
769 : #if defined(__has_builtin)
770 : #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
771 : #else
772 : #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
773 : #endif
774 :
775 : #if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
776 : #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
777 : #endif
778 : #if defined(__has_builtin)
779 : #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
780 : #else
781 : #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
782 : #endif
783 :
784 : #if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
785 : #undef JSON_HEDLEY_GCC_HAS_BUILTIN
786 : #endif
787 : #if defined(__has_builtin)
788 : #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
789 : #else
790 : #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
791 : #endif
792 :
793 : #if defined(JSON_HEDLEY_HAS_FEATURE)
794 : #undef JSON_HEDLEY_HAS_FEATURE
795 : #endif
796 : #if defined(__has_feature)
797 : #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
798 : #else
799 : #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
800 : #endif
801 :
802 : #if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
803 : #undef JSON_HEDLEY_GNUC_HAS_FEATURE
804 : #endif
805 : #if defined(__has_feature)
806 : #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
807 : #else
808 : #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
809 : #endif
810 :
811 : #if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
812 : #undef JSON_HEDLEY_GCC_HAS_FEATURE
813 : #endif
814 : #if defined(__has_feature)
815 : #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
816 : #else
817 : #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
818 : #endif
819 :
820 : #if defined(JSON_HEDLEY_HAS_EXTENSION)
821 : #undef JSON_HEDLEY_HAS_EXTENSION
822 : #endif
823 : #if defined(__has_extension)
824 : #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
825 : #else
826 : #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
827 : #endif
828 :
829 : #if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
830 : #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
831 : #endif
832 : #if defined(__has_extension)
833 : #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
834 : #else
835 : #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
836 : #endif
837 :
838 : #if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
839 : #undef JSON_HEDLEY_GCC_HAS_EXTENSION
840 : #endif
841 : #if defined(__has_extension)
842 : #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
843 : #else
844 : #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
845 : #endif
846 :
847 : #if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
848 : #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
849 : #endif
850 : #if defined(__has_declspec_attribute)
851 : #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
852 : #else
853 : #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
854 : #endif
855 :
856 : #if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
857 : #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
858 : #endif
859 : #if defined(__has_declspec_attribute)
860 : #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
861 : #else
862 : #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
863 : #endif
864 :
865 : #if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
866 : #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
867 : #endif
868 : #if defined(__has_declspec_attribute)
869 : #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
870 : #else
871 : #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
872 : #endif
873 :
874 : #if defined(JSON_HEDLEY_HAS_WARNING)
875 : #undef JSON_HEDLEY_HAS_WARNING
876 : #endif
877 : #if defined(__has_warning)
878 : #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
879 : #else
880 : #define JSON_HEDLEY_HAS_WARNING(warning) (0)
881 : #endif
882 :
883 : #if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
884 : #undef JSON_HEDLEY_GNUC_HAS_WARNING
885 : #endif
886 : #if defined(__has_warning)
887 : #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
888 : #else
889 : #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
890 : #endif
891 :
892 : #if defined(JSON_HEDLEY_GCC_HAS_WARNING)
893 : #undef JSON_HEDLEY_GCC_HAS_WARNING
894 : #endif
895 : #if defined(__has_warning)
896 : #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
897 : #else
898 : #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
899 : #endif
900 :
901 : #if \
902 : (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
903 : defined(__clang__) || \
904 : JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
905 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
906 : JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
907 : JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
908 : JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
909 : JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
910 : JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
911 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
912 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
913 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
914 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
915 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
916 : JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
917 : JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
918 : JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
919 : (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
920 : #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
921 : #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
922 : #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
923 : #else
924 : #define JSON_HEDLEY_PRAGMA(value)
925 : #endif
926 :
927 : #if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
928 : #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
929 : #endif
930 : #if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
931 : #undef JSON_HEDLEY_DIAGNOSTIC_POP
932 : #endif
933 : #if defined(__clang__)
934 : #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
935 : #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
936 : #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
937 : #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
938 : #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
939 : #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
940 : #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
941 : #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
942 : #elif \
943 : JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
944 : JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
945 : #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
946 : #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
947 : #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
948 : #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
949 : #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
950 : #elif \
951 : JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
952 : JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
953 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
954 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
955 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
956 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
957 : #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
958 : #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
959 : #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
960 : #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
961 : #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
962 : #else
963 : #define JSON_HEDLEY_DIAGNOSTIC_PUSH
964 : #define JSON_HEDLEY_DIAGNOSTIC_POP
965 : #endif
966 :
967 : /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
968 : HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
969 : #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
970 : #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
971 : #endif
972 : #if defined(__cplusplus)
973 : # if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
974 : # if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
975 : # if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
976 : # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
977 : JSON_HEDLEY_DIAGNOSTIC_PUSH \
978 : _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
979 : _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
980 : _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
981 : xpr \
982 : JSON_HEDLEY_DIAGNOSTIC_POP
983 : # else
984 : # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
985 : JSON_HEDLEY_DIAGNOSTIC_PUSH \
986 : _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
987 : _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
988 : xpr \
989 : JSON_HEDLEY_DIAGNOSTIC_POP
990 : # endif
991 : # else
992 : # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
993 : JSON_HEDLEY_DIAGNOSTIC_PUSH \
994 : _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
995 : xpr \
996 : JSON_HEDLEY_DIAGNOSTIC_POP
997 : # endif
998 : # endif
999 : #endif
1000 : #if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1001 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1002 : #endif
1003 :
1004 : #if defined(JSON_HEDLEY_CONST_CAST)
1005 : #undef JSON_HEDLEY_CONST_CAST
1006 : #endif
1007 : #if defined(__cplusplus)
1008 : # define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1009 : #elif \
1010 : JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1011 : JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1012 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1013 : # define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1014 : JSON_HEDLEY_DIAGNOSTIC_PUSH \
1015 : JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1016 : ((T) (expr)); \
1017 : JSON_HEDLEY_DIAGNOSTIC_POP \
1018 : }))
1019 : #else
1020 : # define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1021 : #endif
1022 :
1023 : #if defined(JSON_HEDLEY_REINTERPRET_CAST)
1024 : #undef JSON_HEDLEY_REINTERPRET_CAST
1025 : #endif
1026 : #if defined(__cplusplus)
1027 : #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1028 : #else
1029 : #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1030 : #endif
1031 :
1032 : #if defined(JSON_HEDLEY_STATIC_CAST)
1033 : #undef JSON_HEDLEY_STATIC_CAST
1034 : #endif
1035 : #if defined(__cplusplus)
1036 : #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1037 : #else
1038 : #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1039 : #endif
1040 :
1041 : #if defined(JSON_HEDLEY_CPP_CAST)
1042 : #undef JSON_HEDLEY_CPP_CAST
1043 : #endif
1044 : #if defined(__cplusplus)
1045 : # if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1046 : # define JSON_HEDLEY_CPP_CAST(T, expr) \
1047 : JSON_HEDLEY_DIAGNOSTIC_PUSH \
1048 : _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1049 : ((T) (expr)) \
1050 : JSON_HEDLEY_DIAGNOSTIC_POP
1051 : # elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1052 : # define JSON_HEDLEY_CPP_CAST(T, expr) \
1053 : JSON_HEDLEY_DIAGNOSTIC_PUSH \
1054 : _Pragma("diag_suppress=Pe137") \
1055 : JSON_HEDLEY_DIAGNOSTIC_POP
1056 : # else
1057 : # define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1058 : # endif
1059 : #else
1060 : # define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1061 : #endif
1062 :
1063 : #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1064 : #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1065 : #endif
1066 : #if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1067 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1068 : #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1069 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1070 : #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1071 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1072 : #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1073 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1074 : #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1075 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1076 : #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1077 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1078 : #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1079 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1080 : #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1081 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1082 : #elif \
1083 : JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1084 : (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1085 : JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1086 : (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1087 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1088 : (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1089 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1090 : (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1091 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1092 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1093 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1094 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1095 : #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1096 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1097 : #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1098 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1099 : #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1100 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1101 : #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1102 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1103 : #else
1104 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1105 : #endif
1106 :
1107 : #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1108 : #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1109 : #endif
1110 : #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1111 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1112 : #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1113 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1114 : #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1115 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1116 : #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1117 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1118 : #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1119 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1120 : #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1121 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1122 : #elif \
1123 : JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1124 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1125 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1126 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1127 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1128 : #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1129 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1130 : #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1131 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1132 : #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1133 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1134 : #else
1135 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1136 : #endif
1137 :
1138 : #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1139 : #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1140 : #endif
1141 : #if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1142 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1143 : #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1144 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1145 : #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1146 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1147 : #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1148 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1149 : #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1150 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1151 : #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1152 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1153 : #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1154 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1155 : #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1156 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1157 : #elif \
1158 : JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1159 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1160 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1161 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1162 : #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1163 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1164 : #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1165 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1166 : #else
1167 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1168 : #endif
1169 :
1170 : #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1171 : #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1172 : #endif
1173 : #if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1174 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1175 : #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1176 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1177 : #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1178 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1179 : #else
1180 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1181 : #endif
1182 :
1183 : #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1184 : #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1185 : #endif
1186 : #if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1187 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1188 : #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1189 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1190 : #elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1191 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1192 : #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1193 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1194 : #else
1195 : #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1196 : #endif
1197 :
1198 : #if defined(JSON_HEDLEY_DEPRECATED)
1199 : #undef JSON_HEDLEY_DEPRECATED
1200 : #endif
1201 : #if defined(JSON_HEDLEY_DEPRECATED_FOR)
1202 : #undef JSON_HEDLEY_DEPRECATED_FOR
1203 : #endif
1204 : #if \
1205 : JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1206 : JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1207 : #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1208 : #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1209 : #elif \
1210 : (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1211 : JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1212 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1213 : JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1214 : JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1215 : JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1216 : JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1217 : JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1218 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1219 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1220 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1221 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1222 : #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1223 : #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1224 : #elif defined(__cplusplus) && (__cplusplus >= 201402L)
1225 : #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1226 : #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1227 : #elif \
1228 : JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1229 : JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1230 : JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1231 : JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1232 : (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1233 : JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1234 : (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1235 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1236 : (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1237 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1238 : (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1239 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1240 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1241 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1242 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1243 : JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1244 : #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1245 : #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1246 : #elif \
1247 : JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1248 : JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1249 : JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1250 : #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1251 : #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1252 : #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1253 : #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1254 : #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1255 : #else
1256 : #define JSON_HEDLEY_DEPRECATED(since)
1257 : #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1258 : #endif
1259 :
1260 : #if defined(JSON_HEDLEY_UNAVAILABLE)
1261 : #undef JSON_HEDLEY_UNAVAILABLE
1262 : #endif
1263 : #if \
1264 : JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1265 : JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1266 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1267 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1268 : #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1269 : #else
1270 : #define JSON_HEDLEY_UNAVAILABLE(available_since)
1271 : #endif
1272 :
1273 : #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1274 : #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1275 : #endif
1276 : #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1277 : #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1278 : #endif
1279 : #if \
1280 : JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1281 : JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1282 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1283 : JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1284 : (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1285 : JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1286 : (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1287 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1288 : (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1289 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1290 : (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1291 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1292 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1293 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1294 : (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1295 : JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1296 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1297 : #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1298 : #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1299 : #elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1300 : #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1301 : #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1302 : #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1303 : #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1304 : #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1305 : #elif defined(_Check_return_) /* SAL */
1306 : #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1307 : #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1308 : #else
1309 : #define JSON_HEDLEY_WARN_UNUSED_RESULT
1310 : #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1311 : #endif
1312 :
1313 : #if defined(JSON_HEDLEY_SENTINEL)
1314 : #undef JSON_HEDLEY_SENTINEL
1315 : #endif
1316 : #if \
1317 : JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1318 : JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1319 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1320 : JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1321 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1322 : #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1323 : #else
1324 : #define JSON_HEDLEY_SENTINEL(position)
1325 : #endif
1326 :
1327 : #if defined(JSON_HEDLEY_NO_RETURN)
1328 : #undef JSON_HEDLEY_NO_RETURN
1329 : #endif
1330 : #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1331 : #define JSON_HEDLEY_NO_RETURN __noreturn
1332 : #elif \
1333 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1334 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1335 : #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1336 : #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1337 : #define JSON_HEDLEY_NO_RETURN _Noreturn
1338 : #elif defined(__cplusplus) && (__cplusplus >= 201103L)
1339 : #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1340 : #elif \
1341 : JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1342 : JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1343 : JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1344 : JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1345 : JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1346 : JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1347 : (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1348 : JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1349 : (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1350 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1351 : (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1352 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1353 : (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1354 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1355 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1356 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1357 : JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1358 : #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1359 : #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1360 : #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1361 : #elif \
1362 : JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1363 : JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1364 : #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1365 : #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1366 : #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1367 : #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1368 : #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1369 : #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1370 : #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1371 : #else
1372 : #define JSON_HEDLEY_NO_RETURN
1373 : #endif
1374 :
1375 : #if defined(JSON_HEDLEY_NO_ESCAPE)
1376 : #undef JSON_HEDLEY_NO_ESCAPE
1377 : #endif
1378 : #if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1379 : #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1380 : #else
1381 : #define JSON_HEDLEY_NO_ESCAPE
1382 : #endif
1383 :
1384 : #if defined(JSON_HEDLEY_UNREACHABLE)
1385 : #undef JSON_HEDLEY_UNREACHABLE
1386 : #endif
1387 : #if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1388 : #undef JSON_HEDLEY_UNREACHABLE_RETURN
1389 : #endif
1390 : #if defined(JSON_HEDLEY_ASSUME)
1391 : #undef JSON_HEDLEY_ASSUME
1392 : #endif
1393 : #if \
1394 : JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1395 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1396 : JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1397 : #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1398 : #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1399 : #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1400 : #elif \
1401 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1402 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1403 : #if defined(__cplusplus)
1404 : #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1405 : #else
1406 : #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1407 : #endif
1408 : #endif
1409 : #if \
1410 : (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1411 : JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1412 : JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1413 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1414 : JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1415 : JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1416 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1417 : #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1418 : #elif defined(JSON_HEDLEY_ASSUME)
1419 : #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1420 : #endif
1421 : #if !defined(JSON_HEDLEY_ASSUME)
1422 : #if defined(JSON_HEDLEY_UNREACHABLE)
1423 : #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1424 : #else
1425 : #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1426 : #endif
1427 : #endif
1428 : #if defined(JSON_HEDLEY_UNREACHABLE)
1429 : #if \
1430 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1431 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1432 : #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1433 : #else
1434 : #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1435 : #endif
1436 : #else
1437 : #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1438 : #endif
1439 : #if !defined(JSON_HEDLEY_UNREACHABLE)
1440 : #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1441 : #endif
1442 :
1443 : JSON_HEDLEY_DIAGNOSTIC_PUSH
1444 : #if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1445 : #pragma clang diagnostic ignored "-Wpedantic"
1446 : #endif
1447 : #if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1448 : #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1449 : #endif
1450 : #if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1451 : #if defined(__clang__)
1452 : #pragma clang diagnostic ignored "-Wvariadic-macros"
1453 : #elif defined(JSON_HEDLEY_GCC_VERSION)
1454 : #pragma GCC diagnostic ignored "-Wvariadic-macros"
1455 : #endif
1456 : #endif
1457 : #if defined(JSON_HEDLEY_NON_NULL)
1458 : #undef JSON_HEDLEY_NON_NULL
1459 : #endif
1460 : #if \
1461 : JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1462 : JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1463 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1464 : JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1465 : #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1466 : #else
1467 : #define JSON_HEDLEY_NON_NULL(...)
1468 : #endif
1469 : JSON_HEDLEY_DIAGNOSTIC_POP
1470 :
1471 : #if defined(JSON_HEDLEY_PRINTF_FORMAT)
1472 : #undef JSON_HEDLEY_PRINTF_FORMAT
1473 : #endif
1474 : #if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1475 : #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1476 : #elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1477 : #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1478 : #elif \
1479 : JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1480 : JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1481 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1482 : JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1483 : JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1484 : JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1485 : (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1486 : JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1487 : (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1488 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1489 : (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1490 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1491 : (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1492 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1493 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1494 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1495 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1496 : #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1497 : #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1498 : #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1499 : #else
1500 : #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1501 : #endif
1502 :
1503 : #if defined(JSON_HEDLEY_CONSTEXPR)
1504 : #undef JSON_HEDLEY_CONSTEXPR
1505 : #endif
1506 : #if defined(__cplusplus)
1507 : #if __cplusplus >= 201103L
1508 : #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1509 : #endif
1510 : #endif
1511 : #if !defined(JSON_HEDLEY_CONSTEXPR)
1512 : #define JSON_HEDLEY_CONSTEXPR
1513 : #endif
1514 :
1515 : #if defined(JSON_HEDLEY_PREDICT)
1516 : #undef JSON_HEDLEY_PREDICT
1517 : #endif
1518 : #if defined(JSON_HEDLEY_LIKELY)
1519 : #undef JSON_HEDLEY_LIKELY
1520 : #endif
1521 : #if defined(JSON_HEDLEY_UNLIKELY)
1522 : #undef JSON_HEDLEY_UNLIKELY
1523 : #endif
1524 : #if defined(JSON_HEDLEY_UNPREDICTABLE)
1525 : #undef JSON_HEDLEY_UNPREDICTABLE
1526 : #endif
1527 : #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1528 : #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1529 : #endif
1530 : #if \
1531 : (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1532 : JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1533 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1534 : # define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1535 : # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1536 : # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1537 : # define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1538 : # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1539 : #elif \
1540 : (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1541 : JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1542 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1543 : (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1544 : JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1545 : JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1546 : JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1547 : JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1548 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1549 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1550 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1551 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1552 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1553 : JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1554 : JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1555 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1556 : # define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1557 : (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1558 : # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1559 : (__extension__ ({ \
1560 : double hedley_probability_ = (probability); \
1561 : ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1562 : }))
1563 : # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1564 : (__extension__ ({ \
1565 : double hedley_probability_ = (probability); \
1566 : ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1567 : }))
1568 : # define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1569 : # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1570 : #else
1571 : # define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1572 : # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1573 : # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1574 : # define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1575 : # define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1576 : #endif
1577 : #if !defined(JSON_HEDLEY_UNPREDICTABLE)
1578 : #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1579 : #endif
1580 :
1581 : #if defined(JSON_HEDLEY_MALLOC)
1582 : #undef JSON_HEDLEY_MALLOC
1583 : #endif
1584 : #if \
1585 : JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1586 : JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1587 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1588 : JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1589 : JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1590 : JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1591 : JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1592 : (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1593 : JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1594 : (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1595 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1596 : (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1597 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1598 : (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1599 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1600 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1601 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1602 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1603 : #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1604 : #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1605 : #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1606 : #elif \
1607 : JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1608 : JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1609 : #define JSON_HEDLEY_MALLOC __declspec(restrict)
1610 : #else
1611 : #define JSON_HEDLEY_MALLOC
1612 : #endif
1613 :
1614 : #if defined(JSON_HEDLEY_PURE)
1615 : #undef JSON_HEDLEY_PURE
1616 : #endif
1617 : #if \
1618 : JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1619 : JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1620 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1621 : JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1622 : JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1623 : JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1624 : JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1625 : (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1626 : JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1627 : (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1628 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1629 : (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1630 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1631 : (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1632 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1633 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1634 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1635 : JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1636 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1637 : # define JSON_HEDLEY_PURE __attribute__((__pure__))
1638 : #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1639 : # define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1640 : #elif defined(__cplusplus) && \
1641 : ( \
1642 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1643 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1644 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1645 : )
1646 : # define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1647 : #else
1648 : # define JSON_HEDLEY_PURE
1649 : #endif
1650 :
1651 : #if defined(JSON_HEDLEY_CONST)
1652 : #undef JSON_HEDLEY_CONST
1653 : #endif
1654 : #if \
1655 : JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1656 : JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1657 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1658 : JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1659 : JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1660 : JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1661 : JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1662 : (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1663 : JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1664 : (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1665 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1666 : (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1667 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1668 : (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1669 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1670 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1671 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1672 : JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1673 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1674 : #define JSON_HEDLEY_CONST __attribute__((__const__))
1675 : #elif \
1676 : JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1677 : #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1678 : #else
1679 : #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1680 : #endif
1681 :
1682 : #if defined(JSON_HEDLEY_RESTRICT)
1683 : #undef JSON_HEDLEY_RESTRICT
1684 : #endif
1685 : #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1686 : #define JSON_HEDLEY_RESTRICT restrict
1687 : #elif \
1688 : JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1689 : JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1690 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1691 : JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1692 : JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1693 : JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1694 : JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1695 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1696 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1697 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1698 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1699 : (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1700 : JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1701 : defined(__clang__) || \
1702 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1703 : #define JSON_HEDLEY_RESTRICT __restrict
1704 : #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1705 : #define JSON_HEDLEY_RESTRICT _Restrict
1706 : #else
1707 : #define JSON_HEDLEY_RESTRICT
1708 : #endif
1709 :
1710 : #if defined(JSON_HEDLEY_INLINE)
1711 : #undef JSON_HEDLEY_INLINE
1712 : #endif
1713 : #if \
1714 : (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1715 : (defined(__cplusplus) && (__cplusplus >= 199711L))
1716 : #define JSON_HEDLEY_INLINE inline
1717 : #elif \
1718 : defined(JSON_HEDLEY_GCC_VERSION) || \
1719 : JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1720 : #define JSON_HEDLEY_INLINE __inline__
1721 : #elif \
1722 : JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1723 : JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1724 : JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1725 : JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1726 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1727 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1728 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1729 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1730 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1731 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1732 : #define JSON_HEDLEY_INLINE __inline
1733 : #else
1734 : #define JSON_HEDLEY_INLINE
1735 : #endif
1736 :
1737 : #if defined(JSON_HEDLEY_ALWAYS_INLINE)
1738 : #undef JSON_HEDLEY_ALWAYS_INLINE
1739 : #endif
1740 : #if \
1741 : JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1742 : JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1743 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1744 : JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1745 : JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1746 : JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1747 : JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1748 : (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1749 : JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1750 : (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1751 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1752 : (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1753 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1754 : (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1755 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1756 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1757 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1758 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1759 : JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1760 : # define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1761 : #elif \
1762 : JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1763 : JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1764 : # define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1765 : #elif defined(__cplusplus) && \
1766 : ( \
1767 : JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1768 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1769 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1770 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1771 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1772 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1773 : )
1774 : # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1775 : #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1776 : # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1777 : #else
1778 : # define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1779 : #endif
1780 :
1781 : #if defined(JSON_HEDLEY_NEVER_INLINE)
1782 : #undef JSON_HEDLEY_NEVER_INLINE
1783 : #endif
1784 : #if \
1785 : JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1786 : JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1787 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1788 : JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1789 : JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1790 : JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1791 : JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1792 : (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1793 : JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1794 : (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1795 : JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1796 : (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1797 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1798 : (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1799 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1800 : JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1801 : JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1802 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1803 : JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1804 : #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1805 : #elif \
1806 : JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1807 : JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1808 : #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1809 : #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1810 : #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1811 : #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1812 : #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1813 : #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1814 : #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1815 : #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1816 : #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1817 : #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1818 : #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1819 : #else
1820 : #define JSON_HEDLEY_NEVER_INLINE
1821 : #endif
1822 :
1823 : #if defined(JSON_HEDLEY_PRIVATE)
1824 : #undef JSON_HEDLEY_PRIVATE
1825 : #endif
1826 : #if defined(JSON_HEDLEY_PUBLIC)
1827 : #undef JSON_HEDLEY_PUBLIC
1828 : #endif
1829 : #if defined(JSON_HEDLEY_IMPORT)
1830 : #undef JSON_HEDLEY_IMPORT
1831 : #endif
1832 : #if defined(_WIN32) || defined(__CYGWIN__)
1833 : # define JSON_HEDLEY_PRIVATE
1834 : # define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1835 : # define JSON_HEDLEY_IMPORT __declspec(dllimport)
1836 : #else
1837 : # if \
1838 : JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1839 : JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1840 : JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1841 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1842 : JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1843 : JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1844 : ( \
1845 : defined(__TI_EABI__) && \
1846 : ( \
1847 : (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1848 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1849 : ) \
1850 : ) || \
1851 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1852 : # define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1853 : # define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1854 : # else
1855 : # define JSON_HEDLEY_PRIVATE
1856 : # define JSON_HEDLEY_PUBLIC
1857 : # endif
1858 : # define JSON_HEDLEY_IMPORT extern
1859 : #endif
1860 :
1861 : #if defined(JSON_HEDLEY_NO_THROW)
1862 : #undef JSON_HEDLEY_NO_THROW
1863 : #endif
1864 : #if \
1865 : JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
1866 : JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1867 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1868 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1869 : #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
1870 : #elif \
1871 : JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
1872 : JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1873 : JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1874 : #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
1875 : #else
1876 : #define JSON_HEDLEY_NO_THROW
1877 : #endif
1878 :
1879 : #if defined(JSON_HEDLEY_FALL_THROUGH)
1880 : #undef JSON_HEDLEY_FALL_THROUGH
1881 : #endif
1882 : #if \
1883 : JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
1884 : JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
1885 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1886 : #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
1887 : #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
1888 : #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
1889 : #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
1890 : #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
1891 : #elif defined(__fallthrough) /* SAL */
1892 : #define JSON_HEDLEY_FALL_THROUGH __fallthrough
1893 : #else
1894 : #define JSON_HEDLEY_FALL_THROUGH
1895 : #endif
1896 :
1897 : #if defined(JSON_HEDLEY_RETURNS_NON_NULL)
1898 : #undef JSON_HEDLEY_RETURNS_NON_NULL
1899 : #endif
1900 : #if \
1901 : JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
1902 : JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
1903 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1904 : #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
1905 : #elif defined(_Ret_notnull_) /* SAL */
1906 : #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
1907 : #else
1908 : #define JSON_HEDLEY_RETURNS_NON_NULL
1909 : #endif
1910 :
1911 : #if defined(JSON_HEDLEY_ARRAY_PARAM)
1912 : #undef JSON_HEDLEY_ARRAY_PARAM
1913 : #endif
1914 : #if \
1915 : defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
1916 : !defined(__STDC_NO_VLA__) && \
1917 : !defined(__cplusplus) && \
1918 : !defined(JSON_HEDLEY_PGI_VERSION) && \
1919 : !defined(JSON_HEDLEY_TINYC_VERSION)
1920 : #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
1921 : #else
1922 : #define JSON_HEDLEY_ARRAY_PARAM(name)
1923 : #endif
1924 :
1925 : #if defined(JSON_HEDLEY_IS_CONSTANT)
1926 : #undef JSON_HEDLEY_IS_CONSTANT
1927 : #endif
1928 : #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
1929 : #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
1930 : #endif
1931 : /* JSON_HEDLEY_IS_CONSTEXPR_ is for
1932 : HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1933 : #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1934 : #undef JSON_HEDLEY_IS_CONSTEXPR_
1935 : #endif
1936 : #if \
1937 : JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
1938 : JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1939 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1940 : JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
1941 : JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1942 : JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1943 : JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1944 : (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
1945 : JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1946 : JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1947 : #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
1948 : #endif
1949 : #if !defined(__cplusplus)
1950 : # if \
1951 : JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
1952 : JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1953 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1954 : JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1955 : JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1956 : JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1957 : JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
1958 : #if defined(__INTPTR_TYPE__)
1959 : #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
1960 : #else
1961 : #include <stdint.h>
1962 : #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
1963 : #endif
1964 : # elif \
1965 : ( \
1966 : defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
1967 : !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
1968 : !defined(JSON_HEDLEY_PGI_VERSION) && \
1969 : !defined(JSON_HEDLEY_IAR_VERSION)) || \
1970 : (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1971 : JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
1972 : JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
1973 : JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1974 : JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
1975 : #if defined(__INTPTR_TYPE__)
1976 : #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
1977 : #else
1978 : #include <stdint.h>
1979 : #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
1980 : #endif
1981 : # elif \
1982 : defined(JSON_HEDLEY_GCC_VERSION) || \
1983 : defined(JSON_HEDLEY_INTEL_VERSION) || \
1984 : defined(JSON_HEDLEY_TINYC_VERSION) || \
1985 : defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
1986 : JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
1987 : defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
1988 : defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
1989 : defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
1990 : defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
1991 : defined(__clang__)
1992 : # define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
1993 : sizeof(void) != \
1994 : sizeof(*( \
1995 : 1 ? \
1996 : ((void*) ((expr) * 0L) ) : \
1997 : ((struct { char v[sizeof(void) * 2]; } *) 1) \
1998 : ) \
1999 : ) \
2000 : )
2001 : # endif
2002 : #endif
2003 : #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2004 : #if !defined(JSON_HEDLEY_IS_CONSTANT)
2005 : #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2006 : #endif
2007 : #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2008 : #else
2009 : #if !defined(JSON_HEDLEY_IS_CONSTANT)
2010 : #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2011 : #endif
2012 : #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2013 : #endif
2014 :
2015 : #if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2016 : #undef JSON_HEDLEY_BEGIN_C_DECLS
2017 : #endif
2018 : #if defined(JSON_HEDLEY_END_C_DECLS)
2019 : #undef JSON_HEDLEY_END_C_DECLS
2020 : #endif
2021 : #if defined(JSON_HEDLEY_C_DECL)
2022 : #undef JSON_HEDLEY_C_DECL
2023 : #endif
2024 : #if defined(__cplusplus)
2025 : #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2026 : #define JSON_HEDLEY_END_C_DECLS }
2027 : #define JSON_HEDLEY_C_DECL extern "C"
2028 : #else
2029 : #define JSON_HEDLEY_BEGIN_C_DECLS
2030 : #define JSON_HEDLEY_END_C_DECLS
2031 : #define JSON_HEDLEY_C_DECL
2032 : #endif
2033 :
2034 : #if defined(JSON_HEDLEY_STATIC_ASSERT)
2035 : #undef JSON_HEDLEY_STATIC_ASSERT
2036 : #endif
2037 : #if \
2038 : !defined(__cplusplus) && ( \
2039 : (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2040 : (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2041 : JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2042 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2043 : defined(_Static_assert) \
2044 : )
2045 : # define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2046 : #elif \
2047 : (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2048 : JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2049 : JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2050 : # define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2051 : #else
2052 : # define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2053 : #endif
2054 :
2055 : #if defined(JSON_HEDLEY_NULL)
2056 : #undef JSON_HEDLEY_NULL
2057 : #endif
2058 : #if defined(__cplusplus)
2059 : #if __cplusplus >= 201103L
2060 : #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2061 : #elif defined(NULL)
2062 : #define JSON_HEDLEY_NULL NULL
2063 : #else
2064 : #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2065 : #endif
2066 : #elif defined(NULL)
2067 : #define JSON_HEDLEY_NULL NULL
2068 : #else
2069 : #define JSON_HEDLEY_NULL ((void*) 0)
2070 : #endif
2071 :
2072 : #if defined(JSON_HEDLEY_MESSAGE)
2073 : #undef JSON_HEDLEY_MESSAGE
2074 : #endif
2075 : #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2076 : # define JSON_HEDLEY_MESSAGE(msg) \
2077 : JSON_HEDLEY_DIAGNOSTIC_PUSH \
2078 : JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2079 : JSON_HEDLEY_PRAGMA(message msg) \
2080 : JSON_HEDLEY_DIAGNOSTIC_POP
2081 : #elif \
2082 : JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2083 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2084 : # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2085 : #elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2086 : # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2087 : #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2088 : # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2089 : #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2090 : # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2091 : #else
2092 : # define JSON_HEDLEY_MESSAGE(msg)
2093 : #endif
2094 :
2095 : #if defined(JSON_HEDLEY_WARNING)
2096 : #undef JSON_HEDLEY_WARNING
2097 : #endif
2098 : #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2099 : # define JSON_HEDLEY_WARNING(msg) \
2100 : JSON_HEDLEY_DIAGNOSTIC_PUSH \
2101 : JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2102 : JSON_HEDLEY_PRAGMA(clang warning msg) \
2103 : JSON_HEDLEY_DIAGNOSTIC_POP
2104 : #elif \
2105 : JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2106 : JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2107 : JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2108 : # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2109 : #elif \
2110 : JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2111 : JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2112 : # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2113 : #else
2114 : # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2115 : #endif
2116 :
2117 : #if defined(JSON_HEDLEY_REQUIRE)
2118 : #undef JSON_HEDLEY_REQUIRE
2119 : #endif
2120 : #if defined(JSON_HEDLEY_REQUIRE_MSG)
2121 : #undef JSON_HEDLEY_REQUIRE_MSG
2122 : #endif
2123 : #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2124 : # if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2125 : # define JSON_HEDLEY_REQUIRE(expr) \
2126 : JSON_HEDLEY_DIAGNOSTIC_PUSH \
2127 : _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2128 : __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2129 : JSON_HEDLEY_DIAGNOSTIC_POP
2130 : # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2131 : JSON_HEDLEY_DIAGNOSTIC_PUSH \
2132 : _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2133 : __attribute__((diagnose_if(!(expr), msg, "error"))) \
2134 : JSON_HEDLEY_DIAGNOSTIC_POP
2135 : # else
2136 : # define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2137 : # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2138 : # endif
2139 : #else
2140 : # define JSON_HEDLEY_REQUIRE(expr)
2141 : # define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2142 : #endif
2143 :
2144 : #if defined(JSON_HEDLEY_FLAGS)
2145 : #undef JSON_HEDLEY_FLAGS
2146 : #endif
2147 : #if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2148 : #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2149 : #else
2150 : #define JSON_HEDLEY_FLAGS
2151 : #endif
2152 :
2153 : #if defined(JSON_HEDLEY_FLAGS_CAST)
2154 : #undef JSON_HEDLEY_FLAGS_CAST
2155 : #endif
2156 : #if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2157 : # define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2158 : JSON_HEDLEY_DIAGNOSTIC_PUSH \
2159 : _Pragma("warning(disable:188)") \
2160 : ((T) (expr)); \
2161 : JSON_HEDLEY_DIAGNOSTIC_POP \
2162 : }))
2163 : #else
2164 : # define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2165 : #endif
2166 :
2167 : #if defined(JSON_HEDLEY_EMPTY_BASES)
2168 : #undef JSON_HEDLEY_EMPTY_BASES
2169 : #endif
2170 : #if \
2171 : (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2172 : JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2173 : #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2174 : #else
2175 : #define JSON_HEDLEY_EMPTY_BASES
2176 : #endif
2177 :
2178 : /* Remaining macros are deprecated. */
2179 :
2180 : #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2181 : #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2182 : #endif
2183 : #if defined(__clang__)
2184 : #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2185 : #else
2186 : #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2187 : #endif
2188 :
2189 : #if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2190 : #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2191 : #endif
2192 : #define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2193 :
2194 : #if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2195 : #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2196 : #endif
2197 : #define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2198 :
2199 : #if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2200 : #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2201 : #endif
2202 : #define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2203 :
2204 : #if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2205 : #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2206 : #endif
2207 : #define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2208 :
2209 : #if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2210 : #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2211 : #endif
2212 : #define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2213 :
2214 : #if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2215 : #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2216 : #endif
2217 : #define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2218 :
2219 : #if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2220 : #undef JSON_HEDLEY_CLANG_HAS_WARNING
2221 : #endif
2222 : #define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2223 :
2224 : #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2225 :
2226 : // #include <nlohmann/detail/meta/detected.hpp>
2227 :
2228 :
2229 : #include <type_traits>
2230 :
2231 : // #include <nlohmann/detail/meta/void_t.hpp>
2232 :
2233 :
2234 : namespace nlohmann
2235 : {
2236 : namespace detail
2237 : {
2238 : template<typename ...Ts> struct make_void
2239 : {
2240 : using type = void;
2241 : };
2242 : template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
2243 : } // namespace detail
2244 : } // namespace nlohmann
2245 :
2246 :
2247 : // https://en.cppreference.com/w/cpp/experimental/is_detected
2248 : namespace nlohmann
2249 : {
2250 : namespace detail
2251 : {
2252 : struct nonesuch
2253 : {
2254 : nonesuch() = delete;
2255 : ~nonesuch() = delete;
2256 : nonesuch(nonesuch const&) = delete;
2257 : nonesuch(nonesuch const&&) = delete;
2258 : void operator=(nonesuch const&) = delete;
2259 : void operator=(nonesuch&&) = delete;
2260 : };
2261 :
2262 : template<class Default,
2263 : class AlwaysVoid,
2264 : template<class...> class Op,
2265 : class... Args>
2266 : struct detector
2267 : {
2268 : using value_t = std::false_type;
2269 : using type = Default;
2270 : };
2271 :
2272 : template<class Default, template<class...> class Op, class... Args>
2273 : struct detector<Default, void_t<Op<Args...>>, Op, Args...>
2274 : {
2275 : using value_t = std::true_type;
2276 : using type = Op<Args...>;
2277 : };
2278 :
2279 : template<template<class...> class Op, class... Args>
2280 : using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
2281 :
2282 : template<template<class...> class Op, class... Args>
2283 : struct is_detected_lazy : is_detected<Op, Args...> { };
2284 :
2285 : template<template<class...> class Op, class... Args>
2286 : using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
2287 :
2288 : template<class Default, template<class...> class Op, class... Args>
2289 : using detected_or = detector<Default, void, Op, Args...>;
2290 :
2291 : template<class Default, template<class...> class Op, class... Args>
2292 : using detected_or_t = typename detected_or<Default, Op, Args...>::type;
2293 :
2294 : template<class Expected, template<class...> class Op, class... Args>
2295 : using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
2296 :
2297 : template<class To, template<class...> class Op, class... Args>
2298 : using is_detected_convertible =
2299 : std::is_convertible<detected_t<Op, Args...>, To>;
2300 : } // namespace detail
2301 : } // namespace nlohmann
2302 :
2303 :
2304 : // This file contains all internal macro definitions
2305 : // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2306 :
2307 : // exclude unsupported compilers
2308 : #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2309 : #if defined(__clang__)
2310 : #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2311 : #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2312 : #endif
2313 : #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2314 : #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2315 : #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2316 : #endif
2317 : #endif
2318 : #endif
2319 :
2320 : // C++ language standard detection
2321 : // if the user manually specified the used c++ version this is skipped
2322 : #if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2323 : #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2324 : #define JSON_HAS_CPP_20
2325 : #define JSON_HAS_CPP_17
2326 : #define JSON_HAS_CPP_14
2327 : #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2328 : #define JSON_HAS_CPP_17
2329 : #define JSON_HAS_CPP_14
2330 : #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2331 : #define JSON_HAS_CPP_14
2332 : #endif
2333 : // the cpp 11 flag is always specified because it is the minimal required version
2334 : #define JSON_HAS_CPP_11
2335 : #endif
2336 :
2337 : #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2338 : #ifdef JSON_HAS_CPP_17
2339 : #if defined(__cpp_lib_filesystem)
2340 : #define JSON_HAS_FILESYSTEM 1
2341 : #elif defined(__cpp_lib_experimental_filesystem)
2342 : #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2343 : #elif !defined(__has_include)
2344 : #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2345 : #elif __has_include(<filesystem>)
2346 : #define JSON_HAS_FILESYSTEM 1
2347 : #elif __has_include(<experimental/filesystem>)
2348 : #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2349 : #endif
2350 :
2351 : // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2352 : #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2353 : #undef JSON_HAS_FILESYSTEM
2354 : #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2355 : #endif
2356 :
2357 : // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2358 : #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2359 : #undef JSON_HAS_FILESYSTEM
2360 : #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2361 : #endif
2362 :
2363 : // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2364 : #if defined(__clang_major__) && __clang_major__ < 7
2365 : #undef JSON_HAS_FILESYSTEM
2366 : #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2367 : #endif
2368 :
2369 : // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2370 : #if defined(_MSC_VER) && _MSC_VER < 1940
2371 : #undef JSON_HAS_FILESYSTEM
2372 : #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2373 : #endif
2374 :
2375 : // no filesystem support before iOS 13
2376 : #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2377 : #undef JSON_HAS_FILESYSTEM
2378 : #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2379 : #endif
2380 :
2381 : // no filesystem support before macOS Catalina
2382 : #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2383 : #undef JSON_HAS_FILESYSTEM
2384 : #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2385 : #endif
2386 : #endif
2387 : #endif
2388 :
2389 : #ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2390 : #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2391 : #endif
2392 :
2393 : #ifndef JSON_HAS_FILESYSTEM
2394 : #define JSON_HAS_FILESYSTEM 0
2395 : #endif
2396 :
2397 : // disable documentation warnings on clang
2398 : #if defined(__clang__)
2399 : #pragma clang diagnostic push
2400 : #pragma clang diagnostic ignored "-Wdocumentation"
2401 : #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2402 : #endif
2403 :
2404 : // allow disabling exceptions
2405 : #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2406 : #define JSON_THROW(exception) throw exception
2407 : #define JSON_TRY try
2408 : #define JSON_CATCH(exception) catch(exception)
2409 : #define JSON_INTERNAL_CATCH(exception) catch(exception)
2410 : #else
2411 : #include <cstdlib>
2412 : #define JSON_THROW(exception) std::abort()
2413 : #define JSON_TRY if(true)
2414 : #define JSON_CATCH(exception) if(false)
2415 : #define JSON_INTERNAL_CATCH(exception) if(false)
2416 : #endif
2417 :
2418 : // override exception macros
2419 : #if defined(JSON_THROW_USER)
2420 : #undef JSON_THROW
2421 : #define JSON_THROW JSON_THROW_USER
2422 : #endif
2423 : #if defined(JSON_TRY_USER)
2424 : #undef JSON_TRY
2425 : #define JSON_TRY JSON_TRY_USER
2426 : #endif
2427 : #if defined(JSON_CATCH_USER)
2428 : #undef JSON_CATCH
2429 : #define JSON_CATCH JSON_CATCH_USER
2430 : #undef JSON_INTERNAL_CATCH
2431 : #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2432 : #endif
2433 : #if defined(JSON_INTERNAL_CATCH_USER)
2434 : #undef JSON_INTERNAL_CATCH
2435 : #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2436 : #endif
2437 :
2438 : // allow overriding assert
2439 : #if !defined(JSON_ASSERT)
2440 : #include <cassert> // assert
2441 : #define JSON_ASSERT(x) assert(x)
2442 : #endif
2443 :
2444 : // allow to access some private functions (needed by the test suite)
2445 : #if defined(JSON_TESTS_PRIVATE)
2446 : #define JSON_PRIVATE_UNLESS_TESTED public
2447 : #else
2448 : #define JSON_PRIVATE_UNLESS_TESTED private
2449 : #endif
2450 :
2451 : /*!
2452 : @brief macro to briefly define a mapping between an enum and JSON
2453 : @def NLOHMANN_JSON_SERIALIZE_ENUM
2454 : @since version 3.4.0
2455 : */
2456 : #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2457 : template<typename BasicJsonType> \
2458 : inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2459 : { \
2460 : static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2461 : static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2462 : auto it = std::find_if(std::begin(m), std::end(m), \
2463 : [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2464 : { \
2465 : return ej_pair.first == e; \
2466 : }); \
2467 : j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2468 : } \
2469 : template<typename BasicJsonType> \
2470 : inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2471 : { \
2472 : static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2473 : static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2474 : auto it = std::find_if(std::begin(m), std::end(m), \
2475 : [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2476 : { \
2477 : return ej_pair.second == j; \
2478 : }); \
2479 : e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2480 : }
2481 :
2482 : // Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2483 : // may be removed in the future once the class is split.
2484 :
2485 : #define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2486 : template<template<typename, typename, typename...> class ObjectType, \
2487 : template<typename, typename...> class ArrayType, \
2488 : class StringType, class BooleanType, class NumberIntegerType, \
2489 : class NumberUnsignedType, class NumberFloatType, \
2490 : template<typename> class AllocatorType, \
2491 : template<typename, typename = void> class JSONSerializer, \
2492 : class BinaryType>
2493 :
2494 : #define NLOHMANN_BASIC_JSON_TPL \
2495 : basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2496 : NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2497 : AllocatorType, JSONSerializer, BinaryType>
2498 :
2499 : // Macros to simplify conversion from/to types
2500 :
2501 : #define NLOHMANN_JSON_EXPAND( x ) x
2502 : #define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
2503 : #define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2504 : NLOHMANN_JSON_PASTE64, \
2505 : NLOHMANN_JSON_PASTE63, \
2506 : NLOHMANN_JSON_PASTE62, \
2507 : NLOHMANN_JSON_PASTE61, \
2508 : NLOHMANN_JSON_PASTE60, \
2509 : NLOHMANN_JSON_PASTE59, \
2510 : NLOHMANN_JSON_PASTE58, \
2511 : NLOHMANN_JSON_PASTE57, \
2512 : NLOHMANN_JSON_PASTE56, \
2513 : NLOHMANN_JSON_PASTE55, \
2514 : NLOHMANN_JSON_PASTE54, \
2515 : NLOHMANN_JSON_PASTE53, \
2516 : NLOHMANN_JSON_PASTE52, \
2517 : NLOHMANN_JSON_PASTE51, \
2518 : NLOHMANN_JSON_PASTE50, \
2519 : NLOHMANN_JSON_PASTE49, \
2520 : NLOHMANN_JSON_PASTE48, \
2521 : NLOHMANN_JSON_PASTE47, \
2522 : NLOHMANN_JSON_PASTE46, \
2523 : NLOHMANN_JSON_PASTE45, \
2524 : NLOHMANN_JSON_PASTE44, \
2525 : NLOHMANN_JSON_PASTE43, \
2526 : NLOHMANN_JSON_PASTE42, \
2527 : NLOHMANN_JSON_PASTE41, \
2528 : NLOHMANN_JSON_PASTE40, \
2529 : NLOHMANN_JSON_PASTE39, \
2530 : NLOHMANN_JSON_PASTE38, \
2531 : NLOHMANN_JSON_PASTE37, \
2532 : NLOHMANN_JSON_PASTE36, \
2533 : NLOHMANN_JSON_PASTE35, \
2534 : NLOHMANN_JSON_PASTE34, \
2535 : NLOHMANN_JSON_PASTE33, \
2536 : NLOHMANN_JSON_PASTE32, \
2537 : NLOHMANN_JSON_PASTE31, \
2538 : NLOHMANN_JSON_PASTE30, \
2539 : NLOHMANN_JSON_PASTE29, \
2540 : NLOHMANN_JSON_PASTE28, \
2541 : NLOHMANN_JSON_PASTE27, \
2542 : NLOHMANN_JSON_PASTE26, \
2543 : NLOHMANN_JSON_PASTE25, \
2544 : NLOHMANN_JSON_PASTE24, \
2545 : NLOHMANN_JSON_PASTE23, \
2546 : NLOHMANN_JSON_PASTE22, \
2547 : NLOHMANN_JSON_PASTE21, \
2548 : NLOHMANN_JSON_PASTE20, \
2549 : NLOHMANN_JSON_PASTE19, \
2550 : NLOHMANN_JSON_PASTE18, \
2551 : NLOHMANN_JSON_PASTE17, \
2552 : NLOHMANN_JSON_PASTE16, \
2553 : NLOHMANN_JSON_PASTE15, \
2554 : NLOHMANN_JSON_PASTE14, \
2555 : NLOHMANN_JSON_PASTE13, \
2556 : NLOHMANN_JSON_PASTE12, \
2557 : NLOHMANN_JSON_PASTE11, \
2558 : NLOHMANN_JSON_PASTE10, \
2559 : NLOHMANN_JSON_PASTE9, \
2560 : NLOHMANN_JSON_PASTE8, \
2561 : NLOHMANN_JSON_PASTE7, \
2562 : NLOHMANN_JSON_PASTE6, \
2563 : NLOHMANN_JSON_PASTE5, \
2564 : NLOHMANN_JSON_PASTE4, \
2565 : NLOHMANN_JSON_PASTE3, \
2566 : NLOHMANN_JSON_PASTE2, \
2567 : NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2568 : #define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2569 : #define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2570 : #define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2571 : #define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2572 : #define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2573 : #define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2574 : #define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2575 : #define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2576 : #define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2577 : #define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2578 : #define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2579 : #define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2580 : #define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2581 : #define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2582 : #define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2583 : #define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2584 : #define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
2585 : #define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
2586 : #define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
2587 : #define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
2588 : #define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
2589 : #define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
2590 : #define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
2591 : #define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
2592 : #define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
2593 : #define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
2594 : #define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
2595 : #define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
2596 : #define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
2597 : #define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2598 : #define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
2599 : #define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
2600 : #define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
2601 : #define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
2602 : #define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
2603 : #define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
2604 : #define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
2605 : #define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
2606 : #define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
2607 : #define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
2608 : #define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
2609 : #define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
2610 : #define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
2611 : #define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
2612 : #define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
2613 : #define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
2614 : #define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
2615 : #define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
2616 : #define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
2617 : #define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
2618 : #define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
2619 : #define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
2620 : #define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
2621 : #define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2622 : #define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2623 : #define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2624 : #define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
2625 : #define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
2626 : #define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
2627 : #define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
2628 : #define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
2629 : #define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
2630 : #define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
2631 :
2632 : #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2633 : #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2634 :
2635 : /*!
2636 : @brief macro
2637 : @def NLOHMANN_DEFINE_TYPE_INTRUSIVE
2638 : @since version 3.9.0
2639 : */
2640 : #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2641 : friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2642 : friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2643 :
2644 : /*!
2645 : @brief macro
2646 : @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
2647 : @since version 3.9.0
2648 : */
2649 : #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2650 : inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2651 : inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2652 :
2653 :
2654 : // inspired from https://stackoverflow.com/a/26745591
2655 : // allows to call any std function as if (e.g. with begin):
2656 : // using std::begin; begin(x);
2657 : //
2658 : // it allows using the detected idiom to retrieve the return type
2659 : // of such an expression
2660 : #define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2661 : namespace detail { \
2662 : using std::std_name; \
2663 : \
2664 : template<typename... T> \
2665 : using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2666 : } \
2667 : \
2668 : namespace detail2 { \
2669 : struct std_name##_tag \
2670 : { \
2671 : }; \
2672 : \
2673 : template<typename... T> \
2674 : std_name##_tag std_name(T&&...); \
2675 : \
2676 : template<typename... T> \
2677 : using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2678 : \
2679 : template<typename... T> \
2680 : struct would_call_std_##std_name \
2681 : { \
2682 : static constexpr auto const value = ::nlohmann::detail:: \
2683 : is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2684 : }; \
2685 : } /* namespace detail2 */ \
2686 : \
2687 : template<typename... T> \
2688 : struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2689 : { \
2690 : }
2691 :
2692 : #ifndef JSON_USE_IMPLICIT_CONVERSIONS
2693 : #define JSON_USE_IMPLICIT_CONVERSIONS 1
2694 : #endif
2695 :
2696 : #if JSON_USE_IMPLICIT_CONVERSIONS
2697 : #define JSON_EXPLICIT
2698 : #else
2699 : #define JSON_EXPLICIT explicit
2700 : #endif
2701 :
2702 : #ifndef JSON_DIAGNOSTICS
2703 : #define JSON_DIAGNOSTICS 0
2704 : #endif
2705 :
2706 :
2707 : namespace nlohmann
2708 : {
2709 : namespace detail
2710 : {
2711 :
2712 : /*!
2713 : @brief replace all occurrences of a substring by another string
2714 :
2715 : @param[in,out] s the string to manipulate; changed so that all
2716 : occurrences of @a f are replaced with @a t
2717 : @param[in] f the substring to replace with @a t
2718 : @param[in] t the string to replace @a f
2719 :
2720 : @pre The search string @a f must not be empty. **This precondition is
2721 : enforced with an assertion.**
2722 :
2723 : @since version 2.0.0
2724 : */
2725 : inline void replace_substring(std::string& s, const std::string& f,
2726 : const std::string& t)
2727 : {
2728 : JSON_ASSERT(!f.empty());
2729 : for (auto pos = s.find(f); // find first occurrence of f
2730 : pos != std::string::npos; // make sure f was found
2731 : s.replace(pos, f.size(), t), // replace with t, and
2732 : pos = s.find(f, pos + t.size())) // find next occurrence of f
2733 : {}
2734 : }
2735 :
2736 : /*!
2737 : * @brief string escaping as described in RFC 6901 (Sect. 4)
2738 : * @param[in] s string to escape
2739 : * @return escaped string
2740 : *
2741 : * Note the order of escaping "~" to "~0" and "/" to "~1" is important.
2742 : */
2743 : inline std::string escape(std::string s)
2744 : {
2745 : replace_substring(s, "~", "~0");
2746 : replace_substring(s, "/", "~1");
2747 : return s;
2748 : }
2749 :
2750 : /*!
2751 : * @brief string unescaping as described in RFC 6901 (Sect. 4)
2752 : * @param[in] s string to unescape
2753 : * @return unescaped string
2754 : *
2755 : * Note the order of escaping "~1" to "/" and "~0" to "~" is important.
2756 : */
2757 : static void unescape(std::string& s)
2758 : {
2759 : replace_substring(s, "~1", "/");
2760 : replace_substring(s, "~0", "~");
2761 : }
2762 :
2763 : } // namespace detail
2764 : } // namespace nlohmann
2765 :
2766 : // #include <nlohmann/detail/input/position_t.hpp>
2767 :
2768 :
2769 : #include <cstddef> // size_t
2770 :
2771 : namespace nlohmann
2772 : {
2773 : namespace detail
2774 : {
2775 : /// struct to capture the start position of the current token
2776 : struct position_t
2777 : {
2778 : /// the total number of characters read
2779 : std::size_t chars_read_total = 0;
2780 : /// the number of characters read in the current line
2781 : std::size_t chars_read_current_line = 0;
2782 : /// the number of lines read
2783 : std::size_t lines_read = 0;
2784 :
2785 : /// conversion to size_t to preserve SAX interface
2786 : constexpr operator size_t() const
2787 : {
2788 : return chars_read_total;
2789 : }
2790 : };
2791 :
2792 : } // namespace detail
2793 : } // namespace nlohmann
2794 :
2795 : // #include <nlohmann/detail/macro_scope.hpp>
2796 :
2797 :
2798 : namespace nlohmann
2799 : {
2800 : namespace detail
2801 : {
2802 : ////////////////
2803 : // exceptions //
2804 : ////////////////
2805 :
2806 : /// @brief general exception of the @ref basic_json class
2807 : /// @sa https://json.nlohmann.me/api/basic_json/exception/
2808 0 : class exception : public std::exception
2809 : {
2810 : public:
2811 : /// returns the explanatory string
2812 0 : const char* what() const noexcept override
2813 : {
2814 0 : return m.what();
2815 : }
2816 :
2817 : /// the id of the exception
2818 : const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
2819 :
2820 : protected:
2821 : JSON_HEDLEY_NON_NULL(3)
2822 0 : exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
2823 :
2824 0 : static std::string name(const std::string& ename, int id_)
2825 : {
2826 0 : return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
2827 : }
2828 :
2829 : template<typename BasicJsonType>
2830 : static std::string diagnostics(const BasicJsonType& leaf_element)
2831 : {
2832 : #if JSON_DIAGNOSTICS
2833 : std::vector<std::string> tokens;
2834 : for (const auto* current = &leaf_element; current->m_parent != nullptr; current = current->m_parent)
2835 : {
2836 : switch (current->m_parent->type())
2837 : {
2838 : case value_t::array:
2839 : {
2840 : for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
2841 : {
2842 : if (¤t->m_parent->m_value.array->operator[](i) == current)
2843 : {
2844 : tokens.emplace_back(std::to_string(i));
2845 : break;
2846 : }
2847 : }
2848 : break;
2849 : }
2850 :
2851 : case value_t::object:
2852 : {
2853 : for (const auto& element : *current->m_parent->m_value.object)
2854 : {
2855 : if (&element.second == current)
2856 : {
2857 : tokens.emplace_back(element.first.c_str());
2858 : break;
2859 : }
2860 : }
2861 : break;
2862 : }
2863 :
2864 : case value_t::null: // LCOV_EXCL_LINE
2865 : case value_t::string: // LCOV_EXCL_LINE
2866 : case value_t::boolean: // LCOV_EXCL_LINE
2867 : case value_t::number_integer: // LCOV_EXCL_LINE
2868 : case value_t::number_unsigned: // LCOV_EXCL_LINE
2869 : case value_t::number_float: // LCOV_EXCL_LINE
2870 : case value_t::binary: // LCOV_EXCL_LINE
2871 : case value_t::discarded: // LCOV_EXCL_LINE
2872 : default: // LCOV_EXCL_LINE
2873 : break; // LCOV_EXCL_LINE
2874 : }
2875 : }
2876 :
2877 : if (tokens.empty())
2878 : {
2879 : return "";
2880 : }
2881 :
2882 : return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
2883 : [](const std::string & a, const std::string & b)
2884 : {
2885 : return a + "/" + detail::escape(b);
2886 : }) + ") ";
2887 : #else
2888 : static_cast<void>(leaf_element);
2889 0 : return "";
2890 : #endif
2891 : }
2892 :
2893 : private:
2894 : /// an exception object as storage for error messages
2895 : std::runtime_error m;
2896 : };
2897 :
2898 : /// @brief exception indicating a parse error
2899 : /// @sa https://json.nlohmann.me/api/basic_json/parse_error/
2900 0 : class parse_error : public exception
2901 : {
2902 : public:
2903 : /*!
2904 : @brief create a parse error exception
2905 : @param[in] id_ the id of the exception
2906 : @param[in] pos the position where the error occurred (or with
2907 : chars_read_total=0 if the position cannot be
2908 : determined)
2909 : @param[in] what_arg the explanatory string
2910 : @return parse_error object
2911 : */
2912 : template<typename BasicJsonType>
2913 0 : static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context)
2914 : {
2915 0 : std::string w = exception::name("parse_error", id_) + "parse error" +
2916 : position_string(pos) + ": " + exception::diagnostics(context) + what_arg;
2917 0 : return {id_, pos.chars_read_total, w.c_str()};
2918 : }
2919 :
2920 : template<typename BasicJsonType>
2921 : static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context)
2922 : {
2923 : std::string w = exception::name("parse_error", id_) + "parse error" +
2924 : (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
2925 : ": " + exception::diagnostics(context) + what_arg;
2926 : return {id_, byte_, w.c_str()};
2927 : }
2928 :
2929 : /*!
2930 : @brief byte index of the parse error
2931 :
2932 : The byte index of the last read character in the input file.
2933 :
2934 : @note For an input with n bytes, 1 is the index of the first character and
2935 : n+1 is the index of the terminating null byte or the end of file.
2936 : This also holds true when reading a byte vector (CBOR or MessagePack).
2937 : */
2938 : const std::size_t byte;
2939 :
2940 : private:
2941 : parse_error(int id_, std::size_t byte_, const char* what_arg)
2942 0 : : exception(id_, what_arg), byte(byte_) {}
2943 :
2944 0 : static std::string position_string(const position_t& pos)
2945 : {
2946 0 : return " at line " + std::to_string(pos.lines_read + 1) +
2947 0 : ", column " + std::to_string(pos.chars_read_current_line);
2948 : }
2949 : };
2950 :
2951 : /// @brief exception indicating errors with iterators
2952 : /// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
2953 : class invalid_iterator : public exception
2954 : {
2955 : public:
2956 : template<typename BasicJsonType>
2957 0 : static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context)
2958 : {
2959 0 : std::string w = exception::name("invalid_iterator", id_) + exception::diagnostics(context) + what_arg;
2960 0 : return {id_, w.c_str()};
2961 : }
2962 :
2963 : private:
2964 : JSON_HEDLEY_NON_NULL(3)
2965 0 : invalid_iterator(int id_, const char* what_arg)
2966 0 : : exception(id_, what_arg) {}
2967 : };
2968 :
2969 : /// @brief exception indicating executing a member function with a wrong type
2970 : /// @sa https://json.nlohmann.me/api/basic_json/type_error/
2971 : class type_error : public exception
2972 : {
2973 : public:
2974 : template<typename BasicJsonType>
2975 0 : static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
2976 : {
2977 0 : std::string w = exception::name("type_error", id_) + exception::diagnostics(context) + what_arg;
2978 0 : return {id_, w.c_str()};
2979 : }
2980 :
2981 : private:
2982 : JSON_HEDLEY_NON_NULL(3)
2983 0 : type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
2984 : };
2985 :
2986 : /// @brief exception indicating access out of the defined range
2987 : /// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
2988 0 : class out_of_range : public exception
2989 : {
2990 : public:
2991 : template<typename BasicJsonType>
2992 0 : static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context)
2993 : {
2994 0 : std::string w = exception::name("out_of_range", id_) + exception::diagnostics(context) + what_arg;
2995 0 : return {id_, w.c_str()};
2996 : }
2997 :
2998 : private:
2999 : JSON_HEDLEY_NON_NULL(3)
3000 0 : out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
3001 : };
3002 :
3003 : /// @brief exception indicating other library errors
3004 : /// @sa https://json.nlohmann.me/api/basic_json/other_error/
3005 : class other_error : public exception
3006 : {
3007 : public:
3008 : template<typename BasicJsonType>
3009 : static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
3010 : {
3011 : std::string w = exception::name("other_error", id_) + exception::diagnostics(context) + what_arg;
3012 : return {id_, w.c_str()};
3013 : }
3014 :
3015 : private:
3016 : JSON_HEDLEY_NON_NULL(3)
3017 : other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
3018 : };
3019 :
3020 : } // namespace detail
3021 : } // namespace nlohmann
3022 :
3023 : // #include <nlohmann/detail/macro_scope.hpp>
3024 :
3025 : // #include <nlohmann/detail/meta/cpp_future.hpp>
3026 :
3027 :
3028 : #include <cstddef> // size_t
3029 : #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3030 : #include <utility> // index_sequence, make_index_sequence, index_sequence_for
3031 :
3032 : // #include <nlohmann/detail/macro_scope.hpp>
3033 :
3034 :
3035 : namespace nlohmann
3036 : {
3037 : namespace detail
3038 : {
3039 :
3040 : template<typename T>
3041 : using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3042 :
3043 : #ifdef JSON_HAS_CPP_14
3044 :
3045 : // the following utilities are natively available in C++14
3046 : using std::enable_if_t;
3047 : using std::index_sequence;
3048 : using std::make_index_sequence;
3049 : using std::index_sequence_for;
3050 :
3051 : #else
3052 :
3053 : // alias templates to reduce boilerplate
3054 : template<bool B, typename T = void>
3055 : using enable_if_t = typename std::enable_if<B, T>::type;
3056 :
3057 : // The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3058 : // which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3059 :
3060 : //// START OF CODE FROM GOOGLE ABSEIL
3061 :
3062 : // integer_sequence
3063 : //
3064 : // Class template representing a compile-time integer sequence. An instantiation
3065 : // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3066 : // type through its template arguments (which is a common need when
3067 : // working with C++11 variadic templates). `absl::integer_sequence` is designed
3068 : // to be a drop-in replacement for C++14's `std::integer_sequence`.
3069 : //
3070 : // Example:
3071 : //
3072 : // template< class T, T... Ints >
3073 : // void user_function(integer_sequence<T, Ints...>);
3074 : //
3075 : // int main()
3076 : // {
3077 : // // user_function's `T` will be deduced to `int` and `Ints...`
3078 : // // will be deduced to `0, 1, 2, 3, 4`.
3079 : // user_function(make_integer_sequence<int, 5>());
3080 : // }
3081 : template <typename T, T... Ints>
3082 : struct integer_sequence
3083 : {
3084 : using value_type = T;
3085 : static constexpr std::size_t size() noexcept
3086 : {
3087 : return sizeof...(Ints);
3088 : }
3089 : };
3090 :
3091 : // index_sequence
3092 : //
3093 : // A helper template for an `integer_sequence` of `size_t`,
3094 : // `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3095 : // `std::index_sequence`.
3096 : template <size_t... Ints>
3097 : using index_sequence = integer_sequence<size_t, Ints...>;
3098 :
3099 : namespace utility_internal
3100 : {
3101 :
3102 : template <typename Seq, size_t SeqSize, size_t Rem>
3103 : struct Extend;
3104 :
3105 : // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3106 : template <typename T, T... Ints, size_t SeqSize>
3107 : struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3108 : {
3109 : using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3110 : };
3111 :
3112 : template <typename T, T... Ints, size_t SeqSize>
3113 : struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3114 : {
3115 : using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3116 : };
3117 :
3118 : // Recursion helper for 'make_integer_sequence<T, N>'.
3119 : // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3120 : template <typename T, size_t N>
3121 : struct Gen
3122 : {
3123 : using type =
3124 : typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3125 : };
3126 :
3127 : template <typename T>
3128 : struct Gen<T, 0>
3129 : {
3130 : using type = integer_sequence<T>;
3131 : };
3132 :
3133 : } // namespace utility_internal
3134 :
3135 : // Compile-time sequences of integers
3136 :
3137 : // make_integer_sequence
3138 : //
3139 : // This template alias is equivalent to
3140 : // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3141 : // replacement for C++14's `std::make_integer_sequence`.
3142 : template <typename T, T N>
3143 : using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
3144 :
3145 : // make_index_sequence
3146 : //
3147 : // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3148 : // and is designed to be a drop-in replacement for C++14's
3149 : // `std::make_index_sequence`.
3150 : template <size_t N>
3151 : using make_index_sequence = make_integer_sequence<size_t, N>;
3152 :
3153 : // index_sequence_for
3154 : //
3155 : // Converts a typename pack into an index sequence of the same length, and
3156 : // is designed to be a drop-in replacement for C++14's
3157 : // `std::index_sequence_for()`
3158 : template <typename... Ts>
3159 : using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
3160 :
3161 : //// END OF CODE FROM GOOGLE ABSEIL
3162 :
3163 : #endif
3164 :
3165 : // dispatch utility (taken from ranges-v3)
3166 : template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3167 : template<> struct priority_tag<0> {};
3168 :
3169 : // taken from ranges-v3
3170 : template<typename T>
3171 : struct static_const
3172 : {
3173 : static constexpr T value{};
3174 : };
3175 :
3176 : template<typename T>
3177 : constexpr T static_const<T>::value; // NOLINT(readability-redundant-declaration)
3178 :
3179 : } // namespace detail
3180 : } // namespace nlohmann
3181 :
3182 : // #include <nlohmann/detail/meta/identity_tag.hpp>
3183 :
3184 :
3185 : namespace nlohmann
3186 : {
3187 : namespace detail
3188 : {
3189 : // dispatching helper struct
3190 : template <class T> struct identity_tag {};
3191 : } // namespace detail
3192 : } // namespace nlohmann
3193 :
3194 : // #include <nlohmann/detail/meta/type_traits.hpp>
3195 :
3196 :
3197 : #include <limits> // numeric_limits
3198 : #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3199 : #include <utility> // declval
3200 : #include <tuple> // tuple
3201 :
3202 : // #include <nlohmann/detail/macro_scope.hpp>
3203 :
3204 :
3205 : // #include <nlohmann/detail/iterators/iterator_traits.hpp>
3206 :
3207 :
3208 : #include <iterator> // random_access_iterator_tag
3209 :
3210 : // #include <nlohmann/detail/meta/void_t.hpp>
3211 :
3212 : // #include <nlohmann/detail/meta/cpp_future.hpp>
3213 :
3214 :
3215 : namespace nlohmann
3216 : {
3217 : namespace detail
3218 : {
3219 : template<typename It, typename = void>
3220 : struct iterator_types {};
3221 :
3222 : template<typename It>
3223 : struct iterator_types <
3224 : It,
3225 : void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3226 : typename It::reference, typename It::iterator_category >>
3227 : {
3228 : using difference_type = typename It::difference_type;
3229 : using value_type = typename It::value_type;
3230 : using pointer = typename It::pointer;
3231 : using reference = typename It::reference;
3232 : using iterator_category = typename It::iterator_category;
3233 : };
3234 :
3235 : // This is required as some compilers implement std::iterator_traits in a way that
3236 : // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3237 : template<typename T, typename = void>
3238 : struct iterator_traits
3239 : {
3240 : };
3241 :
3242 : template<typename T>
3243 : struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3244 : : iterator_types<T>
3245 : {
3246 : };
3247 :
3248 : template<typename T>
3249 : struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
3250 : {
3251 : using iterator_category = std::random_access_iterator_tag;
3252 : using value_type = T;
3253 : using difference_type = ptrdiff_t;
3254 : using pointer = T*;
3255 : using reference = T&;
3256 : };
3257 : } // namespace detail
3258 : } // namespace nlohmann
3259 :
3260 : // #include <nlohmann/detail/meta/call_std/begin.hpp>
3261 :
3262 :
3263 : // #include <nlohmann/detail/macro_scope.hpp>
3264 :
3265 :
3266 : namespace nlohmann
3267 : {
3268 : NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3269 : } // namespace nlohmann
3270 :
3271 : // #include <nlohmann/detail/meta/call_std/end.hpp>
3272 :
3273 :
3274 : // #include <nlohmann/detail/macro_scope.hpp>
3275 :
3276 :
3277 : namespace nlohmann
3278 : {
3279 : NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3280 : } // namespace nlohmann
3281 :
3282 : // #include <nlohmann/detail/meta/cpp_future.hpp>
3283 :
3284 : // #include <nlohmann/detail/meta/detected.hpp>
3285 :
3286 : // #include <nlohmann/json_fwd.hpp>
3287 : #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3288 : #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3289 :
3290 : #include <cstdint> // int64_t, uint64_t
3291 : #include <map> // map
3292 : #include <memory> // allocator
3293 : #include <string> // string
3294 : #include <vector> // vector
3295 :
3296 : /*!
3297 : @brief namespace for Niels Lohmann
3298 : @see https://github.com/nlohmann
3299 : @since version 1.0.0
3300 : */
3301 : namespace nlohmann
3302 : {
3303 : /*!
3304 : @brief default JSONSerializer template argument
3305 :
3306 : This serializer ignores the template arguments and uses ADL
3307 : ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
3308 : for serialization.
3309 : */
3310 : template<typename T = void, typename SFINAE = void>
3311 : struct adl_serializer;
3312 :
3313 : /// a class to store JSON values
3314 : /// @sa https://json.nlohmann.me/api/basic_json/
3315 : template<template<typename U, typename V, typename... Args> class ObjectType =
3316 : std::map,
3317 : template<typename U, typename... Args> class ArrayType = std::vector,
3318 : class StringType = std::string, class BooleanType = bool,
3319 : class NumberIntegerType = std::int64_t,
3320 : class NumberUnsignedType = std::uint64_t,
3321 : class NumberFloatType = double,
3322 : template<typename U> class AllocatorType = std::allocator,
3323 : template<typename T, typename SFINAE = void> class JSONSerializer =
3324 : adl_serializer,
3325 : class BinaryType = std::vector<std::uint8_t>>
3326 : class basic_json;
3327 :
3328 : /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
3329 : /// @sa https://json.nlohmann.me/api/json_pointer/
3330 : template<typename BasicJsonType>
3331 : class json_pointer;
3332 :
3333 : /*!
3334 : @brief default specialization
3335 : @sa https://json.nlohmann.me/api/json/
3336 : */
3337 : using json = basic_json<>;
3338 :
3339 : /// @brief a minimal map-like container that preserves insertion order
3340 : /// @sa https://json.nlohmann.me/api/ordered_map/
3341 : template<class Key, class T, class IgnoredLess, class Allocator>
3342 : struct ordered_map;
3343 :
3344 : /// @brief specialization that maintains the insertion order of object keys
3345 : /// @sa https://json.nlohmann.me/api/ordered_json/
3346 : using ordered_json = basic_json<nlohmann::ordered_map>;
3347 :
3348 : } // namespace nlohmann
3349 :
3350 : #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3351 :
3352 :
3353 : namespace nlohmann
3354 : {
3355 : /*!
3356 : @brief detail namespace with internal helper functions
3357 :
3358 : This namespace collects functions that should not be exposed,
3359 : implementations of some @ref basic_json methods, and meta-programming helpers.
3360 :
3361 : @since version 2.1.0
3362 : */
3363 : namespace detail
3364 : {
3365 : /////////////
3366 : // helpers //
3367 : /////////////
3368 :
3369 : // Note to maintainers:
3370 : //
3371 : // Every trait in this file expects a non CV-qualified type.
3372 : // The only exceptions are in the 'aliases for detected' section
3373 : // (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3374 : //
3375 : // In this case, T has to be properly CV-qualified to constraint the function arguments
3376 : // (e.g. to_json(BasicJsonType&, const T&))
3377 :
3378 : template<typename> struct is_basic_json : std::false_type {};
3379 :
3380 : NLOHMANN_BASIC_JSON_TPL_DECLARATION
3381 : struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3382 :
3383 : //////////////////////
3384 : // json_ref helpers //
3385 : //////////////////////
3386 :
3387 : template<typename>
3388 : class json_ref;
3389 :
3390 : template<typename>
3391 : struct is_json_ref : std::false_type {};
3392 :
3393 : template<typename T>
3394 : struct is_json_ref<json_ref<T>> : std::true_type {};
3395 :
3396 : //////////////////////////
3397 : // aliases for detected //
3398 : //////////////////////////
3399 :
3400 : template<typename T>
3401 : using mapped_type_t = typename T::mapped_type;
3402 :
3403 : template<typename T>
3404 : using key_type_t = typename T::key_type;
3405 :
3406 : template<typename T>
3407 : using value_type_t = typename T::value_type;
3408 :
3409 : template<typename T>
3410 : using difference_type_t = typename T::difference_type;
3411 :
3412 : template<typename T>
3413 : using pointer_t = typename T::pointer;
3414 :
3415 : template<typename T>
3416 : using reference_t = typename T::reference;
3417 :
3418 : template<typename T>
3419 : using iterator_category_t = typename T::iterator_category;
3420 :
3421 : template<typename T, typename... Args>
3422 : using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3423 :
3424 : template<typename T, typename... Args>
3425 : using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3426 :
3427 : template<typename T, typename U>
3428 : using get_template_function = decltype(std::declval<T>().template get<U>());
3429 :
3430 : // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3431 : template<typename BasicJsonType, typename T, typename = void>
3432 : struct has_from_json : std::false_type {};
3433 :
3434 : // trait checking if j.get<T> is valid
3435 : // use this trait instead of std::is_constructible or std::is_convertible,
3436 : // both rely on, or make use of implicit conversions, and thus fail when T
3437 : // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3438 : template <typename BasicJsonType, typename T>
3439 : struct is_getable
3440 : {
3441 : static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3442 : };
3443 :
3444 : template<typename BasicJsonType, typename T>
3445 : struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3446 : {
3447 : using serializer = typename BasicJsonType::template json_serializer<T, void>;
3448 :
3449 : static constexpr bool value =
3450 : is_detected_exact<void, from_json_function, serializer,
3451 : const BasicJsonType&, T&>::value;
3452 : };
3453 :
3454 : // This trait checks if JSONSerializer<T>::from_json(json const&) exists
3455 : // this overload is used for non-default-constructible user-defined-types
3456 : template<typename BasicJsonType, typename T, typename = void>
3457 : struct has_non_default_from_json : std::false_type {};
3458 :
3459 : template<typename BasicJsonType, typename T>
3460 : struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3461 : {
3462 : using serializer = typename BasicJsonType::template json_serializer<T, void>;
3463 :
3464 : static constexpr bool value =
3465 : is_detected_exact<T, from_json_function, serializer,
3466 : const BasicJsonType&>::value;
3467 : };
3468 :
3469 : // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3470 : // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3471 : template<typename BasicJsonType, typename T, typename = void>
3472 : struct has_to_json : std::false_type {};
3473 :
3474 : template<typename BasicJsonType, typename T>
3475 : struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3476 : {
3477 : using serializer = typename BasicJsonType::template json_serializer<T, void>;
3478 :
3479 : static constexpr bool value =
3480 : is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3481 : T>::value;
3482 : };
3483 :
3484 :
3485 : ///////////////////
3486 : // is_ functions //
3487 : ///////////////////
3488 :
3489 : // https://en.cppreference.com/w/cpp/types/conjunction
3490 : template<class...> struct conjunction : std::true_type { };
3491 : template<class B1> struct conjunction<B1> : B1 { };
3492 : template<class B1, class... Bn>
3493 : struct conjunction<B1, Bn...>
3494 : : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
3495 :
3496 : // https://en.cppreference.com/w/cpp/types/negation
3497 : template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3498 :
3499 : // Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3500 : // std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3501 : // This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3502 : template <typename T>
3503 : struct is_default_constructible : std::is_default_constructible<T> {};
3504 :
3505 : template <typename T1, typename T2>
3506 : struct is_default_constructible<std::pair<T1, T2>>
3507 : : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3508 :
3509 : template <typename T1, typename T2>
3510 : struct is_default_constructible<const std::pair<T1, T2>>
3511 : : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3512 :
3513 : template <typename... Ts>
3514 : struct is_default_constructible<std::tuple<Ts...>>
3515 : : conjunction<is_default_constructible<Ts>...> {};
3516 :
3517 : template <typename... Ts>
3518 : struct is_default_constructible<const std::tuple<Ts...>>
3519 : : conjunction<is_default_constructible<Ts>...> {};
3520 :
3521 :
3522 : template <typename T, typename... Args>
3523 : struct is_constructible : std::is_constructible<T, Args...> {};
3524 :
3525 : template <typename T1, typename T2>
3526 : struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3527 :
3528 : template <typename T1, typename T2>
3529 : struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3530 :
3531 : template <typename... Ts>
3532 : struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3533 :
3534 : template <typename... Ts>
3535 : struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3536 :
3537 :
3538 : template<typename T, typename = void>
3539 : struct is_iterator_traits : std::false_type {};
3540 :
3541 : template<typename T>
3542 : struct is_iterator_traits<iterator_traits<T>>
3543 : {
3544 : private:
3545 : using traits = iterator_traits<T>;
3546 :
3547 : public:
3548 : static constexpr auto value =
3549 : is_detected<value_type_t, traits>::value &&
3550 : is_detected<difference_type_t, traits>::value &&
3551 : is_detected<pointer_t, traits>::value &&
3552 : is_detected<iterator_category_t, traits>::value &&
3553 : is_detected<reference_t, traits>::value;
3554 : };
3555 :
3556 : template<typename T>
3557 : struct is_range
3558 : {
3559 : private:
3560 : using t_ref = typename std::add_lvalue_reference<T>::type;
3561 :
3562 : using iterator = detected_t<result_of_begin, t_ref>;
3563 : using sentinel = detected_t<result_of_end, t_ref>;
3564 :
3565 : // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3566 : // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3567 : // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3568 : static constexpr auto is_iterator_begin =
3569 : is_iterator_traits<iterator_traits<iterator>>::value;
3570 :
3571 : public:
3572 : static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3573 : };
3574 :
3575 : template<typename R>
3576 : using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3577 :
3578 : template<typename T>
3579 : using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3580 :
3581 : // The following implementation of is_complete_type is taken from
3582 : // https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3583 : // and is written by Xiang Fan who agreed to using it in this library.
3584 :
3585 : template<typename T, typename = void>
3586 : struct is_complete_type : std::false_type {};
3587 :
3588 : template<typename T>
3589 : struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3590 :
3591 : template<typename BasicJsonType, typename CompatibleObjectType,
3592 : typename = void>
3593 : struct is_compatible_object_type_impl : std::false_type {};
3594 :
3595 : template<typename BasicJsonType, typename CompatibleObjectType>
3596 : struct is_compatible_object_type_impl <
3597 : BasicJsonType, CompatibleObjectType,
3598 : enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3599 : is_detected<key_type_t, CompatibleObjectType>::value >>
3600 : {
3601 : using object_t = typename BasicJsonType::object_t;
3602 :
3603 : // macOS's is_constructible does not play well with nonesuch...
3604 : static constexpr bool value =
3605 : is_constructible<typename object_t::key_type,
3606 : typename CompatibleObjectType::key_type>::value &&
3607 : is_constructible<typename object_t::mapped_type,
3608 : typename CompatibleObjectType::mapped_type>::value;
3609 : };
3610 :
3611 : template<typename BasicJsonType, typename CompatibleObjectType>
3612 : struct is_compatible_object_type
3613 : : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3614 :
3615 : template<typename BasicJsonType, typename ConstructibleObjectType,
3616 : typename = void>
3617 : struct is_constructible_object_type_impl : std::false_type {};
3618 :
3619 : template<typename BasicJsonType, typename ConstructibleObjectType>
3620 : struct is_constructible_object_type_impl <
3621 : BasicJsonType, ConstructibleObjectType,
3622 : enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3623 : is_detected<key_type_t, ConstructibleObjectType>::value >>
3624 : {
3625 : using object_t = typename BasicJsonType::object_t;
3626 :
3627 : static constexpr bool value =
3628 : (is_default_constructible<ConstructibleObjectType>::value &&
3629 : (std::is_move_assignable<ConstructibleObjectType>::value ||
3630 : std::is_copy_assignable<ConstructibleObjectType>::value) &&
3631 : (is_constructible<typename ConstructibleObjectType::key_type,
3632 : typename object_t::key_type>::value &&
3633 : std::is_same <
3634 : typename object_t::mapped_type,
3635 : typename ConstructibleObjectType::mapped_type >::value)) ||
3636 : (has_from_json<BasicJsonType,
3637 : typename ConstructibleObjectType::mapped_type>::value ||
3638 : has_non_default_from_json <
3639 : BasicJsonType,
3640 : typename ConstructibleObjectType::mapped_type >::value);
3641 : };
3642 :
3643 : template<typename BasicJsonType, typename ConstructibleObjectType>
3644 : struct is_constructible_object_type
3645 : : is_constructible_object_type_impl<BasicJsonType,
3646 : ConstructibleObjectType> {};
3647 :
3648 : template<typename BasicJsonType, typename CompatibleStringType>
3649 : struct is_compatible_string_type
3650 : {
3651 : static constexpr auto value =
3652 : is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
3653 : };
3654 :
3655 : template<typename BasicJsonType, typename ConstructibleStringType>
3656 : struct is_constructible_string_type
3657 : {
3658 : static constexpr auto value =
3659 : is_constructible<ConstructibleStringType,
3660 : typename BasicJsonType::string_t>::value;
3661 : };
3662 :
3663 : template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3664 : struct is_compatible_array_type_impl : std::false_type {};
3665 :
3666 : template<typename BasicJsonType, typename CompatibleArrayType>
3667 : struct is_compatible_array_type_impl <
3668 : BasicJsonType, CompatibleArrayType,
3669 : enable_if_t <
3670 : is_detected<iterator_t, CompatibleArrayType>::value&&
3671 : is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3672 : // special case for types like std::filesystem::path whose iterator's value_type are themselves
3673 : // c.f. https://github.com/nlohmann/json/pull/3073
3674 : !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3675 : {
3676 : static constexpr bool value =
3677 : is_constructible<BasicJsonType,
3678 : range_value_t<CompatibleArrayType>>::value;
3679 : };
3680 :
3681 : template<typename BasicJsonType, typename CompatibleArrayType>
3682 : struct is_compatible_array_type
3683 : : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3684 :
3685 : template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3686 : struct is_constructible_array_type_impl : std::false_type {};
3687 :
3688 : template<typename BasicJsonType, typename ConstructibleArrayType>
3689 : struct is_constructible_array_type_impl <
3690 : BasicJsonType, ConstructibleArrayType,
3691 : enable_if_t<std::is_same<ConstructibleArrayType,
3692 : typename BasicJsonType::value_type>::value >>
3693 : : std::true_type {};
3694 :
3695 : template<typename BasicJsonType, typename ConstructibleArrayType>
3696 : struct is_constructible_array_type_impl <
3697 : BasicJsonType, ConstructibleArrayType,
3698 : enable_if_t < !std::is_same<ConstructibleArrayType,
3699 : typename BasicJsonType::value_type>::value&&
3700 : !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3701 : is_default_constructible<ConstructibleArrayType>::value&&
3702 : (std::is_move_assignable<ConstructibleArrayType>::value ||
3703 : std::is_copy_assignable<ConstructibleArrayType>::value)&&
3704 : is_detected<iterator_t, ConstructibleArrayType>::value&&
3705 : is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3706 : is_detected<range_value_t, ConstructibleArrayType>::value&&
3707 : // special case for types like std::filesystem::path whose iterator's value_type are themselves
3708 : // c.f. https://github.com/nlohmann/json/pull/3073
3709 : !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3710 : is_complete_type <
3711 : detected_t<range_value_t, ConstructibleArrayType >>::value >>
3712 : {
3713 : using value_type = range_value_t<ConstructibleArrayType>;
3714 :
3715 : static constexpr bool value =
3716 : std::is_same<value_type,
3717 : typename BasicJsonType::array_t::value_type>::value ||
3718 : has_from_json<BasicJsonType,
3719 : value_type>::value ||
3720 : has_non_default_from_json <
3721 : BasicJsonType,
3722 : value_type >::value;
3723 : };
3724 :
3725 : template<typename BasicJsonType, typename ConstructibleArrayType>
3726 : struct is_constructible_array_type
3727 : : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3728 :
3729 : template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3730 : typename = void>
3731 : struct is_compatible_integer_type_impl : std::false_type {};
3732 :
3733 : template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3734 : struct is_compatible_integer_type_impl <
3735 : RealIntegerType, CompatibleNumberIntegerType,
3736 : enable_if_t < std::is_integral<RealIntegerType>::value&&
3737 : std::is_integral<CompatibleNumberIntegerType>::value&&
3738 : !std::is_same<bool, CompatibleNumberIntegerType>::value >>
3739 : {
3740 : // is there an assert somewhere on overflows?
3741 : using RealLimits = std::numeric_limits<RealIntegerType>;
3742 : using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3743 :
3744 : static constexpr auto value =
3745 : is_constructible<RealIntegerType,
3746 : CompatibleNumberIntegerType>::value &&
3747 : CompatibleLimits::is_integer &&
3748 : RealLimits::is_signed == CompatibleLimits::is_signed;
3749 : };
3750 :
3751 : template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3752 : struct is_compatible_integer_type
3753 : : is_compatible_integer_type_impl<RealIntegerType,
3754 : CompatibleNumberIntegerType> {};
3755 :
3756 : template<typename BasicJsonType, typename CompatibleType, typename = void>
3757 : struct is_compatible_type_impl: std::false_type {};
3758 :
3759 : template<typename BasicJsonType, typename CompatibleType>
3760 : struct is_compatible_type_impl <
3761 : BasicJsonType, CompatibleType,
3762 : enable_if_t<is_complete_type<CompatibleType>::value >>
3763 : {
3764 : static constexpr bool value =
3765 : has_to_json<BasicJsonType, CompatibleType>::value;
3766 : };
3767 :
3768 : template<typename BasicJsonType, typename CompatibleType>
3769 : struct is_compatible_type
3770 : : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3771 :
3772 : template<typename T1, typename T2>
3773 : struct is_constructible_tuple : std::false_type {};
3774 :
3775 : template<typename T1, typename... Args>
3776 : struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3777 :
3778 : // a naive helper to check if a type is an ordered_map (exploits the fact that
3779 : // ordered_map inherits capacity() from std::vector)
3780 : template <typename T>
3781 : struct is_ordered_map
3782 : {
3783 : using one = char;
3784 :
3785 : struct two
3786 : {
3787 : char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3788 : };
3789 :
3790 : template <typename C> static one test( decltype(&C::capacity) ) ;
3791 : template <typename C> static two test(...);
3792 :
3793 : enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
3794 : };
3795 :
3796 : // to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
3797 : template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
3798 : T conditional_static_cast(U value)
3799 : {
3800 : return static_cast<T>(value);
3801 : }
3802 :
3803 : template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
3804 : T conditional_static_cast(U value)
3805 : {
3806 : return value;
3807 : }
3808 :
3809 : } // namespace detail
3810 : } // namespace nlohmann
3811 :
3812 : // #include <nlohmann/detail/value_t.hpp>
3813 :
3814 :
3815 : #if JSON_HAS_EXPERIMENTAL_FILESYSTEM
3816 : #include <experimental/filesystem>
3817 : namespace nlohmann::detail
3818 : {
3819 : namespace std_fs = std::experimental::filesystem;
3820 : } // namespace nlohmann::detail
3821 : #elif JSON_HAS_FILESYSTEM
3822 : #include <filesystem>
3823 : namespace nlohmann::detail
3824 : {
3825 : namespace std_fs = std::filesystem;
3826 : } // namespace nlohmann::detail
3827 : #endif
3828 :
3829 : namespace nlohmann
3830 : {
3831 : namespace detail
3832 : {
3833 : template<typename BasicJsonType>
3834 : void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
3835 : {
3836 : if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
3837 : {
3838 : JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j));
3839 : }
3840 : n = nullptr;
3841 : }
3842 :
3843 : // overloads for basic_json template parameters
3844 : template < typename BasicJsonType, typename ArithmeticType,
3845 : enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
3846 : !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
3847 : int > = 0 >
3848 2476 : void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
3849 : {
3850 2476 : switch (static_cast<value_t>(j))
3851 : {
3852 : case value_t::number_unsigned:
3853 : {
3854 31 : val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
3855 31 : break;
3856 : }
3857 : case value_t::number_integer:
3858 : {
3859 0 : val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
3860 0 : break;
3861 : }
3862 : case value_t::number_float:
3863 : {
3864 2445 : val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
3865 2445 : break;
3866 : }
3867 :
3868 0 : case value_t::null:
3869 : case value_t::object:
3870 : case value_t::array:
3871 : case value_t::string:
3872 : case value_t::boolean:
3873 : case value_t::binary:
3874 : case value_t::discarded:
3875 : default:
3876 0 : JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
3877 : }
3878 2476 : }
3879 :
3880 : template<typename BasicJsonType>
3881 : void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
3882 : {
3883 : if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
3884 : {
3885 : JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j));
3886 : }
3887 : b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
3888 : }
3889 :
3890 : template<typename BasicJsonType>
3891 84 : void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
3892 : {
3893 84 : if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
3894 : {
3895 0 : JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
3896 : }
3897 : s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
3898 84 : }
3899 :
3900 : template <
3901 : typename BasicJsonType, typename ConstructibleStringType,
3902 : enable_if_t <
3903 : is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value&&
3904 : !std::is_same<typename BasicJsonType::string_t,
3905 : ConstructibleStringType>::value,
3906 : int > = 0 >
3907 : void from_json(const BasicJsonType& j, ConstructibleStringType& s)
3908 : {
3909 : if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
3910 : {
3911 : JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
3912 : }
3913 :
3914 : s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
3915 : }
3916 :
3917 : template<typename BasicJsonType>
3918 : void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
3919 : {
3920 2476 : get_arithmetic_value(j, val);
3921 : }
3922 :
3923 : template<typename BasicJsonType>
3924 : void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
3925 : {
3926 : get_arithmetic_value(j, val);
3927 : }
3928 :
3929 : template<typename BasicJsonType>
3930 : void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
3931 : {
3932 : get_arithmetic_value(j, val);
3933 : }
3934 :
3935 : template<typename BasicJsonType, typename EnumType,
3936 : enable_if_t<std::is_enum<EnumType>::value, int> = 0>
3937 : void from_json(const BasicJsonType& j, EnumType& e)
3938 : {
3939 : typename std::underlying_type<EnumType>::type val;
3940 : get_arithmetic_value(j, val);
3941 : e = static_cast<EnumType>(val);
3942 : }
3943 :
3944 : // forward_list doesn't have an insert method
3945 : template<typename BasicJsonType, typename T, typename Allocator,
3946 : enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
3947 : void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
3948 : {
3949 : if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3950 : {
3951 : JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
3952 : }
3953 : l.clear();
3954 : std::transform(j.rbegin(), j.rend(),
3955 : std::front_inserter(l), [](const BasicJsonType & i)
3956 : {
3957 : return i.template get<T>();
3958 : });
3959 : }
3960 :
3961 : // valarray doesn't have an insert method
3962 : template<typename BasicJsonType, typename T,
3963 : enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
3964 : void from_json(const BasicJsonType& j, std::valarray<T>& l)
3965 : {
3966 : if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3967 : {
3968 : JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
3969 : }
3970 : l.resize(j.size());
3971 : std::transform(j.begin(), j.end(), std::begin(l),
3972 : [](const BasicJsonType & elem)
3973 : {
3974 : return elem.template get<T>();
3975 : });
3976 : }
3977 :
3978 : template<typename BasicJsonType, typename T, std::size_t N>
3979 : auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3980 : -> decltype(j.template get<T>(), void())
3981 : {
3982 : for (std::size_t i = 0; i < N; ++i)
3983 : {
3984 : arr[i] = j.at(i).template get<T>();
3985 : }
3986 : }
3987 :
3988 : template<typename BasicJsonType>
3989 : void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
3990 : {
3991 : arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
3992 : }
3993 :
3994 : template<typename BasicJsonType, typename T, std::size_t N>
3995 : auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
3996 : priority_tag<2> /*unused*/)
3997 : -> decltype(j.template get<T>(), void())
3998 : {
3999 : for (std::size_t i = 0; i < N; ++i)
4000 : {
4001 : arr[i] = j.at(i).template get<T>();
4002 : }
4003 : }
4004 :
4005 : template<typename BasicJsonType, typename ConstructibleArrayType,
4006 : enable_if_t<
4007 : std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4008 : int> = 0>
4009 152 : auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4010 : -> decltype(
4011 : arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4012 : j.template get<typename ConstructibleArrayType::value_type>(),
4013 : void())
4014 : {
4015 : using std::end;
4016 :
4017 : ConstructibleArrayType ret;
4018 152 : ret.reserve(j.size());
4019 304 : std::transform(j.begin(), j.end(),
4020 : std::inserter(ret, end(ret)), [](const BasicJsonType & i)
4021 : {
4022 : // get<BasicJsonType>() returns *this, this won't call a from_json
4023 : // method when value_type is BasicJsonType
4024 : return i.template get<typename ConstructibleArrayType::value_type>();
4025 : });
4026 152 : arr = std::move(ret);
4027 152 : }
4028 :
4029 : template<typename BasicJsonType, typename ConstructibleArrayType,
4030 : enable_if_t<
4031 : std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4032 : int> = 0>
4033 : void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4034 : priority_tag<0> /*unused*/)
4035 : {
4036 : using std::end;
4037 :
4038 : ConstructibleArrayType ret;
4039 : std::transform(
4040 : j.begin(), j.end(), std::inserter(ret, end(ret)),
4041 : [](const BasicJsonType & i)
4042 : {
4043 : // get<BasicJsonType>() returns *this, this won't call a from_json
4044 : // method when value_type is BasicJsonType
4045 : return i.template get<typename ConstructibleArrayType::value_type>();
4046 : });
4047 : arr = std::move(ret);
4048 : }
4049 :
4050 : template < typename BasicJsonType, typename ConstructibleArrayType,
4051 : enable_if_t <
4052 : is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4053 : !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4054 : !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4055 : !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4056 : !is_basic_json<ConstructibleArrayType>::value,
4057 : int > = 0 >
4058 152 : auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4059 : -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4060 : j.template get<typename ConstructibleArrayType::value_type>(),
4061 : void())
4062 : {
4063 152 : if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4064 : {
4065 0 : JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4066 : }
4067 :
4068 152 : from_json_array_impl(j, arr, priority_tag<3> {});
4069 152 : }
4070 :
4071 : template < typename BasicJsonType, typename T, std::size_t... Idx >
4072 : std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4073 : identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4074 : {
4075 : return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4076 : }
4077 :
4078 : template < typename BasicJsonType, typename T, std::size_t N >
4079 : auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4080 : -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4081 : {
4082 : if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4083 : {
4084 : JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4085 : }
4086 :
4087 : return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4088 : }
4089 :
4090 : template<typename BasicJsonType>
4091 : void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4092 : {
4093 : if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4094 : {
4095 : JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j));
4096 : }
4097 :
4098 : bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4099 : }
4100 :
4101 : template<typename BasicJsonType, typename ConstructibleObjectType,
4102 : enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
4103 56 : void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
4104 : {
4105 56 : if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
4106 : {
4107 0 : JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j));
4108 : }
4109 :
4110 : ConstructibleObjectType ret;
4111 : const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4112 : using value_type = typename ConstructibleObjectType::value_type;
4113 56 : std::transform(
4114 : inner_object->begin(), inner_object->end(),
4115 : std::inserter(ret, ret.begin()),
4116 140 : [](typename BasicJsonType::object_t::value_type const & p)
4117 : {
4118 140 : return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
4119 : });
4120 : obj = std::move(ret);
4121 56 : }
4122 :
4123 : // overload for arithmetic types, not chosen for basic_json template arguments
4124 : // (BooleanType, etc..); note: Is it really necessary to provide explicit
4125 : // overloads for boolean_t etc. in case of a custom BooleanType which is not
4126 : // an arithmetic type?
4127 : template < typename BasicJsonType, typename ArithmeticType,
4128 : enable_if_t <
4129 : std::is_arithmetic<ArithmeticType>::value&&
4130 : !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
4131 : !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
4132 : !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
4133 : !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4134 : int > = 0 >
4135 : void from_json(const BasicJsonType& j, ArithmeticType& val)
4136 : {
4137 : switch (static_cast<value_t>(j))
4138 : {
4139 : case value_t::number_unsigned:
4140 : {
4141 : val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4142 : break;
4143 : }
4144 : case value_t::number_integer:
4145 : {
4146 : val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4147 : break;
4148 : }
4149 : case value_t::number_float:
4150 : {
4151 : val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4152 : break;
4153 : }
4154 : case value_t::boolean:
4155 : {
4156 : val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
4157 : break;
4158 : }
4159 :
4160 : case value_t::null:
4161 : case value_t::object:
4162 : case value_t::array:
4163 : case value_t::string:
4164 : case value_t::binary:
4165 : case value_t::discarded:
4166 : default:
4167 : JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
4168 : }
4169 : }
4170 :
4171 : template<typename BasicJsonType, typename... Args, std::size_t... Idx>
4172 : std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
4173 : {
4174 : return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
4175 : }
4176 :
4177 : template < typename BasicJsonType, class A1, class A2 >
4178 : std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
4179 : {
4180 : return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
4181 : std::forward<BasicJsonType>(j).at(1).template get<A2>()};
4182 : }
4183 :
4184 : template<typename BasicJsonType, typename A1, typename A2>
4185 : void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
4186 : {
4187 : p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
4188 : }
4189 :
4190 : template<typename BasicJsonType, typename... Args>
4191 : std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
4192 : {
4193 : return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4194 : }
4195 :
4196 : template<typename BasicJsonType, typename... Args>
4197 : void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
4198 : {
4199 : t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4200 : }
4201 :
4202 : template<typename BasicJsonType, typename TupleRelated>
4203 : auto from_json(BasicJsonType&& j, TupleRelated&& t)
4204 : -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
4205 : {
4206 : if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4207 : {
4208 : JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4209 : }
4210 :
4211 : return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
4212 : }
4213 :
4214 : template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
4215 : typename = enable_if_t < !std::is_constructible <
4216 : typename BasicJsonType::string_t, Key >::value >>
4217 : void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
4218 : {
4219 : if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4220 : {
4221 : JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4222 : }
4223 : m.clear();
4224 : for (const auto& p : j)
4225 : {
4226 : if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
4227 : {
4228 : JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
4229 : }
4230 : m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4231 : }
4232 : }
4233 :
4234 : template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
4235 : typename = enable_if_t < !std::is_constructible <
4236 : typename BasicJsonType::string_t, Key >::value >>
4237 : void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
4238 : {
4239 : if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4240 : {
4241 : JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4242 : }
4243 : m.clear();
4244 : for (const auto& p : j)
4245 : {
4246 : if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
4247 : {
4248 : JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
4249 : }
4250 : m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4251 : }
4252 : }
4253 :
4254 : #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4255 : template<typename BasicJsonType>
4256 : void from_json(const BasicJsonType& j, std_fs::path& p)
4257 : {
4258 : if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4259 : {
4260 : JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
4261 : }
4262 : p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4263 : }
4264 : #endif
4265 :
4266 : struct from_json_fn
4267 : {
4268 : template<typename BasicJsonType, typename T>
4269 : auto operator()(const BasicJsonType& j, T&& val) const
4270 : noexcept(noexcept(from_json(j, std::forward<T>(val))))
4271 : -> decltype(from_json(j, std::forward<T>(val)))
4272 : {
4273 152 : return from_json(j, std::forward<T>(val));
4274 : }
4275 : };
4276 : } // namespace detail
4277 :
4278 : /// namespace to hold default `from_json` function
4279 : /// to see why this is required:
4280 : /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
4281 : namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
4282 : {
4283 : constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value; // NOLINT(misc-definitions-in-headers)
4284 : } // namespace
4285 : } // namespace nlohmann
4286 :
4287 : // #include <nlohmann/detail/conversions/to_json.hpp>
4288 :
4289 :
4290 : #include <algorithm> // copy
4291 : #include <iterator> // begin, end
4292 : #include <string> // string
4293 : #include <tuple> // tuple, get
4294 : #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
4295 : #include <utility> // move, forward, declval, pair
4296 : #include <valarray> // valarray
4297 : #include <vector> // vector
4298 :
4299 : // #include <nlohmann/detail/macro_scope.hpp>
4300 :
4301 : // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
4302 :
4303 :
4304 : #include <cstddef> // size_t
4305 : #include <iterator> // input_iterator_tag
4306 : #include <string> // string, to_string
4307 : #include <tuple> // tuple_size, get, tuple_element
4308 : #include <utility> // move
4309 :
4310 : // #include <nlohmann/detail/meta/type_traits.hpp>
4311 :
4312 : // #include <nlohmann/detail/value_t.hpp>
4313 :
4314 :
4315 : namespace nlohmann
4316 : {
4317 : namespace detail
4318 : {
4319 : template<typename string_type>
4320 0 : void int_to_string( string_type& target, std::size_t value )
4321 : {
4322 : // For ADL
4323 : using std::to_string;
4324 0 : target = to_string(value);
4325 0 : }
4326 4 : template<typename IteratorType> class iteration_proxy_value
4327 : {
4328 : public:
4329 : using difference_type = std::ptrdiff_t;
4330 : using value_type = iteration_proxy_value;
4331 : using pointer = value_type * ;
4332 : using reference = value_type & ;
4333 : using iterator_category = std::input_iterator_tag;
4334 : using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
4335 :
4336 : private:
4337 : /// the iterator
4338 : IteratorType anchor;
4339 : /// an index for arrays (used to create key names)
4340 : std::size_t array_index = 0;
4341 : /// last stringified array index
4342 : mutable std::size_t array_index_last = 0;
4343 : /// a string representation of the array index
4344 : mutable string_type array_index_str = "0";
4345 : /// an empty string (to return a reference for primitive values)
4346 : const string_type empty_str{};
4347 :
4348 : public:
4349 : explicit iteration_proxy_value(IteratorType it) noexcept
4350 8 : : anchor(std::move(it))
4351 : {}
4352 :
4353 : /// dereference operator (needed for range-based for)
4354 : iteration_proxy_value& operator*()
4355 : {
4356 : return *this;
4357 : }
4358 :
4359 : /// increment operator (needed for range-based for)
4360 : iteration_proxy_value& operator++()
4361 : {
4362 6 : ++anchor;
4363 6 : ++array_index;
4364 :
4365 6 : return *this;
4366 : }
4367 :
4368 : /// equality operator (needed for InputIterator)
4369 : bool operator==(const iteration_proxy_value& o) const
4370 : {
4371 : return anchor == o.anchor;
4372 : }
4373 :
4374 : /// inequality operator (needed for range-based for)
4375 : bool operator!=(const iteration_proxy_value& o) const
4376 : {
4377 : return anchor != o.anchor;
4378 : }
4379 :
4380 : /// return key of the iterator
4381 6 : const string_type& key() const
4382 : {
4383 : JSON_ASSERT(anchor.m_object != nullptr);
4384 :
4385 6 : switch (anchor.m_object->type())
4386 : {
4387 : // use integer array index as key
4388 0 : case value_t::array:
4389 : {
4390 0 : if (array_index != array_index_last)
4391 : {
4392 0 : int_to_string( array_index_str, array_index );
4393 0 : array_index_last = array_index;
4394 : }
4395 0 : return array_index_str;
4396 : }
4397 :
4398 : // use key from the object
4399 6 : case value_t::object:
4400 6 : return anchor.key();
4401 :
4402 : // use an empty key for all primitive types
4403 0 : case value_t::null:
4404 : case value_t::string:
4405 : case value_t::boolean:
4406 : case value_t::number_integer:
4407 : case value_t::number_unsigned:
4408 : case value_t::number_float:
4409 : case value_t::binary:
4410 : case value_t::discarded:
4411 : default:
4412 0 : return empty_str;
4413 : }
4414 : }
4415 :
4416 : /// return value of the iterator
4417 : typename IteratorType::reference value() const
4418 : {
4419 : return anchor.value();
4420 : }
4421 : };
4422 :
4423 : /// proxy class for the items() function
4424 : template<typename IteratorType> class iteration_proxy
4425 : {
4426 : private:
4427 : /// the container to iterate
4428 : typename IteratorType::reference container;
4429 :
4430 : public:
4431 : /// construct iteration proxy from a container
4432 : explicit iteration_proxy(typename IteratorType::reference cont) noexcept
4433 : : container(cont) {}
4434 :
4435 : /// return iterator begin (needed for range-based for)
4436 2 : iteration_proxy_value<IteratorType> begin() noexcept
4437 : {
4438 2 : return iteration_proxy_value<IteratorType>(container.begin());
4439 : }
4440 :
4441 : /// return iterator end (needed for range-based for)
4442 2 : iteration_proxy_value<IteratorType> end() noexcept
4443 : {
4444 2 : return iteration_proxy_value<IteratorType>(container.end());
4445 : }
4446 : };
4447 : // Structured Bindings Support
4448 : // For further reference see https://blog.tartanllama.xyz/structured-bindings/
4449 : // And see https://github.com/nlohmann/json/pull/1391
4450 : template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
4451 : auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
4452 : {
4453 : return i.key();
4454 : }
4455 : // Structured Bindings Support
4456 : // For further reference see https://blog.tartanllama.xyz/structured-bindings/
4457 : // And see https://github.com/nlohmann/json/pull/1391
4458 : template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
4459 : auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
4460 : {
4461 : return i.value();
4462 : }
4463 : } // namespace detail
4464 : } // namespace nlohmann
4465 :
4466 : // The Addition to the STD Namespace is required to add
4467 : // Structured Bindings Support to the iteration_proxy_value class
4468 : // For further reference see https://blog.tartanllama.xyz/structured-bindings/
4469 : // And see https://github.com/nlohmann/json/pull/1391
4470 : namespace std
4471 : {
4472 : #if defined(__clang__)
4473 : // Fix: https://github.com/nlohmann/json/issues/1401
4474 : #pragma clang diagnostic push
4475 : #pragma clang diagnostic ignored "-Wmismatched-tags"
4476 : #endif
4477 : template<typename IteratorType>
4478 : class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
4479 : : public std::integral_constant<std::size_t, 2> {};
4480 :
4481 : template<std::size_t N, typename IteratorType>
4482 : class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
4483 : {
4484 : public:
4485 : using type = decltype(
4486 : get<N>(std::declval <
4487 : ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
4488 : };
4489 : #if defined(__clang__)
4490 : #pragma clang diagnostic pop
4491 : #endif
4492 : } // namespace std
4493 :
4494 : // #include <nlohmann/detail/meta/cpp_future.hpp>
4495 :
4496 : // #include <nlohmann/detail/meta/type_traits.hpp>
4497 :
4498 : // #include <nlohmann/detail/value_t.hpp>
4499 :
4500 :
4501 : #if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4502 : #include <experimental/filesystem>
4503 : namespace nlohmann::detail
4504 : {
4505 : namespace std_fs = std::experimental::filesystem;
4506 : } // namespace nlohmann::detail
4507 : #elif JSON_HAS_FILESYSTEM
4508 : #include <filesystem>
4509 : namespace nlohmann::detail
4510 : {
4511 : namespace std_fs = std::filesystem;
4512 : } // namespace nlohmann::detail
4513 : #endif
4514 :
4515 : namespace nlohmann
4516 : {
4517 : namespace detail
4518 : {
4519 : //////////////////
4520 : // constructors //
4521 : //////////////////
4522 :
4523 : /*
4524 : * Note all external_constructor<>::construct functions need to call
4525 : * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an
4526 : * allocated value (e.g., a string). See bug issue
4527 : * https://github.com/nlohmann/json/issues/2865 for more information.
4528 : */
4529 :
4530 : template<value_t> struct external_constructor;
4531 :
4532 : template<>
4533 : struct external_constructor<value_t::boolean>
4534 : {
4535 : template<typename BasicJsonType>
4536 : static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
4537 : {
4538 0 : j.m_value.destroy(j.m_type);
4539 0 : j.m_type = value_t::boolean;
4540 0 : j.m_value = b;
4541 : j.assert_invariant();
4542 : }
4543 : };
4544 :
4545 : template<>
4546 : struct external_constructor<value_t::string>
4547 : {
4548 : template<typename BasicJsonType>
4549 152 : static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
4550 : {
4551 152 : j.m_value.destroy(j.m_type);
4552 152 : j.m_type = value_t::string;
4553 152 : j.m_value = s;
4554 : j.assert_invariant();
4555 152 : }
4556 :
4557 : template<typename BasicJsonType>
4558 : static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
4559 : {
4560 : j.m_value.destroy(j.m_type);
4561 : j.m_type = value_t::string;
4562 : j.m_value = std::move(s);
4563 : j.assert_invariant();
4564 : }
4565 :
4566 : template < typename BasicJsonType, typename CompatibleStringType,
4567 : enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
4568 : int > = 0 >
4569 : static void construct(BasicJsonType& j, const CompatibleStringType& str)
4570 : {
4571 : j.m_value.destroy(j.m_type);
4572 : j.m_type = value_t::string;
4573 : j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
4574 : j.assert_invariant();
4575 : }
4576 : };
4577 :
4578 : template<>
4579 : struct external_constructor<value_t::binary>
4580 : {
4581 : template<typename BasicJsonType>
4582 : static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
4583 : {
4584 : j.m_value.destroy(j.m_type);
4585 : j.m_type = value_t::binary;
4586 : j.m_value = typename BasicJsonType::binary_t(b);
4587 : j.assert_invariant();
4588 : }
4589 :
4590 : template<typename BasicJsonType>
4591 : static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
4592 : {
4593 : j.m_value.destroy(j.m_type);
4594 : j.m_type = value_t::binary;
4595 : j.m_value = typename BasicJsonType::binary_t(std::move(b));
4596 : j.assert_invariant();
4597 : }
4598 : };
4599 :
4600 : template<>
4601 : struct external_constructor<value_t::number_float>
4602 : {
4603 : template<typename BasicJsonType>
4604 : static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
4605 : {
4606 4334 : j.m_value.destroy(j.m_type);
4607 3670 : j.m_type = value_t::number_float;
4608 4334 : j.m_value = val;
4609 : j.assert_invariant();
4610 : }
4611 : };
4612 :
4613 : template<>
4614 : struct external_constructor<value_t::number_unsigned>
4615 : {
4616 : template<typename BasicJsonType>
4617 : static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
4618 : {
4619 200 : j.m_value.destroy(j.m_type);
4620 200 : j.m_type = value_t::number_unsigned;
4621 200 : j.m_value = val;
4622 : j.assert_invariant();
4623 : }
4624 : };
4625 :
4626 : template<>
4627 : struct external_constructor<value_t::number_integer>
4628 : {
4629 : template<typename BasicJsonType>
4630 : static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
4631 : {
4632 8 : j.m_value.destroy(j.m_type);
4633 8 : j.m_type = value_t::number_integer;
4634 8 : j.m_value = val;
4635 : j.assert_invariant();
4636 : }
4637 : };
4638 :
4639 : template<>
4640 : struct external_constructor<value_t::array>
4641 : {
4642 : template<typename BasicJsonType>
4643 : static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
4644 : {
4645 : j.m_value.destroy(j.m_type);
4646 : j.m_type = value_t::array;
4647 : j.m_value = arr;
4648 : j.set_parents();
4649 : j.assert_invariant();
4650 : }
4651 :
4652 : template<typename BasicJsonType>
4653 : static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
4654 : {
4655 : j.m_value.destroy(j.m_type);
4656 : j.m_type = value_t::array;
4657 : j.m_value = std::move(arr);
4658 : j.set_parents();
4659 : j.assert_invariant();
4660 : }
4661 :
4662 : template < typename BasicJsonType, typename CompatibleArrayType,
4663 : enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
4664 : int > = 0 >
4665 : static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
4666 : {
4667 : using std::begin;
4668 : using std::end;
4669 :
4670 : j.m_value.destroy(j.m_type);
4671 : j.m_type = value_t::array;
4672 : j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
4673 : j.set_parents();
4674 : j.assert_invariant();
4675 : }
4676 :
4677 : template<typename BasicJsonType>
4678 : static void construct(BasicJsonType& j, const std::vector<bool>& arr)
4679 : {
4680 : j.m_value.destroy(j.m_type);
4681 : j.m_type = value_t::array;
4682 : j.m_value = value_t::array;
4683 : j.m_value.array->reserve(arr.size());
4684 : for (const bool x : arr)
4685 : {
4686 : j.m_value.array->push_back(x);
4687 : j.set_parent(j.m_value.array->back());
4688 : }
4689 : j.assert_invariant();
4690 : }
4691 :
4692 : template<typename BasicJsonType, typename T,
4693 : enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
4694 : static void construct(BasicJsonType& j, const std::valarray<T>& arr)
4695 : {
4696 : j.m_value.destroy(j.m_type);
4697 : j.m_type = value_t::array;
4698 : j.m_value = value_t::array;
4699 : j.m_value.array->resize(arr.size());
4700 : if (arr.size() > 0)
4701 : {
4702 : std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
4703 : }
4704 : j.set_parents();
4705 : j.assert_invariant();
4706 : }
4707 : };
4708 :
4709 : template<>
4710 : struct external_constructor<value_t::object>
4711 : {
4712 : template<typename BasicJsonType>
4713 : static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
4714 : {
4715 : j.m_value.destroy(j.m_type);
4716 : j.m_type = value_t::object;
4717 : j.m_value = obj;
4718 : j.set_parents();
4719 : j.assert_invariant();
4720 : }
4721 :
4722 : template<typename BasicJsonType>
4723 : static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
4724 : {
4725 : j.m_value.destroy(j.m_type);
4726 : j.m_type = value_t::object;
4727 : j.m_value = std::move(obj);
4728 : j.set_parents();
4729 : j.assert_invariant();
4730 : }
4731 :
4732 : template < typename BasicJsonType, typename CompatibleObjectType,
4733 : enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
4734 : static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
4735 : {
4736 : using std::begin;
4737 : using std::end;
4738 :
4739 : j.m_value.destroy(j.m_type);
4740 : j.m_type = value_t::object;
4741 : j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
4742 : j.set_parents();
4743 : j.assert_invariant();
4744 : }
4745 : };
4746 :
4747 : /////////////
4748 : // to_json //
4749 : /////////////
4750 :
4751 : template<typename BasicJsonType, typename T,
4752 : enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
4753 : void to_json(BasicJsonType& j, T b) noexcept
4754 : {
4755 : external_constructor<value_t::boolean>::construct(j, b);
4756 : }
4757 :
4758 : template<typename BasicJsonType, typename CompatibleString,
4759 : enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
4760 : void to_json(BasicJsonType& j, const CompatibleString& s)
4761 : {
4762 152 : external_constructor<value_t::string>::construct(j, s);
4763 : }
4764 :
4765 : template<typename BasicJsonType>
4766 : void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
4767 : {
4768 : external_constructor<value_t::string>::construct(j, std::move(s));
4769 : }
4770 :
4771 : template<typename BasicJsonType, typename FloatType,
4772 : enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
4773 : void to_json(BasicJsonType& j, FloatType val) noexcept
4774 : {
4775 : external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
4776 : }
4777 :
4778 : template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
4779 : enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
4780 : void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
4781 : {
4782 : external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
4783 : }
4784 :
4785 : template<typename BasicJsonType, typename CompatibleNumberIntegerType,
4786 : enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
4787 : void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
4788 : {
4789 : external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
4790 : }
4791 :
4792 : template<typename BasicJsonType, typename EnumType,
4793 : enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4794 : void to_json(BasicJsonType& j, EnumType e) noexcept
4795 : {
4796 : using underlying_type = typename std::underlying_type<EnumType>::type;
4797 : external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
4798 : }
4799 :
4800 : template<typename BasicJsonType>
4801 : void to_json(BasicJsonType& j, const std::vector<bool>& e)
4802 : {
4803 : external_constructor<value_t::array>::construct(j, e);
4804 : }
4805 :
4806 : template < typename BasicJsonType, typename CompatibleArrayType,
4807 : enable_if_t < is_compatible_array_type<BasicJsonType,
4808 : CompatibleArrayType>::value&&
4809 : !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
4810 : !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
4811 : !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
4812 : !is_basic_json<CompatibleArrayType>::value,
4813 : int > = 0 >
4814 : void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
4815 : {
4816 : external_constructor<value_t::array>::construct(j, arr);
4817 : }
4818 :
4819 : template<typename BasicJsonType>
4820 : void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
4821 : {
4822 : external_constructor<value_t::binary>::construct(j, bin);
4823 : }
4824 :
4825 : template<typename BasicJsonType, typename T,
4826 : enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
4827 : void to_json(BasicJsonType& j, const std::valarray<T>& arr)
4828 : {
4829 : external_constructor<value_t::array>::construct(j, std::move(arr));
4830 : }
4831 :
4832 : template<typename BasicJsonType>
4833 : void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
4834 : {
4835 : external_constructor<value_t::array>::construct(j, std::move(arr));
4836 : }
4837 :
4838 : template < typename BasicJsonType, typename CompatibleObjectType,
4839 : enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
4840 : void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
4841 : {
4842 : external_constructor<value_t::object>::construct(j, obj);
4843 : }
4844 :
4845 : template<typename BasicJsonType>
4846 : void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
4847 : {
4848 : external_constructor<value_t::object>::construct(j, std::move(obj));
4849 : }
4850 :
4851 : template <
4852 : typename BasicJsonType, typename T, std::size_t N,
4853 : enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
4854 : const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4855 : int > = 0 >
4856 : void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4857 : {
4858 : external_constructor<value_t::array>::construct(j, arr);
4859 : }
4860 :
4861 : template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
4862 : void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
4863 : {
4864 : j = { p.first, p.second };
4865 : }
4866 :
4867 : // for https://github.com/nlohmann/json/pull/1134
4868 : template<typename BasicJsonType, typename T,
4869 : enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
4870 : void to_json(BasicJsonType& j, const T& b)
4871 : {
4872 : j = { {b.key(), b.value()} };
4873 : }
4874 :
4875 : template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
4876 : void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
4877 : {
4878 : j = { std::get<Idx>(t)... };
4879 : }
4880 :
4881 : template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
4882 : void to_json(BasicJsonType& j, const T& t)
4883 : {
4884 : to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
4885 : }
4886 :
4887 : #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4888 : template<typename BasicJsonType>
4889 : void to_json(BasicJsonType& j, const std_fs::path& p)
4890 : {
4891 : j = p.string();
4892 : }
4893 : #endif
4894 :
4895 : struct to_json_fn
4896 : {
4897 : template<typename BasicJsonType, typename T>
4898 : auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
4899 : -> decltype(to_json(j, std::forward<T>(val)), void())
4900 : {
4901 4541 : return to_json(j, std::forward<T>(val));
4902 : }
4903 : };
4904 : } // namespace detail
4905 :
4906 : /// namespace to hold default `to_json` function
4907 : /// to see why this is required:
4908 : /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
4909 : namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
4910 : {
4911 : constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value; // NOLINT(misc-definitions-in-headers)
4912 : } // namespace
4913 : } // namespace nlohmann
4914 :
4915 : // #include <nlohmann/detail/meta/identity_tag.hpp>
4916 :
4917 : // #include <nlohmann/detail/meta/type_traits.hpp>
4918 :
4919 :
4920 : namespace nlohmann
4921 : {
4922 :
4923 : /// @sa https://json.nlohmann.me/api/adl_serializer/
4924 : template<typename ValueType, typename>
4925 : struct adl_serializer
4926 : {
4927 : /// @brief convert a JSON value to any value type
4928 : /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
4929 : template<typename BasicJsonType, typename TargetType = ValueType>
4930 : static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
4931 : noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
4932 : -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
4933 : {
4934 : ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
4935 292 : }
4936 :
4937 : /// @brief convert a JSON value to any value type
4938 : /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
4939 : template<typename BasicJsonType, typename TargetType = ValueType>
4940 : static auto from_json(BasicJsonType && j) noexcept(
4941 : noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
4942 : -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
4943 : {
4944 : return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
4945 : }
4946 :
4947 : /// @brief convert any value type to a JSON value
4948 : /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
4949 : template<typename BasicJsonType, typename TargetType = ValueType>
4950 : static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
4951 : noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
4952 : -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
4953 : {
4954 : ::nlohmann::to_json(j, std::forward<TargetType>(val));
4955 : }
4956 : };
4957 : } // namespace nlohmann
4958 :
4959 : // #include <nlohmann/byte_container_with_subtype.hpp>
4960 :
4961 :
4962 : #include <cstdint> // uint8_t, uint64_t
4963 : #include <tuple> // tie
4964 : #include <utility> // move
4965 :
4966 : namespace nlohmann
4967 : {
4968 :
4969 : /// @brief an internal type for a backed binary type
4970 : /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
4971 : template<typename BinaryType>
4972 0 : class byte_container_with_subtype : public BinaryType
4973 : {
4974 : public:
4975 : using container_type = BinaryType;
4976 : using subtype_type = std::uint64_t;
4977 :
4978 : /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4979 0 : byte_container_with_subtype() noexcept(noexcept(container_type()))
4980 0 : : container_type()
4981 : {}
4982 :
4983 : /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4984 : byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
4985 : : container_type(b)
4986 : {}
4987 :
4988 : /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4989 : byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
4990 : : container_type(std::move(b))
4991 : {}
4992 :
4993 : /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4994 : byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
4995 : : container_type(b)
4996 : , m_subtype(subtype_)
4997 : , m_has_subtype(true)
4998 : {}
4999 :
5000 : /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5001 : byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
5002 : : container_type(std::move(b))
5003 : , m_subtype(subtype_)
5004 : , m_has_subtype(true)
5005 : {}
5006 :
5007 : bool operator==(const byte_container_with_subtype& rhs) const
5008 : {
5009 : return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
5010 : std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5011 : }
5012 :
5013 : bool operator!=(const byte_container_with_subtype& rhs) const
5014 : {
5015 : return !(rhs == *this);
5016 : }
5017 :
5018 : /// @brief sets the binary subtype
5019 : /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/
5020 : void set_subtype(subtype_type subtype_) noexcept
5021 : {
5022 : m_subtype = subtype_;
5023 : m_has_subtype = true;
5024 : }
5025 :
5026 : /// @brief return the binary subtype
5027 : /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/
5028 : constexpr subtype_type subtype() const noexcept
5029 : {
5030 : return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
5031 : }
5032 :
5033 : /// @brief return whether the value has a subtype
5034 : /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/
5035 : constexpr bool has_subtype() const noexcept
5036 : {
5037 : return m_has_subtype;
5038 : }
5039 :
5040 : /// @brief clears the binary subtype
5041 : /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/
5042 : void clear_subtype() noexcept
5043 : {
5044 : m_subtype = 0;
5045 : m_has_subtype = false;
5046 : }
5047 :
5048 : private:
5049 : subtype_type m_subtype = 0;
5050 : bool m_has_subtype = false;
5051 : };
5052 :
5053 : } // namespace nlohmann
5054 :
5055 : // #include <nlohmann/detail/conversions/from_json.hpp>
5056 :
5057 : // #include <nlohmann/detail/conversions/to_json.hpp>
5058 :
5059 : // #include <nlohmann/detail/exceptions.hpp>
5060 :
5061 : // #include <nlohmann/detail/hash.hpp>
5062 :
5063 :
5064 : #include <cstdint> // uint8_t
5065 : #include <cstddef> // size_t
5066 : #include <functional> // hash
5067 :
5068 : // #include <nlohmann/detail/macro_scope.hpp>
5069 :
5070 : // #include <nlohmann/detail/value_t.hpp>
5071 :
5072 :
5073 : namespace nlohmann
5074 : {
5075 : namespace detail
5076 : {
5077 :
5078 : // boost::hash_combine
5079 : inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
5080 : {
5081 : seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
5082 : return seed;
5083 : }
5084 :
5085 : /*!
5086 : @brief hash a JSON value
5087 :
5088 : The hash function tries to rely on std::hash where possible. Furthermore, the
5089 : type of the JSON value is taken into account to have different hash values for
5090 : null, 0, 0U, and false, etc.
5091 :
5092 : @tparam BasicJsonType basic_json specialization
5093 : @param j JSON value to hash
5094 : @return hash value of j
5095 : */
5096 : template<typename BasicJsonType>
5097 : std::size_t hash(const BasicJsonType& j)
5098 : {
5099 : using string_t = typename BasicJsonType::string_t;
5100 : using number_integer_t = typename BasicJsonType::number_integer_t;
5101 : using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5102 : using number_float_t = typename BasicJsonType::number_float_t;
5103 :
5104 : const auto type = static_cast<std::size_t>(j.type());
5105 : switch (j.type())
5106 : {
5107 : case BasicJsonType::value_t::null:
5108 : case BasicJsonType::value_t::discarded:
5109 : {
5110 : return combine(type, 0);
5111 : }
5112 :
5113 : case BasicJsonType::value_t::object:
5114 : {
5115 : auto seed = combine(type, j.size());
5116 : for (const auto& element : j.items())
5117 : {
5118 : const auto h = std::hash<string_t> {}(element.key());
5119 : seed = combine(seed, h);
5120 : seed = combine(seed, hash(element.value()));
5121 : }
5122 : return seed;
5123 : }
5124 :
5125 : case BasicJsonType::value_t::array:
5126 : {
5127 : auto seed = combine(type, j.size());
5128 : for (const auto& element : j)
5129 : {
5130 : seed = combine(seed, hash(element));
5131 : }
5132 : return seed;
5133 : }
5134 :
5135 : case BasicJsonType::value_t::string:
5136 : {
5137 : const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
5138 : return combine(type, h);
5139 : }
5140 :
5141 : case BasicJsonType::value_t::boolean:
5142 : {
5143 : const auto h = std::hash<bool> {}(j.template get<bool>());
5144 : return combine(type, h);
5145 : }
5146 :
5147 : case BasicJsonType::value_t::number_integer:
5148 : {
5149 : const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
5150 : return combine(type, h);
5151 : }
5152 :
5153 : case BasicJsonType::value_t::number_unsigned:
5154 : {
5155 : const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
5156 : return combine(type, h);
5157 : }
5158 :
5159 : case BasicJsonType::value_t::number_float:
5160 : {
5161 : const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
5162 : return combine(type, h);
5163 : }
5164 :
5165 : case BasicJsonType::value_t::binary:
5166 : {
5167 : auto seed = combine(type, j.get_binary().size());
5168 : const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
5169 : seed = combine(seed, h);
5170 : seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
5171 : for (const auto byte : j.get_binary())
5172 : {
5173 : seed = combine(seed, std::hash<std::uint8_t> {}(byte));
5174 : }
5175 : return seed;
5176 : }
5177 :
5178 : default: // LCOV_EXCL_LINE
5179 : JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
5180 : return 0; // LCOV_EXCL_LINE
5181 : }
5182 : }
5183 :
5184 : } // namespace detail
5185 : } // namespace nlohmann
5186 :
5187 : // #include <nlohmann/detail/input/binary_reader.hpp>
5188 :
5189 :
5190 : #include <algorithm> // generate_n
5191 : #include <array> // array
5192 : #include <cmath> // ldexp
5193 : #include <cstddef> // size_t
5194 : #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
5195 : #include <cstdio> // snprintf
5196 : #include <cstring> // memcpy
5197 : #include <iterator> // back_inserter
5198 : #include <limits> // numeric_limits
5199 : #include <string> // char_traits, string
5200 : #include <utility> // make_pair, move
5201 : #include <vector> // vector
5202 :
5203 : // #include <nlohmann/detail/exceptions.hpp>
5204 :
5205 : // #include <nlohmann/detail/input/input_adapters.hpp>
5206 :
5207 :
5208 : #include <array> // array
5209 : #include <cstddef> // size_t
5210 : #include <cstring> // strlen
5211 : #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
5212 : #include <memory> // shared_ptr, make_shared, addressof
5213 : #include <numeric> // accumulate
5214 : #include <string> // string, char_traits
5215 : #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
5216 : #include <utility> // pair, declval
5217 :
5218 : #ifndef JSON_NO_IO
5219 : #include <cstdio> // FILE *
5220 : #include <istream> // istream
5221 : #endif // JSON_NO_IO
5222 :
5223 : // #include <nlohmann/detail/iterators/iterator_traits.hpp>
5224 :
5225 : // #include <nlohmann/detail/macro_scope.hpp>
5226 :
5227 :
5228 : namespace nlohmann
5229 : {
5230 : namespace detail
5231 : {
5232 : /// the supported input formats
5233 : enum class input_format_t { json, cbor, msgpack, ubjson, bson };
5234 :
5235 : ////////////////////
5236 : // input adapters //
5237 : ////////////////////
5238 :
5239 : #ifndef JSON_NO_IO
5240 : /*!
5241 : Input adapter for stdio file access. This adapter read only 1 byte and do not use any
5242 : buffer. This adapter is a very low level adapter.
5243 : */
5244 : class file_input_adapter
5245 : {
5246 : public:
5247 : using char_type = char;
5248 :
5249 : JSON_HEDLEY_NON_NULL(2)
5250 : explicit file_input_adapter(std::FILE* f) noexcept
5251 : : m_file(f)
5252 : {}
5253 :
5254 : // make class move-only
5255 : file_input_adapter(const file_input_adapter&) = delete;
5256 : file_input_adapter(file_input_adapter&&) noexcept = default;
5257 : file_input_adapter& operator=(const file_input_adapter&) = delete;
5258 : file_input_adapter& operator=(file_input_adapter&&) = delete;
5259 : ~file_input_adapter() = default;
5260 :
5261 : std::char_traits<char>::int_type get_character() noexcept
5262 : {
5263 : return std::fgetc(m_file);
5264 : }
5265 :
5266 : private:
5267 : /// the file pointer to read from
5268 : std::FILE* m_file;
5269 : };
5270 :
5271 :
5272 : /*!
5273 : Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
5274 : beginning of input. Does not support changing the underlying std::streambuf
5275 : in mid-input. Maintains underlying std::istream and std::streambuf to support
5276 : subsequent use of standard std::istream operations to process any input
5277 : characters following those used in parsing the JSON input. Clears the
5278 : std::istream flags; any input errors (e.g., EOF) will be detected by the first
5279 : subsequent call for input from the std::istream.
5280 : */
5281 : class input_stream_adapter
5282 : {
5283 : public:
5284 : using char_type = char;
5285 :
5286 68 : ~input_stream_adapter()
5287 : {
5288 : // clear stream flags; we use underlying streambuf I/O, do not
5289 : // maintain ifstream flags, except eof
5290 68 : if (is != nullptr)
5291 : {
5292 34 : is->clear(is->rdstate() & std::ios::eofbit);
5293 : }
5294 68 : }
5295 :
5296 : explicit input_stream_adapter(std::istream& i)
5297 34 : : is(&i), sb(i.rdbuf())
5298 : {}
5299 :
5300 : // delete because of pointer members
5301 : input_stream_adapter(const input_stream_adapter&) = delete;
5302 : input_stream_adapter& operator=(input_stream_adapter&) = delete;
5303 : input_stream_adapter& operator=(input_stream_adapter&&) = delete;
5304 :
5305 : input_stream_adapter(input_stream_adapter&& rhs) noexcept
5306 34 : : is(rhs.is), sb(rhs.sb)
5307 : {
5308 34 : rhs.is = nullptr;
5309 34 : rhs.sb = nullptr;
5310 : }
5311 :
5312 : // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
5313 : // ensure that std::char_traits<char>::eof() and the character 0xFF do not
5314 : // end up as the same value, e.g. 0xFFFFFFFF.
5315 103824 : std::char_traits<char>::int_type get_character()
5316 : {
5317 103824 : auto res = sb->sbumpc();
5318 : // set eof manually, as we don't use the istream interface.
5319 103824 : if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
5320 : {
5321 0 : is->clear(is->rdstate() | std::ios::eofbit);
5322 : }
5323 103824 : return res;
5324 : }
5325 :
5326 : private:
5327 : /// the associated input stream
5328 : std::istream* is = nullptr;
5329 : std::streambuf* sb = nullptr;
5330 : };
5331 : #endif // JSON_NO_IO
5332 :
5333 : // General-purpose iterator-based adapter. It might not be as fast as
5334 : // theoretically possible for some containers, but it is extremely versatile.
5335 : template<typename IteratorType>
5336 : class iterator_input_adapter
5337 : {
5338 : public:
5339 : using char_type = typename std::iterator_traits<IteratorType>::value_type;
5340 :
5341 : iterator_input_adapter(IteratorType first, IteratorType last)
5342 : : current(std::move(first)), end(std::move(last))
5343 : {}
5344 :
5345 : typename std::char_traits<char_type>::int_type get_character()
5346 : {
5347 : if (JSON_HEDLEY_LIKELY(current != end))
5348 : {
5349 : auto result = std::char_traits<char_type>::to_int_type(*current);
5350 : std::advance(current, 1);
5351 : return result;
5352 : }
5353 :
5354 : return std::char_traits<char_type>::eof();
5355 : }
5356 :
5357 : private:
5358 : IteratorType current;
5359 : IteratorType end;
5360 :
5361 : template<typename BaseInputAdapter, size_t T>
5362 : friend struct wide_string_input_helper;
5363 :
5364 : bool empty() const
5365 : {
5366 : return current == end;
5367 : }
5368 : };
5369 :
5370 :
5371 : template<typename BaseInputAdapter, size_t T>
5372 : struct wide_string_input_helper;
5373 :
5374 : template<typename BaseInputAdapter>
5375 : struct wide_string_input_helper<BaseInputAdapter, 4>
5376 : {
5377 : // UTF-32
5378 : static void fill_buffer(BaseInputAdapter& input,
5379 : std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
5380 : size_t& utf8_bytes_index,
5381 : size_t& utf8_bytes_filled)
5382 : {
5383 : utf8_bytes_index = 0;
5384 :
5385 : if (JSON_HEDLEY_UNLIKELY(input.empty()))
5386 : {
5387 : utf8_bytes[0] = std::char_traits<char>::eof();
5388 : utf8_bytes_filled = 1;
5389 : }
5390 : else
5391 : {
5392 : // get the current character
5393 : const auto wc = input.get_character();
5394 :
5395 : // UTF-32 to UTF-8 encoding
5396 : if (wc < 0x80)
5397 : {
5398 : utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5399 : utf8_bytes_filled = 1;
5400 : }
5401 : else if (wc <= 0x7FF)
5402 : {
5403 : utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
5404 : utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5405 : utf8_bytes_filled = 2;
5406 : }
5407 : else if (wc <= 0xFFFF)
5408 : {
5409 : utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
5410 : utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5411 : utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5412 : utf8_bytes_filled = 3;
5413 : }
5414 : else if (wc <= 0x10FFFF)
5415 : {
5416 : utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
5417 : utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
5418 : utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5419 : utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5420 : utf8_bytes_filled = 4;
5421 : }
5422 : else
5423 : {
5424 : // unknown character
5425 : utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5426 : utf8_bytes_filled = 1;
5427 : }
5428 : }
5429 : }
5430 : };
5431 :
5432 : template<typename BaseInputAdapter>
5433 : struct wide_string_input_helper<BaseInputAdapter, 2>
5434 : {
5435 : // UTF-16
5436 : static void fill_buffer(BaseInputAdapter& input,
5437 : std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
5438 : size_t& utf8_bytes_index,
5439 : size_t& utf8_bytes_filled)
5440 : {
5441 : utf8_bytes_index = 0;
5442 :
5443 : if (JSON_HEDLEY_UNLIKELY(input.empty()))
5444 : {
5445 : utf8_bytes[0] = std::char_traits<char>::eof();
5446 : utf8_bytes_filled = 1;
5447 : }
5448 : else
5449 : {
5450 : // get the current character
5451 : const auto wc = input.get_character();
5452 :
5453 : // UTF-16 to UTF-8 encoding
5454 : if (wc < 0x80)
5455 : {
5456 : utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5457 : utf8_bytes_filled = 1;
5458 : }
5459 : else if (wc <= 0x7FF)
5460 : {
5461 : utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
5462 : utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5463 : utf8_bytes_filled = 2;
5464 : }
5465 : else if (0xD800 > wc || wc >= 0xE000)
5466 : {
5467 : utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
5468 : utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5469 : utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5470 : utf8_bytes_filled = 3;
5471 : }
5472 : else
5473 : {
5474 : if (JSON_HEDLEY_UNLIKELY(!input.empty()))
5475 : {
5476 : const auto wc2 = static_cast<unsigned int>(input.get_character());
5477 : const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
5478 : utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
5479 : utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
5480 : utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
5481 : utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
5482 : utf8_bytes_filled = 4;
5483 : }
5484 : else
5485 : {
5486 : utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5487 : utf8_bytes_filled = 1;
5488 : }
5489 : }
5490 : }
5491 : }
5492 : };
5493 :
5494 : // Wraps another input apdater to convert wide character types into individual bytes.
5495 : template<typename BaseInputAdapter, typename WideCharType>
5496 : class wide_string_input_adapter
5497 : {
5498 : public:
5499 : using char_type = char;
5500 :
5501 : wide_string_input_adapter(BaseInputAdapter base)
5502 : : base_adapter(base) {}
5503 :
5504 : typename std::char_traits<char>::int_type get_character() noexcept
5505 : {
5506 : // check if buffer needs to be filled
5507 : if (utf8_bytes_index == utf8_bytes_filled)
5508 : {
5509 : fill_buffer<sizeof(WideCharType)>();
5510 :
5511 : JSON_ASSERT(utf8_bytes_filled > 0);
5512 : JSON_ASSERT(utf8_bytes_index == 0);
5513 : }
5514 :
5515 : // use buffer
5516 : JSON_ASSERT(utf8_bytes_filled > 0);
5517 : JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
5518 : return utf8_bytes[utf8_bytes_index++];
5519 : }
5520 :
5521 : private:
5522 : BaseInputAdapter base_adapter;
5523 :
5524 : template<size_t T>
5525 : void fill_buffer()
5526 : {
5527 : wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
5528 : }
5529 :
5530 : /// a buffer for UTF-8 bytes
5531 : std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
5532 :
5533 : /// index to the utf8_codes array for the next valid byte
5534 : std::size_t utf8_bytes_index = 0;
5535 : /// number of valid bytes in the utf8_codes array
5536 : std::size_t utf8_bytes_filled = 0;
5537 : };
5538 :
5539 :
5540 : template<typename IteratorType, typename Enable = void>
5541 : struct iterator_input_adapter_factory
5542 : {
5543 : using iterator_type = IteratorType;
5544 : using char_type = typename std::iterator_traits<iterator_type>::value_type;
5545 : using adapter_type = iterator_input_adapter<iterator_type>;
5546 :
5547 : static adapter_type create(IteratorType first, IteratorType last)
5548 : {
5549 : return adapter_type(std::move(first), std::move(last));
5550 : }
5551 : };
5552 :
5553 : template<typename T>
5554 : struct is_iterator_of_multibyte
5555 : {
5556 : using value_type = typename std::iterator_traits<T>::value_type;
5557 : enum
5558 : {
5559 : value = sizeof(value_type) > 1
5560 : };
5561 : };
5562 :
5563 : template<typename IteratorType>
5564 : struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
5565 : {
5566 : using iterator_type = IteratorType;
5567 : using char_type = typename std::iterator_traits<iterator_type>::value_type;
5568 : using base_adapter_type = iterator_input_adapter<iterator_type>;
5569 : using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
5570 :
5571 : static adapter_type create(IteratorType first, IteratorType last)
5572 : {
5573 : return adapter_type(base_adapter_type(std::move(first), std::move(last)));
5574 : }
5575 : };
5576 :
5577 : // General purpose iterator-based input
5578 : template<typename IteratorType>
5579 : typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
5580 : {
5581 : using factory_type = iterator_input_adapter_factory<IteratorType>;
5582 : return factory_type::create(first, last);
5583 : }
5584 :
5585 : // Convenience shorthand from container to iterator
5586 : // Enables ADL on begin(container) and end(container)
5587 : // Encloses the using declarations in namespace for not to leak them to outside scope
5588 :
5589 : namespace container_input_adapter_factory_impl
5590 : {
5591 :
5592 : using std::begin;
5593 : using std::end;
5594 :
5595 : template<typename ContainerType, typename Enable = void>
5596 : struct container_input_adapter_factory {};
5597 :
5598 : template<typename ContainerType>
5599 : struct container_input_adapter_factory< ContainerType,
5600 : void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
5601 : {
5602 : using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
5603 :
5604 : static adapter_type create(const ContainerType& container)
5605 : {
5606 : return input_adapter(begin(container), end(container));
5607 : }
5608 : };
5609 :
5610 : } // namespace container_input_adapter_factory_impl
5611 :
5612 : template<typename ContainerType>
5613 : typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
5614 : {
5615 : return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
5616 : }
5617 :
5618 : #ifndef JSON_NO_IO
5619 : // Special cases with fast paths
5620 : inline file_input_adapter input_adapter(std::FILE* file)
5621 : {
5622 : return file_input_adapter(file);
5623 : }
5624 :
5625 : inline input_stream_adapter input_adapter(std::istream& stream)
5626 : {
5627 : return input_stream_adapter(stream);
5628 : }
5629 :
5630 : inline input_stream_adapter input_adapter(std::istream&& stream)
5631 : {
5632 : return input_stream_adapter(stream);
5633 : }
5634 : #endif // JSON_NO_IO
5635 :
5636 : using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
5637 :
5638 : // Null-delimited strings, and the like.
5639 : template < typename CharT,
5640 : typename std::enable_if <
5641 : std::is_pointer<CharT>::value&&
5642 : !std::is_array<CharT>::value&&
5643 : std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
5644 : sizeof(typename std::remove_pointer<CharT>::type) == 1,
5645 : int >::type = 0 >
5646 : contiguous_bytes_input_adapter input_adapter(CharT b)
5647 : {
5648 : auto length = std::strlen(reinterpret_cast<const char*>(b));
5649 : const auto* ptr = reinterpret_cast<const char*>(b);
5650 : return input_adapter(ptr, ptr + length);
5651 : }
5652 :
5653 : template<typename T, std::size_t N>
5654 : auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5655 : {
5656 : return input_adapter(array, array + N);
5657 : }
5658 :
5659 : // This class only handles inputs of input_buffer_adapter type.
5660 : // It's required so that expressions like {ptr, len} can be implicitly cast
5661 : // to the correct adapter.
5662 : class span_input_adapter
5663 : {
5664 : public:
5665 : template < typename CharT,
5666 : typename std::enable_if <
5667 : std::is_pointer<CharT>::value&&
5668 : std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
5669 : sizeof(typename std::remove_pointer<CharT>::type) == 1,
5670 : int >::type = 0 >
5671 : span_input_adapter(CharT b, std::size_t l)
5672 : : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
5673 :
5674 : template<class IteratorType,
5675 : typename std::enable_if<
5676 : std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
5677 : int>::type = 0>
5678 : span_input_adapter(IteratorType first, IteratorType last)
5679 : : ia(input_adapter(first, last)) {}
5680 :
5681 : contiguous_bytes_input_adapter&& get()
5682 : {
5683 : return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
5684 : }
5685 :
5686 : private:
5687 : contiguous_bytes_input_adapter ia;
5688 : };
5689 : } // namespace detail
5690 : } // namespace nlohmann
5691 :
5692 : // #include <nlohmann/detail/input/json_sax.hpp>
5693 :
5694 :
5695 : #include <cstddef>
5696 : #include <string> // string
5697 : #include <utility> // move
5698 : #include <vector> // vector
5699 :
5700 : // #include <nlohmann/detail/exceptions.hpp>
5701 :
5702 : // #include <nlohmann/detail/macro_scope.hpp>
5703 :
5704 :
5705 : namespace nlohmann
5706 : {
5707 :
5708 : /*!
5709 : @brief SAX interface
5710 :
5711 : This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
5712 : Each function is called in different situations while the input is parsed. The
5713 : boolean return value informs the parser whether to continue processing the
5714 : input.
5715 : */
5716 : template<typename BasicJsonType>
5717 : struct json_sax
5718 : {
5719 : using number_integer_t = typename BasicJsonType::number_integer_t;
5720 : using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5721 : using number_float_t = typename BasicJsonType::number_float_t;
5722 : using string_t = typename BasicJsonType::string_t;
5723 : using binary_t = typename BasicJsonType::binary_t;
5724 :
5725 : /*!
5726 : @brief a null value was read
5727 : @return whether parsing should proceed
5728 : */
5729 : virtual bool null() = 0;
5730 :
5731 : /*!
5732 : @brief a boolean value was read
5733 : @param[in] val boolean value
5734 : @return whether parsing should proceed
5735 : */
5736 : virtual bool boolean(bool val) = 0;
5737 :
5738 : /*!
5739 : @brief an integer number was read
5740 : @param[in] val integer value
5741 : @return whether parsing should proceed
5742 : */
5743 : virtual bool number_integer(number_integer_t val) = 0;
5744 :
5745 : /*!
5746 : @brief an unsigned integer number was read
5747 : @param[in] val unsigned integer value
5748 : @return whether parsing should proceed
5749 : */
5750 : virtual bool number_unsigned(number_unsigned_t val) = 0;
5751 :
5752 : /*!
5753 : @brief a floating-point number was read
5754 : @param[in] val floating-point value
5755 : @param[in] s raw token value
5756 : @return whether parsing should proceed
5757 : */
5758 : virtual bool number_float(number_float_t val, const string_t& s) = 0;
5759 :
5760 : /*!
5761 : @brief a string value was read
5762 : @param[in] val string value
5763 : @return whether parsing should proceed
5764 : @note It is safe to move the passed string value.
5765 : */
5766 : virtual bool string(string_t& val) = 0;
5767 :
5768 : /*!
5769 : @brief a binary value was read
5770 : @param[in] val binary value
5771 : @return whether parsing should proceed
5772 : @note It is safe to move the passed binary value.
5773 : */
5774 : virtual bool binary(binary_t& val) = 0;
5775 :
5776 : /*!
5777 : @brief the beginning of an object was read
5778 : @param[in] elements number of object elements or -1 if unknown
5779 : @return whether parsing should proceed
5780 : @note binary formats may report the number of elements
5781 : */
5782 : virtual bool start_object(std::size_t elements) = 0;
5783 :
5784 : /*!
5785 : @brief an object key was read
5786 : @param[in] val object key
5787 : @return whether parsing should proceed
5788 : @note It is safe to move the passed string.
5789 : */
5790 : virtual bool key(string_t& val) = 0;
5791 :
5792 : /*!
5793 : @brief the end of an object was read
5794 : @return whether parsing should proceed
5795 : */
5796 : virtual bool end_object() = 0;
5797 :
5798 : /*!
5799 : @brief the beginning of an array was read
5800 : @param[in] elements number of array elements or -1 if unknown
5801 : @return whether parsing should proceed
5802 : @note binary formats may report the number of elements
5803 : */
5804 : virtual bool start_array(std::size_t elements) = 0;
5805 :
5806 : /*!
5807 : @brief the end of an array was read
5808 : @return whether parsing should proceed
5809 : */
5810 : virtual bool end_array() = 0;
5811 :
5812 : /*!
5813 : @brief a parse error occurred
5814 : @param[in] position the position in the input where the error occurs
5815 : @param[in] last_token the last read token
5816 : @param[in] ex an exception object describing the error
5817 : @return whether parsing should proceed (must return false)
5818 : */
5819 : virtual bool parse_error(std::size_t position,
5820 : const std::string& last_token,
5821 : const detail::exception& ex) = 0;
5822 :
5823 : json_sax() = default;
5824 : json_sax(const json_sax&) = default;
5825 : json_sax(json_sax&&) noexcept = default;
5826 : json_sax& operator=(const json_sax&) = default;
5827 : json_sax& operator=(json_sax&&) noexcept = default;
5828 : virtual ~json_sax() = default;
5829 : };
5830 :
5831 :
5832 : namespace detail
5833 : {
5834 : /*!
5835 : @brief SAX implementation to create a JSON value from SAX events
5836 :
5837 : This class implements the @ref json_sax interface and processes the SAX events
5838 : to create a JSON value which makes it basically a DOM parser. The structure or
5839 : hierarchy of the JSON value is managed by the stack `ref_stack` which contains
5840 : a pointer to the respective array or object for each recursion depth.
5841 :
5842 : After successful parsing, the value that is passed by reference to the
5843 : constructor contains the parsed value.
5844 :
5845 : @tparam BasicJsonType the JSON type
5846 : */
5847 : template<typename BasicJsonType>
5848 : class json_sax_dom_parser
5849 : {
5850 : public:
5851 : using number_integer_t = typename BasicJsonType::number_integer_t;
5852 : using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5853 : using number_float_t = typename BasicJsonType::number_float_t;
5854 : using string_t = typename BasicJsonType::string_t;
5855 : using binary_t = typename BasicJsonType::binary_t;
5856 :
5857 : /*!
5858 : @param[in,out] r reference to a JSON value that is manipulated while
5859 : parsing
5860 : @param[in] allow_exceptions_ whether parse errors yield exceptions
5861 : */
5862 34 : explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
5863 34 : : root(r), allow_exceptions(allow_exceptions_)
5864 : {}
5865 :
5866 : // make class move-only
5867 : json_sax_dom_parser(const json_sax_dom_parser&) = delete;
5868 : json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
5869 : json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
5870 : json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
5871 34 : ~json_sax_dom_parser() = default;
5872 :
5873 : bool null()
5874 : {
5875 0 : handle_value(nullptr);
5876 : return true;
5877 : }
5878 :
5879 : bool boolean(bool val)
5880 : {
5881 0 : handle_value(val);
5882 : return true;
5883 : }
5884 :
5885 : bool number_integer(number_integer_t val)
5886 : {
5887 8 : handle_value(val);
5888 : return true;
5889 : }
5890 :
5891 : bool number_unsigned(number_unsigned_t val)
5892 : {
5893 200 : handle_value(val);
5894 : return true;
5895 : }
5896 :
5897 : bool number_float(number_float_t val, const string_t& /*unused*/)
5898 : {
5899 4333 : handle_value(val);
5900 : return true;
5901 : }
5902 :
5903 : bool string(string_t& val)
5904 : {
5905 152 : handle_value(val);
5906 : return true;
5907 : }
5908 :
5909 : bool binary(binary_t& val)
5910 : {
5911 : handle_value(std::move(val));
5912 : return true;
5913 : }
5914 :
5915 596 : bool start_object(std::size_t len)
5916 : {
5917 596 : ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
5918 :
5919 596 : if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
5920 : {
5921 0 : JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
5922 : }
5923 :
5924 596 : return true;
5925 : }
5926 :
5927 : bool key(string_t& val)
5928 : {
5929 : // add null at given key and store the reference for later
5930 1998 : object_element = &(ref_stack.back()->m_value.object->operator[](val));
5931 : return true;
5932 : }
5933 :
5934 : bool end_object()
5935 : {
5936 : ref_stack.back()->set_parents();
5937 : ref_stack.pop_back();
5938 : return true;
5939 : }
5940 :
5941 620 : bool start_array(std::size_t len)
5942 : {
5943 620 : ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
5944 :
5945 620 : if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
5946 : {
5947 0 : JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
5948 : }
5949 :
5950 620 : return true;
5951 : }
5952 :
5953 : bool end_array()
5954 : {
5955 : ref_stack.back()->set_parents();
5956 : ref_stack.pop_back();
5957 : return true;
5958 : }
5959 :
5960 : template<class Exception>
5961 0 : bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
5962 : const Exception& ex)
5963 : {
5964 0 : errored = true;
5965 : static_cast<void>(ex);
5966 0 : if (allow_exceptions)
5967 : {
5968 0 : JSON_THROW(ex);
5969 : }
5970 0 : return false;
5971 : }
5972 :
5973 : constexpr bool is_errored() const
5974 : {
5975 34 : return errored;
5976 : }
5977 :
5978 : private:
5979 : /*!
5980 : @invariant If the ref stack is empty, then the passed value will be the new
5981 : root.
5982 : @invariant If the ref stack contains a value, then it is an array or an
5983 : object to which we can add elements
5984 : */
5985 : template<typename Value>
5986 : JSON_HEDLEY_RETURNS_NON_NULL
5987 5909 : BasicJsonType* handle_value(Value&& v)
5988 : {
5989 5909 : if (ref_stack.empty())
5990 : {
5991 34 : root = BasicJsonType(std::forward<Value>(v));
5992 34 : return &root;
5993 : }
5994 :
5995 : JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
5996 :
5997 5875 : if (ref_stack.back()->is_array())
5998 : {
5999 3877 : ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
6000 3877 : return &(ref_stack.back()->m_value.array->back());
6001 : }
6002 :
6003 : JSON_ASSERT(ref_stack.back()->is_object());
6004 : JSON_ASSERT(object_element);
6005 1998 : *object_element = BasicJsonType(std::forward<Value>(v));
6006 1998 : return object_element;
6007 : }
6008 :
6009 : /// the parsed JSON value
6010 : BasicJsonType& root;
6011 : /// stack to model hierarchy of values
6012 : std::vector<BasicJsonType*> ref_stack {};
6013 : /// helper to hold the reference for the next object element
6014 : BasicJsonType* object_element = nullptr;
6015 : /// whether a syntax error occurred
6016 : bool errored = false;
6017 : /// whether to throw exceptions in case of errors
6018 : const bool allow_exceptions = true;
6019 : };
6020 :
6021 : template<typename BasicJsonType>
6022 : class json_sax_dom_callback_parser
6023 : {
6024 : public:
6025 : using number_integer_t = typename BasicJsonType::number_integer_t;
6026 : using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6027 : using number_float_t = typename BasicJsonType::number_float_t;
6028 : using string_t = typename BasicJsonType::string_t;
6029 : using binary_t = typename BasicJsonType::binary_t;
6030 : using parser_callback_t = typename BasicJsonType::parser_callback_t;
6031 : using parse_event_t = typename BasicJsonType::parse_event_t;
6032 :
6033 0 : json_sax_dom_callback_parser(BasicJsonType& r,
6034 : const parser_callback_t cb,
6035 : const bool allow_exceptions_ = true)
6036 0 : : root(r), callback(cb), allow_exceptions(allow_exceptions_)
6037 : {
6038 0 : keep_stack.push_back(true);
6039 0 : }
6040 :
6041 : // make class move-only
6042 : json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
6043 : json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6044 : json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
6045 : json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6046 0 : ~json_sax_dom_callback_parser() = default;
6047 :
6048 : bool null()
6049 : {
6050 0 : handle_value(nullptr);
6051 : return true;
6052 : }
6053 :
6054 : bool boolean(bool val)
6055 : {
6056 0 : handle_value(val);
6057 : return true;
6058 : }
6059 :
6060 : bool number_integer(number_integer_t val)
6061 : {
6062 0 : handle_value(val);
6063 : return true;
6064 : }
6065 :
6066 : bool number_unsigned(number_unsigned_t val)
6067 : {
6068 0 : handle_value(val);
6069 : return true;
6070 : }
6071 :
6072 : bool number_float(number_float_t val, const string_t& /*unused*/)
6073 : {
6074 0 : handle_value(val);
6075 : return true;
6076 : }
6077 :
6078 : bool string(string_t& val)
6079 : {
6080 0 : handle_value(val);
6081 : return true;
6082 : }
6083 :
6084 : bool binary(binary_t& val)
6085 : {
6086 : handle_value(std::move(val));
6087 : return true;
6088 : }
6089 :
6090 0 : bool start_object(std::size_t len)
6091 : {
6092 : // check callback for object start
6093 0 : const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
6094 0 : keep_stack.push_back(keep);
6095 :
6096 0 : auto val = handle_value(BasicJsonType::value_t::object, true);
6097 0 : ref_stack.push_back(val.second);
6098 :
6099 : // check object limit
6100 0 : if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6101 : {
6102 0 : JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
6103 : }
6104 :
6105 0 : return true;
6106 : }
6107 :
6108 0 : bool key(string_t& val)
6109 : {
6110 : BasicJsonType k = BasicJsonType(val);
6111 :
6112 : // check callback for key
6113 0 : const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
6114 0 : key_keep_stack.push_back(keep);
6115 :
6116 : // add discarded value at given key and store the reference for later
6117 0 : if (keep && ref_stack.back())
6118 : {
6119 0 : object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
6120 : }
6121 :
6122 0 : return true;
6123 : }
6124 :
6125 0 : bool end_object()
6126 : {
6127 0 : if (ref_stack.back())
6128 : {
6129 0 : if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
6130 : {
6131 : // discard object
6132 0 : *ref_stack.back() = discarded;
6133 : }
6134 : else
6135 : {
6136 : ref_stack.back()->set_parents();
6137 : }
6138 : }
6139 :
6140 : JSON_ASSERT(!ref_stack.empty());
6141 : JSON_ASSERT(!keep_stack.empty());
6142 : ref_stack.pop_back();
6143 : keep_stack.pop_back();
6144 :
6145 0 : if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
6146 : {
6147 : // remove discarded value
6148 0 : for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
6149 : {
6150 0 : if (it->is_discarded())
6151 : {
6152 0 : ref_stack.back()->erase(it);
6153 0 : break;
6154 : }
6155 : }
6156 : }
6157 :
6158 0 : return true;
6159 : }
6160 :
6161 0 : bool start_array(std::size_t len)
6162 : {
6163 0 : const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
6164 0 : keep_stack.push_back(keep);
6165 :
6166 0 : auto val = handle_value(BasicJsonType::value_t::array, true);
6167 0 : ref_stack.push_back(val.second);
6168 :
6169 : // check array limit
6170 0 : if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6171 : {
6172 0 : JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
6173 : }
6174 :
6175 0 : return true;
6176 : }
6177 :
6178 0 : bool end_array()
6179 : {
6180 : bool keep = true;
6181 :
6182 0 : if (ref_stack.back())
6183 : {
6184 0 : keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
6185 0 : if (keep)
6186 : {
6187 : ref_stack.back()->set_parents();
6188 : }
6189 : else
6190 : {
6191 : // discard array
6192 0 : *ref_stack.back() = discarded;
6193 : }
6194 : }
6195 :
6196 : JSON_ASSERT(!ref_stack.empty());
6197 : JSON_ASSERT(!keep_stack.empty());
6198 : ref_stack.pop_back();
6199 : keep_stack.pop_back();
6200 :
6201 : // remove discarded value
6202 0 : if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
6203 : {
6204 0 : ref_stack.back()->m_value.array->pop_back();
6205 : }
6206 :
6207 0 : return true;
6208 : }
6209 :
6210 : template<class Exception>
6211 0 : bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
6212 : const Exception& ex)
6213 : {
6214 0 : errored = true;
6215 : static_cast<void>(ex);
6216 0 : if (allow_exceptions)
6217 : {
6218 0 : JSON_THROW(ex);
6219 : }
6220 0 : return false;
6221 : }
6222 :
6223 : constexpr bool is_errored() const
6224 : {
6225 0 : return errored;
6226 : }
6227 :
6228 : private:
6229 : /*!
6230 : @param[in] v value to add to the JSON value we build during parsing
6231 : @param[in] skip_callback whether we should skip calling the callback
6232 : function; this is required after start_array() and
6233 : start_object() SAX events, because otherwise we would call the
6234 : callback function with an empty array or object, respectively.
6235 :
6236 : @invariant If the ref stack is empty, then the passed value will be the new
6237 : root.
6238 : @invariant If the ref stack contains a value, then it is an array or an
6239 : object to which we can add elements
6240 :
6241 : @return pair of boolean (whether value should be kept) and pointer (to the
6242 : passed value in the ref_stack hierarchy; nullptr if not kept)
6243 : */
6244 : template<typename Value>
6245 0 : std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
6246 : {
6247 : JSON_ASSERT(!keep_stack.empty());
6248 :
6249 : // do not handle this value if we know it would be added to a discarded
6250 : // container
6251 0 : if (!keep_stack.back())
6252 : {
6253 0 : return {false, nullptr};
6254 : }
6255 :
6256 : // create value
6257 0 : auto value = BasicJsonType(std::forward<Value>(v));
6258 :
6259 : // check callback
6260 0 : const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
6261 :
6262 : // do not handle this value if we just learnt it shall be discarded
6263 : if (!keep)
6264 : {
6265 0 : return {false, nullptr};
6266 : }
6267 :
6268 0 : if (ref_stack.empty())
6269 : {
6270 0 : root = std::move(value);
6271 0 : return {true, &root};
6272 : }
6273 :
6274 : // skip this value if we already decided to skip the parent
6275 : // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
6276 0 : if (!ref_stack.back())
6277 : {
6278 0 : return {false, nullptr};
6279 : }
6280 :
6281 : // we now only expect arrays and objects
6282 : JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6283 :
6284 : // array
6285 0 : if (ref_stack.back()->is_array())
6286 : {
6287 0 : ref_stack.back()->m_value.array->emplace_back(std::move(value));
6288 0 : return {true, &(ref_stack.back()->m_value.array->back())};
6289 : }
6290 :
6291 : // object
6292 : JSON_ASSERT(ref_stack.back()->is_object());
6293 : // check if we should store an element for the current key
6294 : JSON_ASSERT(!key_keep_stack.empty());
6295 : const bool store_element = key_keep_stack.back();
6296 : key_keep_stack.pop_back();
6297 :
6298 0 : if (!store_element)
6299 : {
6300 0 : return {false, nullptr};
6301 : }
6302 :
6303 : JSON_ASSERT(object_element);
6304 0 : *object_element = std::move(value);
6305 0 : return {true, object_element};
6306 : }
6307 :
6308 : /// the parsed JSON value
6309 : BasicJsonType& root;
6310 : /// stack to model hierarchy of values
6311 : std::vector<BasicJsonType*> ref_stack {};
6312 : /// stack to manage which values to keep
6313 : std::vector<bool> keep_stack {};
6314 : /// stack to manage which object keys to keep
6315 : std::vector<bool> key_keep_stack {};
6316 : /// helper to hold the reference for the next object element
6317 : BasicJsonType* object_element = nullptr;
6318 : /// whether a syntax error occurred
6319 : bool errored = false;
6320 : /// callback function
6321 : const parser_callback_t callback = nullptr;
6322 : /// whether to throw exceptions in case of errors
6323 : const bool allow_exceptions = true;
6324 : /// a discarded value for the callback
6325 : BasicJsonType discarded = BasicJsonType::value_t::discarded;
6326 : };
6327 :
6328 : template<typename BasicJsonType>
6329 : class json_sax_acceptor
6330 : {
6331 : public:
6332 : using number_integer_t = typename BasicJsonType::number_integer_t;
6333 : using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6334 : using number_float_t = typename BasicJsonType::number_float_t;
6335 : using string_t = typename BasicJsonType::string_t;
6336 : using binary_t = typename BasicJsonType::binary_t;
6337 :
6338 : bool null()
6339 : {
6340 : return true;
6341 : }
6342 :
6343 : bool boolean(bool /*unused*/)
6344 : {
6345 : return true;
6346 : }
6347 :
6348 : bool number_integer(number_integer_t /*unused*/)
6349 : {
6350 : return true;
6351 : }
6352 :
6353 : bool number_unsigned(number_unsigned_t /*unused*/)
6354 : {
6355 : return true;
6356 : }
6357 :
6358 : bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
6359 : {
6360 : return true;
6361 : }
6362 :
6363 : bool string(string_t& /*unused*/)
6364 : {
6365 : return true;
6366 : }
6367 :
6368 : bool binary(binary_t& /*unused*/)
6369 : {
6370 : return true;
6371 : }
6372 :
6373 : bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
6374 : {
6375 : return true;
6376 : }
6377 :
6378 : bool key(string_t& /*unused*/)
6379 : {
6380 : return true;
6381 : }
6382 :
6383 : bool end_object()
6384 : {
6385 : return true;
6386 : }
6387 :
6388 : bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
6389 : {
6390 : return true;
6391 : }
6392 :
6393 : bool end_array()
6394 : {
6395 : return true;
6396 : }
6397 :
6398 : bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
6399 : {
6400 : return false;
6401 : }
6402 : };
6403 : } // namespace detail
6404 :
6405 : } // namespace nlohmann
6406 :
6407 : // #include <nlohmann/detail/input/lexer.hpp>
6408 :
6409 :
6410 : #include <array> // array
6411 : #include <clocale> // localeconv
6412 : #include <cstddef> // size_t
6413 : #include <cstdio> // snprintf
6414 : #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
6415 : #include <initializer_list> // initializer_list
6416 : #include <string> // char_traits, string
6417 : #include <utility> // move
6418 : #include <vector> // vector
6419 :
6420 : // #include <nlohmann/detail/input/input_adapters.hpp>
6421 :
6422 : // #include <nlohmann/detail/input/position_t.hpp>
6423 :
6424 : // #include <nlohmann/detail/macro_scope.hpp>
6425 :
6426 :
6427 : namespace nlohmann
6428 : {
6429 : namespace detail
6430 : {
6431 : ///////////
6432 : // lexer //
6433 : ///////////
6434 :
6435 : template<typename BasicJsonType>
6436 : class lexer_base
6437 : {
6438 : public:
6439 : /// token types for the parser
6440 : enum class token_type
6441 : {
6442 : uninitialized, ///< indicating the scanner is uninitialized
6443 : literal_true, ///< the `true` literal
6444 : literal_false, ///< the `false` literal
6445 : literal_null, ///< the `null` literal
6446 : value_string, ///< a string -- use get_string() for actual value
6447 : value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
6448 : value_integer, ///< a signed integer -- use get_number_integer() for actual value
6449 : value_float, ///< an floating point number -- use get_number_float() for actual value
6450 : begin_array, ///< the character for array begin `[`
6451 : begin_object, ///< the character for object begin `{`
6452 : end_array, ///< the character for array end `]`
6453 : end_object, ///< the character for object end `}`
6454 : name_separator, ///< the name separator `:`
6455 : value_separator, ///< the value separator `,`
6456 : parse_error, ///< indicating a parse error
6457 : end_of_input, ///< indicating the end of the input buffer
6458 : literal_or_value ///< a literal or the begin of a value (only for diagnostics)
6459 : };
6460 :
6461 : /// return name of values of type token_type (only used for errors)
6462 : JSON_HEDLEY_RETURNS_NON_NULL
6463 : JSON_HEDLEY_CONST
6464 0 : static const char* token_type_name(const token_type t) noexcept
6465 : {
6466 0 : switch (t)
6467 : {
6468 : case token_type::uninitialized:
6469 : return "<uninitialized>";
6470 0 : case token_type::literal_true:
6471 0 : return "true literal";
6472 0 : case token_type::literal_false:
6473 0 : return "false literal";
6474 0 : case token_type::literal_null:
6475 0 : return "null literal";
6476 0 : case token_type::value_string:
6477 0 : return "string literal";
6478 0 : case token_type::value_unsigned:
6479 : case token_type::value_integer:
6480 : case token_type::value_float:
6481 0 : return "number literal";
6482 0 : case token_type::begin_array:
6483 0 : return "'['";
6484 0 : case token_type::begin_object:
6485 0 : return "'{'";
6486 0 : case token_type::end_array:
6487 0 : return "']'";
6488 0 : case token_type::end_object:
6489 0 : return "'}'";
6490 0 : case token_type::name_separator:
6491 0 : return "':'";
6492 0 : case token_type::value_separator:
6493 0 : return "','";
6494 0 : case token_type::parse_error:
6495 0 : return "<parse error>";
6496 0 : case token_type::end_of_input:
6497 0 : return "end of input";
6498 0 : case token_type::literal_or_value:
6499 0 : return "'[', '{', or a literal";
6500 : // LCOV_EXCL_START
6501 : default: // catch non-enum values
6502 : return "unknown token";
6503 : // LCOV_EXCL_STOP
6504 : }
6505 : }
6506 : };
6507 : /*!
6508 : @brief lexical analysis
6509 :
6510 : This class organizes the lexical analysis during JSON deserialization.
6511 : */
6512 : template<typename BasicJsonType, typename InputAdapterType>
6513 : class lexer : public lexer_base<BasicJsonType>
6514 : {
6515 : using number_integer_t = typename BasicJsonType::number_integer_t;
6516 : using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6517 : using number_float_t = typename BasicJsonType::number_float_t;
6518 : using string_t = typename BasicJsonType::string_t;
6519 : using char_type = typename InputAdapterType::char_type;
6520 : using char_int_type = typename std::char_traits<char_type>::int_type;
6521 :
6522 : public:
6523 : using token_type = typename lexer_base<BasicJsonType>::token_type;
6524 :
6525 34 : explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
6526 : : ia(std::move(adapter))
6527 34 : , ignore_comments(ignore_comments_)
6528 34 : , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
6529 34 : {}
6530 :
6531 : // delete because of pointer members
6532 : lexer(const lexer&) = delete;
6533 : lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6534 : lexer& operator=(lexer&) = delete;
6535 : lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6536 34 : ~lexer() = default;
6537 :
6538 : private:
6539 : /////////////////////
6540 : // locales
6541 : /////////////////////
6542 :
6543 : /// return the locale-dependent decimal point
6544 : JSON_HEDLEY_PURE
6545 : static char get_decimal_point() noexcept
6546 : {
6547 34 : const auto* loc = localeconv();
6548 : JSON_ASSERT(loc != nullptr);
6549 34 : return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
6550 : }
6551 :
6552 : /////////////////////
6553 : // scan functions
6554 : /////////////////////
6555 :
6556 : /*!
6557 : @brief get codepoint from 4 hex characters following `\u`
6558 :
6559 : For input "\u c1 c2 c3 c4" the codepoint is:
6560 : (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
6561 : = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
6562 :
6563 : Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
6564 : must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
6565 : conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
6566 : between the ASCII value of the character and the desired integer value.
6567 :
6568 : @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
6569 : non-hex character)
6570 : */
6571 0 : int get_codepoint()
6572 : {
6573 : // this function only makes sense after reading `\u`
6574 : JSON_ASSERT(current == 'u');
6575 : int codepoint = 0;
6576 :
6577 0 : const auto factors = { 12u, 8u, 4u, 0u };
6578 0 : for (const auto factor : factors)
6579 : {
6580 0 : get();
6581 :
6582 0 : if (current >= '0' && current <= '9')
6583 : {
6584 0 : codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
6585 : }
6586 0 : else if (current >= 'A' && current <= 'F')
6587 : {
6588 0 : codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
6589 : }
6590 0 : else if (current >= 'a' && current <= 'f')
6591 : {
6592 0 : codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
6593 : }
6594 : else
6595 : {
6596 : return -1;
6597 : }
6598 : }
6599 :
6600 : JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
6601 : return codepoint;
6602 : }
6603 :
6604 : /*!
6605 : @brief check if the next byte(s) are inside a given range
6606 :
6607 : Adds the current byte and, for each passed range, reads a new byte and
6608 : checks if it is inside the range. If a violation was detected, set up an
6609 : error message and return false. Otherwise, return true.
6610 :
6611 : @param[in] ranges list of integers; interpreted as list of pairs of
6612 : inclusive lower and upper bound, respectively
6613 :
6614 : @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
6615 : 1, 2, or 3 pairs. This precondition is enforced by an assertion.
6616 :
6617 : @return true if and only if no range violation was detected
6618 : */
6619 0 : bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
6620 : {
6621 : JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
6622 0 : add(current);
6623 :
6624 0 : for (auto range = ranges.begin(); range != ranges.end(); ++range)
6625 : {
6626 0 : get();
6627 0 : if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
6628 : {
6629 : add(current);
6630 : }
6631 : else
6632 : {
6633 0 : error_message = "invalid string: ill-formed UTF-8 byte";
6634 0 : return false;
6635 : }
6636 : }
6637 :
6638 : return true;
6639 : }
6640 :
6641 : /*!
6642 : @brief scan a string literal
6643 :
6644 : This function scans a string according to Sect. 7 of RFC 8259. While
6645 : scanning, bytes are escaped and copied into buffer token_buffer. Then the
6646 : function returns successfully, token_buffer is *not* null-terminated (as it
6647 : may contain \0 bytes), and token_buffer.size() is the number of bytes in the
6648 : string.
6649 :
6650 : @return token_type::value_string if string could be successfully scanned,
6651 : token_type::parse_error otherwise
6652 :
6653 : @note In case of errors, variable error_message contains a textual
6654 : description.
6655 : */
6656 2150 : token_type scan_string()
6657 : {
6658 : // reset token_buffer (ignore opening quote)
6659 2150 : reset();
6660 :
6661 : // we entered the function by reading an open quote
6662 : JSON_ASSERT(current == '\"');
6663 :
6664 : while (true)
6665 : {
6666 : // get next character
6667 16918 : switch (get())
6668 : {
6669 : // end of file while parsing string
6670 0 : case std::char_traits<char_type>::eof():
6671 : {
6672 0 : error_message = "invalid string: missing closing quote";
6673 0 : return token_type::parse_error;
6674 : }
6675 :
6676 : // closing quote
6677 : case '\"':
6678 : {
6679 : return token_type::value_string;
6680 : }
6681 :
6682 : // escapes
6683 0 : case '\\':
6684 : {
6685 0 : switch (get())
6686 : {
6687 : // quotation mark
6688 : case '\"':
6689 : add('\"');
6690 : break;
6691 : // reverse solidus
6692 : case '\\':
6693 : add('\\');
6694 : break;
6695 : // solidus
6696 : case '/':
6697 : add('/');
6698 : break;
6699 : // backspace
6700 : case 'b':
6701 : add('\b');
6702 : break;
6703 : // form feed
6704 : case 'f':
6705 : add('\f');
6706 : break;
6707 : // line feed
6708 : case 'n':
6709 : add('\n');
6710 : break;
6711 : // carriage return
6712 : case 'r':
6713 : add('\r');
6714 : break;
6715 : // tab
6716 : case 't':
6717 : add('\t');
6718 : break;
6719 :
6720 : // unicode escapes
6721 0 : case 'u':
6722 : {
6723 0 : const int codepoint1 = get_codepoint();
6724 : int codepoint = codepoint1; // start with codepoint1
6725 :
6726 0 : if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
6727 : {
6728 0 : error_message = "invalid string: '\\u' must be followed by 4 hex digits";
6729 0 : return token_type::parse_error;
6730 : }
6731 :
6732 : // check if code point is a high surrogate
6733 0 : if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
6734 : {
6735 : // expect next \uxxxx entry
6736 0 : if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
6737 : {
6738 0 : const int codepoint2 = get_codepoint();
6739 :
6740 0 : if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
6741 : {
6742 0 : error_message = "invalid string: '\\u' must be followed by 4 hex digits";
6743 0 : return token_type::parse_error;
6744 : }
6745 :
6746 : // check if codepoint2 is a low surrogate
6747 0 : if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
6748 : {
6749 : // overwrite codepoint
6750 0 : codepoint = static_cast<int>(
6751 : // high surrogate occupies the most significant 22 bits
6752 0 : (static_cast<unsigned int>(codepoint1) << 10u)
6753 : // low surrogate occupies the least significant 15 bits
6754 0 : + static_cast<unsigned int>(codepoint2)
6755 : // there is still the 0xD800, 0xDC00 and 0x10000 noise
6756 : // in the result, so we have to subtract with:
6757 : // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6758 0 : - 0x35FDC00u);
6759 : }
6760 : else
6761 : {
6762 0 : error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
6763 0 : return token_type::parse_error;
6764 : }
6765 : }
6766 : else
6767 : {
6768 0 : error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
6769 0 : return token_type::parse_error;
6770 : }
6771 : }
6772 : else
6773 : {
6774 0 : if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
6775 : {
6776 0 : error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
6777 0 : return token_type::parse_error;
6778 : }
6779 : }
6780 :
6781 : // result of the above calculation yields a proper codepoint
6782 : JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
6783 :
6784 : // translate codepoint into bytes
6785 0 : if (codepoint < 0x80)
6786 : {
6787 : // 1-byte characters: 0xxxxxxx (ASCII)
6788 : add(static_cast<char_int_type>(codepoint));
6789 : }
6790 0 : else if (codepoint <= 0x7FF)
6791 : {
6792 : // 2-byte characters: 110xxxxx 10xxxxxx
6793 0 : add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
6794 : add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6795 : }
6796 0 : else if (codepoint <= 0xFFFF)
6797 : {
6798 : // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6799 0 : add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
6800 0 : add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
6801 : add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6802 : }
6803 : else
6804 : {
6805 : // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6806 0 : add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
6807 0 : add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
6808 0 : add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
6809 : add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6810 : }
6811 :
6812 : break;
6813 : }
6814 :
6815 : // other characters after escape
6816 0 : default:
6817 0 : error_message = "invalid string: forbidden character after backslash";
6818 0 : return token_type::parse_error;
6819 : }
6820 :
6821 : break;
6822 : }
6823 :
6824 : // invalid control characters
6825 0 : case 0x00:
6826 : {
6827 0 : error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
6828 0 : return token_type::parse_error;
6829 : }
6830 :
6831 0 : case 0x01:
6832 : {
6833 0 : error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
6834 0 : return token_type::parse_error;
6835 : }
6836 :
6837 0 : case 0x02:
6838 : {
6839 0 : error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
6840 0 : return token_type::parse_error;
6841 : }
6842 :
6843 0 : case 0x03:
6844 : {
6845 0 : error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
6846 0 : return token_type::parse_error;
6847 : }
6848 :
6849 0 : case 0x04:
6850 : {
6851 0 : error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
6852 0 : return token_type::parse_error;
6853 : }
6854 :
6855 0 : case 0x05:
6856 : {
6857 0 : error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
6858 0 : return token_type::parse_error;
6859 : }
6860 :
6861 0 : case 0x06:
6862 : {
6863 0 : error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
6864 0 : return token_type::parse_error;
6865 : }
6866 :
6867 0 : case 0x07:
6868 : {
6869 0 : error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
6870 0 : return token_type::parse_error;
6871 : }
6872 :
6873 0 : case 0x08:
6874 : {
6875 0 : error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
6876 0 : return token_type::parse_error;
6877 : }
6878 :
6879 0 : case 0x09:
6880 : {
6881 0 : error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
6882 0 : return token_type::parse_error;
6883 : }
6884 :
6885 0 : case 0x0A:
6886 : {
6887 0 : error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
6888 0 : return token_type::parse_error;
6889 : }
6890 :
6891 0 : case 0x0B:
6892 : {
6893 0 : error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
6894 0 : return token_type::parse_error;
6895 : }
6896 :
6897 0 : case 0x0C:
6898 : {
6899 0 : error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
6900 0 : return token_type::parse_error;
6901 : }
6902 :
6903 0 : case 0x0D:
6904 : {
6905 0 : error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
6906 0 : return token_type::parse_error;
6907 : }
6908 :
6909 0 : case 0x0E:
6910 : {
6911 0 : error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
6912 0 : return token_type::parse_error;
6913 : }
6914 :
6915 0 : case 0x0F:
6916 : {
6917 0 : error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
6918 0 : return token_type::parse_error;
6919 : }
6920 :
6921 0 : case 0x10:
6922 : {
6923 0 : error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
6924 0 : return token_type::parse_error;
6925 : }
6926 :
6927 0 : case 0x11:
6928 : {
6929 0 : error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
6930 0 : return token_type::parse_error;
6931 : }
6932 :
6933 0 : case 0x12:
6934 : {
6935 0 : error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
6936 0 : return token_type::parse_error;
6937 : }
6938 :
6939 0 : case 0x13:
6940 : {
6941 0 : error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
6942 0 : return token_type::parse_error;
6943 : }
6944 :
6945 0 : case 0x14:
6946 : {
6947 0 : error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
6948 0 : return token_type::parse_error;
6949 : }
6950 :
6951 0 : case 0x15:
6952 : {
6953 0 : error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
6954 0 : return token_type::parse_error;
6955 : }
6956 :
6957 0 : case 0x16:
6958 : {
6959 0 : error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
6960 0 : return token_type::parse_error;
6961 : }
6962 :
6963 0 : case 0x17:
6964 : {
6965 0 : error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
6966 0 : return token_type::parse_error;
6967 : }
6968 :
6969 0 : case 0x18:
6970 : {
6971 0 : error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
6972 0 : return token_type::parse_error;
6973 : }
6974 :
6975 0 : case 0x19:
6976 : {
6977 0 : error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
6978 0 : return token_type::parse_error;
6979 : }
6980 :
6981 0 : case 0x1A:
6982 : {
6983 0 : error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
6984 0 : return token_type::parse_error;
6985 : }
6986 :
6987 0 : case 0x1B:
6988 : {
6989 0 : error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
6990 0 : return token_type::parse_error;
6991 : }
6992 :
6993 0 : case 0x1C:
6994 : {
6995 0 : error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
6996 0 : return token_type::parse_error;
6997 : }
6998 :
6999 0 : case 0x1D:
7000 : {
7001 0 : error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7002 0 : return token_type::parse_error;
7003 : }
7004 :
7005 0 : case 0x1E:
7006 : {
7007 0 : error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7008 0 : return token_type::parse_error;
7009 : }
7010 :
7011 0 : case 0x1F:
7012 : {
7013 0 : error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7014 0 : return token_type::parse_error;
7015 : }
7016 :
7017 : // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7018 14768 : case 0x20:
7019 : case 0x21:
7020 : case 0x23:
7021 : case 0x24:
7022 : case 0x25:
7023 : case 0x26:
7024 : case 0x27:
7025 : case 0x28:
7026 : case 0x29:
7027 : case 0x2A:
7028 : case 0x2B:
7029 : case 0x2C:
7030 : case 0x2D:
7031 : case 0x2E:
7032 : case 0x2F:
7033 : case 0x30:
7034 : case 0x31:
7035 : case 0x32:
7036 : case 0x33:
7037 : case 0x34:
7038 : case 0x35:
7039 : case 0x36:
7040 : case 0x37:
7041 : case 0x38:
7042 : case 0x39:
7043 : case 0x3A:
7044 : case 0x3B:
7045 : case 0x3C:
7046 : case 0x3D:
7047 : case 0x3E:
7048 : case 0x3F:
7049 : case 0x40:
7050 : case 0x41:
7051 : case 0x42:
7052 : case 0x43:
7053 : case 0x44:
7054 : case 0x45:
7055 : case 0x46:
7056 : case 0x47:
7057 : case 0x48:
7058 : case 0x49:
7059 : case 0x4A:
7060 : case 0x4B:
7061 : case 0x4C:
7062 : case 0x4D:
7063 : case 0x4E:
7064 : case 0x4F:
7065 : case 0x50:
7066 : case 0x51:
7067 : case 0x52:
7068 : case 0x53:
7069 : case 0x54:
7070 : case 0x55:
7071 : case 0x56:
7072 : case 0x57:
7073 : case 0x58:
7074 : case 0x59:
7075 : case 0x5A:
7076 : case 0x5B:
7077 : case 0x5D:
7078 : case 0x5E:
7079 : case 0x5F:
7080 : case 0x60:
7081 : case 0x61:
7082 : case 0x62:
7083 : case 0x63:
7084 : case 0x64:
7085 : case 0x65:
7086 : case 0x66:
7087 : case 0x67:
7088 : case 0x68:
7089 : case 0x69:
7090 : case 0x6A:
7091 : case 0x6B:
7092 : case 0x6C:
7093 : case 0x6D:
7094 : case 0x6E:
7095 : case 0x6F:
7096 : case 0x70:
7097 : case 0x71:
7098 : case 0x72:
7099 : case 0x73:
7100 : case 0x74:
7101 : case 0x75:
7102 : case 0x76:
7103 : case 0x77:
7104 : case 0x78:
7105 : case 0x79:
7106 : case 0x7A:
7107 : case 0x7B:
7108 : case 0x7C:
7109 : case 0x7D:
7110 : case 0x7E:
7111 : case 0x7F:
7112 : {
7113 14768 : add(current);
7114 : break;
7115 : }
7116 :
7117 : // U+0080..U+07FF: bytes C2..DF 80..BF
7118 0 : case 0xC2:
7119 : case 0xC3:
7120 : case 0xC4:
7121 : case 0xC5:
7122 : case 0xC6:
7123 : case 0xC7:
7124 : case 0xC8:
7125 : case 0xC9:
7126 : case 0xCA:
7127 : case 0xCB:
7128 : case 0xCC:
7129 : case 0xCD:
7130 : case 0xCE:
7131 : case 0xCF:
7132 : case 0xD0:
7133 : case 0xD1:
7134 : case 0xD2:
7135 : case 0xD3:
7136 : case 0xD4:
7137 : case 0xD5:
7138 : case 0xD6:
7139 : case 0xD7:
7140 : case 0xD8:
7141 : case 0xD9:
7142 : case 0xDA:
7143 : case 0xDB:
7144 : case 0xDC:
7145 : case 0xDD:
7146 : case 0xDE:
7147 : case 0xDF:
7148 : {
7149 0 : if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
7150 : {
7151 : return token_type::parse_error;
7152 : }
7153 : break;
7154 : }
7155 :
7156 : // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7157 0 : case 0xE0:
7158 : {
7159 0 : if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7160 : {
7161 : return token_type::parse_error;
7162 : }
7163 : break;
7164 : }
7165 :
7166 : // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7167 : // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7168 0 : case 0xE1:
7169 : case 0xE2:
7170 : case 0xE3:
7171 : case 0xE4:
7172 : case 0xE5:
7173 : case 0xE6:
7174 : case 0xE7:
7175 : case 0xE8:
7176 : case 0xE9:
7177 : case 0xEA:
7178 : case 0xEB:
7179 : case 0xEC:
7180 : case 0xEE:
7181 : case 0xEF:
7182 : {
7183 0 : if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7184 : {
7185 : return token_type::parse_error;
7186 : }
7187 : break;
7188 : }
7189 :
7190 : // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7191 0 : case 0xED:
7192 : {
7193 0 : if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7194 : {
7195 : return token_type::parse_error;
7196 : }
7197 : break;
7198 : }
7199 :
7200 : // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7201 0 : case 0xF0:
7202 : {
7203 0 : if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7204 : {
7205 : return token_type::parse_error;
7206 : }
7207 : break;
7208 : }
7209 :
7210 : // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7211 0 : case 0xF1:
7212 : case 0xF2:
7213 : case 0xF3:
7214 : {
7215 0 : if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7216 : {
7217 : return token_type::parse_error;
7218 : }
7219 : break;
7220 : }
7221 :
7222 : // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7223 0 : case 0xF4:
7224 : {
7225 0 : if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
7226 : {
7227 : return token_type::parse_error;
7228 : }
7229 : break;
7230 : }
7231 :
7232 : // remaining bytes (80..C1 and F5..FF) are ill-formed
7233 0 : default:
7234 : {
7235 0 : error_message = "invalid string: ill-formed UTF-8 byte";
7236 0 : return token_type::parse_error;
7237 : }
7238 : }
7239 : }
7240 : }
7241 :
7242 : /*!
7243 : * @brief scan a comment
7244 : * @return whether comment could be scanned successfully
7245 : */
7246 0 : bool scan_comment()
7247 : {
7248 0 : switch (get())
7249 : {
7250 : // single-line comments skip input until a newline or EOF is read
7251 0 : case '/':
7252 : {
7253 : while (true)
7254 : {
7255 0 : switch (get())
7256 : {
7257 : case '\n':
7258 : case '\r':
7259 : case std::char_traits<char_type>::eof():
7260 : case '\0':
7261 : return true;
7262 :
7263 : default:
7264 : break;
7265 : }
7266 : }
7267 : }
7268 :
7269 : // multi-line comments skip input until */ is read
7270 : case '*':
7271 : {
7272 : while (true)
7273 : {
7274 0 : switch (get())
7275 : {
7276 0 : case std::char_traits<char_type>::eof():
7277 : case '\0':
7278 : {
7279 0 : error_message = "invalid comment; missing closing '*/'";
7280 0 : return false;
7281 : }
7282 :
7283 0 : case '*':
7284 : {
7285 0 : switch (get())
7286 : {
7287 : case '/':
7288 : return true;
7289 :
7290 : default:
7291 : {
7292 : unget();
7293 0 : continue;
7294 : }
7295 : }
7296 : }
7297 :
7298 0 : default:
7299 0 : continue;
7300 : }
7301 : }
7302 : }
7303 :
7304 : // unexpected character after reading '/'
7305 0 : default:
7306 : {
7307 0 : error_message = "invalid comment; expecting '/' or '*' after '/'";
7308 0 : return false;
7309 : }
7310 : }
7311 : }
7312 :
7313 : JSON_HEDLEY_NON_NULL(2)
7314 : static void strtof(float& f, const char* str, char** endptr) noexcept
7315 : {
7316 : f = std::strtof(str, endptr);
7317 : }
7318 :
7319 : JSON_HEDLEY_NON_NULL(2)
7320 : static void strtof(double& f, const char* str, char** endptr) noexcept
7321 : {
7322 4333 : f = std::strtod(str, endptr);
7323 : }
7324 :
7325 : JSON_HEDLEY_NON_NULL(2)
7326 : static void strtof(long double& f, const char* str, char** endptr) noexcept
7327 : {
7328 : f = std::strtold(str, endptr);
7329 : }
7330 :
7331 : /*!
7332 : @brief scan a number literal
7333 :
7334 : This function scans a string according to Sect. 6 of RFC 8259.
7335 :
7336 : The function is realized with a deterministic finite state machine derived
7337 : from the grammar described in RFC 8259. Starting in state "init", the
7338 : input is read and used to determined the next state. Only state "done"
7339 : accepts the number. State "error" is a trap state to model errors. In the
7340 : table below, "anything" means any character but the ones listed before.
7341 :
7342 : state | 0 | 1-9 | e E | + | - | . | anything
7343 : ---------|----------|----------|----------|---------|---------|----------|-----------
7344 : init | zero | any1 | [error] | [error] | minus | [error] | [error]
7345 : minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
7346 : zero | done | done | exponent | done | done | decimal1 | done
7347 : any1 | any1 | any1 | exponent | done | done | decimal1 | done
7348 : decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error]
7349 : decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
7350 : exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
7351 : sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
7352 : any2 | any2 | any2 | done | done | done | done | done
7353 :
7354 : The state machine is realized with one label per state (prefixed with
7355 : "scan_number_") and `goto` statements between them. The state machine
7356 : contains cycles, but any cycle can be left when EOF is read. Therefore,
7357 : the function is guaranteed to terminate.
7358 :
7359 : During scanning, the read bytes are stored in token_buffer. This string is
7360 : then converted to a signed integer, an unsigned integer, or a
7361 : floating-point number.
7362 :
7363 : @return token_type::value_unsigned, token_type::value_integer, or
7364 : token_type::value_float if number could be successfully scanned,
7365 : token_type::parse_error otherwise
7366 :
7367 : @note The scanner is independent of the current locale. Internally, the
7368 : locale's decimal point is used instead of `.` to work with the
7369 : locale-dependent converters.
7370 : */
7371 4541 : token_type scan_number() // lgtm [cpp/use-of-goto]
7372 : {
7373 : // reset token_buffer to store the number's bytes
7374 4541 : reset();
7375 :
7376 : // the type of the parsed number; initially set to unsigned; will be
7377 : // changed if minus sign, decimal point or exponent is read
7378 : token_type number_type = token_type::value_unsigned;
7379 :
7380 : // state (init): we just found out we need to scan a number
7381 4541 : switch (current)
7382 : {
7383 940 : case '-':
7384 : {
7385 : add(current);
7386 940 : goto scan_number_minus;
7387 : }
7388 :
7389 1008 : case '0':
7390 : {
7391 : add(current);
7392 1008 : goto scan_number_zero;
7393 : }
7394 :
7395 2593 : case '1':
7396 : case '2':
7397 : case '3':
7398 : case '4':
7399 : case '5':
7400 : case '6':
7401 : case '7':
7402 : case '8':
7403 : case '9':
7404 : {
7405 : add(current);
7406 2593 : goto scan_number_any1;
7407 : }
7408 :
7409 : // all other characters are rejected outside scan_number()
7410 : default: // LCOV_EXCL_LINE
7411 : JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
7412 : }
7413 :
7414 940 : scan_number_minus:
7415 : // state: we just parsed a leading minus sign
7416 : number_type = token_type::value_integer;
7417 940 : switch (get())
7418 : {
7419 646 : case '0':
7420 : {
7421 646 : add(current);
7422 646 : goto scan_number_zero;
7423 : }
7424 :
7425 294 : case '1':
7426 : case '2':
7427 : case '3':
7428 : case '4':
7429 : case '5':
7430 : case '6':
7431 : case '7':
7432 : case '8':
7433 : case '9':
7434 : {
7435 294 : add(current);
7436 294 : goto scan_number_any1;
7437 : }
7438 :
7439 0 : default:
7440 : {
7441 0 : error_message = "invalid number; expected digit after '-'";
7442 0 : return token_type::parse_error;
7443 : }
7444 : }
7445 :
7446 1654 : scan_number_zero:
7447 : // state: we just parse a zero (maybe with a leading minus sign)
7448 1654 : switch (get())
7449 : {
7450 1602 : case '.':
7451 : {
7452 1602 : add(decimal_point_char);
7453 1602 : goto scan_number_decimal1;
7454 : }
7455 :
7456 0 : case 'e':
7457 : case 'E':
7458 : {
7459 0 : add(current);
7460 0 : goto scan_number_exponent;
7461 : }
7462 :
7463 52 : default:
7464 52 : goto scan_number_done;
7465 : }
7466 :
7467 2887 : scan_number_any1:
7468 : // state: we just parsed a number 0-9 (maybe with a leading minus sign)
7469 6597 : switch (get())
7470 : {
7471 3710 : case '0':
7472 : case '1':
7473 : case '2':
7474 : case '3':
7475 : case '4':
7476 : case '5':
7477 : case '6':
7478 : case '7':
7479 : case '8':
7480 : case '9':
7481 : {
7482 3710 : add(current);
7483 3710 : goto scan_number_any1;
7484 : }
7485 :
7486 2731 : case '.':
7487 : {
7488 2731 : add(decimal_point_char);
7489 2731 : goto scan_number_decimal1;
7490 : }
7491 :
7492 0 : case 'e':
7493 : case 'E':
7494 : {
7495 0 : add(current);
7496 0 : goto scan_number_exponent;
7497 : }
7498 :
7499 156 : default:
7500 156 : goto scan_number_done;
7501 : }
7502 :
7503 4333 : scan_number_decimal1:
7504 : // state: we just parsed a decimal point
7505 : number_type = token_type::value_float;
7506 4333 : switch (get())
7507 : {
7508 4333 : case '0':
7509 : case '1':
7510 : case '2':
7511 : case '3':
7512 : case '4':
7513 : case '5':
7514 : case '6':
7515 : case '7':
7516 : case '8':
7517 : case '9':
7518 : {
7519 4333 : add(current);
7520 4333 : goto scan_number_decimal2;
7521 : }
7522 :
7523 0 : default:
7524 : {
7525 0 : error_message = "invalid number; expected digit after '.'";
7526 0 : return token_type::parse_error;
7527 : }
7528 : }
7529 :
7530 21166 : scan_number_decimal2:
7531 : // we just parsed at least one number after a decimal point
7532 21166 : switch (get())
7533 : {
7534 16833 : case '0':
7535 : case '1':
7536 : case '2':
7537 : case '3':
7538 : case '4':
7539 : case '5':
7540 : case '6':
7541 : case '7':
7542 : case '8':
7543 : case '9':
7544 : {
7545 16833 : add(current);
7546 16833 : goto scan_number_decimal2;
7547 : }
7548 :
7549 28 : case 'e':
7550 : case 'E':
7551 : {
7552 28 : add(current);
7553 28 : goto scan_number_exponent;
7554 : }
7555 :
7556 4305 : default:
7557 4305 : goto scan_number_done;
7558 : }
7559 :
7560 28 : scan_number_exponent:
7561 : // we just parsed an exponent
7562 : number_type = token_type::value_float;
7563 28 : switch (get())
7564 : {
7565 28 : case '+':
7566 : case '-':
7567 : {
7568 28 : add(current);
7569 28 : goto scan_number_sign;
7570 : }
7571 :
7572 0 : case '0':
7573 : case '1':
7574 : case '2':
7575 : case '3':
7576 : case '4':
7577 : case '5':
7578 : case '6':
7579 : case '7':
7580 : case '8':
7581 : case '9':
7582 : {
7583 0 : add(current);
7584 0 : goto scan_number_any2;
7585 : }
7586 :
7587 0 : default:
7588 : {
7589 0 : error_message =
7590 : "invalid number; expected '+', '-', or digit after exponent";
7591 0 : return token_type::parse_error;
7592 : }
7593 : }
7594 :
7595 : scan_number_sign:
7596 : // we just parsed an exponent sign
7597 28 : switch (get())
7598 : {
7599 28 : case '0':
7600 : case '1':
7601 : case '2':
7602 : case '3':
7603 : case '4':
7604 : case '5':
7605 : case '6':
7606 : case '7':
7607 : case '8':
7608 : case '9':
7609 : {
7610 28 : add(current);
7611 28 : goto scan_number_any2;
7612 : }
7613 :
7614 0 : default:
7615 : {
7616 0 : error_message = "invalid number; expected digit after exponent sign";
7617 0 : return token_type::parse_error;
7618 : }
7619 : }
7620 :
7621 : scan_number_any2:
7622 : // we just parsed a number after the exponent or exponent sign
7623 56 : switch (get())
7624 : {
7625 28 : case '0':
7626 : case '1':
7627 : case '2':
7628 : case '3':
7629 : case '4':
7630 : case '5':
7631 : case '6':
7632 : case '7':
7633 : case '8':
7634 : case '9':
7635 : {
7636 28 : add(current);
7637 28 : goto scan_number_any2;
7638 : }
7639 :
7640 28 : default:
7641 28 : goto scan_number_done;
7642 : }
7643 :
7644 4541 : scan_number_done:
7645 : // unget the character after the number (we only read it to know that
7646 : // we are done scanning a number)
7647 : unget();
7648 :
7649 4541 : char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
7650 4541 : errno = 0;
7651 :
7652 : // try to parse integers first and fall back to floats
7653 4541 : if (number_type == token_type::value_unsigned)
7654 : {
7655 200 : const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
7656 :
7657 : // we checked the number format before
7658 : JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7659 :
7660 200 : if (errno == 0)
7661 : {
7662 200 : value_unsigned = static_cast<number_unsigned_t>(x);
7663 : if (value_unsigned == x)
7664 : {
7665 200 : return token_type::value_unsigned;
7666 : }
7667 : }
7668 : }
7669 4341 : else if (number_type == token_type::value_integer)
7670 : {
7671 8 : const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
7672 :
7673 : // we checked the number format before
7674 : JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7675 :
7676 8 : if (errno == 0)
7677 : {
7678 8 : value_integer = static_cast<number_integer_t>(x);
7679 : if (value_integer == x)
7680 : {
7681 8 : return token_type::value_integer;
7682 : }
7683 : }
7684 : }
7685 :
7686 : // this code is reached if we parse a floating-point number or if an
7687 : // integer conversion above failed
7688 : strtof(value_float, token_buffer.data(), &endptr);
7689 :
7690 : // we checked the number format before
7691 : JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7692 :
7693 4333 : return token_type::value_float;
7694 : }
7695 :
7696 : /*!
7697 : @param[in] literal_text the literal text to expect
7698 : @param[in] length the length of the passed literal text
7699 : @param[in] return_type the token type to return on success
7700 : */
7701 : JSON_HEDLEY_NON_NULL(2)
7702 : token_type scan_literal(const char_type* literal_text, const std::size_t length,
7703 : token_type return_type)
7704 : {
7705 : JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
7706 0 : for (std::size_t i = 1; i < length; ++i)
7707 : {
7708 0 : if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
7709 : {
7710 0 : error_message = "invalid literal";
7711 0 : return token_type::parse_error;
7712 : }
7713 : }
7714 : return return_type;
7715 : }
7716 :
7717 : /////////////////////
7718 : // input management
7719 : /////////////////////
7720 :
7721 : /// reset token_buffer; current character is beginning of token
7722 6691 : void reset() noexcept
7723 : {
7724 : token_buffer.clear();
7725 : token_string.clear();
7726 6691 : token_string.push_back(std::char_traits<char_type>::to_char_type(current));
7727 6691 : }
7728 :
7729 : /*
7730 : @brief get next character from the input
7731 :
7732 : This function provides the interface to the used input adapter. It does
7733 : not throw in case the input reached EOF, but returns a
7734 : `std::char_traits<char>::eof()` in that case. Stores the scanned characters
7735 : for use in error messages.
7736 :
7737 : @return character read from the input
7738 : */
7739 108371 : char_int_type get()
7740 : {
7741 108371 : ++position.chars_read_total;
7742 108371 : ++position.chars_read_current_line;
7743 :
7744 108371 : if (next_unget)
7745 : {
7746 : // just reset the next_unget variable and work with current
7747 4547 : next_unget = false;
7748 : }
7749 : else
7750 : {
7751 103824 : current = ia.get_character();
7752 : }
7753 :
7754 108371 : if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
7755 : {
7756 108371 : token_string.push_back(std::char_traits<char_type>::to_char_type(current));
7757 : }
7758 :
7759 108371 : if (current == '\n')
7760 : {
7761 4811 : ++position.lines_read;
7762 4811 : position.chars_read_current_line = 0;
7763 : }
7764 :
7765 108371 : return current;
7766 : }
7767 :
7768 : /*!
7769 : @brief unget current character (read it again on next get)
7770 :
7771 : We implement unget by setting variable next_unget to true. The input is not
7772 : changed - we just simulate ungetting by modifying chars_read_total,
7773 : chars_read_current_line, and token_string. The next call to get() will
7774 : behave as if the unget character is read again.
7775 : */
7776 : void unget()
7777 : {
7778 4547 : next_unget = true;
7779 :
7780 4547 : --position.chars_read_total;
7781 :
7782 : // in case we "unget" a newline, we have to also decrement the lines_read
7783 4547 : if (position.chars_read_current_line == 0)
7784 : {
7785 280 : if (position.lines_read > 0)
7786 : {
7787 280 : --position.lines_read;
7788 : }
7789 : }
7790 : else
7791 : {
7792 4267 : --position.chars_read_current_line;
7793 : }
7794 :
7795 4547 : if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
7796 : {
7797 : JSON_ASSERT(!token_string.empty());
7798 : token_string.pop_back();
7799 : }
7800 : }
7801 :
7802 : /// add a character to token_buffer
7803 : void add(char_int_type c)
7804 : {
7805 49570 : token_buffer.push_back(static_cast<typename string_t::value_type>(c));
7806 14768 : }
7807 :
7808 : public:
7809 : /////////////////////
7810 : // value getters
7811 : /////////////////////
7812 :
7813 : /// return integer value
7814 : constexpr number_integer_t get_number_integer() const noexcept
7815 : {
7816 8 : return value_integer;
7817 : }
7818 :
7819 : /// return unsigned integer value
7820 : constexpr number_unsigned_t get_number_unsigned() const noexcept
7821 : {
7822 200 : return value_unsigned;
7823 : }
7824 :
7825 : /// return floating-point value
7826 : constexpr number_float_t get_number_float() const noexcept
7827 : {
7828 4333 : return value_float;
7829 : }
7830 :
7831 : /// return current string value (implicitly resets the token; useful only once)
7832 : string_t& get_string()
7833 : {
7834 1998 : return token_buffer;
7835 : }
7836 :
7837 : /////////////////////
7838 : // diagnostics
7839 : /////////////////////
7840 :
7841 : /// return position of last read token
7842 : constexpr position_t get_position() const noexcept
7843 : {
7844 0 : return position;
7845 : }
7846 :
7847 : /// return the last read token (for errors only). Will never contain EOF
7848 : /// (an arbitrary value that is not a valid char value, often -1), because
7849 : /// 255 may legitimately occur. May contain NUL, which should be escaped.
7850 0 : std::string get_token_string() const
7851 : {
7852 : // escape control characters
7853 : std::string result;
7854 0 : for (const auto c : token_string)
7855 : {
7856 0 : if (static_cast<unsigned char>(c) <= '\x1F')
7857 : {
7858 : // escape control characters
7859 0 : std::array<char, 9> cs{{}};
7860 0 : static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
7861 : result += cs.data();
7862 : }
7863 : else
7864 : {
7865 : // add character as is
7866 0 : result.push_back(static_cast<std::string::value_type>(c));
7867 : }
7868 : }
7869 :
7870 0 : return result;
7871 : }
7872 :
7873 : /// return syntax error message
7874 : JSON_HEDLEY_RETURNS_NON_NULL
7875 : constexpr const char* get_error_message() const noexcept
7876 : {
7877 0 : return error_message;
7878 : }
7879 :
7880 : /////////////////////
7881 : // actual scanner
7882 : /////////////////////
7883 :
7884 : /*!
7885 : @brief skip the UTF-8 byte order mark
7886 : @return true iff there is no BOM or the correct BOM has been skipped
7887 : */
7888 34 : bool skip_bom()
7889 : {
7890 34 : if (get() == 0xEF)
7891 : {
7892 : // check if we completely parse the BOM
7893 28 : return get() == 0xBB && get() == 0xBF;
7894 : }
7895 :
7896 : // the first character is not the beginning of the BOM; unget it to
7897 : // process is later
7898 : unget();
7899 : return true;
7900 : }
7901 :
7902 15780 : void skip_whitespace()
7903 : {
7904 : do
7905 : {
7906 56561 : get();
7907 : }
7908 56561 : while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
7909 15780 : }
7910 :
7911 15780 : token_type scan()
7912 : {
7913 : // initially, skip the BOM
7914 15780 : if (position.chars_read_total == 0 && !skip_bom())
7915 : {
7916 0 : error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
7917 0 : return token_type::parse_error;
7918 : }
7919 :
7920 : // read next character and ignore whitespace
7921 15780 : skip_whitespace();
7922 :
7923 : // ignore comments
7924 15780 : while (ignore_comments && current == '/')
7925 : {
7926 0 : if (!scan_comment())
7927 : {
7928 : return token_type::parse_error;
7929 : }
7930 :
7931 : // skip following whitespace
7932 0 : skip_whitespace();
7933 : }
7934 :
7935 15780 : switch (current)
7936 : {
7937 : // structural characters
7938 : case '[':
7939 : return token_type::begin_array;
7940 620 : case ']':
7941 620 : return token_type::end_array;
7942 596 : case '{':
7943 596 : return token_type::begin_object;
7944 596 : case '}':
7945 596 : return token_type::end_object;
7946 1998 : case ':':
7947 1998 : return token_type::name_separator;
7948 4659 : case ',':
7949 4659 : return token_type::value_separator;
7950 :
7951 : // literals
7952 0 : case 't':
7953 : {
7954 0 : std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}};
7955 : return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
7956 : }
7957 0 : case 'f':
7958 : {
7959 0 : std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}};
7960 : return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
7961 : }
7962 0 : case 'n':
7963 : {
7964 0 : std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}};
7965 : return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
7966 : }
7967 :
7968 : // string
7969 2150 : case '\"':
7970 2150 : return scan_string();
7971 :
7972 : // number
7973 4541 : case '-':
7974 : case '0':
7975 : case '1':
7976 : case '2':
7977 : case '3':
7978 : case '4':
7979 : case '5':
7980 : case '6':
7981 : case '7':
7982 : case '8':
7983 : case '9':
7984 4541 : return scan_number();
7985 :
7986 : // end of input (the null byte is needed when parsing from
7987 : // string literals)
7988 0 : case '\0':
7989 : case std::char_traits<char_type>::eof():
7990 0 : return token_type::end_of_input;
7991 :
7992 : // error
7993 0 : default:
7994 0 : error_message = "invalid literal";
7995 0 : return token_type::parse_error;
7996 : }
7997 : }
7998 :
7999 : private:
8000 : /// input adapter
8001 : InputAdapterType ia;
8002 :
8003 : /// whether comments should be ignored (true) or signaled as errors (false)
8004 : const bool ignore_comments = false;
8005 :
8006 : /// the current character
8007 : char_int_type current = std::char_traits<char_type>::eof();
8008 :
8009 : /// whether the next get() call should just return current
8010 : bool next_unget = false;
8011 :
8012 : /// the start position of the current token
8013 : position_t position {};
8014 :
8015 : /// raw input token string (for error messages)
8016 : std::vector<char_type> token_string {};
8017 :
8018 : /// buffer for variable-length tokens (numbers, strings)
8019 : string_t token_buffer {};
8020 :
8021 : /// a description of occurred lexer errors
8022 : const char* error_message = "";
8023 :
8024 : // number values
8025 : number_integer_t value_integer = 0;
8026 : number_unsigned_t value_unsigned = 0;
8027 : number_float_t value_float = 0;
8028 :
8029 : /// the decimal point
8030 : const char_int_type decimal_point_char = '.';
8031 : };
8032 : } // namespace detail
8033 : } // namespace nlohmann
8034 :
8035 : // #include <nlohmann/detail/macro_scope.hpp>
8036 :
8037 : // #include <nlohmann/detail/meta/is_sax.hpp>
8038 :
8039 :
8040 : #include <cstdint> // size_t
8041 : #include <utility> // declval
8042 : #include <string> // string
8043 :
8044 : // #include <nlohmann/detail/meta/detected.hpp>
8045 :
8046 : // #include <nlohmann/detail/meta/type_traits.hpp>
8047 :
8048 :
8049 : namespace nlohmann
8050 : {
8051 : namespace detail
8052 : {
8053 : template<typename T>
8054 : using null_function_t = decltype(std::declval<T&>().null());
8055 :
8056 : template<typename T>
8057 : using boolean_function_t =
8058 : decltype(std::declval<T&>().boolean(std::declval<bool>()));
8059 :
8060 : template<typename T, typename Integer>
8061 : using number_integer_function_t =
8062 : decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
8063 :
8064 : template<typename T, typename Unsigned>
8065 : using number_unsigned_function_t =
8066 : decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
8067 :
8068 : template<typename T, typename Float, typename String>
8069 : using number_float_function_t = decltype(std::declval<T&>().number_float(
8070 : std::declval<Float>(), std::declval<const String&>()));
8071 :
8072 : template<typename T, typename String>
8073 : using string_function_t =
8074 : decltype(std::declval<T&>().string(std::declval<String&>()));
8075 :
8076 : template<typename T, typename Binary>
8077 : using binary_function_t =
8078 : decltype(std::declval<T&>().binary(std::declval<Binary&>()));
8079 :
8080 : template<typename T>
8081 : using start_object_function_t =
8082 : decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
8083 :
8084 : template<typename T, typename String>
8085 : using key_function_t =
8086 : decltype(std::declval<T&>().key(std::declval<String&>()));
8087 :
8088 : template<typename T>
8089 : using end_object_function_t = decltype(std::declval<T&>().end_object());
8090 :
8091 : template<typename T>
8092 : using start_array_function_t =
8093 : decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
8094 :
8095 : template<typename T>
8096 : using end_array_function_t = decltype(std::declval<T&>().end_array());
8097 :
8098 : template<typename T, typename Exception>
8099 : using parse_error_function_t = decltype(std::declval<T&>().parse_error(
8100 : std::declval<std::size_t>(), std::declval<const std::string&>(),
8101 : std::declval<const Exception&>()));
8102 :
8103 : template<typename SAX, typename BasicJsonType>
8104 : struct is_sax
8105 : {
8106 : private:
8107 : static_assert(is_basic_json<BasicJsonType>::value,
8108 : "BasicJsonType must be of type basic_json<...>");
8109 :
8110 : using number_integer_t = typename BasicJsonType::number_integer_t;
8111 : using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8112 : using number_float_t = typename BasicJsonType::number_float_t;
8113 : using string_t = typename BasicJsonType::string_t;
8114 : using binary_t = typename BasicJsonType::binary_t;
8115 : using exception_t = typename BasicJsonType::exception;
8116 :
8117 : public:
8118 : static constexpr bool value =
8119 : is_detected_exact<bool, null_function_t, SAX>::value &&
8120 : is_detected_exact<bool, boolean_function_t, SAX>::value &&
8121 : is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
8122 : is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
8123 : is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
8124 : is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
8125 : is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
8126 : is_detected_exact<bool, start_object_function_t, SAX>::value &&
8127 : is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
8128 : is_detected_exact<bool, end_object_function_t, SAX>::value &&
8129 : is_detected_exact<bool, start_array_function_t, SAX>::value &&
8130 : is_detected_exact<bool, end_array_function_t, SAX>::value &&
8131 : is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
8132 : };
8133 :
8134 : template<typename SAX, typename BasicJsonType>
8135 : struct is_sax_static_asserts
8136 : {
8137 : private:
8138 : static_assert(is_basic_json<BasicJsonType>::value,
8139 : "BasicJsonType must be of type basic_json<...>");
8140 :
8141 : using number_integer_t = typename BasicJsonType::number_integer_t;
8142 : using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8143 : using number_float_t = typename BasicJsonType::number_float_t;
8144 : using string_t = typename BasicJsonType::string_t;
8145 : using binary_t = typename BasicJsonType::binary_t;
8146 : using exception_t = typename BasicJsonType::exception;
8147 :
8148 : public:
8149 : static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
8150 : "Missing/invalid function: bool null()");
8151 : static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
8152 : "Missing/invalid function: bool boolean(bool)");
8153 : static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
8154 : "Missing/invalid function: bool boolean(bool)");
8155 : static_assert(
8156 : is_detected_exact<bool, number_integer_function_t, SAX,
8157 : number_integer_t>::value,
8158 : "Missing/invalid function: bool number_integer(number_integer_t)");
8159 : static_assert(
8160 : is_detected_exact<bool, number_unsigned_function_t, SAX,
8161 : number_unsigned_t>::value,
8162 : "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
8163 : static_assert(is_detected_exact<bool, number_float_function_t, SAX,
8164 : number_float_t, string_t>::value,
8165 : "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
8166 : static_assert(
8167 : is_detected_exact<bool, string_function_t, SAX, string_t>::value,
8168 : "Missing/invalid function: bool string(string_t&)");
8169 : static_assert(
8170 : is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
8171 : "Missing/invalid function: bool binary(binary_t&)");
8172 : static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
8173 : "Missing/invalid function: bool start_object(std::size_t)");
8174 : static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
8175 : "Missing/invalid function: bool key(string_t&)");
8176 : static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
8177 : "Missing/invalid function: bool end_object()");
8178 : static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
8179 : "Missing/invalid function: bool start_array(std::size_t)");
8180 : static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
8181 : "Missing/invalid function: bool end_array()");
8182 : static_assert(
8183 : is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
8184 : "Missing/invalid function: bool parse_error(std::size_t, const "
8185 : "std::string&, const exception&)");
8186 : };
8187 : } // namespace detail
8188 : } // namespace nlohmann
8189 :
8190 : // #include <nlohmann/detail/meta/type_traits.hpp>
8191 :
8192 : // #include <nlohmann/detail/value_t.hpp>
8193 :
8194 :
8195 : namespace nlohmann
8196 : {
8197 : namespace detail
8198 : {
8199 :
8200 : /// how to treat CBOR tags
8201 : enum class cbor_tag_handler_t
8202 : {
8203 : error, ///< throw a parse_error exception in case of a tag
8204 : ignore, ///< ignore tags
8205 : store ///< store tags as binary type
8206 : };
8207 :
8208 : /*!
8209 : @brief determine system byte order
8210 :
8211 : @return true if and only if system's byte order is little endian
8212 :
8213 : @note from https://stackoverflow.com/a/1001328/266378
8214 : */
8215 : static inline bool little_endianness(int num = 1) noexcept
8216 : {
8217 : return *reinterpret_cast<char*>(&num) == 1;
8218 : }
8219 :
8220 :
8221 : ///////////////////
8222 : // binary reader //
8223 : ///////////////////
8224 :
8225 : /*!
8226 : @brief deserialization of CBOR, MessagePack, and UBJSON values
8227 : */
8228 : template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
8229 : class binary_reader
8230 : {
8231 : using number_integer_t = typename BasicJsonType::number_integer_t;
8232 : using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8233 : using number_float_t = typename BasicJsonType::number_float_t;
8234 : using string_t = typename BasicJsonType::string_t;
8235 : using binary_t = typename BasicJsonType::binary_t;
8236 : using json_sax_t = SAX;
8237 : using char_type = typename InputAdapterType::char_type;
8238 : using char_int_type = typename std::char_traits<char_type>::int_type;
8239 :
8240 : public:
8241 : /*!
8242 : @brief create a binary reader
8243 :
8244 : @param[in] adapter input adapter to read from
8245 : */
8246 : explicit binary_reader(InputAdapterType&& adapter) noexcept : ia(std::move(adapter))
8247 : {
8248 : (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
8249 : }
8250 :
8251 : // make class move-only
8252 : binary_reader(const binary_reader&) = delete;
8253 : binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8254 : binary_reader& operator=(const binary_reader&) = delete;
8255 : binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8256 : ~binary_reader() = default;
8257 :
8258 : /*!
8259 : @param[in] format the binary format to parse
8260 : @param[in] sax_ a SAX event processor
8261 : @param[in] strict whether to expect the input to be consumed completed
8262 : @param[in] tag_handler how to treat CBOR tags
8263 :
8264 : @return whether parsing was successful
8265 : */
8266 : JSON_HEDLEY_NON_NULL(3)
8267 : bool sax_parse(const input_format_t format,
8268 : json_sax_t* sax_,
8269 : const bool strict = true,
8270 : const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
8271 : {
8272 : sax = sax_;
8273 : bool result = false;
8274 :
8275 : switch (format)
8276 : {
8277 : case input_format_t::bson:
8278 : result = parse_bson_internal();
8279 : break;
8280 :
8281 : case input_format_t::cbor:
8282 : result = parse_cbor_internal(true, tag_handler);
8283 : break;
8284 :
8285 : case input_format_t::msgpack:
8286 : result = parse_msgpack_internal();
8287 : break;
8288 :
8289 : case input_format_t::ubjson:
8290 : result = parse_ubjson_internal();
8291 : break;
8292 :
8293 : case input_format_t::json: // LCOV_EXCL_LINE
8294 : default: // LCOV_EXCL_LINE
8295 : JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8296 : }
8297 :
8298 : // strict mode: next byte must be EOF
8299 : if (result && strict)
8300 : {
8301 : if (format == input_format_t::ubjson)
8302 : {
8303 : get_ignore_noop();
8304 : }
8305 : else
8306 : {
8307 : get();
8308 : }
8309 :
8310 : if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
8311 : {
8312 : return sax->parse_error(chars_read, get_token_string(),
8313 : parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"), BasicJsonType()));
8314 : }
8315 : }
8316 :
8317 : return result;
8318 : }
8319 :
8320 : private:
8321 : //////////
8322 : // BSON //
8323 : //////////
8324 :
8325 : /*!
8326 : @brief Reads in a BSON-object and passes it to the SAX-parser.
8327 : @return whether a valid BSON-value was passed to the SAX parser
8328 : */
8329 : bool parse_bson_internal()
8330 : {
8331 : std::int32_t document_size{};
8332 : get_number<std::int32_t, true>(input_format_t::bson, document_size);
8333 :
8334 : if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
8335 : {
8336 : return false;
8337 : }
8338 :
8339 : if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
8340 : {
8341 : return false;
8342 : }
8343 :
8344 : return sax->end_object();
8345 : }
8346 :
8347 : /*!
8348 : @brief Parses a C-style string from the BSON input.
8349 : @param[in,out] result A reference to the string variable where the read
8350 : string is to be stored.
8351 : @return `true` if the \x00-byte indicating the end of the string was
8352 : encountered before the EOF; false` indicates an unexpected EOF.
8353 : */
8354 : bool get_bson_cstr(string_t& result)
8355 : {
8356 : auto out = std::back_inserter(result);
8357 : while (true)
8358 : {
8359 : get();
8360 : if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
8361 : {
8362 : return false;
8363 : }
8364 : if (current == 0x00)
8365 : {
8366 : return true;
8367 : }
8368 : *out++ = static_cast<typename string_t::value_type>(current);
8369 : }
8370 : }
8371 :
8372 : /*!
8373 : @brief Parses a zero-terminated string of length @a len from the BSON
8374 : input.
8375 : @param[in] len The length (including the zero-byte at the end) of the
8376 : string to be read.
8377 : @param[in,out] result A reference to the string variable where the read
8378 : string is to be stored.
8379 : @tparam NumberType The type of the length @a len
8380 : @pre len >= 1
8381 : @return `true` if the string was successfully parsed
8382 : */
8383 : template<typename NumberType>
8384 : bool get_bson_string(const NumberType len, string_t& result)
8385 : {
8386 : if (JSON_HEDLEY_UNLIKELY(len < 1))
8387 : {
8388 : auto last_token = get_token_string();
8389 : return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"), BasicJsonType()));
8390 : }
8391 :
8392 : return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
8393 : }
8394 :
8395 : /*!
8396 : @brief Parses a byte array input of length @a len from the BSON input.
8397 : @param[in] len The length of the byte array to be read.
8398 : @param[in,out] result A reference to the binary variable where the read
8399 : array is to be stored.
8400 : @tparam NumberType The type of the length @a len
8401 : @pre len >= 0
8402 : @return `true` if the byte array was successfully parsed
8403 : */
8404 : template<typename NumberType>
8405 : bool get_bson_binary(const NumberType len, binary_t& result)
8406 : {
8407 : if (JSON_HEDLEY_UNLIKELY(len < 0))
8408 : {
8409 : auto last_token = get_token_string();
8410 : return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"), BasicJsonType()));
8411 : }
8412 :
8413 : // All BSON binary values have a subtype
8414 : std::uint8_t subtype{};
8415 : get_number<std::uint8_t>(input_format_t::bson, subtype);
8416 : result.set_subtype(subtype);
8417 :
8418 : return get_binary(input_format_t::bson, len, result);
8419 : }
8420 :
8421 : /*!
8422 : @brief Read a BSON document element of the given @a element_type.
8423 : @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
8424 : @param[in] element_type_parse_position The position in the input stream,
8425 : where the `element_type` was read.
8426 : @warning Not all BSON element types are supported yet. An unsupported
8427 : @a element_type will give rise to a parse_error.114:
8428 : Unsupported BSON record type 0x...
8429 : @return whether a valid BSON-object/array was passed to the SAX parser
8430 : */
8431 : bool parse_bson_element_internal(const char_int_type element_type,
8432 : const std::size_t element_type_parse_position)
8433 : {
8434 : switch (element_type)
8435 : {
8436 : case 0x01: // double
8437 : {
8438 : double number{};
8439 : return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
8440 : }
8441 :
8442 : case 0x02: // string
8443 : {
8444 : std::int32_t len{};
8445 : string_t value;
8446 : return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
8447 : }
8448 :
8449 : case 0x03: // object
8450 : {
8451 : return parse_bson_internal();
8452 : }
8453 :
8454 : case 0x04: // array
8455 : {
8456 : return parse_bson_array();
8457 : }
8458 :
8459 : case 0x05: // binary
8460 : {
8461 : std::int32_t len{};
8462 : binary_t value;
8463 : return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
8464 : }
8465 :
8466 : case 0x08: // boolean
8467 : {
8468 : return sax->boolean(get() != 0);
8469 : }
8470 :
8471 : case 0x0A: // null
8472 : {
8473 : return sax->null();
8474 : }
8475 :
8476 : case 0x10: // int32
8477 : {
8478 : std::int32_t value{};
8479 : return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
8480 : }
8481 :
8482 : case 0x12: // int64
8483 : {
8484 : std::int64_t value{};
8485 : return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
8486 : }
8487 :
8488 : default: // anything else not supported (yet)
8489 : {
8490 : std::array<char, 3> cr{{}};
8491 : static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8492 : return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()), BasicJsonType()));
8493 : }
8494 : }
8495 : }
8496 :
8497 : /*!
8498 : @brief Read a BSON element list (as specified in the BSON-spec)
8499 :
8500 : The same binary layout is used for objects and arrays, hence it must be
8501 : indicated with the argument @a is_array which one is expected
8502 : (true --> array, false --> object).
8503 :
8504 : @param[in] is_array Determines if the element list being read is to be
8505 : treated as an object (@a is_array == false), or as an
8506 : array (@a is_array == true).
8507 : @return whether a valid BSON-object/array was passed to the SAX parser
8508 : */
8509 : bool parse_bson_element_list(const bool is_array)
8510 : {
8511 : string_t key;
8512 :
8513 : while (auto element_type = get())
8514 : {
8515 : if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
8516 : {
8517 : return false;
8518 : }
8519 :
8520 : const std::size_t element_type_parse_position = chars_read;
8521 : if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
8522 : {
8523 : return false;
8524 : }
8525 :
8526 : if (!is_array && !sax->key(key))
8527 : {
8528 : return false;
8529 : }
8530 :
8531 : if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
8532 : {
8533 : return false;
8534 : }
8535 :
8536 : // get_bson_cstr only appends
8537 : key.clear();
8538 : }
8539 :
8540 : return true;
8541 : }
8542 :
8543 : /*!
8544 : @brief Reads an array from the BSON input and passes it to the SAX-parser.
8545 : @return whether a valid BSON-array was passed to the SAX parser
8546 : */
8547 : bool parse_bson_array()
8548 : {
8549 : std::int32_t document_size{};
8550 : get_number<std::int32_t, true>(input_format_t::bson, document_size);
8551 :
8552 : if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
8553 : {
8554 : return false;
8555 : }
8556 :
8557 : if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
8558 : {
8559 : return false;
8560 : }
8561 :
8562 : return sax->end_array();
8563 : }
8564 :
8565 : //////////
8566 : // CBOR //
8567 : //////////
8568 :
8569 : /*!
8570 : @param[in] get_char whether a new character should be retrieved from the
8571 : input (true) or whether the last read character should
8572 : be considered instead (false)
8573 : @param[in] tag_handler how CBOR tags should be treated
8574 :
8575 : @return whether a valid CBOR value was passed to the SAX parser
8576 : */
8577 : bool parse_cbor_internal(const bool get_char,
8578 : const cbor_tag_handler_t tag_handler)
8579 : {
8580 : switch (get_char ? get() : current)
8581 : {
8582 : // EOF
8583 : case std::char_traits<char_type>::eof():
8584 : return unexpect_eof(input_format_t::cbor, "value");
8585 :
8586 : // Integer 0x00..0x17 (0..23)
8587 : case 0x00:
8588 : case 0x01:
8589 : case 0x02:
8590 : case 0x03:
8591 : case 0x04:
8592 : case 0x05:
8593 : case 0x06:
8594 : case 0x07:
8595 : case 0x08:
8596 : case 0x09:
8597 : case 0x0A:
8598 : case 0x0B:
8599 : case 0x0C:
8600 : case 0x0D:
8601 : case 0x0E:
8602 : case 0x0F:
8603 : case 0x10:
8604 : case 0x11:
8605 : case 0x12:
8606 : case 0x13:
8607 : case 0x14:
8608 : case 0x15:
8609 : case 0x16:
8610 : case 0x17:
8611 : return sax->number_unsigned(static_cast<number_unsigned_t>(current));
8612 :
8613 : case 0x18: // Unsigned integer (one-byte uint8_t follows)
8614 : {
8615 : std::uint8_t number{};
8616 : return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8617 : }
8618 :
8619 : case 0x19: // Unsigned integer (two-byte uint16_t follows)
8620 : {
8621 : std::uint16_t number{};
8622 : return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8623 : }
8624 :
8625 : case 0x1A: // Unsigned integer (four-byte uint32_t follows)
8626 : {
8627 : std::uint32_t number{};
8628 : return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8629 : }
8630 :
8631 : case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
8632 : {
8633 : std::uint64_t number{};
8634 : return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8635 : }
8636 :
8637 : // Negative integer -1-0x00..-1-0x17 (-1..-24)
8638 : case 0x20:
8639 : case 0x21:
8640 : case 0x22:
8641 : case 0x23:
8642 : case 0x24:
8643 : case 0x25:
8644 : case 0x26:
8645 : case 0x27:
8646 : case 0x28:
8647 : case 0x29:
8648 : case 0x2A:
8649 : case 0x2B:
8650 : case 0x2C:
8651 : case 0x2D:
8652 : case 0x2E:
8653 : case 0x2F:
8654 : case 0x30:
8655 : case 0x31:
8656 : case 0x32:
8657 : case 0x33:
8658 : case 0x34:
8659 : case 0x35:
8660 : case 0x36:
8661 : case 0x37:
8662 : return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
8663 :
8664 : case 0x38: // Negative integer (one-byte uint8_t follows)
8665 : {
8666 : std::uint8_t number{};
8667 : return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8668 : }
8669 :
8670 : case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
8671 : {
8672 : std::uint16_t number{};
8673 : return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8674 : }
8675 :
8676 : case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
8677 : {
8678 : std::uint32_t number{};
8679 : return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8680 : }
8681 :
8682 : case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
8683 : {
8684 : std::uint64_t number{};
8685 : return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
8686 : - static_cast<number_integer_t>(number));
8687 : }
8688 :
8689 : // Binary data (0x00..0x17 bytes follow)
8690 : case 0x40:
8691 : case 0x41:
8692 : case 0x42:
8693 : case 0x43:
8694 : case 0x44:
8695 : case 0x45:
8696 : case 0x46:
8697 : case 0x47:
8698 : case 0x48:
8699 : case 0x49:
8700 : case 0x4A:
8701 : case 0x4B:
8702 : case 0x4C:
8703 : case 0x4D:
8704 : case 0x4E:
8705 : case 0x4F:
8706 : case 0x50:
8707 : case 0x51:
8708 : case 0x52:
8709 : case 0x53:
8710 : case 0x54:
8711 : case 0x55:
8712 : case 0x56:
8713 : case 0x57:
8714 : case 0x58: // Binary data (one-byte uint8_t for n follows)
8715 : case 0x59: // Binary data (two-byte uint16_t for n follow)
8716 : case 0x5A: // Binary data (four-byte uint32_t for n follow)
8717 : case 0x5B: // Binary data (eight-byte uint64_t for n follow)
8718 : case 0x5F: // Binary data (indefinite length)
8719 : {
8720 : binary_t b;
8721 : return get_cbor_binary(b) && sax->binary(b);
8722 : }
8723 :
8724 : // UTF-8 string (0x00..0x17 bytes follow)
8725 : case 0x60:
8726 : case 0x61:
8727 : case 0x62:
8728 : case 0x63:
8729 : case 0x64:
8730 : case 0x65:
8731 : case 0x66:
8732 : case 0x67:
8733 : case 0x68:
8734 : case 0x69:
8735 : case 0x6A:
8736 : case 0x6B:
8737 : case 0x6C:
8738 : case 0x6D:
8739 : case 0x6E:
8740 : case 0x6F:
8741 : case 0x70:
8742 : case 0x71:
8743 : case 0x72:
8744 : case 0x73:
8745 : case 0x74:
8746 : case 0x75:
8747 : case 0x76:
8748 : case 0x77:
8749 : case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
8750 : case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
8751 : case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
8752 : case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
8753 : case 0x7F: // UTF-8 string (indefinite length)
8754 : {
8755 : string_t s;
8756 : return get_cbor_string(s) && sax->string(s);
8757 : }
8758 :
8759 : // array (0x00..0x17 data items follow)
8760 : case 0x80:
8761 : case 0x81:
8762 : case 0x82:
8763 : case 0x83:
8764 : case 0x84:
8765 : case 0x85:
8766 : case 0x86:
8767 : case 0x87:
8768 : case 0x88:
8769 : case 0x89:
8770 : case 0x8A:
8771 : case 0x8B:
8772 : case 0x8C:
8773 : case 0x8D:
8774 : case 0x8E:
8775 : case 0x8F:
8776 : case 0x90:
8777 : case 0x91:
8778 : case 0x92:
8779 : case 0x93:
8780 : case 0x94:
8781 : case 0x95:
8782 : case 0x96:
8783 : case 0x97:
8784 : return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
8785 :
8786 : case 0x98: // array (one-byte uint8_t for n follows)
8787 : {
8788 : std::uint8_t len{};
8789 : return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8790 : }
8791 :
8792 : case 0x99: // array (two-byte uint16_t for n follow)
8793 : {
8794 : std::uint16_t len{};
8795 : return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8796 : }
8797 :
8798 : case 0x9A: // array (four-byte uint32_t for n follow)
8799 : {
8800 : std::uint32_t len{};
8801 : return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8802 : }
8803 :
8804 : case 0x9B: // array (eight-byte uint64_t for n follow)
8805 : {
8806 : std::uint64_t len{};
8807 : return get_number(input_format_t::cbor, len) && get_cbor_array(detail::conditional_static_cast<std::size_t>(len), tag_handler);
8808 : }
8809 :
8810 : case 0x9F: // array (indefinite length)
8811 : return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
8812 :
8813 : // map (0x00..0x17 pairs of data items follow)
8814 : case 0xA0:
8815 : case 0xA1:
8816 : case 0xA2:
8817 : case 0xA3:
8818 : case 0xA4:
8819 : case 0xA5:
8820 : case 0xA6:
8821 : case 0xA7:
8822 : case 0xA8:
8823 : case 0xA9:
8824 : case 0xAA:
8825 : case 0xAB:
8826 : case 0xAC:
8827 : case 0xAD:
8828 : case 0xAE:
8829 : case 0xAF:
8830 : case 0xB0:
8831 : case 0xB1:
8832 : case 0xB2:
8833 : case 0xB3:
8834 : case 0xB4:
8835 : case 0xB5:
8836 : case 0xB6:
8837 : case 0xB7:
8838 : return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
8839 :
8840 : case 0xB8: // map (one-byte uint8_t for n follows)
8841 : {
8842 : std::uint8_t len{};
8843 : return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8844 : }
8845 :
8846 : case 0xB9: // map (two-byte uint16_t for n follow)
8847 : {
8848 : std::uint16_t len{};
8849 : return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8850 : }
8851 :
8852 : case 0xBA: // map (four-byte uint32_t for n follow)
8853 : {
8854 : std::uint32_t len{};
8855 : return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8856 : }
8857 :
8858 : case 0xBB: // map (eight-byte uint64_t for n follow)
8859 : {
8860 : std::uint64_t len{};
8861 : return get_number(input_format_t::cbor, len) && get_cbor_object(detail::conditional_static_cast<std::size_t>(len), tag_handler);
8862 : }
8863 :
8864 : case 0xBF: // map (indefinite length)
8865 : return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
8866 :
8867 : case 0xC6: // tagged item
8868 : case 0xC7:
8869 : case 0xC8:
8870 : case 0xC9:
8871 : case 0xCA:
8872 : case 0xCB:
8873 : case 0xCC:
8874 : case 0xCD:
8875 : case 0xCE:
8876 : case 0xCF:
8877 : case 0xD0:
8878 : case 0xD1:
8879 : case 0xD2:
8880 : case 0xD3:
8881 : case 0xD4:
8882 : case 0xD8: // tagged item (1 bytes follow)
8883 : case 0xD9: // tagged item (2 bytes follow)
8884 : case 0xDA: // tagged item (4 bytes follow)
8885 : case 0xDB: // tagged item (8 bytes follow)
8886 : {
8887 : switch (tag_handler)
8888 : {
8889 : case cbor_tag_handler_t::error:
8890 : {
8891 : auto last_token = get_token_string();
8892 : return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
8893 : }
8894 :
8895 : case cbor_tag_handler_t::ignore:
8896 : {
8897 : // ignore binary subtype
8898 : switch (current)
8899 : {
8900 : case 0xD8:
8901 : {
8902 : std::uint8_t subtype_to_ignore{};
8903 : get_number(input_format_t::cbor, subtype_to_ignore);
8904 : break;
8905 : }
8906 : case 0xD9:
8907 : {
8908 : std::uint16_t subtype_to_ignore{};
8909 : get_number(input_format_t::cbor, subtype_to_ignore);
8910 : break;
8911 : }
8912 : case 0xDA:
8913 : {
8914 : std::uint32_t subtype_to_ignore{};
8915 : get_number(input_format_t::cbor, subtype_to_ignore);
8916 : break;
8917 : }
8918 : case 0xDB:
8919 : {
8920 : std::uint64_t subtype_to_ignore{};
8921 : get_number(input_format_t::cbor, subtype_to_ignore);
8922 : break;
8923 : }
8924 : default:
8925 : break;
8926 : }
8927 : return parse_cbor_internal(true, tag_handler);
8928 : }
8929 :
8930 : case cbor_tag_handler_t::store:
8931 : {
8932 : binary_t b;
8933 : // use binary subtype and store in binary container
8934 : switch (current)
8935 : {
8936 : case 0xD8:
8937 : {
8938 : std::uint8_t subtype{};
8939 : get_number(input_format_t::cbor, subtype);
8940 : b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
8941 : break;
8942 : }
8943 : case 0xD9:
8944 : {
8945 : std::uint16_t subtype{};
8946 : get_number(input_format_t::cbor, subtype);
8947 : b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
8948 : break;
8949 : }
8950 : case 0xDA:
8951 : {
8952 : std::uint32_t subtype{};
8953 : get_number(input_format_t::cbor, subtype);
8954 : b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
8955 : break;
8956 : }
8957 : case 0xDB:
8958 : {
8959 : std::uint64_t subtype{};
8960 : get_number(input_format_t::cbor, subtype);
8961 : b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
8962 : break;
8963 : }
8964 : default:
8965 : return parse_cbor_internal(true, tag_handler);
8966 : }
8967 : get();
8968 : return get_cbor_binary(b) && sax->binary(b);
8969 : }
8970 :
8971 : default: // LCOV_EXCL_LINE
8972 : JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8973 : return false; // LCOV_EXCL_LINE
8974 : }
8975 : }
8976 :
8977 : case 0xF4: // false
8978 : return sax->boolean(false);
8979 :
8980 : case 0xF5: // true
8981 : return sax->boolean(true);
8982 :
8983 : case 0xF6: // null
8984 : return sax->null();
8985 :
8986 : case 0xF9: // Half-Precision Float (two-byte IEEE 754)
8987 : {
8988 : const auto byte1_raw = get();
8989 : if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
8990 : {
8991 : return false;
8992 : }
8993 : const auto byte2_raw = get();
8994 : if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
8995 : {
8996 : return false;
8997 : }
8998 :
8999 : const auto byte1 = static_cast<unsigned char>(byte1_raw);
9000 : const auto byte2 = static_cast<unsigned char>(byte2_raw);
9001 :
9002 : // code from RFC 7049, Appendix D, Figure 3:
9003 : // As half-precision floating-point numbers were only added
9004 : // to IEEE 754 in 2008, today's programming platforms often
9005 : // still only have limited support for them. It is very
9006 : // easy to include at least decoding support for them even
9007 : // without such support. An example of a small decoder for
9008 : // half-precision floating-point numbers in the C language
9009 : // is shown in Fig. 3.
9010 : const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
9011 : const double val = [&half]
9012 : {
9013 : const int exp = (half >> 10u) & 0x1Fu;
9014 : const unsigned int mant = half & 0x3FFu;
9015 : JSON_ASSERT(0 <= exp&& exp <= 32);
9016 : JSON_ASSERT(mant <= 1024);
9017 : switch (exp)
9018 : {
9019 : case 0:
9020 : return std::ldexp(mant, -24);
9021 : case 31:
9022 : return (mant == 0)
9023 : ? std::numeric_limits<double>::infinity()
9024 : : std::numeric_limits<double>::quiet_NaN();
9025 : default:
9026 : return std::ldexp(mant + 1024, exp - 25);
9027 : }
9028 : }();
9029 : return sax->number_float((half & 0x8000u) != 0
9030 : ? static_cast<number_float_t>(-val)
9031 : : static_cast<number_float_t>(val), "");
9032 : }
9033 :
9034 : case 0xFA: // Single-Precision Float (four-byte IEEE 754)
9035 : {
9036 : float number{};
9037 : return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9038 : }
9039 :
9040 : case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
9041 : {
9042 : double number{};
9043 : return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9044 : }
9045 :
9046 : default: // anything else (0xFF is handled inside the other types)
9047 : {
9048 : auto last_token = get_token_string();
9049 : return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
9050 : }
9051 : }
9052 : }
9053 :
9054 : /*!
9055 : @brief reads a CBOR string
9056 :
9057 : This function first reads starting bytes to determine the expected
9058 : string length and then copies this number of bytes into a string.
9059 : Additionally, CBOR's strings with indefinite lengths are supported.
9060 :
9061 : @param[out] result created string
9062 :
9063 : @return whether string creation completed
9064 : */
9065 : bool get_cbor_string(string_t& result)
9066 : {
9067 : if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
9068 : {
9069 : return false;
9070 : }
9071 :
9072 : switch (current)
9073 : {
9074 : // UTF-8 string (0x00..0x17 bytes follow)
9075 : case 0x60:
9076 : case 0x61:
9077 : case 0x62:
9078 : case 0x63:
9079 : case 0x64:
9080 : case 0x65:
9081 : case 0x66:
9082 : case 0x67:
9083 : case 0x68:
9084 : case 0x69:
9085 : case 0x6A:
9086 : case 0x6B:
9087 : case 0x6C:
9088 : case 0x6D:
9089 : case 0x6E:
9090 : case 0x6F:
9091 : case 0x70:
9092 : case 0x71:
9093 : case 0x72:
9094 : case 0x73:
9095 : case 0x74:
9096 : case 0x75:
9097 : case 0x76:
9098 : case 0x77:
9099 : {
9100 : return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
9101 : }
9102 :
9103 : case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9104 : {
9105 : std::uint8_t len{};
9106 : return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9107 : }
9108 :
9109 : case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9110 : {
9111 : std::uint16_t len{};
9112 : return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9113 : }
9114 :
9115 : case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9116 : {
9117 : std::uint32_t len{};
9118 : return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9119 : }
9120 :
9121 : case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9122 : {
9123 : std::uint64_t len{};
9124 : return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9125 : }
9126 :
9127 : case 0x7F: // UTF-8 string (indefinite length)
9128 : {
9129 : while (get() != 0xFF)
9130 : {
9131 : string_t chunk;
9132 : if (!get_cbor_string(chunk))
9133 : {
9134 : return false;
9135 : }
9136 : result.append(chunk);
9137 : }
9138 : return true;
9139 : }
9140 :
9141 : default:
9142 : {
9143 : auto last_token = get_token_string();
9144 : return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"), BasicJsonType()));
9145 : }
9146 : }
9147 : }
9148 :
9149 : /*!
9150 : @brief reads a CBOR byte array
9151 :
9152 : This function first reads starting bytes to determine the expected
9153 : byte array length and then copies this number of bytes into the byte array.
9154 : Additionally, CBOR's byte arrays with indefinite lengths are supported.
9155 :
9156 : @param[out] result created byte array
9157 :
9158 : @return whether byte array creation completed
9159 : */
9160 : bool get_cbor_binary(binary_t& result)
9161 : {
9162 : if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
9163 : {
9164 : return false;
9165 : }
9166 :
9167 : switch (current)
9168 : {
9169 : // Binary data (0x00..0x17 bytes follow)
9170 : case 0x40:
9171 : case 0x41:
9172 : case 0x42:
9173 : case 0x43:
9174 : case 0x44:
9175 : case 0x45:
9176 : case 0x46:
9177 : case 0x47:
9178 : case 0x48:
9179 : case 0x49:
9180 : case 0x4A:
9181 : case 0x4B:
9182 : case 0x4C:
9183 : case 0x4D:
9184 : case 0x4E:
9185 : case 0x4F:
9186 : case 0x50:
9187 : case 0x51:
9188 : case 0x52:
9189 : case 0x53:
9190 : case 0x54:
9191 : case 0x55:
9192 : case 0x56:
9193 : case 0x57:
9194 : {
9195 : return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
9196 : }
9197 :
9198 : case 0x58: // Binary data (one-byte uint8_t for n follows)
9199 : {
9200 : std::uint8_t len{};
9201 : return get_number(input_format_t::cbor, len) &&
9202 : get_binary(input_format_t::cbor, len, result);
9203 : }
9204 :
9205 : case 0x59: // Binary data (two-byte uint16_t for n follow)
9206 : {
9207 : std::uint16_t len{};
9208 : return get_number(input_format_t::cbor, len) &&
9209 : get_binary(input_format_t::cbor, len, result);
9210 : }
9211 :
9212 : case 0x5A: // Binary data (four-byte uint32_t for n follow)
9213 : {
9214 : std::uint32_t len{};
9215 : return get_number(input_format_t::cbor, len) &&
9216 : get_binary(input_format_t::cbor, len, result);
9217 : }
9218 :
9219 : case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9220 : {
9221 : std::uint64_t len{};
9222 : return get_number(input_format_t::cbor, len) &&
9223 : get_binary(input_format_t::cbor, len, result);
9224 : }
9225 :
9226 : case 0x5F: // Binary data (indefinite length)
9227 : {
9228 : while (get() != 0xFF)
9229 : {
9230 : binary_t chunk;
9231 : if (!get_cbor_binary(chunk))
9232 : {
9233 : return false;
9234 : }
9235 : result.insert(result.end(), chunk.begin(), chunk.end());
9236 : }
9237 : return true;
9238 : }
9239 :
9240 : default:
9241 : {
9242 : auto last_token = get_token_string();
9243 : return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"), BasicJsonType()));
9244 : }
9245 : }
9246 : }
9247 :
9248 : /*!
9249 : @param[in] len the length of the array or static_cast<std::size_t>(-1) for an
9250 : array of indefinite size
9251 : @param[in] tag_handler how CBOR tags should be treated
9252 : @return whether array creation completed
9253 : */
9254 : bool get_cbor_array(const std::size_t len,
9255 : const cbor_tag_handler_t tag_handler)
9256 : {
9257 : if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
9258 : {
9259 : return false;
9260 : }
9261 :
9262 : if (len != static_cast<std::size_t>(-1))
9263 : {
9264 : for (std::size_t i = 0; i < len; ++i)
9265 : {
9266 : if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
9267 : {
9268 : return false;
9269 : }
9270 : }
9271 : }
9272 : else
9273 : {
9274 : while (get() != 0xFF)
9275 : {
9276 : if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
9277 : {
9278 : return false;
9279 : }
9280 : }
9281 : }
9282 :
9283 : return sax->end_array();
9284 : }
9285 :
9286 : /*!
9287 : @param[in] len the length of the object or static_cast<std::size_t>(-1) for an
9288 : object of indefinite size
9289 : @param[in] tag_handler how CBOR tags should be treated
9290 : @return whether object creation completed
9291 : */
9292 : bool get_cbor_object(const std::size_t len,
9293 : const cbor_tag_handler_t tag_handler)
9294 : {
9295 : if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
9296 : {
9297 : return false;
9298 : }
9299 :
9300 : if (len != 0)
9301 : {
9302 : string_t key;
9303 : if (len != static_cast<std::size_t>(-1))
9304 : {
9305 : for (std::size_t i = 0; i < len; ++i)
9306 : {
9307 : get();
9308 : if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
9309 : {
9310 : return false;
9311 : }
9312 :
9313 : if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
9314 : {
9315 : return false;
9316 : }
9317 : key.clear();
9318 : }
9319 : }
9320 : else
9321 : {
9322 : while (get() != 0xFF)
9323 : {
9324 : if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
9325 : {
9326 : return false;
9327 : }
9328 :
9329 : if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
9330 : {
9331 : return false;
9332 : }
9333 : key.clear();
9334 : }
9335 : }
9336 : }
9337 :
9338 : return sax->end_object();
9339 : }
9340 :
9341 : /////////////
9342 : // MsgPack //
9343 : /////////////
9344 :
9345 : /*!
9346 : @return whether a valid MessagePack value was passed to the SAX parser
9347 : */
9348 : bool parse_msgpack_internal()
9349 : {
9350 : switch (get())
9351 : {
9352 : // EOF
9353 : case std::char_traits<char_type>::eof():
9354 : return unexpect_eof(input_format_t::msgpack, "value");
9355 :
9356 : // positive fixint
9357 : case 0x00:
9358 : case 0x01:
9359 : case 0x02:
9360 : case 0x03:
9361 : case 0x04:
9362 : case 0x05:
9363 : case 0x06:
9364 : case 0x07:
9365 : case 0x08:
9366 : case 0x09:
9367 : case 0x0A:
9368 : case 0x0B:
9369 : case 0x0C:
9370 : case 0x0D:
9371 : case 0x0E:
9372 : case 0x0F:
9373 : case 0x10:
9374 : case 0x11:
9375 : case 0x12:
9376 : case 0x13:
9377 : case 0x14:
9378 : case 0x15:
9379 : case 0x16:
9380 : case 0x17:
9381 : case 0x18:
9382 : case 0x19:
9383 : case 0x1A:
9384 : case 0x1B:
9385 : case 0x1C:
9386 : case 0x1D:
9387 : case 0x1E:
9388 : case 0x1F:
9389 : case 0x20:
9390 : case 0x21:
9391 : case 0x22:
9392 : case 0x23:
9393 : case 0x24:
9394 : case 0x25:
9395 : case 0x26:
9396 : case 0x27:
9397 : case 0x28:
9398 : case 0x29:
9399 : case 0x2A:
9400 : case 0x2B:
9401 : case 0x2C:
9402 : case 0x2D:
9403 : case 0x2E:
9404 : case 0x2F:
9405 : case 0x30:
9406 : case 0x31:
9407 : case 0x32:
9408 : case 0x33:
9409 : case 0x34:
9410 : case 0x35:
9411 : case 0x36:
9412 : case 0x37:
9413 : case 0x38:
9414 : case 0x39:
9415 : case 0x3A:
9416 : case 0x3B:
9417 : case 0x3C:
9418 : case 0x3D:
9419 : case 0x3E:
9420 : case 0x3F:
9421 : case 0x40:
9422 : case 0x41:
9423 : case 0x42:
9424 : case 0x43:
9425 : case 0x44:
9426 : case 0x45:
9427 : case 0x46:
9428 : case 0x47:
9429 : case 0x48:
9430 : case 0x49:
9431 : case 0x4A:
9432 : case 0x4B:
9433 : case 0x4C:
9434 : case 0x4D:
9435 : case 0x4E:
9436 : case 0x4F:
9437 : case 0x50:
9438 : case 0x51:
9439 : case 0x52:
9440 : case 0x53:
9441 : case 0x54:
9442 : case 0x55:
9443 : case 0x56:
9444 : case 0x57:
9445 : case 0x58:
9446 : case 0x59:
9447 : case 0x5A:
9448 : case 0x5B:
9449 : case 0x5C:
9450 : case 0x5D:
9451 : case 0x5E:
9452 : case 0x5F:
9453 : case 0x60:
9454 : case 0x61:
9455 : case 0x62:
9456 : case 0x63:
9457 : case 0x64:
9458 : case 0x65:
9459 : case 0x66:
9460 : case 0x67:
9461 : case 0x68:
9462 : case 0x69:
9463 : case 0x6A:
9464 : case 0x6B:
9465 : case 0x6C:
9466 : case 0x6D:
9467 : case 0x6E:
9468 : case 0x6F:
9469 : case 0x70:
9470 : case 0x71:
9471 : case 0x72:
9472 : case 0x73:
9473 : case 0x74:
9474 : case 0x75:
9475 : case 0x76:
9476 : case 0x77:
9477 : case 0x78:
9478 : case 0x79:
9479 : case 0x7A:
9480 : case 0x7B:
9481 : case 0x7C:
9482 : case 0x7D:
9483 : case 0x7E:
9484 : case 0x7F:
9485 : return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9486 :
9487 : // fixmap
9488 : case 0x80:
9489 : case 0x81:
9490 : case 0x82:
9491 : case 0x83:
9492 : case 0x84:
9493 : case 0x85:
9494 : case 0x86:
9495 : case 0x87:
9496 : case 0x88:
9497 : case 0x89:
9498 : case 0x8A:
9499 : case 0x8B:
9500 : case 0x8C:
9501 : case 0x8D:
9502 : case 0x8E:
9503 : case 0x8F:
9504 : return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
9505 :
9506 : // fixarray
9507 : case 0x90:
9508 : case 0x91:
9509 : case 0x92:
9510 : case 0x93:
9511 : case 0x94:
9512 : case 0x95:
9513 : case 0x96:
9514 : case 0x97:
9515 : case 0x98:
9516 : case 0x99:
9517 : case 0x9A:
9518 : case 0x9B:
9519 : case 0x9C:
9520 : case 0x9D:
9521 : case 0x9E:
9522 : case 0x9F:
9523 : return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
9524 :
9525 : // fixstr
9526 : case 0xA0:
9527 : case 0xA1:
9528 : case 0xA2:
9529 : case 0xA3:
9530 : case 0xA4:
9531 : case 0xA5:
9532 : case 0xA6:
9533 : case 0xA7:
9534 : case 0xA8:
9535 : case 0xA9:
9536 : case 0xAA:
9537 : case 0xAB:
9538 : case 0xAC:
9539 : case 0xAD:
9540 : case 0xAE:
9541 : case 0xAF:
9542 : case 0xB0:
9543 : case 0xB1:
9544 : case 0xB2:
9545 : case 0xB3:
9546 : case 0xB4:
9547 : case 0xB5:
9548 : case 0xB6:
9549 : case 0xB7:
9550 : case 0xB8:
9551 : case 0xB9:
9552 : case 0xBA:
9553 : case 0xBB:
9554 : case 0xBC:
9555 : case 0xBD:
9556 : case 0xBE:
9557 : case 0xBF:
9558 : case 0xD9: // str 8
9559 : case 0xDA: // str 16
9560 : case 0xDB: // str 32
9561 : {
9562 : string_t s;
9563 : return get_msgpack_string(s) && sax->string(s);
9564 : }
9565 :
9566 : case 0xC0: // nil
9567 : return sax->null();
9568 :
9569 : case 0xC2: // false
9570 : return sax->boolean(false);
9571 :
9572 : case 0xC3: // true
9573 : return sax->boolean(true);
9574 :
9575 : case 0xC4: // bin 8
9576 : case 0xC5: // bin 16
9577 : case 0xC6: // bin 32
9578 : case 0xC7: // ext 8
9579 : case 0xC8: // ext 16
9580 : case 0xC9: // ext 32
9581 : case 0xD4: // fixext 1
9582 : case 0xD5: // fixext 2
9583 : case 0xD6: // fixext 4
9584 : case 0xD7: // fixext 8
9585 : case 0xD8: // fixext 16
9586 : {
9587 : binary_t b;
9588 : return get_msgpack_binary(b) && sax->binary(b);
9589 : }
9590 :
9591 : case 0xCA: // float 32
9592 : {
9593 : float number{};
9594 : return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
9595 : }
9596 :
9597 : case 0xCB: // float 64
9598 : {
9599 : double number{};
9600 : return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
9601 : }
9602 :
9603 : case 0xCC: // uint 8
9604 : {
9605 : std::uint8_t number{};
9606 : return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9607 : }
9608 :
9609 : case 0xCD: // uint 16
9610 : {
9611 : std::uint16_t number{};
9612 : return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9613 : }
9614 :
9615 : case 0xCE: // uint 32
9616 : {
9617 : std::uint32_t number{};
9618 : return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9619 : }
9620 :
9621 : case 0xCF: // uint 64
9622 : {
9623 : std::uint64_t number{};
9624 : return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9625 : }
9626 :
9627 : case 0xD0: // int 8
9628 : {
9629 : std::int8_t number{};
9630 : return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9631 : }
9632 :
9633 : case 0xD1: // int 16
9634 : {
9635 : std::int16_t number{};
9636 : return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9637 : }
9638 :
9639 : case 0xD2: // int 32
9640 : {
9641 : std::int32_t number{};
9642 : return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9643 : }
9644 :
9645 : case 0xD3: // int 64
9646 : {
9647 : std::int64_t number{};
9648 : return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9649 : }
9650 :
9651 : case 0xDC: // array 16
9652 : {
9653 : std::uint16_t len{};
9654 : return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
9655 : }
9656 :
9657 : case 0xDD: // array 32
9658 : {
9659 : std::uint32_t len{};
9660 : return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
9661 : }
9662 :
9663 : case 0xDE: // map 16
9664 : {
9665 : std::uint16_t len{};
9666 : return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
9667 : }
9668 :
9669 : case 0xDF: // map 32
9670 : {
9671 : std::uint32_t len{};
9672 : return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
9673 : }
9674 :
9675 : // negative fixint
9676 : case 0xE0:
9677 : case 0xE1:
9678 : case 0xE2:
9679 : case 0xE3:
9680 : case 0xE4:
9681 : case 0xE5:
9682 : case 0xE6:
9683 : case 0xE7:
9684 : case 0xE8:
9685 : case 0xE9:
9686 : case 0xEA:
9687 : case 0xEB:
9688 : case 0xEC:
9689 : case 0xED:
9690 : case 0xEE:
9691 : case 0xEF:
9692 : case 0xF0:
9693 : case 0xF1:
9694 : case 0xF2:
9695 : case 0xF3:
9696 : case 0xF4:
9697 : case 0xF5:
9698 : case 0xF6:
9699 : case 0xF7:
9700 : case 0xF8:
9701 : case 0xF9:
9702 : case 0xFA:
9703 : case 0xFB:
9704 : case 0xFC:
9705 : case 0xFD:
9706 : case 0xFE:
9707 : case 0xFF:
9708 : return sax->number_integer(static_cast<std::int8_t>(current));
9709 :
9710 : default: // anything else
9711 : {
9712 : auto last_token = get_token_string();
9713 : return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
9714 : }
9715 : }
9716 : }
9717 :
9718 : /*!
9719 : @brief reads a MessagePack string
9720 :
9721 : This function first reads starting bytes to determine the expected
9722 : string length and then copies this number of bytes into a string.
9723 :
9724 : @param[out] result created string
9725 :
9726 : @return whether string creation completed
9727 : */
9728 : bool get_msgpack_string(string_t& result)
9729 : {
9730 : if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
9731 : {
9732 : return false;
9733 : }
9734 :
9735 : switch (current)
9736 : {
9737 : // fixstr
9738 : case 0xA0:
9739 : case 0xA1:
9740 : case 0xA2:
9741 : case 0xA3:
9742 : case 0xA4:
9743 : case 0xA5:
9744 : case 0xA6:
9745 : case 0xA7:
9746 : case 0xA8:
9747 : case 0xA9:
9748 : case 0xAA:
9749 : case 0xAB:
9750 : case 0xAC:
9751 : case 0xAD:
9752 : case 0xAE:
9753 : case 0xAF:
9754 : case 0xB0:
9755 : case 0xB1:
9756 : case 0xB2:
9757 : case 0xB3:
9758 : case 0xB4:
9759 : case 0xB5:
9760 : case 0xB6:
9761 : case 0xB7:
9762 : case 0xB8:
9763 : case 0xB9:
9764 : case 0xBA:
9765 : case 0xBB:
9766 : case 0xBC:
9767 : case 0xBD:
9768 : case 0xBE:
9769 : case 0xBF:
9770 : {
9771 : return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
9772 : }
9773 :
9774 : case 0xD9: // str 8
9775 : {
9776 : std::uint8_t len{};
9777 : return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9778 : }
9779 :
9780 : case 0xDA: // str 16
9781 : {
9782 : std::uint16_t len{};
9783 : return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9784 : }
9785 :
9786 : case 0xDB: // str 32
9787 : {
9788 : std::uint32_t len{};
9789 : return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9790 : }
9791 :
9792 : default:
9793 : {
9794 : auto last_token = get_token_string();
9795 : return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"), BasicJsonType()));
9796 : }
9797 : }
9798 : }
9799 :
9800 : /*!
9801 : @brief reads a MessagePack byte array
9802 :
9803 : This function first reads starting bytes to determine the expected
9804 : byte array length and then copies this number of bytes into a byte array.
9805 :
9806 : @param[out] result created byte array
9807 :
9808 : @return whether byte array creation completed
9809 : */
9810 : bool get_msgpack_binary(binary_t& result)
9811 : {
9812 : // helper function to set the subtype
9813 : auto assign_and_return_true = [&result](std::int8_t subtype)
9814 : {
9815 : result.set_subtype(static_cast<std::uint8_t>(subtype));
9816 : return true;
9817 : };
9818 :
9819 : switch (current)
9820 : {
9821 : case 0xC4: // bin 8
9822 : {
9823 : std::uint8_t len{};
9824 : return get_number(input_format_t::msgpack, len) &&
9825 : get_binary(input_format_t::msgpack, len, result);
9826 : }
9827 :
9828 : case 0xC5: // bin 16
9829 : {
9830 : std::uint16_t len{};
9831 : return get_number(input_format_t::msgpack, len) &&
9832 : get_binary(input_format_t::msgpack, len, result);
9833 : }
9834 :
9835 : case 0xC6: // bin 32
9836 : {
9837 : std::uint32_t len{};
9838 : return get_number(input_format_t::msgpack, len) &&
9839 : get_binary(input_format_t::msgpack, len, result);
9840 : }
9841 :
9842 : case 0xC7: // ext 8
9843 : {
9844 : std::uint8_t len{};
9845 : std::int8_t subtype{};
9846 : return get_number(input_format_t::msgpack, len) &&
9847 : get_number(input_format_t::msgpack, subtype) &&
9848 : get_binary(input_format_t::msgpack, len, result) &&
9849 : assign_and_return_true(subtype);
9850 : }
9851 :
9852 : case 0xC8: // ext 16
9853 : {
9854 : std::uint16_t len{};
9855 : std::int8_t subtype{};
9856 : return get_number(input_format_t::msgpack, len) &&
9857 : get_number(input_format_t::msgpack, subtype) &&
9858 : get_binary(input_format_t::msgpack, len, result) &&
9859 : assign_and_return_true(subtype);
9860 : }
9861 :
9862 : case 0xC9: // ext 32
9863 : {
9864 : std::uint32_t len{};
9865 : std::int8_t subtype{};
9866 : return get_number(input_format_t::msgpack, len) &&
9867 : get_number(input_format_t::msgpack, subtype) &&
9868 : get_binary(input_format_t::msgpack, len, result) &&
9869 : assign_and_return_true(subtype);
9870 : }
9871 :
9872 : case 0xD4: // fixext 1
9873 : {
9874 : std::int8_t subtype{};
9875 : return get_number(input_format_t::msgpack, subtype) &&
9876 : get_binary(input_format_t::msgpack, 1, result) &&
9877 : assign_and_return_true(subtype);
9878 : }
9879 :
9880 : case 0xD5: // fixext 2
9881 : {
9882 : std::int8_t subtype{};
9883 : return get_number(input_format_t::msgpack, subtype) &&
9884 : get_binary(input_format_t::msgpack, 2, result) &&
9885 : assign_and_return_true(subtype);
9886 : }
9887 :
9888 : case 0xD6: // fixext 4
9889 : {
9890 : std::int8_t subtype{};
9891 : return get_number(input_format_t::msgpack, subtype) &&
9892 : get_binary(input_format_t::msgpack, 4, result) &&
9893 : assign_and_return_true(subtype);
9894 : }
9895 :
9896 : case 0xD7: // fixext 8
9897 : {
9898 : std::int8_t subtype{};
9899 : return get_number(input_format_t::msgpack, subtype) &&
9900 : get_binary(input_format_t::msgpack, 8, result) &&
9901 : assign_and_return_true(subtype);
9902 : }
9903 :
9904 : case 0xD8: // fixext 16
9905 : {
9906 : std::int8_t subtype{};
9907 : return get_number(input_format_t::msgpack, subtype) &&
9908 : get_binary(input_format_t::msgpack, 16, result) &&
9909 : assign_and_return_true(subtype);
9910 : }
9911 :
9912 : default: // LCOV_EXCL_LINE
9913 : return false; // LCOV_EXCL_LINE
9914 : }
9915 : }
9916 :
9917 : /*!
9918 : @param[in] len the length of the array
9919 : @return whether array creation completed
9920 : */
9921 : bool get_msgpack_array(const std::size_t len)
9922 : {
9923 : if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
9924 : {
9925 : return false;
9926 : }
9927 :
9928 : for (std::size_t i = 0; i < len; ++i)
9929 : {
9930 : if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
9931 : {
9932 : return false;
9933 : }
9934 : }
9935 :
9936 : return sax->end_array();
9937 : }
9938 :
9939 : /*!
9940 : @param[in] len the length of the object
9941 : @return whether object creation completed
9942 : */
9943 : bool get_msgpack_object(const std::size_t len)
9944 : {
9945 : if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
9946 : {
9947 : return false;
9948 : }
9949 :
9950 : string_t key;
9951 : for (std::size_t i = 0; i < len; ++i)
9952 : {
9953 : get();
9954 : if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
9955 : {
9956 : return false;
9957 : }
9958 :
9959 : if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
9960 : {
9961 : return false;
9962 : }
9963 : key.clear();
9964 : }
9965 :
9966 : return sax->end_object();
9967 : }
9968 :
9969 : ////////////
9970 : // UBJSON //
9971 : ////////////
9972 :
9973 : /*!
9974 : @param[in] get_char whether a new character should be retrieved from the
9975 : input (true, default) or whether the last read
9976 : character should be considered instead
9977 :
9978 : @return whether a valid UBJSON value was passed to the SAX parser
9979 : */
9980 : bool parse_ubjson_internal(const bool get_char = true)
9981 : {
9982 : return get_ubjson_value(get_char ? get_ignore_noop() : current);
9983 : }
9984 :
9985 : /*!
9986 : @brief reads a UBJSON string
9987 :
9988 : This function is either called after reading the 'S' byte explicitly
9989 : indicating a string, or in case of an object key where the 'S' byte can be
9990 : left out.
9991 :
9992 : @param[out] result created string
9993 : @param[in] get_char whether a new character should be retrieved from the
9994 : input (true, default) or whether the last read
9995 : character should be considered instead
9996 :
9997 : @return whether string creation completed
9998 : */
9999 : bool get_ubjson_string(string_t& result, const bool get_char = true)
10000 : {
10001 : if (get_char)
10002 : {
10003 : get(); // TODO(niels): may we ignore N here?
10004 : }
10005 :
10006 : if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
10007 : {
10008 : return false;
10009 : }
10010 :
10011 : switch (current)
10012 : {
10013 : case 'U':
10014 : {
10015 : std::uint8_t len{};
10016 : return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10017 : }
10018 :
10019 : case 'i':
10020 : {
10021 : std::int8_t len{};
10022 : return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10023 : }
10024 :
10025 : case 'I':
10026 : {
10027 : std::int16_t len{};
10028 : return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10029 : }
10030 :
10031 : case 'l':
10032 : {
10033 : std::int32_t len{};
10034 : return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10035 : }
10036 :
10037 : case 'L':
10038 : {
10039 : std::int64_t len{};
10040 : return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10041 : }
10042 :
10043 : default:
10044 : auto last_token = get_token_string();
10045 : return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"), BasicJsonType()));
10046 : }
10047 : }
10048 :
10049 : /*!
10050 : @param[out] result determined size
10051 : @return whether size determination completed
10052 : */
10053 : bool get_ubjson_size_value(std::size_t& result)
10054 : {
10055 : switch (get_ignore_noop())
10056 : {
10057 : case 'U':
10058 : {
10059 : std::uint8_t number{};
10060 : if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10061 : {
10062 : return false;
10063 : }
10064 : result = static_cast<std::size_t>(number);
10065 : return true;
10066 : }
10067 :
10068 : case 'i':
10069 : {
10070 : std::int8_t number{};
10071 : if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10072 : {
10073 : return false;
10074 : }
10075 : result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
10076 : return true;
10077 : }
10078 :
10079 : case 'I':
10080 : {
10081 : std::int16_t number{};
10082 : if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10083 : {
10084 : return false;
10085 : }
10086 : result = static_cast<std::size_t>(number);
10087 : return true;
10088 : }
10089 :
10090 : case 'l':
10091 : {
10092 : std::int32_t number{};
10093 : if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10094 : {
10095 : return false;
10096 : }
10097 : result = static_cast<std::size_t>(number);
10098 : return true;
10099 : }
10100 :
10101 : case 'L':
10102 : {
10103 : std::int64_t number{};
10104 : if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10105 : {
10106 : return false;
10107 : }
10108 : result = static_cast<std::size_t>(number);
10109 : return true;
10110 : }
10111 :
10112 : default:
10113 : {
10114 : auto last_token = get_token_string();
10115 : return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"), BasicJsonType()));
10116 : }
10117 : }
10118 : }
10119 :
10120 : /*!
10121 : @brief determine the type and size for a container
10122 :
10123 : In the optimized UBJSON format, a type and a size can be provided to allow
10124 : for a more compact representation.
10125 :
10126 : @param[out] result pair of the size and the type
10127 :
10128 : @return whether pair creation completed
10129 : */
10130 : bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result)
10131 : {
10132 : result.first = string_t::npos; // size
10133 : result.second = 0; // type
10134 :
10135 : get_ignore_noop();
10136 :
10137 : if (current == '$')
10138 : {
10139 : result.second = get(); // must not ignore 'N', because 'N' maybe the type
10140 : if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type")))
10141 : {
10142 : return false;
10143 : }
10144 :
10145 : get_ignore_noop();
10146 : if (JSON_HEDLEY_UNLIKELY(current != '#'))
10147 : {
10148 : if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
10149 : {
10150 : return false;
10151 : }
10152 : auto last_token = get_token_string();
10153 : return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"), BasicJsonType()));
10154 : }
10155 :
10156 : return get_ubjson_size_value(result.first);
10157 : }
10158 :
10159 : if (current == '#')
10160 : {
10161 : return get_ubjson_size_value(result.first);
10162 : }
10163 :
10164 : return true;
10165 : }
10166 :
10167 : /*!
10168 : @param prefix the previously read or set type prefix
10169 : @return whether value creation completed
10170 : */
10171 : bool get_ubjson_value(const char_int_type prefix)
10172 : {
10173 : switch (prefix)
10174 : {
10175 : case std::char_traits<char_type>::eof(): // EOF
10176 : return unexpect_eof(input_format_t::ubjson, "value");
10177 :
10178 : case 'T': // true
10179 : return sax->boolean(true);
10180 : case 'F': // false
10181 : return sax->boolean(false);
10182 :
10183 : case 'Z': // null
10184 : return sax->null();
10185 :
10186 : case 'U':
10187 : {
10188 : std::uint8_t number{};
10189 : return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number);
10190 : }
10191 :
10192 : case 'i':
10193 : {
10194 : std::int8_t number{};
10195 : return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
10196 : }
10197 :
10198 : case 'I':
10199 : {
10200 : std::int16_t number{};
10201 : return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
10202 : }
10203 :
10204 : case 'l':
10205 : {
10206 : std::int32_t number{};
10207 : return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
10208 : }
10209 :
10210 : case 'L':
10211 : {
10212 : std::int64_t number{};
10213 : return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
10214 : }
10215 :
10216 : case 'd':
10217 : {
10218 : float number{};
10219 : return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10220 : }
10221 :
10222 : case 'D':
10223 : {
10224 : double number{};
10225 : return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10226 : }
10227 :
10228 : case 'H':
10229 : {
10230 : return get_ubjson_high_precision_number();
10231 : }
10232 :
10233 : case 'C': // char
10234 : {
10235 : get();
10236 : if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char")))
10237 : {
10238 : return false;
10239 : }
10240 : if (JSON_HEDLEY_UNLIKELY(current > 127))
10241 : {
10242 : auto last_token = get_token_string();
10243 : return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"), BasicJsonType()));
10244 : }
10245 : string_t s(1, static_cast<typename string_t::value_type>(current));
10246 : return sax->string(s);
10247 : }
10248 :
10249 : case 'S': // string
10250 : {
10251 : string_t s;
10252 : return get_ubjson_string(s) && sax->string(s);
10253 : }
10254 :
10255 : case '[': // array
10256 : return get_ubjson_array();
10257 :
10258 : case '{': // object
10259 : return get_ubjson_object();
10260 :
10261 : default: // anything else
10262 : {
10263 : auto last_token = get_token_string();
10264 : return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
10265 : }
10266 : }
10267 : }
10268 :
10269 : /*!
10270 : @return whether array creation completed
10271 : */
10272 : bool get_ubjson_array()
10273 : {
10274 : std::pair<std::size_t, char_int_type> size_and_type;
10275 : if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
10276 : {
10277 : return false;
10278 : }
10279 :
10280 : if (size_and_type.first != string_t::npos)
10281 : {
10282 : if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
10283 : {
10284 : return false;
10285 : }
10286 :
10287 : if (size_and_type.second != 0)
10288 : {
10289 : if (size_and_type.second != 'N')
10290 : {
10291 : for (std::size_t i = 0; i < size_and_type.first; ++i)
10292 : {
10293 : if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
10294 : {
10295 : return false;
10296 : }
10297 : }
10298 : }
10299 : }
10300 : else
10301 : {
10302 : for (std::size_t i = 0; i < size_and_type.first; ++i)
10303 : {
10304 : if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
10305 : {
10306 : return false;
10307 : }
10308 : }
10309 : }
10310 : }
10311 : else
10312 : {
10313 : if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
10314 : {
10315 : return false;
10316 : }
10317 :
10318 : while (current != ']')
10319 : {
10320 : if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
10321 : {
10322 : return false;
10323 : }
10324 : get_ignore_noop();
10325 : }
10326 : }
10327 :
10328 : return sax->end_array();
10329 : }
10330 :
10331 : /*!
10332 : @return whether object creation completed
10333 : */
10334 : bool get_ubjson_object()
10335 : {
10336 : std::pair<std::size_t, char_int_type> size_and_type;
10337 : if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
10338 : {
10339 : return false;
10340 : }
10341 :
10342 : string_t key;
10343 : if (size_and_type.first != string_t::npos)
10344 : {
10345 : if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
10346 : {
10347 : return false;
10348 : }
10349 :
10350 : if (size_and_type.second != 0)
10351 : {
10352 : for (std::size_t i = 0; i < size_and_type.first; ++i)
10353 : {
10354 : if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
10355 : {
10356 : return false;
10357 : }
10358 : if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
10359 : {
10360 : return false;
10361 : }
10362 : key.clear();
10363 : }
10364 : }
10365 : else
10366 : {
10367 : for (std::size_t i = 0; i < size_and_type.first; ++i)
10368 : {
10369 : if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
10370 : {
10371 : return false;
10372 : }
10373 : if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
10374 : {
10375 : return false;
10376 : }
10377 : key.clear();
10378 : }
10379 : }
10380 : }
10381 : else
10382 : {
10383 : if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
10384 : {
10385 : return false;
10386 : }
10387 :
10388 : while (current != '}')
10389 : {
10390 : if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
10391 : {
10392 : return false;
10393 : }
10394 : if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
10395 : {
10396 : return false;
10397 : }
10398 : get_ignore_noop();
10399 : key.clear();
10400 : }
10401 : }
10402 :
10403 : return sax->end_object();
10404 : }
10405 :
10406 : // Note, no reader for UBJSON binary types is implemented because they do
10407 : // not exist
10408 :
10409 : bool get_ubjson_high_precision_number()
10410 : {
10411 : // get size of following number string
10412 : std::size_t size{};
10413 : auto res = get_ubjson_size_value(size);
10414 : if (JSON_HEDLEY_UNLIKELY(!res))
10415 : {
10416 : return res;
10417 : }
10418 :
10419 : // get number string
10420 : std::vector<char> number_vector;
10421 : for (std::size_t i = 0; i < size; ++i)
10422 : {
10423 : get();
10424 : if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number")))
10425 : {
10426 : return false;
10427 : }
10428 : number_vector.push_back(static_cast<char>(current));
10429 : }
10430 :
10431 : // parse number string
10432 : using ia_type = decltype(detail::input_adapter(number_vector));
10433 : auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
10434 : const auto result_number = number_lexer.scan();
10435 : const auto number_string = number_lexer.get_token_string();
10436 : const auto result_remainder = number_lexer.scan();
10437 :
10438 : using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
10439 :
10440 : if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
10441 : {
10442 : return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType()));
10443 : }
10444 :
10445 : switch (result_number)
10446 : {
10447 : case token_type::value_integer:
10448 : return sax->number_integer(number_lexer.get_number_integer());
10449 : case token_type::value_unsigned:
10450 : return sax->number_unsigned(number_lexer.get_number_unsigned());
10451 : case token_type::value_float:
10452 : return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
10453 : case token_type::uninitialized:
10454 : case token_type::literal_true:
10455 : case token_type::literal_false:
10456 : case token_type::literal_null:
10457 : case token_type::value_string:
10458 : case token_type::begin_array:
10459 : case token_type::begin_object:
10460 : case token_type::end_array:
10461 : case token_type::end_object:
10462 : case token_type::name_separator:
10463 : case token_type::value_separator:
10464 : case token_type::parse_error:
10465 : case token_type::end_of_input:
10466 : case token_type::literal_or_value:
10467 : default:
10468 : return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType()));
10469 : }
10470 : }
10471 :
10472 : ///////////////////////
10473 : // Utility functions //
10474 : ///////////////////////
10475 :
10476 : /*!
10477 : @brief get next character from the input
10478 :
10479 : This function provides the interface to the used input adapter. It does
10480 : not throw in case the input reached EOF, but returns a -'ve valued
10481 : `std::char_traits<char_type>::eof()` in that case.
10482 :
10483 : @return character read from the input
10484 : */
10485 : char_int_type get()
10486 : {
10487 : ++chars_read;
10488 : return current = ia.get_character();
10489 : }
10490 :
10491 : /*!
10492 : @return character read from the input after ignoring all 'N' entries
10493 : */
10494 : char_int_type get_ignore_noop()
10495 : {
10496 : do
10497 : {
10498 : get();
10499 : }
10500 : while (current == 'N');
10501 :
10502 : return current;
10503 : }
10504 :
10505 : /*
10506 : @brief read a number from the input
10507 :
10508 : @tparam NumberType the type of the number
10509 : @param[in] format the current format (for diagnostics)
10510 : @param[out] result number of type @a NumberType
10511 :
10512 : @return whether conversion completed
10513 :
10514 : @note This function needs to respect the system's endianness, because
10515 : bytes in CBOR, MessagePack, and UBJSON are stored in network order
10516 : (big endian) and therefore need reordering on little endian systems.
10517 : */
10518 : template<typename NumberType, bool InputIsLittleEndian = false>
10519 : bool get_number(const input_format_t format, NumberType& result)
10520 : {
10521 : // step 1: read input into array with system's byte order
10522 : std::array<std::uint8_t, sizeof(NumberType)> vec{};
10523 : for (std::size_t i = 0; i < sizeof(NumberType); ++i)
10524 : {
10525 : get();
10526 : if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
10527 : {
10528 : return false;
10529 : }
10530 :
10531 : // reverse byte order prior to conversion if necessary
10532 : if (is_little_endian != InputIsLittleEndian)
10533 : {
10534 : vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
10535 : }
10536 : else
10537 : {
10538 : vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
10539 : }
10540 : }
10541 :
10542 : // step 2: convert array into number of type T and return
10543 : std::memcpy(&result, vec.data(), sizeof(NumberType));
10544 : return true;
10545 : }
10546 :
10547 : /*!
10548 : @brief create a string by reading characters from the input
10549 :
10550 : @tparam NumberType the type of the number
10551 : @param[in] format the current format (for diagnostics)
10552 : @param[in] len number of characters to read
10553 : @param[out] result string created by reading @a len bytes
10554 :
10555 : @return whether string creation completed
10556 :
10557 : @note We can not reserve @a len bytes for the result, because @a len
10558 : may be too large. Usually, @ref unexpect_eof() detects the end of
10559 : the input before we run out of string memory.
10560 : */
10561 : template<typename NumberType>
10562 : bool get_string(const input_format_t format,
10563 : const NumberType len,
10564 : string_t& result)
10565 : {
10566 : bool success = true;
10567 : for (NumberType i = 0; i < len; i++)
10568 : {
10569 : get();
10570 : if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
10571 : {
10572 : success = false;
10573 : break;
10574 : }
10575 : result.push_back(static_cast<typename string_t::value_type>(current));
10576 : }
10577 : return success;
10578 : }
10579 :
10580 : /*!
10581 : @brief create a byte array by reading bytes from the input
10582 :
10583 : @tparam NumberType the type of the number
10584 : @param[in] format the current format (for diagnostics)
10585 : @param[in] len number of bytes to read
10586 : @param[out] result byte array created by reading @a len bytes
10587 :
10588 : @return whether byte array creation completed
10589 :
10590 : @note We can not reserve @a len bytes for the result, because @a len
10591 : may be too large. Usually, @ref unexpect_eof() detects the end of
10592 : the input before we run out of memory.
10593 : */
10594 : template<typename NumberType>
10595 : bool get_binary(const input_format_t format,
10596 : const NumberType len,
10597 : binary_t& result)
10598 : {
10599 : bool success = true;
10600 : for (NumberType i = 0; i < len; i++)
10601 : {
10602 : get();
10603 : if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
10604 : {
10605 : success = false;
10606 : break;
10607 : }
10608 : result.push_back(static_cast<std::uint8_t>(current));
10609 : }
10610 : return success;
10611 : }
10612 :
10613 : /*!
10614 : @param[in] format the current format (for diagnostics)
10615 : @param[in] context further context information (for diagnostics)
10616 : @return whether the last read character is not EOF
10617 : */
10618 : JSON_HEDLEY_NON_NULL(3)
10619 : bool unexpect_eof(const input_format_t format, const char* context) const
10620 : {
10621 : if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
10622 : {
10623 : return sax->parse_error(chars_read, "<end of file>",
10624 : parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), BasicJsonType()));
10625 : }
10626 : return true;
10627 : }
10628 :
10629 : /*!
10630 : @return a string representation of the last read byte
10631 : */
10632 : std::string get_token_string() const
10633 : {
10634 : std::array<char, 3> cr{{}};
10635 : static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
10636 : return std::string{cr.data()};
10637 : }
10638 :
10639 : /*!
10640 : @param[in] format the current format
10641 : @param[in] detail a detailed error message
10642 : @param[in] context further context information
10643 : @return a message string to use in the parse_error exceptions
10644 : */
10645 : std::string exception_message(const input_format_t format,
10646 : const std::string& detail,
10647 : const std::string& context) const
10648 : {
10649 : std::string error_msg = "syntax error while parsing ";
10650 :
10651 : switch (format)
10652 : {
10653 : case input_format_t::cbor:
10654 : error_msg += "CBOR";
10655 : break;
10656 :
10657 : case input_format_t::msgpack:
10658 : error_msg += "MessagePack";
10659 : break;
10660 :
10661 : case input_format_t::ubjson:
10662 : error_msg += "UBJSON";
10663 : break;
10664 :
10665 : case input_format_t::bson:
10666 : error_msg += "BSON";
10667 : break;
10668 :
10669 : case input_format_t::json: // LCOV_EXCL_LINE
10670 : default: // LCOV_EXCL_LINE
10671 : JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10672 : }
10673 :
10674 : return error_msg + " " + context + ": " + detail;
10675 : }
10676 :
10677 : private:
10678 : /// input adapter
10679 : InputAdapterType ia;
10680 :
10681 : /// the current character
10682 : char_int_type current = std::char_traits<char_type>::eof();
10683 :
10684 : /// the number of characters read
10685 : std::size_t chars_read = 0;
10686 :
10687 : /// whether we can assume little endianness
10688 : const bool is_little_endian = little_endianness();
10689 :
10690 : /// the SAX parser
10691 : json_sax_t* sax = nullptr;
10692 : };
10693 : } // namespace detail
10694 : } // namespace nlohmann
10695 :
10696 : // #include <nlohmann/detail/input/input_adapters.hpp>
10697 :
10698 : // #include <nlohmann/detail/input/lexer.hpp>
10699 :
10700 : // #include <nlohmann/detail/input/parser.hpp>
10701 :
10702 :
10703 : #include <cmath> // isfinite
10704 : #include <cstdint> // uint8_t
10705 : #include <functional> // function
10706 : #include <string> // string
10707 : #include <utility> // move
10708 : #include <vector> // vector
10709 :
10710 : // #include <nlohmann/detail/exceptions.hpp>
10711 :
10712 : // #include <nlohmann/detail/input/input_adapters.hpp>
10713 :
10714 : // #include <nlohmann/detail/input/json_sax.hpp>
10715 :
10716 : // #include <nlohmann/detail/input/lexer.hpp>
10717 :
10718 : // #include <nlohmann/detail/macro_scope.hpp>
10719 :
10720 : // #include <nlohmann/detail/meta/is_sax.hpp>
10721 :
10722 : // #include <nlohmann/detail/value_t.hpp>
10723 :
10724 :
10725 : namespace nlohmann
10726 : {
10727 : namespace detail
10728 : {
10729 : ////////////
10730 : // parser //
10731 : ////////////
10732 :
10733 : enum class parse_event_t : std::uint8_t
10734 : {
10735 : /// the parser read `{` and started to process a JSON object
10736 : object_start,
10737 : /// the parser read `}` and finished processing a JSON object
10738 : object_end,
10739 : /// the parser read `[` and started to process a JSON array
10740 : array_start,
10741 : /// the parser read `]` and finished processing a JSON array
10742 : array_end,
10743 : /// the parser read a key of a value in an object
10744 : key,
10745 : /// the parser finished reading a JSON value
10746 : value
10747 : };
10748 :
10749 : template<typename BasicJsonType>
10750 : using parser_callback_t =
10751 : std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
10752 :
10753 : /*!
10754 : @brief syntax analysis
10755 :
10756 : This class implements a recursive descent parser.
10757 : */
10758 : template<typename BasicJsonType, typename InputAdapterType>
10759 : class parser
10760 : {
10761 : using number_integer_t = typename BasicJsonType::number_integer_t;
10762 : using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
10763 : using number_float_t = typename BasicJsonType::number_float_t;
10764 : using string_t = typename BasicJsonType::string_t;
10765 : using lexer_t = lexer<BasicJsonType, InputAdapterType>;
10766 : using token_type = typename lexer_t::token_type;
10767 :
10768 : public:
10769 : /// a parser reading from an input adapter
10770 34 : explicit parser(InputAdapterType&& adapter,
10771 : const parser_callback_t<BasicJsonType> cb = nullptr,
10772 : const bool allow_exceptions_ = true,
10773 : const bool skip_comments = false)
10774 34 : : callback(cb)
10775 34 : , m_lexer(std::move(adapter), skip_comments)
10776 34 : , allow_exceptions(allow_exceptions_)
10777 : {
10778 : // read first token
10779 : get_token();
10780 0 : }
10781 :
10782 : /*!
10783 : @brief public parser interface
10784 :
10785 : @param[in] strict whether to expect the last token to be EOF
10786 : @param[in,out] result parsed JSON value
10787 :
10788 : @throw parse_error.101 in case of an unexpected token
10789 : @throw parse_error.102 if to_unicode fails or surrogate error
10790 : @throw parse_error.103 if to_unicode fails
10791 : */
10792 34 : void parse(const bool strict, BasicJsonType& result)
10793 : {
10794 34 : if (callback)
10795 : {
10796 0 : json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
10797 0 : sax_parse_internal(&sdp);
10798 :
10799 : // in strict mode, input must be completely read
10800 0 : if (strict && (get_token() != token_type::end_of_input))
10801 : {
10802 0 : sdp.parse_error(m_lexer.get_position(),
10803 : m_lexer.get_token_string(),
10804 0 : parse_error::create(101, m_lexer.get_position(),
10805 0 : exception_message(token_type::end_of_input, "value"), BasicJsonType()));
10806 : }
10807 :
10808 : // in case of an error, return discarded value
10809 0 : if (sdp.is_errored())
10810 : {
10811 0 : result = value_t::discarded;
10812 : return;
10813 : }
10814 :
10815 : // set top-level value to null if it was discarded by the callback
10816 : // function
10817 0 : if (result.is_discarded())
10818 : {
10819 0 : result = nullptr;
10820 : }
10821 0 : }
10822 : else
10823 : {
10824 34 : json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
10825 34 : sax_parse_internal(&sdp);
10826 :
10827 : // in strict mode, input must be completely read
10828 34 : if (strict && (get_token() != token_type::end_of_input))
10829 : {
10830 0 : sdp.parse_error(m_lexer.get_position(),
10831 : m_lexer.get_token_string(),
10832 0 : parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
10833 : }
10834 :
10835 : // in case of an error, return discarded value
10836 34 : if (sdp.is_errored())
10837 : {
10838 0 : result = value_t::discarded;
10839 : return;
10840 : }
10841 : }
10842 :
10843 : result.assert_invariant();
10844 : }
10845 :
10846 : /*!
10847 : @brief public accept interface
10848 :
10849 : @param[in] strict whether to expect the last token to be EOF
10850 : @return whether the input is a proper JSON text
10851 : */
10852 : bool accept(const bool strict = true)
10853 : {
10854 : json_sax_acceptor<BasicJsonType> sax_acceptor;
10855 : return sax_parse(&sax_acceptor, strict);
10856 : }
10857 :
10858 : template<typename SAX>
10859 : JSON_HEDLEY_NON_NULL(2)
10860 : bool sax_parse(SAX* sax, const bool strict = true)
10861 : {
10862 : (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
10863 : const bool result = sax_parse_internal(sax);
10864 :
10865 : // strict mode: next byte must be EOF
10866 : if (result && strict && (get_token() != token_type::end_of_input))
10867 : {
10868 : return sax->parse_error(m_lexer.get_position(),
10869 : m_lexer.get_token_string(),
10870 : parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
10871 : }
10872 :
10873 : return result;
10874 : }
10875 :
10876 : private:
10877 : template<typename SAX>
10878 : JSON_HEDLEY_NON_NULL(2)
10879 34 : bool sax_parse_internal(SAX* sax)
10880 : {
10881 : // stack to remember the hierarchy of structured values we are parsing
10882 : // true = array; false = object
10883 : std::vector<bool> states;
10884 : // value to avoid a goto (see comment where set to true)
10885 : bool skip_to_state_evaluation = false;
10886 :
10887 : while (true)
10888 : {
10889 7125 : if (!skip_to_state_evaluation)
10890 : {
10891 : // invariant: get_token() was called before each iteration
10892 5909 : switch (last_token)
10893 : {
10894 596 : case token_type::begin_object:
10895 : {
10896 596 : if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
10897 : {
10898 : return false;
10899 : }
10900 :
10901 : // closing } -> we are done
10902 596 : if (get_token() == token_type::end_object)
10903 : {
10904 0 : if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
10905 : {
10906 : return false;
10907 : }
10908 : break;
10909 : }
10910 :
10911 : // parse key
10912 596 : if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
10913 : {
10914 0 : return sax->parse_error(m_lexer.get_position(),
10915 : m_lexer.get_token_string(),
10916 0 : parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType()));
10917 : }
10918 0 : if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
10919 : {
10920 : return false;
10921 : }
10922 :
10923 : // parse separator (:)
10924 596 : if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
10925 : {
10926 0 : return sax->parse_error(m_lexer.get_position(),
10927 : m_lexer.get_token_string(),
10928 0 : parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType()));
10929 : }
10930 :
10931 : // remember we are now inside an object
10932 596 : states.push_back(false);
10933 :
10934 : // parse values
10935 : get_token();
10936 596 : continue;
10937 : }
10938 :
10939 620 : case token_type::begin_array:
10940 : {
10941 620 : if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
10942 : {
10943 : return false;
10944 : }
10945 :
10946 : // closing ] -> we are done
10947 620 : if (get_token() == token_type::end_array)
10948 : {
10949 0 : if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
10950 : {
10951 : return false;
10952 : }
10953 : break;
10954 : }
10955 :
10956 : // remember we are now inside an array
10957 620 : states.push_back(true);
10958 :
10959 : // parse values (no need to call get_token)
10960 620 : continue;
10961 : }
10962 :
10963 4333 : case token_type::value_float:
10964 : {
10965 : const auto res = m_lexer.get_number_float();
10966 :
10967 4333 : if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
10968 : {
10969 0 : return sax->parse_error(m_lexer.get_position(),
10970 : m_lexer.get_token_string(),
10971 0 : out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'", BasicJsonType()));
10972 : }
10973 :
10974 4333 : if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
10975 : {
10976 : return false;
10977 : }
10978 :
10979 : break;
10980 : }
10981 :
10982 0 : case token_type::literal_false:
10983 : {
10984 0 : if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
10985 : {
10986 : return false;
10987 : }
10988 : break;
10989 : }
10990 :
10991 : case token_type::literal_null:
10992 : {
10993 : if (JSON_HEDLEY_UNLIKELY(!sax->null()))
10994 : {
10995 : return false;
10996 : }
10997 : break;
10998 : }
10999 :
11000 0 : case token_type::literal_true:
11001 : {
11002 0 : if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
11003 : {
11004 : return false;
11005 : }
11006 : break;
11007 : }
11008 :
11009 8 : case token_type::value_integer:
11010 : {
11011 8 : if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
11012 : {
11013 : return false;
11014 : }
11015 : break;
11016 : }
11017 :
11018 152 : case token_type::value_string:
11019 : {
11020 : if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
11021 : {
11022 : return false;
11023 : }
11024 : break;
11025 : }
11026 :
11027 200 : case token_type::value_unsigned:
11028 : {
11029 200 : if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
11030 : {
11031 : return false;
11032 : }
11033 : break;
11034 : }
11035 :
11036 0 : case token_type::parse_error:
11037 : {
11038 : // using "uninitialized" to avoid "expected" message
11039 0 : return sax->parse_error(m_lexer.get_position(),
11040 : m_lexer.get_token_string(),
11041 0 : parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), BasicJsonType()));
11042 : }
11043 :
11044 0 : case token_type::uninitialized:
11045 : case token_type::end_array:
11046 : case token_type::end_object:
11047 : case token_type::name_separator:
11048 : case token_type::value_separator:
11049 : case token_type::end_of_input:
11050 : case token_type::literal_or_value:
11051 : default: // the last token was unexpected
11052 : {
11053 0 : return sax->parse_error(m_lexer.get_position(),
11054 : m_lexer.get_token_string(),
11055 0 : parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), BasicJsonType()));
11056 : }
11057 620 : }
11058 : }
11059 : else
11060 : {
11061 : skip_to_state_evaluation = false;
11062 : }
11063 :
11064 : // we reached this line after we successfully parsed a value
11065 : if (states.empty())
11066 : {
11067 : // empty stack: we reached the end of the hierarchy: done
11068 : return true;
11069 : }
11070 :
11071 5875 : if (states.back()) // array
11072 : {
11073 : // comma -> next value
11074 7134 : if (get_token() == token_type::value_separator)
11075 : {
11076 : // parse a new value
11077 : get_token();
11078 3257 : continue;
11079 : }
11080 :
11081 : // closing ]
11082 620 : if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
11083 : {
11084 0 : if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
11085 : {
11086 : return false;
11087 : }
11088 :
11089 : // We are done with this array. Before we can parse a
11090 : // new value, we need to evaluate the new state first.
11091 : // By setting skip_to_state_evaluation to false, we
11092 : // are effectively jumping to the beginning of this if.
11093 : JSON_ASSERT(!states.empty());
11094 : states.pop_back();
11095 : skip_to_state_evaluation = true;
11096 620 : continue;
11097 : }
11098 :
11099 0 : return sax->parse_error(m_lexer.get_position(),
11100 : m_lexer.get_token_string(),
11101 0 : parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), BasicJsonType()));
11102 : }
11103 :
11104 : // states.back() is false -> object
11105 :
11106 : // comma -> next value
11107 3400 : if (get_token() == token_type::value_separator)
11108 : {
11109 : // parse key
11110 1402 : if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
11111 : {
11112 0 : return sax->parse_error(m_lexer.get_position(),
11113 : m_lexer.get_token_string(),
11114 0 : parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType()));
11115 : }
11116 :
11117 0 : if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
11118 : {
11119 : return false;
11120 : }
11121 :
11122 : // parse separator (:)
11123 1402 : if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
11124 : {
11125 0 : return sax->parse_error(m_lexer.get_position(),
11126 : m_lexer.get_token_string(),
11127 0 : parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType()));
11128 : }
11129 :
11130 : // parse values
11131 : get_token();
11132 1402 : continue;
11133 : }
11134 :
11135 : // closing }
11136 596 : if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
11137 : {
11138 0 : if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
11139 : {
11140 : return false;
11141 : }
11142 :
11143 : // We are done with this object. Before we can parse a
11144 : // new value, we need to evaluate the new state first.
11145 : // By setting skip_to_state_evaluation to false, we
11146 : // are effectively jumping to the beginning of this if.
11147 : JSON_ASSERT(!states.empty());
11148 : states.pop_back();
11149 : skip_to_state_evaluation = true;
11150 596 : continue;
11151 : }
11152 :
11153 0 : return sax->parse_error(m_lexer.get_position(),
11154 : m_lexer.get_token_string(),
11155 0 : parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), BasicJsonType()));
11156 : }
11157 : }
11158 :
11159 : /// get next token from lexer
11160 : token_type get_token()
11161 : {
11162 9719 : return last_token = m_lexer.scan();
11163 : }
11164 :
11165 0 : std::string exception_message(const token_type expected, const std::string& context)
11166 : {
11167 0 : std::string error_msg = "syntax error ";
11168 :
11169 0 : if (!context.empty())
11170 : {
11171 0 : error_msg += "while parsing " + context + " ";
11172 : }
11173 :
11174 : error_msg += "- ";
11175 :
11176 0 : if (last_token == token_type::parse_error)
11177 : {
11178 0 : error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
11179 : m_lexer.get_token_string() + "'";
11180 : }
11181 : else
11182 : {
11183 0 : error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
11184 : }
11185 :
11186 0 : if (expected != token_type::uninitialized)
11187 : {
11188 0 : error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
11189 : }
11190 :
11191 0 : return error_msg;
11192 : }
11193 :
11194 : private:
11195 : /// callback function
11196 : const parser_callback_t<BasicJsonType> callback = nullptr;
11197 : /// the type of the last read token
11198 : token_type last_token = token_type::uninitialized;
11199 : /// the lexer
11200 : lexer_t m_lexer;
11201 : /// whether to throw exceptions in case of errors
11202 : const bool allow_exceptions = true;
11203 : };
11204 :
11205 : } // namespace detail
11206 : } // namespace nlohmann
11207 :
11208 : // #include <nlohmann/detail/iterators/internal_iterator.hpp>
11209 :
11210 :
11211 : // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
11212 :
11213 :
11214 : #include <cstddef> // ptrdiff_t
11215 : #include <limits> // numeric_limits
11216 :
11217 : // #include <nlohmann/detail/macro_scope.hpp>
11218 :
11219 :
11220 : namespace nlohmann
11221 : {
11222 : namespace detail
11223 : {
11224 : /*
11225 : @brief an iterator for primitive JSON types
11226 :
11227 : This class models an iterator for primitive JSON types (boolean, number,
11228 : string). It's only purpose is to allow the iterator/const_iterator classes
11229 : to "iterate" over primitive values. Internally, the iterator is modeled by
11230 : a `difference_type` variable. Value begin_value (`0`) models the begin,
11231 : end_value (`1`) models past the end.
11232 : */
11233 756 : class primitive_iterator_t
11234 : {
11235 : private:
11236 : using difference_type = std::ptrdiff_t;
11237 : static constexpr difference_type begin_value = 0;
11238 : static constexpr difference_type end_value = begin_value + 1;
11239 :
11240 : JSON_PRIVATE_UNLESS_TESTED:
11241 : /// iterator as signed integer type
11242 : difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
11243 :
11244 : public:
11245 : constexpr difference_type get_value() const noexcept
11246 : {
11247 : return m_it;
11248 : }
11249 :
11250 : /// set iterator to a defined beginning
11251 : void set_begin() noexcept
11252 : {
11253 0 : m_it = begin_value;
11254 0 : }
11255 :
11256 : /// set iterator to a defined past the end
11257 : void set_end() noexcept
11258 : {
11259 0 : m_it = end_value;
11260 0 : }
11261 :
11262 : /// return whether the iterator can be dereferenced
11263 : constexpr bool is_begin() const noexcept
11264 : {
11265 0 : return m_it == begin_value;
11266 : }
11267 :
11268 : /// return whether the iterator is at end
11269 : constexpr bool is_end() const noexcept
11270 : {
11271 : return m_it == end_value;
11272 : }
11273 :
11274 : friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
11275 : {
11276 0 : return lhs.m_it == rhs.m_it;
11277 : }
11278 :
11279 : friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
11280 : {
11281 : return lhs.m_it < rhs.m_it;
11282 : }
11283 :
11284 : primitive_iterator_t operator+(difference_type n) noexcept
11285 : {
11286 : auto result = *this;
11287 : result += n;
11288 : return result;
11289 : }
11290 :
11291 : friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
11292 : {
11293 : return lhs.m_it - rhs.m_it;
11294 : }
11295 :
11296 : primitive_iterator_t& operator++() noexcept
11297 : {
11298 0 : ++m_it;
11299 0 : return *this;
11300 : }
11301 :
11302 : primitive_iterator_t const operator++(int) noexcept // NOLINT(readability-const-return-type)
11303 : {
11304 : auto result = *this;
11305 : ++m_it;
11306 : return result;
11307 : }
11308 :
11309 : primitive_iterator_t& operator--() noexcept
11310 : {
11311 : --m_it;
11312 : return *this;
11313 : }
11314 :
11315 : primitive_iterator_t const operator--(int) noexcept // NOLINT(readability-const-return-type)
11316 : {
11317 : auto result = *this;
11318 : --m_it;
11319 : return result;
11320 : }
11321 :
11322 : primitive_iterator_t& operator+=(difference_type n) noexcept
11323 : {
11324 : m_it += n;
11325 : return *this;
11326 : }
11327 :
11328 : primitive_iterator_t& operator-=(difference_type n) noexcept
11329 : {
11330 : m_it -= n;
11331 : return *this;
11332 : }
11333 : };
11334 : } // namespace detail
11335 : } // namespace nlohmann
11336 :
11337 :
11338 : namespace nlohmann
11339 : {
11340 : namespace detail
11341 : {
11342 : /*!
11343 : @brief an iterator value
11344 :
11345 : @note This structure could easily be a union, but MSVC currently does not allow
11346 : unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
11347 : */
11348 : template<typename BasicJsonType> struct internal_iterator
11349 : {
11350 : /// iterator for JSON objects
11351 : typename BasicJsonType::object_t::iterator object_iterator {};
11352 : /// iterator for JSON arrays
11353 : typename BasicJsonType::array_t::iterator array_iterator {};
11354 : /// generic iterator for all other types
11355 : primitive_iterator_t primitive_iterator {};
11356 : };
11357 : } // namespace detail
11358 : } // namespace nlohmann
11359 :
11360 : // #include <nlohmann/detail/iterators/iter_impl.hpp>
11361 :
11362 :
11363 : #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
11364 : #include <type_traits> // conditional, is_const, remove_const
11365 :
11366 : // #include <nlohmann/detail/exceptions.hpp>
11367 :
11368 : // #include <nlohmann/detail/iterators/internal_iterator.hpp>
11369 :
11370 : // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
11371 :
11372 : // #include <nlohmann/detail/macro_scope.hpp>
11373 :
11374 : // #include <nlohmann/detail/meta/cpp_future.hpp>
11375 :
11376 : // #include <nlohmann/detail/meta/type_traits.hpp>
11377 :
11378 : // #include <nlohmann/detail/value_t.hpp>
11379 :
11380 :
11381 : namespace nlohmann
11382 : {
11383 : namespace detail
11384 : {
11385 : // forward declare, to be able to friend it later on
11386 : template<typename IteratorType> class iteration_proxy;
11387 : template<typename IteratorType> class iteration_proxy_value;
11388 :
11389 : /*!
11390 : @brief a template for a bidirectional iterator for the @ref basic_json class
11391 : This class implements a both iterators (iterator and const_iterator) for the
11392 : @ref basic_json class.
11393 : @note An iterator is called *initialized* when a pointer to a JSON value has
11394 : been set (e.g., by a constructor or a copy assignment). If the iterator is
11395 : default-constructed, it is *uninitialized* and most methods are undefined.
11396 : **The library uses assertions to detect calls on uninitialized iterators.**
11397 : @requirement The class satisfies the following concept requirements:
11398 : -
11399 : [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
11400 : The iterator that can be moved can be moved in both directions (i.e.
11401 : incremented and decremented).
11402 : @since version 1.0.0, simplified in version 2.0.9, change to bidirectional
11403 : iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
11404 : */
11405 : template<typename BasicJsonType>
11406 : class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
11407 : {
11408 : /// the iterator with BasicJsonType of different const-ness
11409 : using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
11410 : /// allow basic_json to access private members
11411 : friend other_iter_impl;
11412 : friend BasicJsonType;
11413 : friend iteration_proxy<iter_impl>;
11414 : friend iteration_proxy_value<iter_impl>;
11415 :
11416 : using object_t = typename BasicJsonType::object_t;
11417 : using array_t = typename BasicJsonType::array_t;
11418 : // make sure BasicJsonType is basic_json or const basic_json
11419 : static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
11420 : "iter_impl only accepts (const) basic_json");
11421 :
11422 : public:
11423 :
11424 : /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
11425 : /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
11426 : /// A user-defined iterator should provide publicly accessible typedefs named
11427 : /// iterator_category, value_type, difference_type, pointer, and reference.
11428 : /// Note that value_type is required to be non-const, even for constant iterators.
11429 : using iterator_category = std::bidirectional_iterator_tag;
11430 :
11431 : /// the type of the values when the iterator is dereferenced
11432 : using value_type = typename BasicJsonType::value_type;
11433 : /// a type to represent differences between iterators
11434 : using difference_type = typename BasicJsonType::difference_type;
11435 : /// defines a pointer to the type iterated over (value_type)
11436 : using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
11437 : typename BasicJsonType::const_pointer,
11438 : typename BasicJsonType::pointer>::type;
11439 : /// defines a reference to the type iterated over (value_type)
11440 : using reference =
11441 : typename std::conditional<std::is_const<BasicJsonType>::value,
11442 : typename BasicJsonType::const_reference,
11443 : typename BasicJsonType::reference>::type;
11444 :
11445 : iter_impl() = default;
11446 : ~iter_impl() = default;
11447 : iter_impl(iter_impl&&) noexcept = default;
11448 : iter_impl& operator=(iter_impl&&) noexcept = default;
11449 :
11450 : /*!
11451 : @brief constructor for a given JSON instance
11452 : @param[in] object pointer to a JSON object for this iterator
11453 : @pre object != nullptr
11454 : @post The iterator is initialized; i.e. `m_object != nullptr`.
11455 : */
11456 756 : explicit iter_impl(pointer object) noexcept : m_object(object)
11457 : {
11458 : JSON_ASSERT(m_object != nullptr);
11459 :
11460 756 : switch (m_object->m_type)
11461 : {
11462 : case value_t::object:
11463 : {
11464 452 : m_it.object_iterator = typename object_t::iterator();
11465 452 : break;
11466 : }
11467 :
11468 : case value_t::array:
11469 : {
11470 304 : m_it.array_iterator = typename array_t::iterator();
11471 304 : break;
11472 : }
11473 :
11474 0 : case value_t::null:
11475 : case value_t::string:
11476 : case value_t::boolean:
11477 : case value_t::number_integer:
11478 : case value_t::number_unsigned:
11479 : case value_t::number_float:
11480 : case value_t::binary:
11481 : case value_t::discarded:
11482 : default:
11483 : {
11484 0 : m_it.primitive_iterator = primitive_iterator_t();
11485 0 : break;
11486 : }
11487 : }
11488 : }
11489 :
11490 : /*!
11491 : @note The conventional copy constructor and copy assignment are implicitly
11492 : defined. Combined with the following converting constructor and
11493 : assignment, they support: (1) copy from iterator to iterator, (2)
11494 : copy from const iterator to const iterator, and (3) conversion from
11495 : iterator to const iterator. However conversion from const iterator
11496 : to iterator is not defined.
11497 : */
11498 :
11499 : /*!
11500 : @brief const copy constructor
11501 : @param[in] other const iterator to copy from
11502 : @note This copy constructor had to be defined explicitly to circumvent a bug
11503 : occurring on msvc v19.0 compiler (VS 2015) debug build. For more
11504 : information refer to: https://github.com/nlohmann/json/issues/1608
11505 : */
11506 : iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
11507 : : m_object(other.m_object), m_it(other.m_it)
11508 : {}
11509 :
11510 : /*!
11511 : @brief converting assignment
11512 : @param[in] other const iterator to copy from
11513 : @return const/non-const iterator
11514 : @note It is not checked whether @a other is initialized.
11515 : */
11516 : iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
11517 : {
11518 : if (&other != this)
11519 : {
11520 : m_object = other.m_object;
11521 : m_it = other.m_it;
11522 : }
11523 : return *this;
11524 : }
11525 :
11526 : /*!
11527 : @brief converting constructor
11528 : @param[in] other non-const iterator to copy from
11529 : @note It is not checked whether @a other is initialized.
11530 : */
11531 0 : iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
11532 0 : : m_object(other.m_object), m_it(other.m_it)
11533 : {}
11534 :
11535 : /*!
11536 : @brief converting assignment
11537 : @param[in] other non-const iterator to copy from
11538 : @return const/non-const iterator
11539 : @note It is not checked whether @a other is initialized.
11540 : */
11541 : iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
11542 : {
11543 : m_object = other.m_object;
11544 : m_it = other.m_it;
11545 : return *this;
11546 : }
11547 :
11548 : JSON_PRIVATE_UNLESS_TESTED:
11549 : /*!
11550 : @brief set the iterator to the first value
11551 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11552 : */
11553 : void set_begin() noexcept
11554 : {
11555 : JSON_ASSERT(m_object != nullptr);
11556 :
11557 154 : switch (m_object->m_type)
11558 : {
11559 2 : case value_t::object:
11560 : {
11561 2 : m_it.object_iterator = m_object->m_value.object->begin();
11562 2 : break;
11563 : }
11564 :
11565 152 : case value_t::array:
11566 : {
11567 152 : m_it.array_iterator = m_object->m_value.array->begin();
11568 152 : break;
11569 : }
11570 :
11571 0 : case value_t::null:
11572 : {
11573 : // set to end so begin()==end() is true: null is empty
11574 : m_it.primitive_iterator.set_end();
11575 : break;
11576 : }
11577 :
11578 0 : case value_t::string:
11579 : case value_t::boolean:
11580 : case value_t::number_integer:
11581 : case value_t::number_unsigned:
11582 : case value_t::number_float:
11583 : case value_t::binary:
11584 : case value_t::discarded:
11585 : default:
11586 : {
11587 : m_it.primitive_iterator.set_begin();
11588 : break;
11589 : }
11590 : }
11591 : }
11592 :
11593 : /*!
11594 : @brief set the iterator past the last value
11595 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11596 : */
11597 : void set_end() noexcept
11598 : {
11599 : JSON_ASSERT(m_object != nullptr);
11600 :
11601 602 : switch (m_object->m_type)
11602 : {
11603 450 : case value_t::object:
11604 : {
11605 450 : m_it.object_iterator = m_object->m_value.object->end();
11606 450 : break;
11607 : }
11608 :
11609 152 : case value_t::array:
11610 : {
11611 152 : m_it.array_iterator = m_object->m_value.array->end();
11612 152 : break;
11613 : }
11614 :
11615 0 : case value_t::null:
11616 : case value_t::string:
11617 : case value_t::boolean:
11618 : case value_t::number_integer:
11619 : case value_t::number_unsigned:
11620 : case value_t::number_float:
11621 : case value_t::binary:
11622 : case value_t::discarded:
11623 : default:
11624 : {
11625 : m_it.primitive_iterator.set_end();
11626 : break;
11627 : }
11628 : }
11629 : }
11630 :
11631 : public:
11632 : /*!
11633 : @brief return a reference to the value pointed to by the iterator
11634 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11635 : */
11636 2043 : reference operator*() const
11637 : {
11638 : JSON_ASSERT(m_object != nullptr);
11639 :
11640 2043 : switch (m_object->m_type)
11641 : {
11642 186 : case value_t::object:
11643 : {
11644 : JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
11645 186 : return m_it.object_iterator->second;
11646 : }
11647 :
11648 1857 : case value_t::array:
11649 : {
11650 : JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
11651 1857 : return *m_it.array_iterator;
11652 : }
11653 :
11654 0 : case value_t::null:
11655 0 : JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11656 :
11657 0 : case value_t::string:
11658 : case value_t::boolean:
11659 : case value_t::number_integer:
11660 : case value_t::number_unsigned:
11661 : case value_t::number_float:
11662 : case value_t::binary:
11663 : case value_t::discarded:
11664 : default:
11665 : {
11666 0 : if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
11667 : {
11668 : return *m_object;
11669 : }
11670 :
11671 0 : JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11672 : }
11673 : }
11674 : }
11675 :
11676 : /*!
11677 : @brief dereference the iterator
11678 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11679 : */
11680 420 : pointer operator->() const
11681 : {
11682 : JSON_ASSERT(m_object != nullptr);
11683 :
11684 420 : switch (m_object->m_type)
11685 : {
11686 420 : case value_t::object:
11687 : {
11688 : JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
11689 420 : return &(m_it.object_iterator->second);
11690 : }
11691 :
11692 0 : case value_t::array:
11693 : {
11694 : JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
11695 0 : return &*m_it.array_iterator;
11696 : }
11697 :
11698 0 : case value_t::null:
11699 : case value_t::string:
11700 : case value_t::boolean:
11701 : case value_t::number_integer:
11702 : case value_t::number_unsigned:
11703 : case value_t::number_float:
11704 : case value_t::binary:
11705 : case value_t::discarded:
11706 : default:
11707 : {
11708 0 : if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
11709 : {
11710 : return m_object;
11711 : }
11712 :
11713 0 : JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11714 : }
11715 : }
11716 : }
11717 :
11718 : /*!
11719 : @brief post-increment (it++)
11720 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11721 : */
11722 : iter_impl const operator++(int) // NOLINT(readability-const-return-type)
11723 : {
11724 : auto result = *this;
11725 : ++(*this);
11726 : return result;
11727 : }
11728 :
11729 : /*!
11730 : @brief pre-increment (++it)
11731 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11732 : */
11733 1863 : iter_impl& operator++()
11734 : {
11735 : JSON_ASSERT(m_object != nullptr);
11736 :
11737 1863 : switch (m_object->m_type)
11738 : {
11739 6 : case value_t::object:
11740 : {
11741 6 : std::advance(m_it.object_iterator, 1);
11742 : break;
11743 : }
11744 :
11745 1857 : case value_t::array:
11746 : {
11747 0 : std::advance(m_it.array_iterator, 1);
11748 : break;
11749 : }
11750 :
11751 0 : case value_t::null:
11752 : case value_t::string:
11753 : case value_t::boolean:
11754 : case value_t::number_integer:
11755 : case value_t::number_unsigned:
11756 : case value_t::number_float:
11757 : case value_t::binary:
11758 : case value_t::discarded:
11759 : default:
11760 : {
11761 : ++m_it.primitive_iterator;
11762 : break;
11763 : }
11764 : }
11765 :
11766 1863 : return *this;
11767 : }
11768 :
11769 : /*!
11770 : @brief post-decrement (it--)
11771 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11772 : */
11773 : iter_impl const operator--(int) // NOLINT(readability-const-return-type)
11774 : {
11775 : auto result = *this;
11776 : --(*this);
11777 : return result;
11778 : }
11779 :
11780 : /*!
11781 : @brief pre-decrement (--it)
11782 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11783 : */
11784 : iter_impl& operator--()
11785 : {
11786 : JSON_ASSERT(m_object != nullptr);
11787 :
11788 : switch (m_object->m_type)
11789 : {
11790 : case value_t::object:
11791 : {
11792 : std::advance(m_it.object_iterator, -1);
11793 : break;
11794 : }
11795 :
11796 : case value_t::array:
11797 : {
11798 : std::advance(m_it.array_iterator, -1);
11799 : break;
11800 : }
11801 :
11802 : case value_t::null:
11803 : case value_t::string:
11804 : case value_t::boolean:
11805 : case value_t::number_integer:
11806 : case value_t::number_unsigned:
11807 : case value_t::number_float:
11808 : case value_t::binary:
11809 : case value_t::discarded:
11810 : default:
11811 : {
11812 : --m_it.primitive_iterator;
11813 : break;
11814 : }
11815 : }
11816 :
11817 : return *this;
11818 : }
11819 :
11820 : /*!
11821 : @brief comparison: equal
11822 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11823 : */
11824 : template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
11825 2241 : bool operator==(const IterImpl& other) const
11826 : {
11827 : // if objects are not the same, the comparison is undefined
11828 2241 : if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
11829 : {
11830 0 : JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
11831 : }
11832 :
11833 : JSON_ASSERT(m_object != nullptr);
11834 :
11835 2241 : switch (m_object->m_type)
11836 : {
11837 232 : case value_t::object:
11838 232 : return (m_it.object_iterator == other.m_it.object_iterator);
11839 :
11840 2009 : case value_t::array:
11841 2009 : return (m_it.array_iterator == other.m_it.array_iterator);
11842 :
11843 0 : case value_t::null:
11844 : case value_t::string:
11845 : case value_t::boolean:
11846 : case value_t::number_integer:
11847 : case value_t::number_unsigned:
11848 : case value_t::number_float:
11849 : case value_t::binary:
11850 : case value_t::discarded:
11851 : default:
11852 0 : return (m_it.primitive_iterator == other.m_it.primitive_iterator);
11853 : }
11854 : }
11855 :
11856 : /*!
11857 : @brief comparison: not equal
11858 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11859 : */
11860 : template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
11861 : bool operator!=(const IterImpl& other) const
11862 : {
11863 2017 : return !operator==(other);
11864 : }
11865 :
11866 : /*!
11867 : @brief comparison: smaller
11868 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11869 : */
11870 : bool operator<(const iter_impl& other) const
11871 : {
11872 : // if objects are not the same, the comparison is undefined
11873 : if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
11874 : {
11875 : JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
11876 : }
11877 :
11878 : JSON_ASSERT(m_object != nullptr);
11879 :
11880 : switch (m_object->m_type)
11881 : {
11882 : case value_t::object:
11883 : JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object));
11884 :
11885 : case value_t::array:
11886 : return (m_it.array_iterator < other.m_it.array_iterator);
11887 :
11888 : case value_t::null:
11889 : case value_t::string:
11890 : case value_t::boolean:
11891 : case value_t::number_integer:
11892 : case value_t::number_unsigned:
11893 : case value_t::number_float:
11894 : case value_t::binary:
11895 : case value_t::discarded:
11896 : default:
11897 : return (m_it.primitive_iterator < other.m_it.primitive_iterator);
11898 : }
11899 : }
11900 :
11901 : /*!
11902 : @brief comparison: less than or equal
11903 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11904 : */
11905 : bool operator<=(const iter_impl& other) const
11906 : {
11907 : return !other.operator < (*this);
11908 : }
11909 :
11910 : /*!
11911 : @brief comparison: greater than
11912 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11913 : */
11914 : bool operator>(const iter_impl& other) const
11915 : {
11916 : return !operator<=(other);
11917 : }
11918 :
11919 : /*!
11920 : @brief comparison: greater than or equal
11921 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11922 : */
11923 : bool operator>=(const iter_impl& other) const
11924 : {
11925 : return !operator<(other);
11926 : }
11927 :
11928 : /*!
11929 : @brief add to iterator
11930 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11931 : */
11932 : iter_impl& operator+=(difference_type i)
11933 : {
11934 : JSON_ASSERT(m_object != nullptr);
11935 :
11936 : switch (m_object->m_type)
11937 : {
11938 : case value_t::object:
11939 : JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
11940 :
11941 : case value_t::array:
11942 : {
11943 : std::advance(m_it.array_iterator, i);
11944 : break;
11945 : }
11946 :
11947 : case value_t::null:
11948 : case value_t::string:
11949 : case value_t::boolean:
11950 : case value_t::number_integer:
11951 : case value_t::number_unsigned:
11952 : case value_t::number_float:
11953 : case value_t::binary:
11954 : case value_t::discarded:
11955 : default:
11956 : {
11957 : m_it.primitive_iterator += i;
11958 : break;
11959 : }
11960 : }
11961 :
11962 : return *this;
11963 : }
11964 :
11965 : /*!
11966 : @brief subtract from iterator
11967 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11968 : */
11969 : iter_impl& operator-=(difference_type i)
11970 : {
11971 : return operator+=(-i);
11972 : }
11973 :
11974 : /*!
11975 : @brief add to iterator
11976 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11977 : */
11978 : iter_impl operator+(difference_type i) const
11979 : {
11980 : auto result = *this;
11981 : result += i;
11982 : return result;
11983 : }
11984 :
11985 : /*!
11986 : @brief addition of distance and iterator
11987 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11988 : */
11989 : friend iter_impl operator+(difference_type i, const iter_impl& it)
11990 : {
11991 : auto result = it;
11992 : result += i;
11993 : return result;
11994 : }
11995 :
11996 : /*!
11997 : @brief subtract from iterator
11998 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
11999 : */
12000 : iter_impl operator-(difference_type i) const
12001 : {
12002 : auto result = *this;
12003 : result -= i;
12004 : return result;
12005 : }
12006 :
12007 : /*!
12008 : @brief return difference
12009 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
12010 : */
12011 : difference_type operator-(const iter_impl& other) const
12012 : {
12013 : JSON_ASSERT(m_object != nullptr);
12014 :
12015 : switch (m_object->m_type)
12016 : {
12017 : case value_t::object:
12018 : JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
12019 :
12020 : case value_t::array:
12021 : return m_it.array_iterator - other.m_it.array_iterator;
12022 :
12023 : case value_t::null:
12024 : case value_t::string:
12025 : case value_t::boolean:
12026 : case value_t::number_integer:
12027 : case value_t::number_unsigned:
12028 : case value_t::number_float:
12029 : case value_t::binary:
12030 : case value_t::discarded:
12031 : default:
12032 : return m_it.primitive_iterator - other.m_it.primitive_iterator;
12033 : }
12034 : }
12035 :
12036 : /*!
12037 : @brief access to successor
12038 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
12039 : */
12040 : reference operator[](difference_type n) const
12041 : {
12042 : JSON_ASSERT(m_object != nullptr);
12043 :
12044 : switch (m_object->m_type)
12045 : {
12046 : case value_t::object:
12047 : JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object));
12048 :
12049 : case value_t::array:
12050 : return *std::next(m_it.array_iterator, n);
12051 :
12052 : case value_t::null:
12053 : JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
12054 :
12055 : case value_t::string:
12056 : case value_t::boolean:
12057 : case value_t::number_integer:
12058 : case value_t::number_unsigned:
12059 : case value_t::number_float:
12060 : case value_t::binary:
12061 : case value_t::discarded:
12062 : default:
12063 : {
12064 : if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
12065 : {
12066 : return *m_object;
12067 : }
12068 :
12069 : JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
12070 : }
12071 : }
12072 : }
12073 :
12074 : /*!
12075 : @brief return the key of an object iterator
12076 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
12077 : */
12078 6 : const typename object_t::key_type& key() const
12079 : {
12080 : JSON_ASSERT(m_object != nullptr);
12081 :
12082 6 : if (JSON_HEDLEY_LIKELY(m_object->is_object()))
12083 : {
12084 6 : return m_it.object_iterator->first;
12085 : }
12086 :
12087 0 : JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object));
12088 : }
12089 :
12090 : /*!
12091 : @brief return the value of an iterator
12092 : @pre The iterator is initialized; i.e. `m_object != nullptr`.
12093 : */
12094 : reference value() const
12095 : {
12096 18 : return operator*();
12097 : }
12098 :
12099 : JSON_PRIVATE_UNLESS_TESTED:
12100 : /// associated JSON instance
12101 : pointer m_object = nullptr;
12102 : /// the actual iterator of the associated instance
12103 : internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
12104 : };
12105 : } // namespace detail
12106 : } // namespace nlohmann
12107 :
12108 : // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
12109 :
12110 : // #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
12111 :
12112 :
12113 : #include <cstddef> // ptrdiff_t
12114 : #include <iterator> // reverse_iterator
12115 : #include <utility> // declval
12116 :
12117 : namespace nlohmann
12118 : {
12119 : namespace detail
12120 : {
12121 : //////////////////////
12122 : // reverse_iterator //
12123 : //////////////////////
12124 :
12125 : /*!
12126 : @brief a template for a reverse iterator class
12127 :
12128 : @tparam Base the base iterator type to reverse. Valid types are @ref
12129 : iterator (to create @ref reverse_iterator) and @ref const_iterator (to
12130 : create @ref const_reverse_iterator).
12131 :
12132 : @requirement The class satisfies the following concept requirements:
12133 : -
12134 : [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
12135 : The iterator that can be moved can be moved in both directions (i.e.
12136 : incremented and decremented).
12137 : - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
12138 : It is possible to write to the pointed-to element (only if @a Base is
12139 : @ref iterator).
12140 :
12141 : @since version 1.0.0
12142 : */
12143 : template<typename Base>
12144 : class json_reverse_iterator : public std::reverse_iterator<Base>
12145 : {
12146 : public:
12147 : using difference_type = std::ptrdiff_t;
12148 : /// shortcut to the reverse iterator adapter
12149 : using base_iterator = std::reverse_iterator<Base>;
12150 : /// the reference type for the pointed-to element
12151 : using reference = typename Base::reference;
12152 :
12153 : /// create reverse iterator from iterator
12154 : explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
12155 : : base_iterator(it) {}
12156 :
12157 : /// create reverse iterator from base class
12158 : explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
12159 :
12160 : /// post-increment (it++)
12161 : json_reverse_iterator const operator++(int) // NOLINT(readability-const-return-type)
12162 : {
12163 : return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
12164 : }
12165 :
12166 : /// pre-increment (++it)
12167 : json_reverse_iterator& operator++()
12168 : {
12169 : return static_cast<json_reverse_iterator&>(base_iterator::operator++());
12170 : }
12171 :
12172 : /// post-decrement (it--)
12173 : json_reverse_iterator const operator--(int) // NOLINT(readability-const-return-type)
12174 : {
12175 : return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
12176 : }
12177 :
12178 : /// pre-decrement (--it)
12179 : json_reverse_iterator& operator--()
12180 : {
12181 : return static_cast<json_reverse_iterator&>(base_iterator::operator--());
12182 : }
12183 :
12184 : /// add to iterator
12185 : json_reverse_iterator& operator+=(difference_type i)
12186 : {
12187 : return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
12188 : }
12189 :
12190 : /// add to iterator
12191 : json_reverse_iterator operator+(difference_type i) const
12192 : {
12193 : return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
12194 : }
12195 :
12196 : /// subtract from iterator
12197 : json_reverse_iterator operator-(difference_type i) const
12198 : {
12199 : return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
12200 : }
12201 :
12202 : /// return difference
12203 : difference_type operator-(const json_reverse_iterator& other) const
12204 : {
12205 : return base_iterator(*this) - base_iterator(other);
12206 : }
12207 :
12208 : /// access to successor
12209 : reference operator[](difference_type n) const
12210 : {
12211 : return *(this->operator+(n));
12212 : }
12213 :
12214 : /// return the key of an object iterator
12215 : auto key() const -> decltype(std::declval<Base>().key())
12216 : {
12217 : auto it = --this->base();
12218 : return it.key();
12219 : }
12220 :
12221 : /// return the value of an iterator
12222 : reference value() const
12223 : {
12224 : auto it = --this->base();
12225 : return it.operator * ();
12226 : }
12227 : };
12228 : } // namespace detail
12229 : } // namespace nlohmann
12230 :
12231 : // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12232 :
12233 : // #include <nlohmann/detail/json_pointer.hpp>
12234 :
12235 :
12236 : #include <algorithm> // all_of
12237 : #include <cctype> // isdigit
12238 : #include <limits> // max
12239 : #include <numeric> // accumulate
12240 : #include <string> // string
12241 : #include <utility> // move
12242 : #include <vector> // vector
12243 :
12244 : // #include <nlohmann/detail/exceptions.hpp>
12245 :
12246 : // #include <nlohmann/detail/macro_scope.hpp>
12247 :
12248 : // #include <nlohmann/detail/string_escape.hpp>
12249 :
12250 : // #include <nlohmann/detail/value_t.hpp>
12251 :
12252 :
12253 : namespace nlohmann
12254 : {
12255 :
12256 : /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
12257 : /// @sa https://json.nlohmann.me/api/json_pointer/
12258 : template<typename BasicJsonType>
12259 : class json_pointer
12260 : {
12261 : // allow basic_json to access private members
12262 : NLOHMANN_BASIC_JSON_TPL_DECLARATION
12263 : friend class basic_json;
12264 :
12265 : public:
12266 : /// @brief create JSON pointer
12267 : /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
12268 : explicit json_pointer(const std::string& s = "")
12269 : : reference_tokens(split(s))
12270 : {}
12271 :
12272 : /// @brief return a string representation of the JSON pointer
12273 : /// @sa https://json.nlohmann.me/api/json_pointer/to_string/
12274 : std::string to_string() const
12275 : {
12276 : return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
12277 : std::string{},
12278 : [](const std::string & a, const std::string & b)
12279 : {
12280 : return a + "/" + detail::escape(b);
12281 : });
12282 : }
12283 :
12284 : /// @brief return a string representation of the JSON pointer
12285 : /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
12286 : operator std::string() const
12287 : {
12288 : return to_string();
12289 : }
12290 :
12291 : /// @brief append another JSON pointer at the end of this JSON pointer
12292 : /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
12293 : json_pointer& operator/=(const json_pointer& ptr)
12294 : {
12295 : reference_tokens.insert(reference_tokens.end(),
12296 : ptr.reference_tokens.begin(),
12297 : ptr.reference_tokens.end());
12298 : return *this;
12299 : }
12300 :
12301 : /// @brief append an unescaped reference token at the end of this JSON pointer
12302 : /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
12303 : json_pointer& operator/=(std::string token)
12304 : {
12305 : push_back(std::move(token));
12306 : return *this;
12307 : }
12308 :
12309 : /// @brief append an array index at the end of this JSON pointer
12310 : /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
12311 : json_pointer& operator/=(std::size_t array_idx)
12312 : {
12313 : return *this /= std::to_string(array_idx);
12314 : }
12315 :
12316 : /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
12317 : /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
12318 : friend json_pointer operator/(const json_pointer& lhs,
12319 : const json_pointer& rhs)
12320 : {
12321 : return json_pointer(lhs) /= rhs;
12322 : }
12323 :
12324 : /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
12325 : /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
12326 : friend json_pointer operator/(const json_pointer& lhs, std::string token) // NOLINT(performance-unnecessary-value-param)
12327 : {
12328 : return json_pointer(lhs) /= std::move(token);
12329 : }
12330 :
12331 : /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
12332 : /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
12333 : friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
12334 : {
12335 : return json_pointer(lhs) /= array_idx;
12336 : }
12337 :
12338 : /// @brief returns the parent of this JSON pointer
12339 : /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
12340 : json_pointer parent_pointer() const
12341 : {
12342 : if (empty())
12343 : {
12344 : return *this;
12345 : }
12346 :
12347 : json_pointer res = *this;
12348 : res.pop_back();
12349 : return res;
12350 : }
12351 :
12352 : /// @brief remove last reference token
12353 : /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
12354 : void pop_back()
12355 : {
12356 : if (JSON_HEDLEY_UNLIKELY(empty()))
12357 : {
12358 : JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
12359 : }
12360 :
12361 : reference_tokens.pop_back();
12362 : }
12363 :
12364 : /// @brief return last reference token
12365 : /// @sa https://json.nlohmann.me/api/json_pointer/back/
12366 : const std::string& back() const
12367 : {
12368 : if (JSON_HEDLEY_UNLIKELY(empty()))
12369 : {
12370 : JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
12371 : }
12372 :
12373 : return reference_tokens.back();
12374 : }
12375 :
12376 : /// @brief append an unescaped token at the end of the reference pointer
12377 : /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
12378 : void push_back(const std::string& token)
12379 : {
12380 : reference_tokens.push_back(token);
12381 : }
12382 :
12383 : /// @brief append an unescaped token at the end of the reference pointer
12384 : /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
12385 : void push_back(std::string&& token)
12386 : {
12387 : reference_tokens.push_back(std::move(token));
12388 : }
12389 :
12390 : /// @brief return whether pointer points to the root document
12391 : /// @sa https://json.nlohmann.me/api/json_pointer/empty/
12392 : bool empty() const noexcept
12393 : {
12394 : return reference_tokens.empty();
12395 : }
12396 :
12397 : private:
12398 : /*!
12399 : @param[in] s reference token to be converted into an array index
12400 :
12401 : @return integer representation of @a s
12402 :
12403 : @throw parse_error.106 if an array index begins with '0'
12404 : @throw parse_error.109 if an array index begins not with a digit
12405 : @throw out_of_range.404 if string @a s could not be converted to an integer
12406 : @throw out_of_range.410 if an array index exceeds size_type
12407 : */
12408 : static typename BasicJsonType::size_type array_index(const std::string& s)
12409 : {
12410 : using size_type = typename BasicJsonType::size_type;
12411 :
12412 : // error condition (cf. RFC 6901, Sect. 4)
12413 : if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
12414 : {
12415 : JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", BasicJsonType()));
12416 : }
12417 :
12418 : // error condition (cf. RFC 6901, Sect. 4)
12419 : if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
12420 : {
12421 : JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType()));
12422 : }
12423 :
12424 : std::size_t processed_chars = 0;
12425 : unsigned long long res = 0; // NOLINT(runtime/int)
12426 : JSON_TRY
12427 : {
12428 : res = std::stoull(s, &processed_chars);
12429 : }
12430 : JSON_CATCH(std::out_of_range&)
12431 : {
12432 : JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
12433 : }
12434 :
12435 : // check if the string was completely read
12436 : if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
12437 : {
12438 : JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
12439 : }
12440 :
12441 : // only triggered on special platforms (like 32bit), see also
12442 : // https://github.com/nlohmann/json/pull/2203
12443 : if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
12444 : {
12445 : JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", BasicJsonType())); // LCOV_EXCL_LINE
12446 : }
12447 :
12448 : return static_cast<size_type>(res);
12449 : }
12450 :
12451 : JSON_PRIVATE_UNLESS_TESTED:
12452 : json_pointer top() const
12453 : {
12454 : if (JSON_HEDLEY_UNLIKELY(empty()))
12455 : {
12456 : JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
12457 : }
12458 :
12459 : json_pointer result = *this;
12460 : result.reference_tokens = {reference_tokens[0]};
12461 : return result;
12462 : }
12463 :
12464 : private:
12465 : /*!
12466 : @brief create and return a reference to the pointed to value
12467 :
12468 : @complexity Linear in the number of reference tokens.
12469 :
12470 : @throw parse_error.109 if array index is not a number
12471 : @throw type_error.313 if value cannot be unflattened
12472 : */
12473 : BasicJsonType& get_and_create(BasicJsonType& j) const
12474 : {
12475 : auto* result = &j;
12476 :
12477 : // in case no reference tokens exist, return a reference to the JSON value
12478 : // j which will be overwritten by a primitive value
12479 : for (const auto& reference_token : reference_tokens)
12480 : {
12481 : switch (result->type())
12482 : {
12483 : case detail::value_t::null:
12484 : {
12485 : if (reference_token == "0")
12486 : {
12487 : // start a new array if reference token is 0
12488 : result = &result->operator[](0);
12489 : }
12490 : else
12491 : {
12492 : // start a new object otherwise
12493 : result = &result->operator[](reference_token);
12494 : }
12495 : break;
12496 : }
12497 :
12498 : case detail::value_t::object:
12499 : {
12500 : // create an entry in the object
12501 : result = &result->operator[](reference_token);
12502 : break;
12503 : }
12504 :
12505 : case detail::value_t::array:
12506 : {
12507 : // create an entry in the array
12508 : result = &result->operator[](array_index(reference_token));
12509 : break;
12510 : }
12511 :
12512 : /*
12513 : The following code is only reached if there exists a reference
12514 : token _and_ the current value is primitive. In this case, we have
12515 : an error situation, because primitive values may only occur as
12516 : single value; that is, with an empty list of reference tokens.
12517 : */
12518 : case detail::value_t::string:
12519 : case detail::value_t::boolean:
12520 : case detail::value_t::number_integer:
12521 : case detail::value_t::number_unsigned:
12522 : case detail::value_t::number_float:
12523 : case detail::value_t::binary:
12524 : case detail::value_t::discarded:
12525 : default:
12526 : JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j));
12527 : }
12528 : }
12529 :
12530 : return *result;
12531 : }
12532 :
12533 : /*!
12534 : @brief return a reference to the pointed to value
12535 :
12536 : @note This version does not throw if a value is not present, but tries to
12537 : create nested values instead. For instance, calling this function
12538 : with pointer `"/this/that"` on a null value is equivalent to calling
12539 : `operator[]("this").operator[]("that")` on that value, effectively
12540 : changing the null value to an object.
12541 :
12542 : @param[in] ptr a JSON value
12543 :
12544 : @return reference to the JSON value pointed to by the JSON pointer
12545 :
12546 : @complexity Linear in the length of the JSON pointer.
12547 :
12548 : @throw parse_error.106 if an array index begins with '0'
12549 : @throw parse_error.109 if an array index was not a number
12550 : @throw out_of_range.404 if the JSON pointer can not be resolved
12551 : */
12552 : BasicJsonType& get_unchecked(BasicJsonType* ptr) const
12553 : {
12554 : for (const auto& reference_token : reference_tokens)
12555 : {
12556 : // convert null values to arrays or objects before continuing
12557 : if (ptr->is_null())
12558 : {
12559 : // check if reference token is a number
12560 : const bool nums =
12561 : std::all_of(reference_token.begin(), reference_token.end(),
12562 : [](const unsigned char x)
12563 : {
12564 : return std::isdigit(x);
12565 : });
12566 :
12567 : // change value to array for numbers or "-" or to object otherwise
12568 : *ptr = (nums || reference_token == "-")
12569 : ? detail::value_t::array
12570 : : detail::value_t::object;
12571 : }
12572 :
12573 : switch (ptr->type())
12574 : {
12575 : case detail::value_t::object:
12576 : {
12577 : // use unchecked object access
12578 : ptr = &ptr->operator[](reference_token);
12579 : break;
12580 : }
12581 :
12582 : case detail::value_t::array:
12583 : {
12584 : if (reference_token == "-")
12585 : {
12586 : // explicitly treat "-" as index beyond the end
12587 : ptr = &ptr->operator[](ptr->m_value.array->size());
12588 : }
12589 : else
12590 : {
12591 : // convert array index to number; unchecked access
12592 : ptr = &ptr->operator[](array_index(reference_token));
12593 : }
12594 : break;
12595 : }
12596 :
12597 : case detail::value_t::null:
12598 : case detail::value_t::string:
12599 : case detail::value_t::boolean:
12600 : case detail::value_t::number_integer:
12601 : case detail::value_t::number_unsigned:
12602 : case detail::value_t::number_float:
12603 : case detail::value_t::binary:
12604 : case detail::value_t::discarded:
12605 : default:
12606 : JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
12607 : }
12608 : }
12609 :
12610 : return *ptr;
12611 : }
12612 :
12613 : /*!
12614 : @throw parse_error.106 if an array index begins with '0'
12615 : @throw parse_error.109 if an array index was not a number
12616 : @throw out_of_range.402 if the array index '-' is used
12617 : @throw out_of_range.404 if the JSON pointer can not be resolved
12618 : */
12619 : BasicJsonType& get_checked(BasicJsonType* ptr) const
12620 : {
12621 : for (const auto& reference_token : reference_tokens)
12622 : {
12623 : switch (ptr->type())
12624 : {
12625 : case detail::value_t::object:
12626 : {
12627 : // note: at performs range check
12628 : ptr = &ptr->at(reference_token);
12629 : break;
12630 : }
12631 :
12632 : case detail::value_t::array:
12633 : {
12634 : if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12635 : {
12636 : // "-" always fails the range check
12637 : JSON_THROW(detail::out_of_range::create(402,
12638 : "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12639 : ") is out of range", *ptr));
12640 : }
12641 :
12642 : // note: at performs range check
12643 : ptr = &ptr->at(array_index(reference_token));
12644 : break;
12645 : }
12646 :
12647 : case detail::value_t::null:
12648 : case detail::value_t::string:
12649 : case detail::value_t::boolean:
12650 : case detail::value_t::number_integer:
12651 : case detail::value_t::number_unsigned:
12652 : case detail::value_t::number_float:
12653 : case detail::value_t::binary:
12654 : case detail::value_t::discarded:
12655 : default:
12656 : JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
12657 : }
12658 : }
12659 :
12660 : return *ptr;
12661 : }
12662 :
12663 : /*!
12664 : @brief return a const reference to the pointed to value
12665 :
12666 : @param[in] ptr a JSON value
12667 :
12668 : @return const reference to the JSON value pointed to by the JSON
12669 : pointer
12670 :
12671 : @throw parse_error.106 if an array index begins with '0'
12672 : @throw parse_error.109 if an array index was not a number
12673 : @throw out_of_range.402 if the array index '-' is used
12674 : @throw out_of_range.404 if the JSON pointer can not be resolved
12675 : */
12676 : const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
12677 : {
12678 : for (const auto& reference_token : reference_tokens)
12679 : {
12680 : switch (ptr->type())
12681 : {
12682 : case detail::value_t::object:
12683 : {
12684 : // use unchecked object access
12685 : ptr = &ptr->operator[](reference_token);
12686 : break;
12687 : }
12688 :
12689 : case detail::value_t::array:
12690 : {
12691 : if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12692 : {
12693 : // "-" cannot be used for const access
12694 : JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range", *ptr));
12695 : }
12696 :
12697 : // use unchecked array access
12698 : ptr = &ptr->operator[](array_index(reference_token));
12699 : break;
12700 : }
12701 :
12702 : case detail::value_t::null:
12703 : case detail::value_t::string:
12704 : case detail::value_t::boolean:
12705 : case detail::value_t::number_integer:
12706 : case detail::value_t::number_unsigned:
12707 : case detail::value_t::number_float:
12708 : case detail::value_t::binary:
12709 : case detail::value_t::discarded:
12710 : default:
12711 : JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
12712 : }
12713 : }
12714 :
12715 : return *ptr;
12716 : }
12717 :
12718 : /*!
12719 : @throw parse_error.106 if an array index begins with '0'
12720 : @throw parse_error.109 if an array index was not a number
12721 : @throw out_of_range.402 if the array index '-' is used
12722 : @throw out_of_range.404 if the JSON pointer can not be resolved
12723 : */
12724 : const BasicJsonType& get_checked(const BasicJsonType* ptr) const
12725 : {
12726 : for (const auto& reference_token : reference_tokens)
12727 : {
12728 : switch (ptr->type())
12729 : {
12730 : case detail::value_t::object:
12731 : {
12732 : // note: at performs range check
12733 : ptr = &ptr->at(reference_token);
12734 : break;
12735 : }
12736 :
12737 : case detail::value_t::array:
12738 : {
12739 : if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12740 : {
12741 : // "-" always fails the range check
12742 : JSON_THROW(detail::out_of_range::create(402,
12743 : "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12744 : ") is out of range", *ptr));
12745 : }
12746 :
12747 : // note: at performs range check
12748 : ptr = &ptr->at(array_index(reference_token));
12749 : break;
12750 : }
12751 :
12752 : case detail::value_t::null:
12753 : case detail::value_t::string:
12754 : case detail::value_t::boolean:
12755 : case detail::value_t::number_integer:
12756 : case detail::value_t::number_unsigned:
12757 : case detail::value_t::number_float:
12758 : case detail::value_t::binary:
12759 : case detail::value_t::discarded:
12760 : default:
12761 : JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
12762 : }
12763 : }
12764 :
12765 : return *ptr;
12766 : }
12767 :
12768 : /*!
12769 : @throw parse_error.106 if an array index begins with '0'
12770 : @throw parse_error.109 if an array index was not a number
12771 : */
12772 : bool contains(const BasicJsonType* ptr) const
12773 : {
12774 : for (const auto& reference_token : reference_tokens)
12775 : {
12776 : switch (ptr->type())
12777 : {
12778 : case detail::value_t::object:
12779 : {
12780 : if (!ptr->contains(reference_token))
12781 : {
12782 : // we did not find the key in the object
12783 : return false;
12784 : }
12785 :
12786 : ptr = &ptr->operator[](reference_token);
12787 : break;
12788 : }
12789 :
12790 : case detail::value_t::array:
12791 : {
12792 : if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12793 : {
12794 : // "-" always fails the range check
12795 : return false;
12796 : }
12797 : if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
12798 : {
12799 : // invalid char
12800 : return false;
12801 : }
12802 : if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
12803 : {
12804 : if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
12805 : {
12806 : // first char should be between '1' and '9'
12807 : return false;
12808 : }
12809 : for (std::size_t i = 1; i < reference_token.size(); i++)
12810 : {
12811 : if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
12812 : {
12813 : // other char should be between '0' and '9'
12814 : return false;
12815 : }
12816 : }
12817 : }
12818 :
12819 : const auto idx = array_index(reference_token);
12820 : if (idx >= ptr->size())
12821 : {
12822 : // index out of range
12823 : return false;
12824 : }
12825 :
12826 : ptr = &ptr->operator[](idx);
12827 : break;
12828 : }
12829 :
12830 : case detail::value_t::null:
12831 : case detail::value_t::string:
12832 : case detail::value_t::boolean:
12833 : case detail::value_t::number_integer:
12834 : case detail::value_t::number_unsigned:
12835 : case detail::value_t::number_float:
12836 : case detail::value_t::binary:
12837 : case detail::value_t::discarded:
12838 : default:
12839 : {
12840 : // we do not expect primitive values if there is still a
12841 : // reference token to process
12842 : return false;
12843 : }
12844 : }
12845 : }
12846 :
12847 : // no reference token left means we found a primitive value
12848 : return true;
12849 : }
12850 :
12851 : /*!
12852 : @brief split the string input to reference tokens
12853 :
12854 : @note This function is only called by the json_pointer constructor.
12855 : All exceptions below are documented there.
12856 :
12857 : @throw parse_error.107 if the pointer is not empty or begins with '/'
12858 : @throw parse_error.108 if character '~' is not followed by '0' or '1'
12859 : */
12860 : static std::vector<std::string> split(const std::string& reference_string)
12861 : {
12862 : std::vector<std::string> result;
12863 :
12864 : // special case: empty reference string -> no reference tokens
12865 : if (reference_string.empty())
12866 : {
12867 : return result;
12868 : }
12869 :
12870 : // check if nonempty reference string begins with slash
12871 : if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
12872 : {
12873 : JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", BasicJsonType()));
12874 : }
12875 :
12876 : // extract the reference tokens:
12877 : // - slash: position of the last read slash (or end of string)
12878 : // - start: position after the previous slash
12879 : for (
12880 : // search for the first slash after the first character
12881 : std::size_t slash = reference_string.find_first_of('/', 1),
12882 : // set the beginning of the first reference token
12883 : start = 1;
12884 : // we can stop if start == 0 (if slash == std::string::npos)
12885 : start != 0;
12886 : // set the beginning of the next reference token
12887 : // (will eventually be 0 if slash == std::string::npos)
12888 : start = (slash == std::string::npos) ? 0 : slash + 1,
12889 : // find next slash
12890 : slash = reference_string.find_first_of('/', start))
12891 : {
12892 : // use the text between the beginning of the reference token
12893 : // (start) and the last slash (slash).
12894 : auto reference_token = reference_string.substr(start, slash - start);
12895 :
12896 : // check reference tokens are properly escaped
12897 : for (std::size_t pos = reference_token.find_first_of('~');
12898 : pos != std::string::npos;
12899 : pos = reference_token.find_first_of('~', pos + 1))
12900 : {
12901 : JSON_ASSERT(reference_token[pos] == '~');
12902 :
12903 : // ~ must be followed by 0 or 1
12904 : if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
12905 : (reference_token[pos + 1] != '0' &&
12906 : reference_token[pos + 1] != '1')))
12907 : {
12908 : JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType()));
12909 : }
12910 : }
12911 :
12912 : // finally, store the reference token
12913 : detail::unescape(reference_token);
12914 : result.push_back(reference_token);
12915 : }
12916 :
12917 : return result;
12918 : }
12919 :
12920 : private:
12921 : /*!
12922 : @param[in] reference_string the reference string to the current value
12923 : @param[in] value the value to consider
12924 : @param[in,out] result the result object to insert values to
12925 :
12926 : @note Empty objects or arrays are flattened to `null`.
12927 : */
12928 : static void flatten(const std::string& reference_string,
12929 : const BasicJsonType& value,
12930 : BasicJsonType& result)
12931 : {
12932 : switch (value.type())
12933 : {
12934 : case detail::value_t::array:
12935 : {
12936 : if (value.m_value.array->empty())
12937 : {
12938 : // flatten empty array as null
12939 : result[reference_string] = nullptr;
12940 : }
12941 : else
12942 : {
12943 : // iterate array and use index as reference string
12944 : for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
12945 : {
12946 : flatten(reference_string + "/" + std::to_string(i),
12947 : value.m_value.array->operator[](i), result);
12948 : }
12949 : }
12950 : break;
12951 : }
12952 :
12953 : case detail::value_t::object:
12954 : {
12955 : if (value.m_value.object->empty())
12956 : {
12957 : // flatten empty object as null
12958 : result[reference_string] = nullptr;
12959 : }
12960 : else
12961 : {
12962 : // iterate object and use keys as reference string
12963 : for (const auto& element : *value.m_value.object)
12964 : {
12965 : flatten(reference_string + "/" + detail::escape(element.first), element.second, result);
12966 : }
12967 : }
12968 : break;
12969 : }
12970 :
12971 : case detail::value_t::null:
12972 : case detail::value_t::string:
12973 : case detail::value_t::boolean:
12974 : case detail::value_t::number_integer:
12975 : case detail::value_t::number_unsigned:
12976 : case detail::value_t::number_float:
12977 : case detail::value_t::binary:
12978 : case detail::value_t::discarded:
12979 : default:
12980 : {
12981 : // add primitive value with its reference string
12982 : result[reference_string] = value;
12983 : break;
12984 : }
12985 : }
12986 : }
12987 :
12988 : /*!
12989 : @param[in] value flattened JSON
12990 :
12991 : @return unflattened JSON
12992 :
12993 : @throw parse_error.109 if array index is not a number
12994 : @throw type_error.314 if value is not an object
12995 : @throw type_error.315 if object values are not primitive
12996 : @throw type_error.313 if value cannot be unflattened
12997 : */
12998 : static BasicJsonType
12999 : unflatten(const BasicJsonType& value)
13000 : {
13001 : if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
13002 : {
13003 : JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value));
13004 : }
13005 :
13006 : BasicJsonType result;
13007 :
13008 : // iterate the JSON object values
13009 : for (const auto& element : *value.m_value.object)
13010 : {
13011 : if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
13012 : {
13013 : JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second));
13014 : }
13015 :
13016 : // assign value to reference pointed to by JSON pointer; Note that if
13017 : // the JSON pointer is "" (i.e., points to the whole value), function
13018 : // get_and_create returns a reference to result itself. An assignment
13019 : // will then create a primitive value.
13020 : json_pointer(element.first).get_and_create(result) = element.second;
13021 : }
13022 :
13023 : return result;
13024 : }
13025 :
13026 : /*!
13027 : @brief compares two JSON pointers for equality
13028 :
13029 : @param[in] lhs JSON pointer to compare
13030 : @param[in] rhs JSON pointer to compare
13031 : @return whether @a lhs is equal to @a rhs
13032 :
13033 : @complexity Linear in the length of the JSON pointer
13034 :
13035 : @exceptionsafety No-throw guarantee: this function never throws exceptions.
13036 : */
13037 : friend bool operator==(json_pointer const& lhs,
13038 : json_pointer const& rhs) noexcept
13039 : {
13040 : return lhs.reference_tokens == rhs.reference_tokens;
13041 : }
13042 :
13043 : /*!
13044 : @brief compares two JSON pointers for inequality
13045 :
13046 : @param[in] lhs JSON pointer to compare
13047 : @param[in] rhs JSON pointer to compare
13048 : @return whether @a lhs is not equal @a rhs
13049 :
13050 : @complexity Linear in the length of the JSON pointer
13051 :
13052 : @exceptionsafety No-throw guarantee: this function never throws exceptions.
13053 : */
13054 : friend bool operator!=(json_pointer const& lhs,
13055 : json_pointer const& rhs) noexcept
13056 : {
13057 : return !(lhs == rhs);
13058 : }
13059 :
13060 : /// the reference tokens
13061 : std::vector<std::string> reference_tokens;
13062 : };
13063 : } // namespace nlohmann
13064 :
13065 : // #include <nlohmann/detail/json_ref.hpp>
13066 :
13067 :
13068 : #include <initializer_list>
13069 : #include <utility>
13070 :
13071 : // #include <nlohmann/detail/meta/type_traits.hpp>
13072 :
13073 :
13074 : namespace nlohmann
13075 : {
13076 : namespace detail
13077 : {
13078 : template<typename BasicJsonType>
13079 : class json_ref
13080 : {
13081 : public:
13082 : using value_type = BasicJsonType;
13083 :
13084 : json_ref(value_type&& value)
13085 : : owned_value(std::move(value))
13086 : {}
13087 :
13088 : json_ref(const value_type& value)
13089 : : value_ref(&value)
13090 : {}
13091 :
13092 : json_ref(std::initializer_list<json_ref> init)
13093 : : owned_value(init)
13094 : {}
13095 :
13096 : template <
13097 : class... Args,
13098 : enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
13099 : json_ref(Args && ... args)
13100 : : owned_value(std::forward<Args>(args)...)
13101 : {}
13102 :
13103 : // class should be movable only
13104 : json_ref(json_ref&&) noexcept = default;
13105 : json_ref(const json_ref&) = delete;
13106 : json_ref& operator=(const json_ref&) = delete;
13107 : json_ref& operator=(json_ref&&) = delete;
13108 : ~json_ref() = default;
13109 :
13110 : value_type moved_or_copied() const
13111 : {
13112 : if (value_ref == nullptr)
13113 : {
13114 : return std::move(owned_value);
13115 : }
13116 : return *value_ref;
13117 : }
13118 :
13119 : value_type const& operator*() const
13120 : {
13121 : return value_ref ? *value_ref : owned_value;
13122 : }
13123 :
13124 : value_type const* operator->() const
13125 : {
13126 : return &** this;
13127 : }
13128 :
13129 : private:
13130 : mutable value_type owned_value = nullptr;
13131 : value_type const* value_ref = nullptr;
13132 : };
13133 : } // namespace detail
13134 : } // namespace nlohmann
13135 :
13136 : // #include <nlohmann/detail/macro_scope.hpp>
13137 :
13138 : // #include <nlohmann/detail/string_escape.hpp>
13139 :
13140 : // #include <nlohmann/detail/meta/cpp_future.hpp>
13141 :
13142 : // #include <nlohmann/detail/meta/type_traits.hpp>
13143 :
13144 : // #include <nlohmann/detail/output/binary_writer.hpp>
13145 :
13146 :
13147 : #include <algorithm> // reverse
13148 : #include <array> // array
13149 : #include <cmath> // isnan, isinf
13150 : #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
13151 : #include <cstring> // memcpy
13152 : #include <limits> // numeric_limits
13153 : #include <string> // string
13154 : #include <utility> // move
13155 :
13156 : // #include <nlohmann/detail/input/binary_reader.hpp>
13157 :
13158 : // #include <nlohmann/detail/macro_scope.hpp>
13159 :
13160 : // #include <nlohmann/detail/output/output_adapters.hpp>
13161 :
13162 :
13163 : #include <algorithm> // copy
13164 : #include <cstddef> // size_t
13165 : #include <iterator> // back_inserter
13166 : #include <memory> // shared_ptr, make_shared
13167 : #include <string> // basic_string
13168 : #include <vector> // vector
13169 :
13170 : #ifndef JSON_NO_IO
13171 : #include <ios> // streamsize
13172 : #include <ostream> // basic_ostream
13173 : #endif // JSON_NO_IO
13174 :
13175 : // #include <nlohmann/detail/macro_scope.hpp>
13176 :
13177 :
13178 : namespace nlohmann
13179 : {
13180 : namespace detail
13181 : {
13182 : /// abstract output adapter interface
13183 : template<typename CharType> struct output_adapter_protocol
13184 : {
13185 : virtual void write_character(CharType c) = 0;
13186 : virtual void write_characters(const CharType* s, std::size_t length) = 0;
13187 : virtual ~output_adapter_protocol() = default;
13188 :
13189 : output_adapter_protocol() = default;
13190 : output_adapter_protocol(const output_adapter_protocol&) = default;
13191 : output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
13192 : output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
13193 : output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
13194 : };
13195 :
13196 : /// a type to simplify interfaces
13197 : template<typename CharType>
13198 : using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
13199 :
13200 : /// output adapter for byte vectors
13201 : template<typename CharType, typename AllocatorType = std::allocator<CharType>>
13202 : class output_vector_adapter : public output_adapter_protocol<CharType>
13203 : {
13204 : public:
13205 : explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
13206 : : v(vec)
13207 : {}
13208 :
13209 : void write_character(CharType c) override
13210 : {
13211 : v.push_back(c);
13212 : }
13213 :
13214 : JSON_HEDLEY_NON_NULL(2)
13215 : void write_characters(const CharType* s, std::size_t length) override
13216 : {
13217 : std::copy(s, s + length, std::back_inserter(v));
13218 : }
13219 :
13220 : private:
13221 : std::vector<CharType, AllocatorType>& v;
13222 : };
13223 :
13224 : #ifndef JSON_NO_IO
13225 : /// output adapter for output streams
13226 : template<typename CharType>
13227 : class output_stream_adapter : public output_adapter_protocol<CharType>
13228 : {
13229 : public:
13230 : explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
13231 : : stream(s)
13232 : {}
13233 :
13234 : void write_character(CharType c) override
13235 : {
13236 : stream.put(c);
13237 : }
13238 :
13239 : JSON_HEDLEY_NON_NULL(2)
13240 : void write_characters(const CharType* s, std::size_t length) override
13241 : {
13242 : stream.write(s, static_cast<std::streamsize>(length));
13243 : }
13244 :
13245 : private:
13246 : std::basic_ostream<CharType>& stream;
13247 : };
13248 : #endif // JSON_NO_IO
13249 :
13250 : /// output adapter for basic_string
13251 : template<typename CharType, typename StringType = std::basic_string<CharType>>
13252 : class output_string_adapter : public output_adapter_protocol<CharType>
13253 : {
13254 : public:
13255 : explicit output_string_adapter(StringType& s) noexcept
13256 : : str(s)
13257 : {}
13258 :
13259 : void write_character(CharType c) override
13260 : {
13261 : str.push_back(c);
13262 : }
13263 :
13264 : JSON_HEDLEY_NON_NULL(2)
13265 : void write_characters(const CharType* s, std::size_t length) override
13266 : {
13267 : str.append(s, length);
13268 : }
13269 :
13270 : private:
13271 : StringType& str;
13272 : };
13273 :
13274 : template<typename CharType, typename StringType = std::basic_string<CharType>>
13275 : class output_adapter
13276 : {
13277 : public:
13278 : template<typename AllocatorType = std::allocator<CharType>>
13279 : output_adapter(std::vector<CharType, AllocatorType>& vec)
13280 : : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
13281 :
13282 : #ifndef JSON_NO_IO
13283 : output_adapter(std::basic_ostream<CharType>& s)
13284 : : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
13285 : #endif // JSON_NO_IO
13286 :
13287 : output_adapter(StringType& s)
13288 : : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
13289 :
13290 : operator output_adapter_t<CharType>()
13291 : {
13292 : return oa;
13293 : }
13294 :
13295 : private:
13296 : output_adapter_t<CharType> oa = nullptr;
13297 : };
13298 : } // namespace detail
13299 : } // namespace nlohmann
13300 :
13301 :
13302 : namespace nlohmann
13303 : {
13304 : namespace detail
13305 : {
13306 : ///////////////////
13307 : // binary writer //
13308 : ///////////////////
13309 :
13310 : /*!
13311 : @brief serialization to CBOR and MessagePack values
13312 : */
13313 : template<typename BasicJsonType, typename CharType>
13314 : class binary_writer
13315 : {
13316 : using string_t = typename BasicJsonType::string_t;
13317 : using binary_t = typename BasicJsonType::binary_t;
13318 : using number_float_t = typename BasicJsonType::number_float_t;
13319 :
13320 : public:
13321 : /*!
13322 : @brief create a binary writer
13323 :
13324 : @param[in] adapter output adapter to write to
13325 : */
13326 : explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
13327 : {
13328 : JSON_ASSERT(oa);
13329 : }
13330 :
13331 : /*!
13332 : @param[in] j JSON value to serialize
13333 : @pre j.type() == value_t::object
13334 : */
13335 : void write_bson(const BasicJsonType& j)
13336 : {
13337 : switch (j.type())
13338 : {
13339 : case value_t::object:
13340 : {
13341 : write_bson_object(*j.m_value.object);
13342 : break;
13343 : }
13344 :
13345 : case value_t::null:
13346 : case value_t::array:
13347 : case value_t::string:
13348 : case value_t::boolean:
13349 : case value_t::number_integer:
13350 : case value_t::number_unsigned:
13351 : case value_t::number_float:
13352 : case value_t::binary:
13353 : case value_t::discarded:
13354 : default:
13355 : {
13356 : JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j));
13357 : }
13358 : }
13359 : }
13360 :
13361 : /*!
13362 : @param[in] j JSON value to serialize
13363 : */
13364 : void write_cbor(const BasicJsonType& j)
13365 : {
13366 : switch (j.type())
13367 : {
13368 : case value_t::null:
13369 : {
13370 : oa->write_character(to_char_type(0xF6));
13371 : break;
13372 : }
13373 :
13374 : case value_t::boolean:
13375 : {
13376 : oa->write_character(j.m_value.boolean
13377 : ? to_char_type(0xF5)
13378 : : to_char_type(0xF4));
13379 : break;
13380 : }
13381 :
13382 : case value_t::number_integer:
13383 : {
13384 : if (j.m_value.number_integer >= 0)
13385 : {
13386 : // CBOR does not differentiate between positive signed
13387 : // integers and unsigned integers. Therefore, we used the
13388 : // code from the value_t::number_unsigned case here.
13389 : if (j.m_value.number_integer <= 0x17)
13390 : {
13391 : write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13392 : }
13393 : else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
13394 : {
13395 : oa->write_character(to_char_type(0x18));
13396 : write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13397 : }
13398 : else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
13399 : {
13400 : oa->write_character(to_char_type(0x19));
13401 : write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13402 : }
13403 : else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
13404 : {
13405 : oa->write_character(to_char_type(0x1A));
13406 : write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13407 : }
13408 : else
13409 : {
13410 : oa->write_character(to_char_type(0x1B));
13411 : write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13412 : }
13413 : }
13414 : else
13415 : {
13416 : // The conversions below encode the sign in the first
13417 : // byte, and the value is converted to a positive number.
13418 : const auto positive_number = -1 - j.m_value.number_integer;
13419 : if (j.m_value.number_integer >= -24)
13420 : {
13421 : write_number(static_cast<std::uint8_t>(0x20 + positive_number));
13422 : }
13423 : else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
13424 : {
13425 : oa->write_character(to_char_type(0x38));
13426 : write_number(static_cast<std::uint8_t>(positive_number));
13427 : }
13428 : else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
13429 : {
13430 : oa->write_character(to_char_type(0x39));
13431 : write_number(static_cast<std::uint16_t>(positive_number));
13432 : }
13433 : else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
13434 : {
13435 : oa->write_character(to_char_type(0x3A));
13436 : write_number(static_cast<std::uint32_t>(positive_number));
13437 : }
13438 : else
13439 : {
13440 : oa->write_character(to_char_type(0x3B));
13441 : write_number(static_cast<std::uint64_t>(positive_number));
13442 : }
13443 : }
13444 : break;
13445 : }
13446 :
13447 : case value_t::number_unsigned:
13448 : {
13449 : if (j.m_value.number_unsigned <= 0x17)
13450 : {
13451 : write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
13452 : }
13453 : else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
13454 : {
13455 : oa->write_character(to_char_type(0x18));
13456 : write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
13457 : }
13458 : else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
13459 : {
13460 : oa->write_character(to_char_type(0x19));
13461 : write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
13462 : }
13463 : else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
13464 : {
13465 : oa->write_character(to_char_type(0x1A));
13466 : write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
13467 : }
13468 : else
13469 : {
13470 : oa->write_character(to_char_type(0x1B));
13471 : write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
13472 : }
13473 : break;
13474 : }
13475 :
13476 : case value_t::number_float:
13477 : {
13478 : if (std::isnan(j.m_value.number_float))
13479 : {
13480 : // NaN is 0xf97e00 in CBOR
13481 : oa->write_character(to_char_type(0xF9));
13482 : oa->write_character(to_char_type(0x7E));
13483 : oa->write_character(to_char_type(0x00));
13484 : }
13485 : else if (std::isinf(j.m_value.number_float))
13486 : {
13487 : // Infinity is 0xf97c00, -Infinity is 0xf9fc00
13488 : oa->write_character(to_char_type(0xf9));
13489 : oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
13490 : oa->write_character(to_char_type(0x00));
13491 : }
13492 : else
13493 : {
13494 : write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
13495 : }
13496 : break;
13497 : }
13498 :
13499 : case value_t::string:
13500 : {
13501 : // step 1: write control byte and the string length
13502 : const auto N = j.m_value.string->size();
13503 : if (N <= 0x17)
13504 : {
13505 : write_number(static_cast<std::uint8_t>(0x60 + N));
13506 : }
13507 : else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13508 : {
13509 : oa->write_character(to_char_type(0x78));
13510 : write_number(static_cast<std::uint8_t>(N));
13511 : }
13512 : else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13513 : {
13514 : oa->write_character(to_char_type(0x79));
13515 : write_number(static_cast<std::uint16_t>(N));
13516 : }
13517 : else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13518 : {
13519 : oa->write_character(to_char_type(0x7A));
13520 : write_number(static_cast<std::uint32_t>(N));
13521 : }
13522 : // LCOV_EXCL_START
13523 : else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13524 : {
13525 : oa->write_character(to_char_type(0x7B));
13526 : write_number(static_cast<std::uint64_t>(N));
13527 : }
13528 : // LCOV_EXCL_STOP
13529 :
13530 : // step 2: write the string
13531 : oa->write_characters(
13532 : reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
13533 : j.m_value.string->size());
13534 : break;
13535 : }
13536 :
13537 : case value_t::array:
13538 : {
13539 : // step 1: write control byte and the array size
13540 : const auto N = j.m_value.array->size();
13541 : if (N <= 0x17)
13542 : {
13543 : write_number(static_cast<std::uint8_t>(0x80 + N));
13544 : }
13545 : else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13546 : {
13547 : oa->write_character(to_char_type(0x98));
13548 : write_number(static_cast<std::uint8_t>(N));
13549 : }
13550 : else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13551 : {
13552 : oa->write_character(to_char_type(0x99));
13553 : write_number(static_cast<std::uint16_t>(N));
13554 : }
13555 : else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13556 : {
13557 : oa->write_character(to_char_type(0x9A));
13558 : write_number(static_cast<std::uint32_t>(N));
13559 : }
13560 : // LCOV_EXCL_START
13561 : else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13562 : {
13563 : oa->write_character(to_char_type(0x9B));
13564 : write_number(static_cast<std::uint64_t>(N));
13565 : }
13566 : // LCOV_EXCL_STOP
13567 :
13568 : // step 2: write each element
13569 : for (const auto& el : *j.m_value.array)
13570 : {
13571 : write_cbor(el);
13572 : }
13573 : break;
13574 : }
13575 :
13576 : case value_t::binary:
13577 : {
13578 : if (j.m_value.binary->has_subtype())
13579 : {
13580 : if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
13581 : {
13582 : write_number(static_cast<std::uint8_t>(0xd8));
13583 : write_number(static_cast<std::uint8_t>(j.m_value.binary->subtype()));
13584 : }
13585 : else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
13586 : {
13587 : write_number(static_cast<std::uint8_t>(0xd9));
13588 : write_number(static_cast<std::uint16_t>(j.m_value.binary->subtype()));
13589 : }
13590 : else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
13591 : {
13592 : write_number(static_cast<std::uint8_t>(0xda));
13593 : write_number(static_cast<std::uint32_t>(j.m_value.binary->subtype()));
13594 : }
13595 : else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
13596 : {
13597 : write_number(static_cast<std::uint8_t>(0xdb));
13598 : write_number(static_cast<std::uint64_t>(j.m_value.binary->subtype()));
13599 : }
13600 : }
13601 :
13602 : // step 1: write control byte and the binary array size
13603 : const auto N = j.m_value.binary->size();
13604 : if (N <= 0x17)
13605 : {
13606 : write_number(static_cast<std::uint8_t>(0x40 + N));
13607 : }
13608 : else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13609 : {
13610 : oa->write_character(to_char_type(0x58));
13611 : write_number(static_cast<std::uint8_t>(N));
13612 : }
13613 : else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13614 : {
13615 : oa->write_character(to_char_type(0x59));
13616 : write_number(static_cast<std::uint16_t>(N));
13617 : }
13618 : else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13619 : {
13620 : oa->write_character(to_char_type(0x5A));
13621 : write_number(static_cast<std::uint32_t>(N));
13622 : }
13623 : // LCOV_EXCL_START
13624 : else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13625 : {
13626 : oa->write_character(to_char_type(0x5B));
13627 : write_number(static_cast<std::uint64_t>(N));
13628 : }
13629 : // LCOV_EXCL_STOP
13630 :
13631 : // step 2: write each element
13632 : oa->write_characters(
13633 : reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13634 : N);
13635 :
13636 : break;
13637 : }
13638 :
13639 : case value_t::object:
13640 : {
13641 : // step 1: write control byte and the object size
13642 : const auto N = j.m_value.object->size();
13643 : if (N <= 0x17)
13644 : {
13645 : write_number(static_cast<std::uint8_t>(0xA0 + N));
13646 : }
13647 : else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13648 : {
13649 : oa->write_character(to_char_type(0xB8));
13650 : write_number(static_cast<std::uint8_t>(N));
13651 : }
13652 : else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13653 : {
13654 : oa->write_character(to_char_type(0xB9));
13655 : write_number(static_cast<std::uint16_t>(N));
13656 : }
13657 : else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13658 : {
13659 : oa->write_character(to_char_type(0xBA));
13660 : write_number(static_cast<std::uint32_t>(N));
13661 : }
13662 : // LCOV_EXCL_START
13663 : else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13664 : {
13665 : oa->write_character(to_char_type(0xBB));
13666 : write_number(static_cast<std::uint64_t>(N));
13667 : }
13668 : // LCOV_EXCL_STOP
13669 :
13670 : // step 2: write each element
13671 : for (const auto& el : *j.m_value.object)
13672 : {
13673 : write_cbor(el.first);
13674 : write_cbor(el.second);
13675 : }
13676 : break;
13677 : }
13678 :
13679 : case value_t::discarded:
13680 : default:
13681 : break;
13682 : }
13683 : }
13684 :
13685 : /*!
13686 : @param[in] j JSON value to serialize
13687 : */
13688 : void write_msgpack(const BasicJsonType& j)
13689 : {
13690 : switch (j.type())
13691 : {
13692 : case value_t::null: // nil
13693 : {
13694 : oa->write_character(to_char_type(0xC0));
13695 : break;
13696 : }
13697 :
13698 : case value_t::boolean: // true and false
13699 : {
13700 : oa->write_character(j.m_value.boolean
13701 : ? to_char_type(0xC3)
13702 : : to_char_type(0xC2));
13703 : break;
13704 : }
13705 :
13706 : case value_t::number_integer:
13707 : {
13708 : if (j.m_value.number_integer >= 0)
13709 : {
13710 : // MessagePack does not differentiate between positive
13711 : // signed integers and unsigned integers. Therefore, we used
13712 : // the code from the value_t::number_unsigned case here.
13713 : if (j.m_value.number_unsigned < 128)
13714 : {
13715 : // positive fixnum
13716 : write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13717 : }
13718 : else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
13719 : {
13720 : // uint 8
13721 : oa->write_character(to_char_type(0xCC));
13722 : write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13723 : }
13724 : else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
13725 : {
13726 : // uint 16
13727 : oa->write_character(to_char_type(0xCD));
13728 : write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13729 : }
13730 : else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
13731 : {
13732 : // uint 32
13733 : oa->write_character(to_char_type(0xCE));
13734 : write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13735 : }
13736 : else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
13737 : {
13738 : // uint 64
13739 : oa->write_character(to_char_type(0xCF));
13740 : write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13741 : }
13742 : }
13743 : else
13744 : {
13745 : if (j.m_value.number_integer >= -32)
13746 : {
13747 : // negative fixnum
13748 : write_number(static_cast<std::int8_t>(j.m_value.number_integer));
13749 : }
13750 : else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
13751 : j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
13752 : {
13753 : // int 8
13754 : oa->write_character(to_char_type(0xD0));
13755 : write_number(static_cast<std::int8_t>(j.m_value.number_integer));
13756 : }
13757 : else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
13758 : j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
13759 : {
13760 : // int 16
13761 : oa->write_character(to_char_type(0xD1));
13762 : write_number(static_cast<std::int16_t>(j.m_value.number_integer));
13763 : }
13764 : else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
13765 : j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
13766 : {
13767 : // int 32
13768 : oa->write_character(to_char_type(0xD2));
13769 : write_number(static_cast<std::int32_t>(j.m_value.number_integer));
13770 : }
13771 : else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
13772 : j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
13773 : {
13774 : // int 64
13775 : oa->write_character(to_char_type(0xD3));
13776 : write_number(static_cast<std::int64_t>(j.m_value.number_integer));
13777 : }
13778 : }
13779 : break;
13780 : }
13781 :
13782 : case value_t::number_unsigned:
13783 : {
13784 : if (j.m_value.number_unsigned < 128)
13785 : {
13786 : // positive fixnum
13787 : write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13788 : }
13789 : else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
13790 : {
13791 : // uint 8
13792 : oa->write_character(to_char_type(0xCC));
13793 : write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13794 : }
13795 : else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
13796 : {
13797 : // uint 16
13798 : oa->write_character(to_char_type(0xCD));
13799 : write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13800 : }
13801 : else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
13802 : {
13803 : // uint 32
13804 : oa->write_character(to_char_type(0xCE));
13805 : write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13806 : }
13807 : else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
13808 : {
13809 : // uint 64
13810 : oa->write_character(to_char_type(0xCF));
13811 : write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13812 : }
13813 : break;
13814 : }
13815 :
13816 : case value_t::number_float:
13817 : {
13818 : write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
13819 : break;
13820 : }
13821 :
13822 : case value_t::string:
13823 : {
13824 : // step 1: write control byte and the string length
13825 : const auto N = j.m_value.string->size();
13826 : if (N <= 31)
13827 : {
13828 : // fixstr
13829 : write_number(static_cast<std::uint8_t>(0xA0 | N));
13830 : }
13831 : else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13832 : {
13833 : // str 8
13834 : oa->write_character(to_char_type(0xD9));
13835 : write_number(static_cast<std::uint8_t>(N));
13836 : }
13837 : else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13838 : {
13839 : // str 16
13840 : oa->write_character(to_char_type(0xDA));
13841 : write_number(static_cast<std::uint16_t>(N));
13842 : }
13843 : else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13844 : {
13845 : // str 32
13846 : oa->write_character(to_char_type(0xDB));
13847 : write_number(static_cast<std::uint32_t>(N));
13848 : }
13849 :
13850 : // step 2: write the string
13851 : oa->write_characters(
13852 : reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
13853 : j.m_value.string->size());
13854 : break;
13855 : }
13856 :
13857 : case value_t::array:
13858 : {
13859 : // step 1: write control byte and the array size
13860 : const auto N = j.m_value.array->size();
13861 : if (N <= 15)
13862 : {
13863 : // fixarray
13864 : write_number(static_cast<std::uint8_t>(0x90 | N));
13865 : }
13866 : else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13867 : {
13868 : // array 16
13869 : oa->write_character(to_char_type(0xDC));
13870 : write_number(static_cast<std::uint16_t>(N));
13871 : }
13872 : else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13873 : {
13874 : // array 32
13875 : oa->write_character(to_char_type(0xDD));
13876 : write_number(static_cast<std::uint32_t>(N));
13877 : }
13878 :
13879 : // step 2: write each element
13880 : for (const auto& el : *j.m_value.array)
13881 : {
13882 : write_msgpack(el);
13883 : }
13884 : break;
13885 : }
13886 :
13887 : case value_t::binary:
13888 : {
13889 : // step 0: determine if the binary type has a set subtype to
13890 : // determine whether or not to use the ext or fixext types
13891 : const bool use_ext = j.m_value.binary->has_subtype();
13892 :
13893 : // step 1: write control byte and the byte string length
13894 : const auto N = j.m_value.binary->size();
13895 : if (N <= (std::numeric_limits<std::uint8_t>::max)())
13896 : {
13897 : std::uint8_t output_type{};
13898 : bool fixed = true;
13899 : if (use_ext)
13900 : {
13901 : switch (N)
13902 : {
13903 : case 1:
13904 : output_type = 0xD4; // fixext 1
13905 : break;
13906 : case 2:
13907 : output_type = 0xD5; // fixext 2
13908 : break;
13909 : case 4:
13910 : output_type = 0xD6; // fixext 4
13911 : break;
13912 : case 8:
13913 : output_type = 0xD7; // fixext 8
13914 : break;
13915 : case 16:
13916 : output_type = 0xD8; // fixext 16
13917 : break;
13918 : default:
13919 : output_type = 0xC7; // ext 8
13920 : fixed = false;
13921 : break;
13922 : }
13923 :
13924 : }
13925 : else
13926 : {
13927 : output_type = 0xC4; // bin 8
13928 : fixed = false;
13929 : }
13930 :
13931 : oa->write_character(to_char_type(output_type));
13932 : if (!fixed)
13933 : {
13934 : write_number(static_cast<std::uint8_t>(N));
13935 : }
13936 : }
13937 : else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13938 : {
13939 : std::uint8_t output_type = use_ext
13940 : ? 0xC8 // ext 16
13941 : : 0xC5; // bin 16
13942 :
13943 : oa->write_character(to_char_type(output_type));
13944 : write_number(static_cast<std::uint16_t>(N));
13945 : }
13946 : else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13947 : {
13948 : std::uint8_t output_type = use_ext
13949 : ? 0xC9 // ext 32
13950 : : 0xC6; // bin 32
13951 :
13952 : oa->write_character(to_char_type(output_type));
13953 : write_number(static_cast<std::uint32_t>(N));
13954 : }
13955 :
13956 : // step 1.5: if this is an ext type, write the subtype
13957 : if (use_ext)
13958 : {
13959 : write_number(static_cast<std::int8_t>(j.m_value.binary->subtype()));
13960 : }
13961 :
13962 : // step 2: write the byte string
13963 : oa->write_characters(
13964 : reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13965 : N);
13966 :
13967 : break;
13968 : }
13969 :
13970 : case value_t::object:
13971 : {
13972 : // step 1: write control byte and the object size
13973 : const auto N = j.m_value.object->size();
13974 : if (N <= 15)
13975 : {
13976 : // fixmap
13977 : write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
13978 : }
13979 : else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13980 : {
13981 : // map 16
13982 : oa->write_character(to_char_type(0xDE));
13983 : write_number(static_cast<std::uint16_t>(N));
13984 : }
13985 : else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13986 : {
13987 : // map 32
13988 : oa->write_character(to_char_type(0xDF));
13989 : write_number(static_cast<std::uint32_t>(N));
13990 : }
13991 :
13992 : // step 2: write each element
13993 : for (const auto& el : *j.m_value.object)
13994 : {
13995 : write_msgpack(el.first);
13996 : write_msgpack(el.second);
13997 : }
13998 : break;
13999 : }
14000 :
14001 : case value_t::discarded:
14002 : default:
14003 : break;
14004 : }
14005 : }
14006 :
14007 : /*!
14008 : @param[in] j JSON value to serialize
14009 : @param[in] use_count whether to use '#' prefixes (optimized format)
14010 : @param[in] use_type whether to use '$' prefixes (optimized format)
14011 : @param[in] add_prefix whether prefixes need to be used for this value
14012 : */
14013 : void write_ubjson(const BasicJsonType& j, const bool use_count,
14014 : const bool use_type, const bool add_prefix = true)
14015 : {
14016 : switch (j.type())
14017 : {
14018 : case value_t::null:
14019 : {
14020 : if (add_prefix)
14021 : {
14022 : oa->write_character(to_char_type('Z'));
14023 : }
14024 : break;
14025 : }
14026 :
14027 : case value_t::boolean:
14028 : {
14029 : if (add_prefix)
14030 : {
14031 : oa->write_character(j.m_value.boolean
14032 : ? to_char_type('T')
14033 : : to_char_type('F'));
14034 : }
14035 : break;
14036 : }
14037 :
14038 : case value_t::number_integer:
14039 : {
14040 : write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
14041 : break;
14042 : }
14043 :
14044 : case value_t::number_unsigned:
14045 : {
14046 : write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
14047 : break;
14048 : }
14049 :
14050 : case value_t::number_float:
14051 : {
14052 : write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
14053 : break;
14054 : }
14055 :
14056 : case value_t::string:
14057 : {
14058 : if (add_prefix)
14059 : {
14060 : oa->write_character(to_char_type('S'));
14061 : }
14062 : write_number_with_ubjson_prefix(j.m_value.string->size(), true);
14063 : oa->write_characters(
14064 : reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
14065 : j.m_value.string->size());
14066 : break;
14067 : }
14068 :
14069 : case value_t::array:
14070 : {
14071 : if (add_prefix)
14072 : {
14073 : oa->write_character(to_char_type('['));
14074 : }
14075 :
14076 : bool prefix_required = true;
14077 : if (use_type && !j.m_value.array->empty())
14078 : {
14079 : JSON_ASSERT(use_count);
14080 : const CharType first_prefix = ubjson_prefix(j.front());
14081 : const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
14082 : [this, first_prefix](const BasicJsonType & v)
14083 : {
14084 : return ubjson_prefix(v) == first_prefix;
14085 : });
14086 :
14087 : if (same_prefix)
14088 : {
14089 : prefix_required = false;
14090 : oa->write_character(to_char_type('$'));
14091 : oa->write_character(first_prefix);
14092 : }
14093 : }
14094 :
14095 : if (use_count)
14096 : {
14097 : oa->write_character(to_char_type('#'));
14098 : write_number_with_ubjson_prefix(j.m_value.array->size(), true);
14099 : }
14100 :
14101 : for (const auto& el : *j.m_value.array)
14102 : {
14103 : write_ubjson(el, use_count, use_type, prefix_required);
14104 : }
14105 :
14106 : if (!use_count)
14107 : {
14108 : oa->write_character(to_char_type(']'));
14109 : }
14110 :
14111 : break;
14112 : }
14113 :
14114 : case value_t::binary:
14115 : {
14116 : if (add_prefix)
14117 : {
14118 : oa->write_character(to_char_type('['));
14119 : }
14120 :
14121 : if (use_type && !j.m_value.binary->empty())
14122 : {
14123 : JSON_ASSERT(use_count);
14124 : oa->write_character(to_char_type('$'));
14125 : oa->write_character('U');
14126 : }
14127 :
14128 : if (use_count)
14129 : {
14130 : oa->write_character(to_char_type('#'));
14131 : write_number_with_ubjson_prefix(j.m_value.binary->size(), true);
14132 : }
14133 :
14134 : if (use_type)
14135 : {
14136 : oa->write_characters(
14137 : reinterpret_cast<const CharType*>(j.m_value.binary->data()),
14138 : j.m_value.binary->size());
14139 : }
14140 : else
14141 : {
14142 : for (size_t i = 0; i < j.m_value.binary->size(); ++i)
14143 : {
14144 : oa->write_character(to_char_type('U'));
14145 : oa->write_character(j.m_value.binary->data()[i]);
14146 : }
14147 : }
14148 :
14149 : if (!use_count)
14150 : {
14151 : oa->write_character(to_char_type(']'));
14152 : }
14153 :
14154 : break;
14155 : }
14156 :
14157 : case value_t::object:
14158 : {
14159 : if (add_prefix)
14160 : {
14161 : oa->write_character(to_char_type('{'));
14162 : }
14163 :
14164 : bool prefix_required = true;
14165 : if (use_type && !j.m_value.object->empty())
14166 : {
14167 : JSON_ASSERT(use_count);
14168 : const CharType first_prefix = ubjson_prefix(j.front());
14169 : const bool same_prefix = std::all_of(j.begin(), j.end(),
14170 : [this, first_prefix](const BasicJsonType & v)
14171 : {
14172 : return ubjson_prefix(v) == first_prefix;
14173 : });
14174 :
14175 : if (same_prefix)
14176 : {
14177 : prefix_required = false;
14178 : oa->write_character(to_char_type('$'));
14179 : oa->write_character(first_prefix);
14180 : }
14181 : }
14182 :
14183 : if (use_count)
14184 : {
14185 : oa->write_character(to_char_type('#'));
14186 : write_number_with_ubjson_prefix(j.m_value.object->size(), true);
14187 : }
14188 :
14189 : for (const auto& el : *j.m_value.object)
14190 : {
14191 : write_number_with_ubjson_prefix(el.first.size(), true);
14192 : oa->write_characters(
14193 : reinterpret_cast<const CharType*>(el.first.c_str()),
14194 : el.first.size());
14195 : write_ubjson(el.second, use_count, use_type, prefix_required);
14196 : }
14197 :
14198 : if (!use_count)
14199 : {
14200 : oa->write_character(to_char_type('}'));
14201 : }
14202 :
14203 : break;
14204 : }
14205 :
14206 : case value_t::discarded:
14207 : default:
14208 : break;
14209 : }
14210 : }
14211 :
14212 : private:
14213 : //////////
14214 : // BSON //
14215 : //////////
14216 :
14217 : /*!
14218 : @return The size of a BSON document entry header, including the id marker
14219 : and the entry name size (and its null-terminator).
14220 : */
14221 : static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
14222 : {
14223 : const auto it = name.find(static_cast<typename string_t::value_type>(0));
14224 : if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
14225 : {
14226 : JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j));
14227 : static_cast<void>(j);
14228 : }
14229 :
14230 : return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
14231 : }
14232 :
14233 : /*!
14234 : @brief Writes the given @a element_type and @a name to the output adapter
14235 : */
14236 : void write_bson_entry_header(const string_t& name,
14237 : const std::uint8_t element_type)
14238 : {
14239 : oa->write_character(to_char_type(element_type)); // boolean
14240 : oa->write_characters(
14241 : reinterpret_cast<const CharType*>(name.c_str()),
14242 : name.size() + 1u);
14243 : }
14244 :
14245 : /*!
14246 : @brief Writes a BSON element with key @a name and boolean value @a value
14247 : */
14248 : void write_bson_boolean(const string_t& name,
14249 : const bool value)
14250 : {
14251 : write_bson_entry_header(name, 0x08);
14252 : oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
14253 : }
14254 :
14255 : /*!
14256 : @brief Writes a BSON element with key @a name and double value @a value
14257 : */
14258 : void write_bson_double(const string_t& name,
14259 : const double value)
14260 : {
14261 : write_bson_entry_header(name, 0x01);
14262 : write_number<double, true>(value);
14263 : }
14264 :
14265 : /*!
14266 : @return The size of the BSON-encoded string in @a value
14267 : */
14268 : static std::size_t calc_bson_string_size(const string_t& value)
14269 : {
14270 : return sizeof(std::int32_t) + value.size() + 1ul;
14271 : }
14272 :
14273 : /*!
14274 : @brief Writes a BSON element with key @a name and string value @a value
14275 : */
14276 : void write_bson_string(const string_t& name,
14277 : const string_t& value)
14278 : {
14279 : write_bson_entry_header(name, 0x02);
14280 :
14281 : write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
14282 : oa->write_characters(
14283 : reinterpret_cast<const CharType*>(value.c_str()),
14284 : value.size() + 1);
14285 : }
14286 :
14287 : /*!
14288 : @brief Writes a BSON element with key @a name and null value
14289 : */
14290 : void write_bson_null(const string_t& name)
14291 : {
14292 : write_bson_entry_header(name, 0x0A);
14293 : }
14294 :
14295 : /*!
14296 : @return The size of the BSON-encoded integer @a value
14297 : */
14298 : static std::size_t calc_bson_integer_size(const std::int64_t value)
14299 : {
14300 : return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
14301 : ? sizeof(std::int32_t)
14302 : : sizeof(std::int64_t);
14303 : }
14304 :
14305 : /*!
14306 : @brief Writes a BSON element with key @a name and integer @a value
14307 : */
14308 : void write_bson_integer(const string_t& name,
14309 : const std::int64_t value)
14310 : {
14311 : if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
14312 : {
14313 : write_bson_entry_header(name, 0x10); // int32
14314 : write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
14315 : }
14316 : else
14317 : {
14318 : write_bson_entry_header(name, 0x12); // int64
14319 : write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
14320 : }
14321 : }
14322 :
14323 : /*!
14324 : @return The size of the BSON-encoded unsigned integer in @a j
14325 : */
14326 : static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
14327 : {
14328 : return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14329 : ? sizeof(std::int32_t)
14330 : : sizeof(std::int64_t);
14331 : }
14332 :
14333 : /*!
14334 : @brief Writes a BSON element with key @a name and unsigned @a value
14335 : */
14336 : void write_bson_unsigned(const string_t& name,
14337 : const BasicJsonType& j)
14338 : {
14339 : if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14340 : {
14341 : write_bson_entry_header(name, 0x10 /* int32 */);
14342 : write_number<std::int32_t, true>(static_cast<std::int32_t>(j.m_value.number_unsigned));
14343 : }
14344 : else if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14345 : {
14346 : write_bson_entry_header(name, 0x12 /* int64 */);
14347 : write_number<std::int64_t, true>(static_cast<std::int64_t>(j.m_value.number_unsigned));
14348 : }
14349 : else
14350 : {
14351 : JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", j));
14352 : }
14353 : }
14354 :
14355 : /*!
14356 : @brief Writes a BSON element with key @a name and object @a value
14357 : */
14358 : void write_bson_object_entry(const string_t& name,
14359 : const typename BasicJsonType::object_t& value)
14360 : {
14361 : write_bson_entry_header(name, 0x03); // object
14362 : write_bson_object(value);
14363 : }
14364 :
14365 : /*!
14366 : @return The size of the BSON-encoded array @a value
14367 : */
14368 : static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
14369 : {
14370 : std::size_t array_index = 0ul;
14371 :
14372 : const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
14373 : {
14374 : return result + calc_bson_element_size(std::to_string(array_index++), el);
14375 : });
14376 :
14377 : return sizeof(std::int32_t) + embedded_document_size + 1ul;
14378 : }
14379 :
14380 : /*!
14381 : @return The size of the BSON-encoded binary array @a value
14382 : */
14383 : static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
14384 : {
14385 : return sizeof(std::int32_t) + value.size() + 1ul;
14386 : }
14387 :
14388 : /*!
14389 : @brief Writes a BSON element with key @a name and array @a value
14390 : */
14391 : void write_bson_array(const string_t& name,
14392 : const typename BasicJsonType::array_t& value)
14393 : {
14394 : write_bson_entry_header(name, 0x04); // array
14395 : write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
14396 :
14397 : std::size_t array_index = 0ul;
14398 :
14399 : for (const auto& el : value)
14400 : {
14401 : write_bson_element(std::to_string(array_index++), el);
14402 : }
14403 :
14404 : oa->write_character(to_char_type(0x00));
14405 : }
14406 :
14407 : /*!
14408 : @brief Writes a BSON element with key @a name and binary value @a value
14409 : */
14410 : void write_bson_binary(const string_t& name,
14411 : const binary_t& value)
14412 : {
14413 : write_bson_entry_header(name, 0x05);
14414 :
14415 : write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
14416 : write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
14417 :
14418 : oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
14419 : }
14420 :
14421 : /*!
14422 : @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
14423 : @return The calculated size for the BSON document entry for @a j with the given @a name.
14424 : */
14425 : static std::size_t calc_bson_element_size(const string_t& name,
14426 : const BasicJsonType& j)
14427 : {
14428 : const auto header_size = calc_bson_entry_header_size(name, j);
14429 : switch (j.type())
14430 : {
14431 : case value_t::object:
14432 : return header_size + calc_bson_object_size(*j.m_value.object);
14433 :
14434 : case value_t::array:
14435 : return header_size + calc_bson_array_size(*j.m_value.array);
14436 :
14437 : case value_t::binary:
14438 : return header_size + calc_bson_binary_size(*j.m_value.binary);
14439 :
14440 : case value_t::boolean:
14441 : return header_size + 1ul;
14442 :
14443 : case value_t::number_float:
14444 : return header_size + 8ul;
14445 :
14446 : case value_t::number_integer:
14447 : return header_size + calc_bson_integer_size(j.m_value.number_integer);
14448 :
14449 : case value_t::number_unsigned:
14450 : return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
14451 :
14452 : case value_t::string:
14453 : return header_size + calc_bson_string_size(*j.m_value.string);
14454 :
14455 : case value_t::null:
14456 : return header_size + 0ul;
14457 :
14458 : // LCOV_EXCL_START
14459 : case value_t::discarded:
14460 : default:
14461 : JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
14462 : return 0ul;
14463 : // LCOV_EXCL_STOP
14464 : }
14465 : }
14466 :
14467 : /*!
14468 : @brief Serializes the JSON value @a j to BSON and associates it with the
14469 : key @a name.
14470 : @param name The name to associate with the JSON entity @a j within the
14471 : current BSON document
14472 : */
14473 : void write_bson_element(const string_t& name,
14474 : const BasicJsonType& j)
14475 : {
14476 : switch (j.type())
14477 : {
14478 : case value_t::object:
14479 : return write_bson_object_entry(name, *j.m_value.object);
14480 :
14481 : case value_t::array:
14482 : return write_bson_array(name, *j.m_value.array);
14483 :
14484 : case value_t::binary:
14485 : return write_bson_binary(name, *j.m_value.binary);
14486 :
14487 : case value_t::boolean:
14488 : return write_bson_boolean(name, j.m_value.boolean);
14489 :
14490 : case value_t::number_float:
14491 : return write_bson_double(name, j.m_value.number_float);
14492 :
14493 : case value_t::number_integer:
14494 : return write_bson_integer(name, j.m_value.number_integer);
14495 :
14496 : case value_t::number_unsigned:
14497 : return write_bson_unsigned(name, j);
14498 :
14499 : case value_t::string:
14500 : return write_bson_string(name, *j.m_value.string);
14501 :
14502 : case value_t::null:
14503 : return write_bson_null(name);
14504 :
14505 : // LCOV_EXCL_START
14506 : case value_t::discarded:
14507 : default:
14508 : JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
14509 : return;
14510 : // LCOV_EXCL_STOP
14511 : }
14512 : }
14513 :
14514 : /*!
14515 : @brief Calculates the size of the BSON serialization of the given
14516 : JSON-object @a j.
14517 : @param[in] value JSON value to serialize
14518 : @pre value.type() == value_t::object
14519 : */
14520 : static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
14521 : {
14522 : std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
14523 : [](size_t result, const typename BasicJsonType::object_t::value_type & el)
14524 : {
14525 : return result += calc_bson_element_size(el.first, el.second);
14526 : });
14527 :
14528 : return sizeof(std::int32_t) + document_size + 1ul;
14529 : }
14530 :
14531 : /*!
14532 : @param[in] value JSON value to serialize
14533 : @pre value.type() == value_t::object
14534 : */
14535 : void write_bson_object(const typename BasicJsonType::object_t& value)
14536 : {
14537 : write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
14538 :
14539 : for (const auto& el : value)
14540 : {
14541 : write_bson_element(el.first, el.second);
14542 : }
14543 :
14544 : oa->write_character(to_char_type(0x00));
14545 : }
14546 :
14547 : //////////
14548 : // CBOR //
14549 : //////////
14550 :
14551 : static constexpr CharType get_cbor_float_prefix(float /*unused*/)
14552 : {
14553 : return to_char_type(0xFA); // Single-Precision Float
14554 : }
14555 :
14556 : static constexpr CharType get_cbor_float_prefix(double /*unused*/)
14557 : {
14558 : return to_char_type(0xFB); // Double-Precision Float
14559 : }
14560 :
14561 : /////////////
14562 : // MsgPack //
14563 : /////////////
14564 :
14565 : static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
14566 : {
14567 : return to_char_type(0xCA); // float 32
14568 : }
14569 :
14570 : static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
14571 : {
14572 : return to_char_type(0xCB); // float 64
14573 : }
14574 :
14575 : ////////////
14576 : // UBJSON //
14577 : ////////////
14578 :
14579 : // UBJSON: write number (floating point)
14580 : template<typename NumberType, typename std::enable_if<
14581 : std::is_floating_point<NumberType>::value, int>::type = 0>
14582 : void write_number_with_ubjson_prefix(const NumberType n,
14583 : const bool add_prefix)
14584 : {
14585 : if (add_prefix)
14586 : {
14587 : oa->write_character(get_ubjson_float_prefix(n));
14588 : }
14589 : write_number(n);
14590 : }
14591 :
14592 : // UBJSON: write number (unsigned integer)
14593 : template<typename NumberType, typename std::enable_if<
14594 : std::is_unsigned<NumberType>::value, int>::type = 0>
14595 : void write_number_with_ubjson_prefix(const NumberType n,
14596 : const bool add_prefix)
14597 : {
14598 : if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
14599 : {
14600 : if (add_prefix)
14601 : {
14602 : oa->write_character(to_char_type('i')); // int8
14603 : }
14604 : write_number(static_cast<std::uint8_t>(n));
14605 : }
14606 : else if (n <= (std::numeric_limits<std::uint8_t>::max)())
14607 : {
14608 : if (add_prefix)
14609 : {
14610 : oa->write_character(to_char_type('U')); // uint8
14611 : }
14612 : write_number(static_cast<std::uint8_t>(n));
14613 : }
14614 : else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
14615 : {
14616 : if (add_prefix)
14617 : {
14618 : oa->write_character(to_char_type('I')); // int16
14619 : }
14620 : write_number(static_cast<std::int16_t>(n));
14621 : }
14622 : else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14623 : {
14624 : if (add_prefix)
14625 : {
14626 : oa->write_character(to_char_type('l')); // int32
14627 : }
14628 : write_number(static_cast<std::int32_t>(n));
14629 : }
14630 : else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14631 : {
14632 : if (add_prefix)
14633 : {
14634 : oa->write_character(to_char_type('L')); // int64
14635 : }
14636 : write_number(static_cast<std::int64_t>(n));
14637 : }
14638 : else
14639 : {
14640 : if (add_prefix)
14641 : {
14642 : oa->write_character(to_char_type('H')); // high-precision number
14643 : }
14644 :
14645 : const auto number = BasicJsonType(n).dump();
14646 : write_number_with_ubjson_prefix(number.size(), true);
14647 : for (std::size_t i = 0; i < number.size(); ++i)
14648 : {
14649 : oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
14650 : }
14651 : }
14652 : }
14653 :
14654 : // UBJSON: write number (signed integer)
14655 : template < typename NumberType, typename std::enable_if <
14656 : std::is_signed<NumberType>::value&&
14657 : !std::is_floating_point<NumberType>::value, int >::type = 0 >
14658 : void write_number_with_ubjson_prefix(const NumberType n,
14659 : const bool add_prefix)
14660 : {
14661 : if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
14662 : {
14663 : if (add_prefix)
14664 : {
14665 : oa->write_character(to_char_type('i')); // int8
14666 : }
14667 : write_number(static_cast<std::int8_t>(n));
14668 : }
14669 : else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
14670 : {
14671 : if (add_prefix)
14672 : {
14673 : oa->write_character(to_char_type('U')); // uint8
14674 : }
14675 : write_number(static_cast<std::uint8_t>(n));
14676 : }
14677 : else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
14678 : {
14679 : if (add_prefix)
14680 : {
14681 : oa->write_character(to_char_type('I')); // int16
14682 : }
14683 : write_number(static_cast<std::int16_t>(n));
14684 : }
14685 : else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
14686 : {
14687 : if (add_prefix)
14688 : {
14689 : oa->write_character(to_char_type('l')); // int32
14690 : }
14691 : write_number(static_cast<std::int32_t>(n));
14692 : }
14693 : else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
14694 : {
14695 : if (add_prefix)
14696 : {
14697 : oa->write_character(to_char_type('L')); // int64
14698 : }
14699 : write_number(static_cast<std::int64_t>(n));
14700 : }
14701 : // LCOV_EXCL_START
14702 : else
14703 : {
14704 : if (add_prefix)
14705 : {
14706 : oa->write_character(to_char_type('H')); // high-precision number
14707 : }
14708 :
14709 : const auto number = BasicJsonType(n).dump();
14710 : write_number_with_ubjson_prefix(number.size(), true);
14711 : for (std::size_t i = 0; i < number.size(); ++i)
14712 : {
14713 : oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
14714 : }
14715 : }
14716 : // LCOV_EXCL_STOP
14717 : }
14718 :
14719 : /*!
14720 : @brief determine the type prefix of container values
14721 : */
14722 : CharType ubjson_prefix(const BasicJsonType& j) const noexcept
14723 : {
14724 : switch (j.type())
14725 : {
14726 : case value_t::null:
14727 : return 'Z';
14728 :
14729 : case value_t::boolean:
14730 : return j.m_value.boolean ? 'T' : 'F';
14731 :
14732 : case value_t::number_integer:
14733 : {
14734 : if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
14735 : {
14736 : return 'i';
14737 : }
14738 : if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
14739 : {
14740 : return 'U';
14741 : }
14742 : if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
14743 : {
14744 : return 'I';
14745 : }
14746 : if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
14747 : {
14748 : return 'l';
14749 : }
14750 : if ((std::numeric_limits<std::int64_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
14751 : {
14752 : return 'L';
14753 : }
14754 : // anything else is treated as high-precision number
14755 : return 'H'; // LCOV_EXCL_LINE
14756 : }
14757 :
14758 : case value_t::number_unsigned:
14759 : {
14760 : if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
14761 : {
14762 : return 'i';
14763 : }
14764 : if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
14765 : {
14766 : return 'U';
14767 : }
14768 : if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
14769 : {
14770 : return 'I';
14771 : }
14772 : if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14773 : {
14774 : return 'l';
14775 : }
14776 : if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14777 : {
14778 : return 'L';
14779 : }
14780 : // anything else is treated as high-precision number
14781 : return 'H'; // LCOV_EXCL_LINE
14782 : }
14783 :
14784 : case value_t::number_float:
14785 : return get_ubjson_float_prefix(j.m_value.number_float);
14786 :
14787 : case value_t::string:
14788 : return 'S';
14789 :
14790 : case value_t::array: // fallthrough
14791 : case value_t::binary:
14792 : return '[';
14793 :
14794 : case value_t::object:
14795 : return '{';
14796 :
14797 : case value_t::discarded:
14798 : default: // discarded values
14799 : return 'N';
14800 : }
14801 : }
14802 :
14803 : static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
14804 : {
14805 : return 'd'; // float 32
14806 : }
14807 :
14808 : static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
14809 : {
14810 : return 'D'; // float 64
14811 : }
14812 :
14813 : ///////////////////////
14814 : // Utility functions //
14815 : ///////////////////////
14816 :
14817 : /*
14818 : @brief write a number to output input
14819 : @param[in] n number of type @a NumberType
14820 : @tparam NumberType the type of the number
14821 : @tparam OutputIsLittleEndian Set to true if output data is
14822 : required to be little endian
14823 :
14824 : @note This function needs to respect the system's endianness, because bytes
14825 : in CBOR, MessagePack, and UBJSON are stored in network order (big
14826 : endian) and therefore need reordering on little endian systems.
14827 : */
14828 : template<typename NumberType, bool OutputIsLittleEndian = false>
14829 : void write_number(const NumberType n)
14830 : {
14831 : // step 1: write number to array of length NumberType
14832 : std::array<CharType, sizeof(NumberType)> vec{};
14833 : std::memcpy(vec.data(), &n, sizeof(NumberType));
14834 :
14835 : // step 2: write array to output (with possible reordering)
14836 : if (is_little_endian != OutputIsLittleEndian)
14837 : {
14838 : // reverse byte order prior to conversion if necessary
14839 : std::reverse(vec.begin(), vec.end());
14840 : }
14841 :
14842 : oa->write_characters(vec.data(), sizeof(NumberType));
14843 : }
14844 :
14845 : void write_compact_float(const number_float_t n, detail::input_format_t format)
14846 : {
14847 : #ifdef __GNUC__
14848 : #pragma GCC diagnostic push
14849 : #pragma GCC diagnostic ignored "-Wfloat-equal"
14850 : #endif
14851 : if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
14852 : static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
14853 : static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
14854 : {
14855 : oa->write_character(format == detail::input_format_t::cbor
14856 : ? get_cbor_float_prefix(static_cast<float>(n))
14857 : : get_msgpack_float_prefix(static_cast<float>(n)));
14858 : write_number(static_cast<float>(n));
14859 : }
14860 : else
14861 : {
14862 : oa->write_character(format == detail::input_format_t::cbor
14863 : ? get_cbor_float_prefix(n)
14864 : : get_msgpack_float_prefix(n));
14865 : write_number(n);
14866 : }
14867 : #ifdef __GNUC__
14868 : #pragma GCC diagnostic pop
14869 : #endif
14870 : }
14871 :
14872 : public:
14873 : // The following to_char_type functions are implement the conversion
14874 : // between uint8_t and CharType. In case CharType is not unsigned,
14875 : // such a conversion is required to allow values greater than 128.
14876 : // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
14877 : template < typename C = CharType,
14878 : enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
14879 : static constexpr CharType to_char_type(std::uint8_t x) noexcept
14880 : {
14881 : return *reinterpret_cast<char*>(&x);
14882 : }
14883 :
14884 : template < typename C = CharType,
14885 : enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
14886 : static CharType to_char_type(std::uint8_t x) noexcept
14887 : {
14888 : static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
14889 : static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
14890 : CharType result;
14891 : std::memcpy(&result, &x, sizeof(x));
14892 : return result;
14893 : }
14894 :
14895 : template<typename C = CharType,
14896 : enable_if_t<std::is_unsigned<C>::value>* = nullptr>
14897 : static constexpr CharType to_char_type(std::uint8_t x) noexcept
14898 : {
14899 : return x;
14900 : }
14901 :
14902 : template < typename InputCharType, typename C = CharType,
14903 : enable_if_t <
14904 : std::is_signed<C>::value &&
14905 : std::is_signed<char>::value &&
14906 : std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
14907 : > * = nullptr >
14908 : static constexpr CharType to_char_type(InputCharType x) noexcept
14909 : {
14910 : return x;
14911 : }
14912 :
14913 : private:
14914 : /// whether we can assume little endianness
14915 : const bool is_little_endian = little_endianness();
14916 :
14917 : /// the output
14918 : output_adapter_t<CharType> oa = nullptr;
14919 : };
14920 : } // namespace detail
14921 : } // namespace nlohmann
14922 :
14923 : // #include <nlohmann/detail/output/output_adapters.hpp>
14924 :
14925 : // #include <nlohmann/detail/output/serializer.hpp>
14926 :
14927 :
14928 : #include <algorithm> // reverse, remove, fill, find, none_of
14929 : #include <array> // array
14930 : #include <clocale> // localeconv, lconv
14931 : #include <cmath> // labs, isfinite, isnan, signbit
14932 : #include <cstddef> // size_t, ptrdiff_t
14933 : #include <cstdint> // uint8_t
14934 : #include <cstdio> // snprintf
14935 : #include <limits> // numeric_limits
14936 : #include <string> // string, char_traits
14937 : #include <iomanip> // setfill, setw
14938 : #include <sstream> // stringstream
14939 : #include <type_traits> // is_same
14940 : #include <utility> // move
14941 :
14942 : // #include <nlohmann/detail/conversions/to_chars.hpp>
14943 :
14944 :
14945 : #include <array> // array
14946 : #include <cmath> // signbit, isfinite
14947 : #include <cstdint> // intN_t, uintN_t
14948 : #include <cstring> // memcpy, memmove
14949 : #include <limits> // numeric_limits
14950 : #include <type_traits> // conditional
14951 :
14952 : // #include <nlohmann/detail/macro_scope.hpp>
14953 :
14954 :
14955 : namespace nlohmann
14956 : {
14957 : namespace detail
14958 : {
14959 :
14960 : /*!
14961 : @brief implements the Grisu2 algorithm for binary to decimal floating-point
14962 : conversion.
14963 :
14964 : This implementation is a slightly modified version of the reference
14965 : implementation which may be obtained from
14966 : http://florian.loitsch.com/publications (bench.tar.gz).
14967 :
14968 : The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
14969 :
14970 : For a detailed description of the algorithm see:
14971 :
14972 : [1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
14973 : Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
14974 : Language Design and Implementation, PLDI 2010
14975 : [2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
14976 : Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
14977 : Design and Implementation, PLDI 1996
14978 : */
14979 : namespace dtoa_impl
14980 : {
14981 :
14982 : template<typename Target, typename Source>
14983 : Target reinterpret_bits(const Source source)
14984 : {
14985 : static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
14986 :
14987 : Target target;
14988 : std::memcpy(&target, &source, sizeof(Source));
14989 : return target;
14990 : }
14991 :
14992 : struct diyfp // f * 2^e
14993 : {
14994 : static constexpr int kPrecision = 64; // = q
14995 :
14996 : std::uint64_t f = 0;
14997 : int e = 0;
14998 :
14999 : constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
15000 :
15001 : /*!
15002 : @brief returns x - y
15003 : @pre x.e == y.e and x.f >= y.f
15004 : */
15005 : static diyfp sub(const diyfp& x, const diyfp& y) noexcept
15006 : {
15007 : JSON_ASSERT(x.e == y.e);
15008 : JSON_ASSERT(x.f >= y.f);
15009 :
15010 : return {x.f - y.f, x.e};
15011 : }
15012 :
15013 : /*!
15014 : @brief returns x * y
15015 : @note The result is rounded. (Only the upper q bits are returned.)
15016 : */
15017 : static diyfp mul(const diyfp& x, const diyfp& y) noexcept
15018 : {
15019 : static_assert(kPrecision == 64, "internal error");
15020 :
15021 : // Computes:
15022 : // f = round((x.f * y.f) / 2^q)
15023 : // e = x.e + y.e + q
15024 :
15025 : // Emulate the 64-bit * 64-bit multiplication:
15026 : //
15027 : // p = u * v
15028 : // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
15029 : // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
15030 : // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
15031 : // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
15032 : // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
15033 : // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
15034 : // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
15035 : //
15036 : // (Since Q might be larger than 2^32 - 1)
15037 : //
15038 : // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
15039 : //
15040 : // (Q_hi + H does not overflow a 64-bit int)
15041 : //
15042 : // = p_lo + 2^64 p_hi
15043 :
15044 : const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
15045 : const std::uint64_t u_hi = x.f >> 32u;
15046 : const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
15047 : const std::uint64_t v_hi = y.f >> 32u;
15048 :
15049 : const std::uint64_t p0 = u_lo * v_lo;
15050 : const std::uint64_t p1 = u_lo * v_hi;
15051 : const std::uint64_t p2 = u_hi * v_lo;
15052 : const std::uint64_t p3 = u_hi * v_hi;
15053 :
15054 : const std::uint64_t p0_hi = p0 >> 32u;
15055 : const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
15056 : const std::uint64_t p1_hi = p1 >> 32u;
15057 : const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
15058 : const std::uint64_t p2_hi = p2 >> 32u;
15059 :
15060 : std::uint64_t Q = p0_hi + p1_lo + p2_lo;
15061 :
15062 : // The full product might now be computed as
15063 : //
15064 : // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
15065 : // p_lo = p0_lo + (Q << 32)
15066 : //
15067 : // But in this particular case here, the full p_lo is not required.
15068 : // Effectively we only need to add the highest bit in p_lo to p_hi (and
15069 : // Q_hi + 1 does not overflow).
15070 :
15071 : Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
15072 :
15073 : const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
15074 :
15075 : return {h, x.e + y.e + 64};
15076 : }
15077 :
15078 : /*!
15079 : @brief normalize x such that the significand is >= 2^(q-1)
15080 : @pre x.f != 0
15081 : */
15082 : static diyfp normalize(diyfp x) noexcept
15083 : {
15084 : JSON_ASSERT(x.f != 0);
15085 :
15086 : while ((x.f >> 63u) == 0)
15087 : {
15088 : x.f <<= 1u;
15089 : x.e--;
15090 : }
15091 :
15092 : return x;
15093 : }
15094 :
15095 : /*!
15096 : @brief normalize x such that the result has the exponent E
15097 : @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
15098 : */
15099 : static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
15100 : {
15101 : const int delta = x.e - target_exponent;
15102 :
15103 : JSON_ASSERT(delta >= 0);
15104 : JSON_ASSERT(((x.f << delta) >> delta) == x.f);
15105 :
15106 : return {x.f << delta, target_exponent};
15107 : }
15108 : };
15109 :
15110 : struct boundaries
15111 : {
15112 : diyfp w;
15113 : diyfp minus;
15114 : diyfp plus;
15115 : };
15116 :
15117 : /*!
15118 : Compute the (normalized) diyfp representing the input number 'value' and its
15119 : boundaries.
15120 :
15121 : @pre value must be finite and positive
15122 : */
15123 : template<typename FloatType>
15124 : boundaries compute_boundaries(FloatType value)
15125 : {
15126 : JSON_ASSERT(std::isfinite(value));
15127 : JSON_ASSERT(value > 0);
15128 :
15129 : // Convert the IEEE representation into a diyfp.
15130 : //
15131 : // If v is denormal:
15132 : // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
15133 : // If v is normalized:
15134 : // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
15135 :
15136 : static_assert(std::numeric_limits<FloatType>::is_iec559,
15137 : "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
15138 :
15139 : constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
15140 : constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
15141 : constexpr int kMinExp = 1 - kBias;
15142 : constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
15143 :
15144 : using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
15145 :
15146 : const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
15147 : const std::uint64_t E = bits >> (kPrecision - 1);
15148 : const std::uint64_t F = bits & (kHiddenBit - 1);
15149 :
15150 : const bool is_denormal = E == 0;
15151 : const diyfp v = is_denormal
15152 : ? diyfp(F, kMinExp)
15153 : : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
15154 :
15155 : // Compute the boundaries m- and m+ of the floating-point value
15156 : // v = f * 2^e.
15157 : //
15158 : // Determine v- and v+, the floating-point predecessor and successor if v,
15159 : // respectively.
15160 : //
15161 : // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
15162 : // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
15163 : //
15164 : // v+ = v + 2^e
15165 : //
15166 : // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
15167 : // between m- and m+ round to v, regardless of how the input rounding
15168 : // algorithm breaks ties.
15169 : //
15170 : // ---+-------------+-------------+-------------+-------------+--- (A)
15171 : // v- m- v m+ v+
15172 : //
15173 : // -----------------+------+------+-------------+-------------+--- (B)
15174 : // v- m- v m+ v+
15175 :
15176 : const bool lower_boundary_is_closer = F == 0 && E > 1;
15177 : const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
15178 : const diyfp m_minus = lower_boundary_is_closer
15179 : ? diyfp(4 * v.f - 1, v.e - 2) // (B)
15180 : : diyfp(2 * v.f - 1, v.e - 1); // (A)
15181 :
15182 : // Determine the normalized w+ = m+.
15183 : const diyfp w_plus = diyfp::normalize(m_plus);
15184 :
15185 : // Determine w- = m- such that e_(w-) = e_(w+).
15186 : const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
15187 :
15188 : return {diyfp::normalize(v), w_minus, w_plus};
15189 : }
15190 :
15191 : // Given normalized diyfp w, Grisu needs to find a (normalized) cached
15192 : // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
15193 : // within a certain range [alpha, gamma] (Definition 3.2 from [1])
15194 : //
15195 : // alpha <= e = e_c + e_w + q <= gamma
15196 : //
15197 : // or
15198 : //
15199 : // f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
15200 : // <= f_c * f_w * 2^gamma
15201 : //
15202 : // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
15203 : //
15204 : // 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
15205 : //
15206 : // or
15207 : //
15208 : // 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
15209 : //
15210 : // The choice of (alpha,gamma) determines the size of the table and the form of
15211 : // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
15212 : // in practice:
15213 : //
15214 : // The idea is to cut the number c * w = f * 2^e into two parts, which can be
15215 : // processed independently: An integral part p1, and a fractional part p2:
15216 : //
15217 : // f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
15218 : // = (f div 2^-e) + (f mod 2^-e) * 2^e
15219 : // = p1 + p2 * 2^e
15220 : //
15221 : // The conversion of p1 into decimal form requires a series of divisions and
15222 : // modulos by (a power of) 10. These operations are faster for 32-bit than for
15223 : // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
15224 : // achieved by choosing
15225 : //
15226 : // -e >= 32 or e <= -32 := gamma
15227 : //
15228 : // In order to convert the fractional part
15229 : //
15230 : // p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
15231 : //
15232 : // into decimal form, the fraction is repeatedly multiplied by 10 and the digits
15233 : // d[-i] are extracted in order:
15234 : //
15235 : // (10 * p2) div 2^-e = d[-1]
15236 : // (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
15237 : //
15238 : // The multiplication by 10 must not overflow. It is sufficient to choose
15239 : //
15240 : // 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
15241 : //
15242 : // Since p2 = f mod 2^-e < 2^-e,
15243 : //
15244 : // -e <= 60 or e >= -60 := alpha
15245 :
15246 : constexpr int kAlpha = -60;
15247 : constexpr int kGamma = -32;
15248 :
15249 : struct cached_power // c = f * 2^e ~= 10^k
15250 : {
15251 : std::uint64_t f;
15252 : int e;
15253 : int k;
15254 : };
15255 :
15256 : /*!
15257 : For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
15258 : power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
15259 : satisfies (Definition 3.2 from [1])
15260 :
15261 : alpha <= e_c + e + q <= gamma.
15262 : */
15263 : inline cached_power get_cached_power_for_binary_exponent(int e)
15264 : {
15265 : // Now
15266 : //
15267 : // alpha <= e_c + e + q <= gamma (1)
15268 : // ==> f_c * 2^alpha <= c * 2^e * 2^q
15269 : //
15270 : // and since the c's are normalized, 2^(q-1) <= f_c,
15271 : //
15272 : // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
15273 : // ==> 2^(alpha - e - 1) <= c
15274 : //
15275 : // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
15276 : //
15277 : // k = ceil( log_10( 2^(alpha - e - 1) ) )
15278 : // = ceil( (alpha - e - 1) * log_10(2) )
15279 : //
15280 : // From the paper:
15281 : // "In theory the result of the procedure could be wrong since c is rounded,
15282 : // and the computation itself is approximated [...]. In practice, however,
15283 : // this simple function is sufficient."
15284 : //
15285 : // For IEEE double precision floating-point numbers converted into
15286 : // normalized diyfp's w = f * 2^e, with q = 64,
15287 : //
15288 : // e >= -1022 (min IEEE exponent)
15289 : // -52 (p - 1)
15290 : // -52 (p - 1, possibly normalize denormal IEEE numbers)
15291 : // -11 (normalize the diyfp)
15292 : // = -1137
15293 : //
15294 : // and
15295 : //
15296 : // e <= +1023 (max IEEE exponent)
15297 : // -52 (p - 1)
15298 : // -11 (normalize the diyfp)
15299 : // = 960
15300 : //
15301 : // This binary exponent range [-1137,960] results in a decimal exponent
15302 : // range [-307,324]. One does not need to store a cached power for each
15303 : // k in this range. For each such k it suffices to find a cached power
15304 : // such that the exponent of the product lies in [alpha,gamma].
15305 : // This implies that the difference of the decimal exponents of adjacent
15306 : // table entries must be less than or equal to
15307 : //
15308 : // floor( (gamma - alpha) * log_10(2) ) = 8.
15309 : //
15310 : // (A smaller distance gamma-alpha would require a larger table.)
15311 :
15312 : // NB:
15313 : // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
15314 :
15315 : constexpr int kCachedPowersMinDecExp = -300;
15316 : constexpr int kCachedPowersDecStep = 8;
15317 :
15318 : static constexpr std::array<cached_power, 79> kCachedPowers =
15319 : {
15320 : {
15321 : { 0xAB70FE17C79AC6CA, -1060, -300 },
15322 : { 0xFF77B1FCBEBCDC4F, -1034, -292 },
15323 : { 0xBE5691EF416BD60C, -1007, -284 },
15324 : { 0x8DD01FAD907FFC3C, -980, -276 },
15325 : { 0xD3515C2831559A83, -954, -268 },
15326 : { 0x9D71AC8FADA6C9B5, -927, -260 },
15327 : { 0xEA9C227723EE8BCB, -901, -252 },
15328 : { 0xAECC49914078536D, -874, -244 },
15329 : { 0x823C12795DB6CE57, -847, -236 },
15330 : { 0xC21094364DFB5637, -821, -228 },
15331 : { 0x9096EA6F3848984F, -794, -220 },
15332 : { 0xD77485CB25823AC7, -768, -212 },
15333 : { 0xA086CFCD97BF97F4, -741, -204 },
15334 : { 0xEF340A98172AACE5, -715, -196 },
15335 : { 0xB23867FB2A35B28E, -688, -188 },
15336 : { 0x84C8D4DFD2C63F3B, -661, -180 },
15337 : { 0xC5DD44271AD3CDBA, -635, -172 },
15338 : { 0x936B9FCEBB25C996, -608, -164 },
15339 : { 0xDBAC6C247D62A584, -582, -156 },
15340 : { 0xA3AB66580D5FDAF6, -555, -148 },
15341 : { 0xF3E2F893DEC3F126, -529, -140 },
15342 : { 0xB5B5ADA8AAFF80B8, -502, -132 },
15343 : { 0x87625F056C7C4A8B, -475, -124 },
15344 : { 0xC9BCFF6034C13053, -449, -116 },
15345 : { 0x964E858C91BA2655, -422, -108 },
15346 : { 0xDFF9772470297EBD, -396, -100 },
15347 : { 0xA6DFBD9FB8E5B88F, -369, -92 },
15348 : { 0xF8A95FCF88747D94, -343, -84 },
15349 : { 0xB94470938FA89BCF, -316, -76 },
15350 : { 0x8A08F0F8BF0F156B, -289, -68 },
15351 : { 0xCDB02555653131B6, -263, -60 },
15352 : { 0x993FE2C6D07B7FAC, -236, -52 },
15353 : { 0xE45C10C42A2B3B06, -210, -44 },
15354 : { 0xAA242499697392D3, -183, -36 },
15355 : { 0xFD87B5F28300CA0E, -157, -28 },
15356 : { 0xBCE5086492111AEB, -130, -20 },
15357 : { 0x8CBCCC096F5088CC, -103, -12 },
15358 : { 0xD1B71758E219652C, -77, -4 },
15359 : { 0x9C40000000000000, -50, 4 },
15360 : { 0xE8D4A51000000000, -24, 12 },
15361 : { 0xAD78EBC5AC620000, 3, 20 },
15362 : { 0x813F3978F8940984, 30, 28 },
15363 : { 0xC097CE7BC90715B3, 56, 36 },
15364 : { 0x8F7E32CE7BEA5C70, 83, 44 },
15365 : { 0xD5D238A4ABE98068, 109, 52 },
15366 : { 0x9F4F2726179A2245, 136, 60 },
15367 : { 0xED63A231D4C4FB27, 162, 68 },
15368 : { 0xB0DE65388CC8ADA8, 189, 76 },
15369 : { 0x83C7088E1AAB65DB, 216, 84 },
15370 : { 0xC45D1DF942711D9A, 242, 92 },
15371 : { 0x924D692CA61BE758, 269, 100 },
15372 : { 0xDA01EE641A708DEA, 295, 108 },
15373 : { 0xA26DA3999AEF774A, 322, 116 },
15374 : { 0xF209787BB47D6B85, 348, 124 },
15375 : { 0xB454E4A179DD1877, 375, 132 },
15376 : { 0x865B86925B9BC5C2, 402, 140 },
15377 : { 0xC83553C5C8965D3D, 428, 148 },
15378 : { 0x952AB45CFA97A0B3, 455, 156 },
15379 : { 0xDE469FBD99A05FE3, 481, 164 },
15380 : { 0xA59BC234DB398C25, 508, 172 },
15381 : { 0xF6C69A72A3989F5C, 534, 180 },
15382 : { 0xB7DCBF5354E9BECE, 561, 188 },
15383 : { 0x88FCF317F22241E2, 588, 196 },
15384 : { 0xCC20CE9BD35C78A5, 614, 204 },
15385 : { 0x98165AF37B2153DF, 641, 212 },
15386 : { 0xE2A0B5DC971F303A, 667, 220 },
15387 : { 0xA8D9D1535CE3B396, 694, 228 },
15388 : { 0xFB9B7CD9A4A7443C, 720, 236 },
15389 : { 0xBB764C4CA7A44410, 747, 244 },
15390 : { 0x8BAB8EEFB6409C1A, 774, 252 },
15391 : { 0xD01FEF10A657842C, 800, 260 },
15392 : { 0x9B10A4E5E9913129, 827, 268 },
15393 : { 0xE7109BFBA19C0C9D, 853, 276 },
15394 : { 0xAC2820D9623BF429, 880, 284 },
15395 : { 0x80444B5E7AA7CF85, 907, 292 },
15396 : { 0xBF21E44003ACDD2D, 933, 300 },
15397 : { 0x8E679C2F5E44FF8F, 960, 308 },
15398 : { 0xD433179D9C8CB841, 986, 316 },
15399 : { 0x9E19DB92B4E31BA9, 1013, 324 },
15400 : }
15401 : };
15402 :
15403 : // This computation gives exactly the same results for k as
15404 : // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
15405 : // for |e| <= 1500, but doesn't require floating-point operations.
15406 : // NB: log_10(2) ~= 78913 / 2^18
15407 : JSON_ASSERT(e >= -1500);
15408 : JSON_ASSERT(e <= 1500);
15409 : const int f = kAlpha - e - 1;
15410 : const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
15411 :
15412 : const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
15413 : JSON_ASSERT(index >= 0);
15414 : JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
15415 :
15416 : const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
15417 : JSON_ASSERT(kAlpha <= cached.e + e + 64);
15418 : JSON_ASSERT(kGamma >= cached.e + e + 64);
15419 :
15420 : return cached;
15421 : }
15422 :
15423 : /*!
15424 : For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
15425 : For n == 0, returns 1 and sets pow10 := 1.
15426 : */
15427 : inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
15428 : {
15429 : // LCOV_EXCL_START
15430 : if (n >= 1000000000)
15431 : {
15432 : pow10 = 1000000000;
15433 : return 10;
15434 : }
15435 : // LCOV_EXCL_STOP
15436 : if (n >= 100000000)
15437 : {
15438 : pow10 = 100000000;
15439 : return 9;
15440 : }
15441 : if (n >= 10000000)
15442 : {
15443 : pow10 = 10000000;
15444 : return 8;
15445 : }
15446 : if (n >= 1000000)
15447 : {
15448 : pow10 = 1000000;
15449 : return 7;
15450 : }
15451 : if (n >= 100000)
15452 : {
15453 : pow10 = 100000;
15454 : return 6;
15455 : }
15456 : if (n >= 10000)
15457 : {
15458 : pow10 = 10000;
15459 : return 5;
15460 : }
15461 : if (n >= 1000)
15462 : {
15463 : pow10 = 1000;
15464 : return 4;
15465 : }
15466 : if (n >= 100)
15467 : {
15468 : pow10 = 100;
15469 : return 3;
15470 : }
15471 : if (n >= 10)
15472 : {
15473 : pow10 = 10;
15474 : return 2;
15475 : }
15476 :
15477 : pow10 = 1;
15478 : return 1;
15479 : }
15480 :
15481 : inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
15482 : std::uint64_t rest, std::uint64_t ten_k)
15483 : {
15484 : JSON_ASSERT(len >= 1);
15485 : JSON_ASSERT(dist <= delta);
15486 : JSON_ASSERT(rest <= delta);
15487 : JSON_ASSERT(ten_k > 0);
15488 :
15489 : // <--------------------------- delta ---->
15490 : // <---- dist --------->
15491 : // --------------[------------------+-------------------]--------------
15492 : // M- w M+
15493 : //
15494 : // ten_k
15495 : // <------>
15496 : // <---- rest ---->
15497 : // --------------[------------------+----+--------------]--------------
15498 : // w V
15499 : // = buf * 10^k
15500 : //
15501 : // ten_k represents a unit-in-the-last-place in the decimal representation
15502 : // stored in buf.
15503 : // Decrement buf by ten_k while this takes buf closer to w.
15504 :
15505 : // The tests are written in this order to avoid overflow in unsigned
15506 : // integer arithmetic.
15507 :
15508 : while (rest < dist
15509 : && delta - rest >= ten_k
15510 : && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
15511 : {
15512 : JSON_ASSERT(buf[len - 1] != '0');
15513 : buf[len - 1]--;
15514 : rest += ten_k;
15515 : }
15516 : }
15517 :
15518 : /*!
15519 : Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
15520 : M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
15521 : */
15522 : inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
15523 : diyfp M_minus, diyfp w, diyfp M_plus)
15524 : {
15525 : static_assert(kAlpha >= -60, "internal error");
15526 : static_assert(kGamma <= -32, "internal error");
15527 :
15528 : // Generates the digits (and the exponent) of a decimal floating-point
15529 : // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
15530 : // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
15531 : //
15532 : // <--------------------------- delta ---->
15533 : // <---- dist --------->
15534 : // --------------[------------------+-------------------]--------------
15535 : // M- w M+
15536 : //
15537 : // Grisu2 generates the digits of M+ from left to right and stops as soon as
15538 : // V is in [M-,M+].
15539 :
15540 : JSON_ASSERT(M_plus.e >= kAlpha);
15541 : JSON_ASSERT(M_plus.e <= kGamma);
15542 :
15543 : std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
15544 : std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
15545 :
15546 : // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
15547 : //
15548 : // M+ = f * 2^e
15549 : // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
15550 : // = ((p1 ) * 2^-e + (p2 )) * 2^e
15551 : // = p1 + p2 * 2^e
15552 :
15553 : const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
15554 :
15555 : auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
15556 : std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
15557 :
15558 : // 1)
15559 : //
15560 : // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
15561 :
15562 : JSON_ASSERT(p1 > 0);
15563 :
15564 : std::uint32_t pow10{};
15565 : const int k = find_largest_pow10(p1, pow10);
15566 :
15567 : // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
15568 : //
15569 : // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
15570 : // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
15571 : //
15572 : // M+ = p1 + p2 * 2^e
15573 : // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
15574 : // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
15575 : // = d[k-1] * 10^(k-1) + ( rest) * 2^e
15576 : //
15577 : // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
15578 : //
15579 : // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
15580 : //
15581 : // but stop as soon as
15582 : //
15583 : // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
15584 :
15585 : int n = k;
15586 : while (n > 0)
15587 : {
15588 : // Invariants:
15589 : // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
15590 : // pow10 = 10^(n-1) <= p1 < 10^n
15591 : //
15592 : const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
15593 : const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
15594 : //
15595 : // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
15596 : // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
15597 : //
15598 : JSON_ASSERT(d <= 9);
15599 : buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
15600 : //
15601 : // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
15602 : //
15603 : p1 = r;
15604 : n--;
15605 : //
15606 : // M+ = buffer * 10^n + (p1 + p2 * 2^e)
15607 : // pow10 = 10^n
15608 : //
15609 :
15610 : // Now check if enough digits have been generated.
15611 : // Compute
15612 : //
15613 : // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
15614 : //
15615 : // Note:
15616 : // Since rest and delta share the same exponent e, it suffices to
15617 : // compare the significands.
15618 : const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
15619 : if (rest <= delta)
15620 : {
15621 : // V = buffer * 10^n, with M- <= V <= M+.
15622 :
15623 : decimal_exponent += n;
15624 :
15625 : // We may now just stop. But instead look if the buffer could be
15626 : // decremented to bring V closer to w.
15627 : //
15628 : // pow10 = 10^n is now 1 ulp in the decimal representation V.
15629 : // The rounding procedure works with diyfp's with an implicit
15630 : // exponent of e.
15631 : //
15632 : // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
15633 : //
15634 : const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
15635 : grisu2_round(buffer, length, dist, delta, rest, ten_n);
15636 :
15637 : return;
15638 : }
15639 :
15640 : pow10 /= 10;
15641 : //
15642 : // pow10 = 10^(n-1) <= p1 < 10^n
15643 : // Invariants restored.
15644 : }
15645 :
15646 : // 2)
15647 : //
15648 : // The digits of the integral part have been generated:
15649 : //
15650 : // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
15651 : // = buffer + p2 * 2^e
15652 : //
15653 : // Now generate the digits of the fractional part p2 * 2^e.
15654 : //
15655 : // Note:
15656 : // No decimal point is generated: the exponent is adjusted instead.
15657 : //
15658 : // p2 actually represents the fraction
15659 : //
15660 : // p2 * 2^e
15661 : // = p2 / 2^-e
15662 : // = d[-1] / 10^1 + d[-2] / 10^2 + ...
15663 : //
15664 : // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
15665 : //
15666 : // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
15667 : // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
15668 : //
15669 : // using
15670 : //
15671 : // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
15672 : // = ( d) * 2^-e + ( r)
15673 : //
15674 : // or
15675 : // 10^m * p2 * 2^e = d + r * 2^e
15676 : //
15677 : // i.e.
15678 : //
15679 : // M+ = buffer + p2 * 2^e
15680 : // = buffer + 10^-m * (d + r * 2^e)
15681 : // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
15682 : //
15683 : // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
15684 :
15685 : JSON_ASSERT(p2 > delta);
15686 :
15687 : int m = 0;
15688 : for (;;)
15689 : {
15690 : // Invariant:
15691 : // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
15692 : // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
15693 : // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
15694 : // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
15695 : //
15696 : JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
15697 : p2 *= 10;
15698 : const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
15699 : const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
15700 : //
15701 : // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
15702 : // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
15703 : // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
15704 : //
15705 : JSON_ASSERT(d <= 9);
15706 : buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
15707 : //
15708 : // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
15709 : //
15710 : p2 = r;
15711 : m++;
15712 : //
15713 : // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
15714 : // Invariant restored.
15715 :
15716 : // Check if enough digits have been generated.
15717 : //
15718 : // 10^-m * p2 * 2^e <= delta * 2^e
15719 : // p2 * 2^e <= 10^m * delta * 2^e
15720 : // p2 <= 10^m * delta
15721 : delta *= 10;
15722 : dist *= 10;
15723 : if (p2 <= delta)
15724 : {
15725 : break;
15726 : }
15727 : }
15728 :
15729 : // V = buffer * 10^-m, with M- <= V <= M+.
15730 :
15731 : decimal_exponent -= m;
15732 :
15733 : // 1 ulp in the decimal representation is now 10^-m.
15734 : // Since delta and dist are now scaled by 10^m, we need to do the
15735 : // same with ulp in order to keep the units in sync.
15736 : //
15737 : // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
15738 : //
15739 : const std::uint64_t ten_m = one.f;
15740 : grisu2_round(buffer, length, dist, delta, p2, ten_m);
15741 :
15742 : // By construction this algorithm generates the shortest possible decimal
15743 : // number (Loitsch, Theorem 6.2) which rounds back to w.
15744 : // For an input number of precision p, at least
15745 : //
15746 : // N = 1 + ceil(p * log_10(2))
15747 : //
15748 : // decimal digits are sufficient to identify all binary floating-point
15749 : // numbers (Matula, "In-and-Out conversions").
15750 : // This implies that the algorithm does not produce more than N decimal
15751 : // digits.
15752 : //
15753 : // N = 17 for p = 53 (IEEE double precision)
15754 : // N = 9 for p = 24 (IEEE single precision)
15755 : }
15756 :
15757 : /*!
15758 : v = buf * 10^decimal_exponent
15759 : len is the length of the buffer (number of decimal digits)
15760 : The buffer must be large enough, i.e. >= max_digits10.
15761 : */
15762 : JSON_HEDLEY_NON_NULL(1)
15763 : inline void grisu2(char* buf, int& len, int& decimal_exponent,
15764 : diyfp m_minus, diyfp v, diyfp m_plus)
15765 : {
15766 : JSON_ASSERT(m_plus.e == m_minus.e);
15767 : JSON_ASSERT(m_plus.e == v.e);
15768 :
15769 : // --------(-----------------------+-----------------------)-------- (A)
15770 : // m- v m+
15771 : //
15772 : // --------------------(-----------+-----------------------)-------- (B)
15773 : // m- v m+
15774 : //
15775 : // First scale v (and m- and m+) such that the exponent is in the range
15776 : // [alpha, gamma].
15777 :
15778 : const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
15779 :
15780 : const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
15781 :
15782 : // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
15783 : const diyfp w = diyfp::mul(v, c_minus_k);
15784 : const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
15785 : const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
15786 :
15787 : // ----(---+---)---------------(---+---)---------------(---+---)----
15788 : // w- w w+
15789 : // = c*m- = c*v = c*m+
15790 : //
15791 : // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
15792 : // w+ are now off by a small amount.
15793 : // In fact:
15794 : //
15795 : // w - v * 10^k < 1 ulp
15796 : //
15797 : // To account for this inaccuracy, add resp. subtract 1 ulp.
15798 : //
15799 : // --------+---[---------------(---+---)---------------]---+--------
15800 : // w- M- w M+ w+
15801 : //
15802 : // Now any number in [M-, M+] (bounds included) will round to w when input,
15803 : // regardless of how the input rounding algorithm breaks ties.
15804 : //
15805 : // And digit_gen generates the shortest possible such number in [M-, M+].
15806 : // Note that this does not mean that Grisu2 always generates the shortest
15807 : // possible number in the interval (m-, m+).
15808 : const diyfp M_minus(w_minus.f + 1, w_minus.e);
15809 : const diyfp M_plus (w_plus.f - 1, w_plus.e );
15810 :
15811 : decimal_exponent = -cached.k; // = -(-k) = k
15812 :
15813 : grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
15814 : }
15815 :
15816 : /*!
15817 : v = buf * 10^decimal_exponent
15818 : len is the length of the buffer (number of decimal digits)
15819 : The buffer must be large enough, i.e. >= max_digits10.
15820 : */
15821 : template<typename FloatType>
15822 : JSON_HEDLEY_NON_NULL(1)
15823 : void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
15824 : {
15825 : static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
15826 : "internal error: not enough precision");
15827 :
15828 : JSON_ASSERT(std::isfinite(value));
15829 : JSON_ASSERT(value > 0);
15830 :
15831 : // If the neighbors (and boundaries) of 'value' are always computed for double-precision
15832 : // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
15833 : // decimal representations are not exactly "short".
15834 : //
15835 : // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
15836 : // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
15837 : // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
15838 : // does.
15839 : // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
15840 : // representation using the corresponding std::from_chars function recovers value exactly". That
15841 : // indicates that single precision floating-point numbers should be recovered using
15842 : // 'std::strtof'.
15843 : //
15844 : // NB: If the neighbors are computed for single-precision numbers, there is a single float
15845 : // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
15846 : // value is off by 1 ulp.
15847 : #if 0
15848 : const boundaries w = compute_boundaries(static_cast<double>(value));
15849 : #else
15850 : const boundaries w = compute_boundaries(value);
15851 : #endif
15852 :
15853 : grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
15854 : }
15855 :
15856 : /*!
15857 : @brief appends a decimal representation of e to buf
15858 : @return a pointer to the element following the exponent.
15859 : @pre -1000 < e < 1000
15860 : */
15861 : JSON_HEDLEY_NON_NULL(1)
15862 : JSON_HEDLEY_RETURNS_NON_NULL
15863 : inline char* append_exponent(char* buf, int e)
15864 : {
15865 : JSON_ASSERT(e > -1000);
15866 : JSON_ASSERT(e < 1000);
15867 :
15868 : if (e < 0)
15869 : {
15870 : e = -e;
15871 : *buf++ = '-';
15872 : }
15873 : else
15874 : {
15875 : *buf++ = '+';
15876 : }
15877 :
15878 : auto k = static_cast<std::uint32_t>(e);
15879 : if (k < 10)
15880 : {
15881 : // Always print at least two digits in the exponent.
15882 : // This is for compatibility with printf("%g").
15883 : *buf++ = '0';
15884 : *buf++ = static_cast<char>('0' + k);
15885 : }
15886 : else if (k < 100)
15887 : {
15888 : *buf++ = static_cast<char>('0' + k / 10);
15889 : k %= 10;
15890 : *buf++ = static_cast<char>('0' + k);
15891 : }
15892 : else
15893 : {
15894 : *buf++ = static_cast<char>('0' + k / 100);
15895 : k %= 100;
15896 : *buf++ = static_cast<char>('0' + k / 10);
15897 : k %= 10;
15898 : *buf++ = static_cast<char>('0' + k);
15899 : }
15900 :
15901 : return buf;
15902 : }
15903 :
15904 : /*!
15905 : @brief prettify v = buf * 10^decimal_exponent
15906 :
15907 : If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
15908 : notation. Otherwise it will be printed in exponential notation.
15909 :
15910 : @pre min_exp < 0
15911 : @pre max_exp > 0
15912 : */
15913 : JSON_HEDLEY_NON_NULL(1)
15914 : JSON_HEDLEY_RETURNS_NON_NULL
15915 : inline char* format_buffer(char* buf, int len, int decimal_exponent,
15916 : int min_exp, int max_exp)
15917 : {
15918 : JSON_ASSERT(min_exp < 0);
15919 : JSON_ASSERT(max_exp > 0);
15920 :
15921 : const int k = len;
15922 : const int n = len + decimal_exponent;
15923 :
15924 : // v = buf * 10^(n-k)
15925 : // k is the length of the buffer (number of decimal digits)
15926 : // n is the position of the decimal point relative to the start of the buffer.
15927 :
15928 : if (k <= n && n <= max_exp)
15929 : {
15930 : // digits[000]
15931 : // len <= max_exp + 2
15932 :
15933 : std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
15934 : // Make it look like a floating-point number (#362, #378)
15935 : buf[n + 0] = '.';
15936 : buf[n + 1] = '0';
15937 : return buf + (static_cast<size_t>(n) + 2);
15938 : }
15939 :
15940 : if (0 < n && n <= max_exp)
15941 : {
15942 : // dig.its
15943 : // len <= max_digits10 + 1
15944 :
15945 : JSON_ASSERT(k > n);
15946 :
15947 : std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
15948 : buf[n] = '.';
15949 : return buf + (static_cast<size_t>(k) + 1U);
15950 : }
15951 :
15952 : if (min_exp < n && n <= 0)
15953 : {
15954 : // 0.[000]digits
15955 : // len <= 2 + (-min_exp - 1) + max_digits10
15956 :
15957 : std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
15958 : buf[0] = '0';
15959 : buf[1] = '.';
15960 : std::memset(buf + 2, '0', static_cast<size_t>(-n));
15961 : return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
15962 : }
15963 :
15964 : if (k == 1)
15965 : {
15966 : // dE+123
15967 : // len <= 1 + 5
15968 :
15969 : buf += 1;
15970 : }
15971 : else
15972 : {
15973 : // d.igitsE+123
15974 : // len <= max_digits10 + 1 + 5
15975 :
15976 : std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
15977 : buf[1] = '.';
15978 : buf += 1 + static_cast<size_t>(k);
15979 : }
15980 :
15981 : *buf++ = 'e';
15982 : return append_exponent(buf, n - 1);
15983 : }
15984 :
15985 : } // namespace dtoa_impl
15986 :
15987 : /*!
15988 : @brief generates a decimal representation of the floating-point number value in [first, last).
15989 :
15990 : The format of the resulting decimal representation is similar to printf's %g
15991 : format. Returns an iterator pointing past-the-end of the decimal representation.
15992 :
15993 : @note The input number must be finite, i.e. NaN's and Inf's are not supported.
15994 : @note The buffer must be large enough.
15995 : @note The result is NOT null-terminated.
15996 : */
15997 : template<typename FloatType>
15998 : JSON_HEDLEY_NON_NULL(1, 2)
15999 : JSON_HEDLEY_RETURNS_NON_NULL
16000 : char* to_chars(char* first, const char* last, FloatType value)
16001 : {
16002 : static_cast<void>(last); // maybe unused - fix warning
16003 : JSON_ASSERT(std::isfinite(value));
16004 :
16005 : // Use signbit(value) instead of (value < 0) since signbit works for -0.
16006 : if (std::signbit(value))
16007 : {
16008 : value = -value;
16009 : *first++ = '-';
16010 : }
16011 :
16012 : #ifdef __GNUC__
16013 : #pragma GCC diagnostic push
16014 : #pragma GCC diagnostic ignored "-Wfloat-equal"
16015 : #endif
16016 : if (value == 0) // +-0
16017 : {
16018 : *first++ = '0';
16019 : // Make it look like a floating-point number (#362, #378)
16020 : *first++ = '.';
16021 : *first++ = '0';
16022 : return first;
16023 : }
16024 : #ifdef __GNUC__
16025 : #pragma GCC diagnostic pop
16026 : #endif
16027 :
16028 : JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
16029 :
16030 : // Compute v = buffer * 10^decimal_exponent.
16031 : // The decimal digits are stored in the buffer, which needs to be interpreted
16032 : // as an unsigned decimal integer.
16033 : // len is the length of the buffer, i.e. the number of decimal digits.
16034 : int len = 0;
16035 : int decimal_exponent = 0;
16036 : dtoa_impl::grisu2(first, len, decimal_exponent, value);
16037 :
16038 : JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
16039 :
16040 : // Format the buffer like printf("%.*g", prec, value)
16041 : constexpr int kMinExp = -4;
16042 : // Use digits10 here to increase compatibility with version 2.
16043 : constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
16044 :
16045 : JSON_ASSERT(last - first >= kMaxExp + 2);
16046 : JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
16047 : JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
16048 :
16049 : return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
16050 : }
16051 :
16052 : } // namespace detail
16053 : } // namespace nlohmann
16054 :
16055 : // #include <nlohmann/detail/exceptions.hpp>
16056 :
16057 : // #include <nlohmann/detail/macro_scope.hpp>
16058 :
16059 : // #include <nlohmann/detail/meta/cpp_future.hpp>
16060 :
16061 : // #include <nlohmann/detail/output/binary_writer.hpp>
16062 :
16063 : // #include <nlohmann/detail/output/output_adapters.hpp>
16064 :
16065 : // #include <nlohmann/detail/value_t.hpp>
16066 :
16067 :
16068 : namespace nlohmann
16069 : {
16070 : namespace detail
16071 : {
16072 : ///////////////////
16073 : // serialization //
16074 : ///////////////////
16075 :
16076 : /// how to treat decoding errors
16077 : enum class error_handler_t
16078 : {
16079 : strict, ///< throw a type_error exception in case of invalid UTF-8
16080 : replace, ///< replace invalid UTF-8 sequences with U+FFFD
16081 : ignore ///< ignore invalid UTF-8 sequences
16082 : };
16083 :
16084 : template<typename BasicJsonType>
16085 : class serializer
16086 : {
16087 : using string_t = typename BasicJsonType::string_t;
16088 : using number_float_t = typename BasicJsonType::number_float_t;
16089 : using number_integer_t = typename BasicJsonType::number_integer_t;
16090 : using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
16091 : using binary_char_t = typename BasicJsonType::binary_t::value_type;
16092 : static constexpr std::uint8_t UTF8_ACCEPT = 0;
16093 : static constexpr std::uint8_t UTF8_REJECT = 1;
16094 :
16095 : public:
16096 : /*!
16097 : @param[in] s output stream to serialize to
16098 : @param[in] ichar indentation character to use
16099 : @param[in] error_handler_ how to react on decoding errors
16100 : */
16101 : serializer(output_adapter_t<char> s, const char ichar,
16102 : error_handler_t error_handler_ = error_handler_t::strict)
16103 : : o(std::move(s))
16104 : , loc(std::localeconv())
16105 : , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
16106 : , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
16107 : , indent_char(ichar)
16108 : , indent_string(512, indent_char)
16109 : , error_handler(error_handler_)
16110 : {}
16111 :
16112 : // delete because of pointer members
16113 : serializer(const serializer&) = delete;
16114 : serializer& operator=(const serializer&) = delete;
16115 : serializer(serializer&&) = delete;
16116 : serializer& operator=(serializer&&) = delete;
16117 : ~serializer() = default;
16118 :
16119 : /*!
16120 : @brief internal implementation of the serialization function
16121 :
16122 : This function is called by the public member function dump and organizes
16123 : the serialization internally. The indentation level is propagated as
16124 : additional parameter. In case of arrays and objects, the function is
16125 : called recursively.
16126 :
16127 : - strings and object keys are escaped using `escape_string()`
16128 : - integer numbers are converted implicitly via `operator<<`
16129 : - floating-point numbers are converted to a string using `"%g"` format
16130 : - binary values are serialized as objects containing the subtype and the
16131 : byte array
16132 :
16133 : @param[in] val value to serialize
16134 : @param[in] pretty_print whether the output shall be pretty-printed
16135 : @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
16136 : in the output are escaped with `\uXXXX` sequences, and the result consists
16137 : of ASCII characters only.
16138 : @param[in] indent_step the indent level
16139 : @param[in] current_indent the current indent level (only used internally)
16140 : */
16141 : void dump(const BasicJsonType& val,
16142 : const bool pretty_print,
16143 : const bool ensure_ascii,
16144 : const unsigned int indent_step,
16145 : const unsigned int current_indent = 0)
16146 : {
16147 : switch (val.m_type)
16148 : {
16149 : case value_t::object:
16150 : {
16151 : if (val.m_value.object->empty())
16152 : {
16153 : o->write_characters("{}", 2);
16154 : return;
16155 : }
16156 :
16157 : if (pretty_print)
16158 : {
16159 : o->write_characters("{\n", 2);
16160 :
16161 : // variable to hold indentation for recursive calls
16162 : const auto new_indent = current_indent + indent_step;
16163 : if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
16164 : {
16165 : indent_string.resize(indent_string.size() * 2, ' ');
16166 : }
16167 :
16168 : // first n-1 elements
16169 : auto i = val.m_value.object->cbegin();
16170 : for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
16171 : {
16172 : o->write_characters(indent_string.c_str(), new_indent);
16173 : o->write_character('\"');
16174 : dump_escaped(i->first, ensure_ascii);
16175 : o->write_characters("\": ", 3);
16176 : dump(i->second, true, ensure_ascii, indent_step, new_indent);
16177 : o->write_characters(",\n", 2);
16178 : }
16179 :
16180 : // last element
16181 : JSON_ASSERT(i != val.m_value.object->cend());
16182 : JSON_ASSERT(std::next(i) == val.m_value.object->cend());
16183 : o->write_characters(indent_string.c_str(), new_indent);
16184 : o->write_character('\"');
16185 : dump_escaped(i->first, ensure_ascii);
16186 : o->write_characters("\": ", 3);
16187 : dump(i->second, true, ensure_ascii, indent_step, new_indent);
16188 :
16189 : o->write_character('\n');
16190 : o->write_characters(indent_string.c_str(), current_indent);
16191 : o->write_character('}');
16192 : }
16193 : else
16194 : {
16195 : o->write_character('{');
16196 :
16197 : // first n-1 elements
16198 : auto i = val.m_value.object->cbegin();
16199 : for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
16200 : {
16201 : o->write_character('\"');
16202 : dump_escaped(i->first, ensure_ascii);
16203 : o->write_characters("\":", 2);
16204 : dump(i->second, false, ensure_ascii, indent_step, current_indent);
16205 : o->write_character(',');
16206 : }
16207 :
16208 : // last element
16209 : JSON_ASSERT(i != val.m_value.object->cend());
16210 : JSON_ASSERT(std::next(i) == val.m_value.object->cend());
16211 : o->write_character('\"');
16212 : dump_escaped(i->first, ensure_ascii);
16213 : o->write_characters("\":", 2);
16214 : dump(i->second, false, ensure_ascii, indent_step, current_indent);
16215 :
16216 : o->write_character('}');
16217 : }
16218 :
16219 : return;
16220 : }
16221 :
16222 : case value_t::array:
16223 : {
16224 : if (val.m_value.array->empty())
16225 : {
16226 : o->write_characters("[]", 2);
16227 : return;
16228 : }
16229 :
16230 : if (pretty_print)
16231 : {
16232 : o->write_characters("[\n", 2);
16233 :
16234 : // variable to hold indentation for recursive calls
16235 : const auto new_indent = current_indent + indent_step;
16236 : if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
16237 : {
16238 : indent_string.resize(indent_string.size() * 2, ' ');
16239 : }
16240 :
16241 : // first n-1 elements
16242 : for (auto i = val.m_value.array->cbegin();
16243 : i != val.m_value.array->cend() - 1; ++i)
16244 : {
16245 : o->write_characters(indent_string.c_str(), new_indent);
16246 : dump(*i, true, ensure_ascii, indent_step, new_indent);
16247 : o->write_characters(",\n", 2);
16248 : }
16249 :
16250 : // last element
16251 : JSON_ASSERT(!val.m_value.array->empty());
16252 : o->write_characters(indent_string.c_str(), new_indent);
16253 : dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
16254 :
16255 : o->write_character('\n');
16256 : o->write_characters(indent_string.c_str(), current_indent);
16257 : o->write_character(']');
16258 : }
16259 : else
16260 : {
16261 : o->write_character('[');
16262 :
16263 : // first n-1 elements
16264 : for (auto i = val.m_value.array->cbegin();
16265 : i != val.m_value.array->cend() - 1; ++i)
16266 : {
16267 : dump(*i, false, ensure_ascii, indent_step, current_indent);
16268 : o->write_character(',');
16269 : }
16270 :
16271 : // last element
16272 : JSON_ASSERT(!val.m_value.array->empty());
16273 : dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
16274 :
16275 : o->write_character(']');
16276 : }
16277 :
16278 : return;
16279 : }
16280 :
16281 : case value_t::string:
16282 : {
16283 : o->write_character('\"');
16284 : dump_escaped(*val.m_value.string, ensure_ascii);
16285 : o->write_character('\"');
16286 : return;
16287 : }
16288 :
16289 : case value_t::binary:
16290 : {
16291 : if (pretty_print)
16292 : {
16293 : o->write_characters("{\n", 2);
16294 :
16295 : // variable to hold indentation for recursive calls
16296 : const auto new_indent = current_indent + indent_step;
16297 : if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
16298 : {
16299 : indent_string.resize(indent_string.size() * 2, ' ');
16300 : }
16301 :
16302 : o->write_characters(indent_string.c_str(), new_indent);
16303 :
16304 : o->write_characters("\"bytes\": [", 10);
16305 :
16306 : if (!val.m_value.binary->empty())
16307 : {
16308 : for (auto i = val.m_value.binary->cbegin();
16309 : i != val.m_value.binary->cend() - 1; ++i)
16310 : {
16311 : dump_integer(*i);
16312 : o->write_characters(", ", 2);
16313 : }
16314 : dump_integer(val.m_value.binary->back());
16315 : }
16316 :
16317 : o->write_characters("],\n", 3);
16318 : o->write_characters(indent_string.c_str(), new_indent);
16319 :
16320 : o->write_characters("\"subtype\": ", 11);
16321 : if (val.m_value.binary->has_subtype())
16322 : {
16323 : dump_integer(val.m_value.binary->subtype());
16324 : }
16325 : else
16326 : {
16327 : o->write_characters("null", 4);
16328 : }
16329 : o->write_character('\n');
16330 : o->write_characters(indent_string.c_str(), current_indent);
16331 : o->write_character('}');
16332 : }
16333 : else
16334 : {
16335 : o->write_characters("{\"bytes\":[", 10);
16336 :
16337 : if (!val.m_value.binary->empty())
16338 : {
16339 : for (auto i = val.m_value.binary->cbegin();
16340 : i != val.m_value.binary->cend() - 1; ++i)
16341 : {
16342 : dump_integer(*i);
16343 : o->write_character(',');
16344 : }
16345 : dump_integer(val.m_value.binary->back());
16346 : }
16347 :
16348 : o->write_characters("],\"subtype\":", 12);
16349 : if (val.m_value.binary->has_subtype())
16350 : {
16351 : dump_integer(val.m_value.binary->subtype());
16352 : o->write_character('}');
16353 : }
16354 : else
16355 : {
16356 : o->write_characters("null}", 5);
16357 : }
16358 : }
16359 : return;
16360 : }
16361 :
16362 : case value_t::boolean:
16363 : {
16364 : if (val.m_value.boolean)
16365 : {
16366 : o->write_characters("true", 4);
16367 : }
16368 : else
16369 : {
16370 : o->write_characters("false", 5);
16371 : }
16372 : return;
16373 : }
16374 :
16375 : case value_t::number_integer:
16376 : {
16377 : dump_integer(val.m_value.number_integer);
16378 : return;
16379 : }
16380 :
16381 : case value_t::number_unsigned:
16382 : {
16383 : dump_integer(val.m_value.number_unsigned);
16384 : return;
16385 : }
16386 :
16387 : case value_t::number_float:
16388 : {
16389 : dump_float(val.m_value.number_float);
16390 : return;
16391 : }
16392 :
16393 : case value_t::discarded:
16394 : {
16395 : o->write_characters("<discarded>", 11);
16396 : return;
16397 : }
16398 :
16399 : case value_t::null:
16400 : {
16401 : o->write_characters("null", 4);
16402 : return;
16403 : }
16404 :
16405 : default: // LCOV_EXCL_LINE
16406 : JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16407 : }
16408 : }
16409 :
16410 : JSON_PRIVATE_UNLESS_TESTED:
16411 : /*!
16412 : @brief dump escaped string
16413 :
16414 : Escape a string by replacing certain special characters by a sequence of an
16415 : escape character (backslash) and another character and other control
16416 : characters by a sequence of "\u" followed by a four-digit hex
16417 : representation. The escaped string is written to output stream @a o.
16418 :
16419 : @param[in] s the string to escape
16420 : @param[in] ensure_ascii whether to escape non-ASCII characters with
16421 : \uXXXX sequences
16422 :
16423 : @complexity Linear in the length of string @a s.
16424 : */
16425 : void dump_escaped(const string_t& s, const bool ensure_ascii)
16426 : {
16427 : std::uint32_t codepoint{};
16428 : std::uint8_t state = UTF8_ACCEPT;
16429 : std::size_t bytes = 0; // number of bytes written to string_buffer
16430 :
16431 : // number of bytes written at the point of the last valid byte
16432 : std::size_t bytes_after_last_accept = 0;
16433 : std::size_t undumped_chars = 0;
16434 :
16435 : for (std::size_t i = 0; i < s.size(); ++i)
16436 : {
16437 : const auto byte = static_cast<std::uint8_t>(s[i]);
16438 :
16439 : switch (decode(state, codepoint, byte))
16440 : {
16441 : case UTF8_ACCEPT: // decode found a new code point
16442 : {
16443 : switch (codepoint)
16444 : {
16445 : case 0x08: // backspace
16446 : {
16447 : string_buffer[bytes++] = '\\';
16448 : string_buffer[bytes++] = 'b';
16449 : break;
16450 : }
16451 :
16452 : case 0x09: // horizontal tab
16453 : {
16454 : string_buffer[bytes++] = '\\';
16455 : string_buffer[bytes++] = 't';
16456 : break;
16457 : }
16458 :
16459 : case 0x0A: // newline
16460 : {
16461 : string_buffer[bytes++] = '\\';
16462 : string_buffer[bytes++] = 'n';
16463 : break;
16464 : }
16465 :
16466 : case 0x0C: // formfeed
16467 : {
16468 : string_buffer[bytes++] = '\\';
16469 : string_buffer[bytes++] = 'f';
16470 : break;
16471 : }
16472 :
16473 : case 0x0D: // carriage return
16474 : {
16475 : string_buffer[bytes++] = '\\';
16476 : string_buffer[bytes++] = 'r';
16477 : break;
16478 : }
16479 :
16480 : case 0x22: // quotation mark
16481 : {
16482 : string_buffer[bytes++] = '\\';
16483 : string_buffer[bytes++] = '\"';
16484 : break;
16485 : }
16486 :
16487 : case 0x5C: // reverse solidus
16488 : {
16489 : string_buffer[bytes++] = '\\';
16490 : string_buffer[bytes++] = '\\';
16491 : break;
16492 : }
16493 :
16494 : default:
16495 : {
16496 : // escape control characters (0x00..0x1F) or, if
16497 : // ensure_ascii parameter is used, non-ASCII characters
16498 : if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
16499 : {
16500 : if (codepoint <= 0xFFFF)
16501 : {
16502 : // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
16503 : static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
16504 : static_cast<std::uint16_t>(codepoint)));
16505 : bytes += 6;
16506 : }
16507 : else
16508 : {
16509 : // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
16510 : static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
16511 : static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
16512 : static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
16513 : bytes += 12;
16514 : }
16515 : }
16516 : else
16517 : {
16518 : // copy byte to buffer (all previous bytes
16519 : // been copied have in default case above)
16520 : string_buffer[bytes++] = s[i];
16521 : }
16522 : break;
16523 : }
16524 : }
16525 :
16526 : // write buffer and reset index; there must be 13 bytes
16527 : // left, as this is the maximal number of bytes to be
16528 : // written ("\uxxxx\uxxxx\0") for one code point
16529 : if (string_buffer.size() - bytes < 13)
16530 : {
16531 : o->write_characters(string_buffer.data(), bytes);
16532 : bytes = 0;
16533 : }
16534 :
16535 : // remember the byte position of this accept
16536 : bytes_after_last_accept = bytes;
16537 : undumped_chars = 0;
16538 : break;
16539 : }
16540 :
16541 : case UTF8_REJECT: // decode found invalid UTF-8 byte
16542 : {
16543 : switch (error_handler)
16544 : {
16545 : case error_handler_t::strict:
16546 : {
16547 : std::stringstream ss;
16548 : ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (byte | 0);
16549 : JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + ss.str(), BasicJsonType()));
16550 : }
16551 :
16552 : case error_handler_t::ignore:
16553 : case error_handler_t::replace:
16554 : {
16555 : // in case we saw this character the first time, we
16556 : // would like to read it again, because the byte
16557 : // may be OK for itself, but just not OK for the
16558 : // previous sequence
16559 : if (undumped_chars > 0)
16560 : {
16561 : --i;
16562 : }
16563 :
16564 : // reset length buffer to the last accepted index;
16565 : // thus removing/ignoring the invalid characters
16566 : bytes = bytes_after_last_accept;
16567 :
16568 : if (error_handler == error_handler_t::replace)
16569 : {
16570 : // add a replacement character
16571 : if (ensure_ascii)
16572 : {
16573 : string_buffer[bytes++] = '\\';
16574 : string_buffer[bytes++] = 'u';
16575 : string_buffer[bytes++] = 'f';
16576 : string_buffer[bytes++] = 'f';
16577 : string_buffer[bytes++] = 'f';
16578 : string_buffer[bytes++] = 'd';
16579 : }
16580 : else
16581 : {
16582 : string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
16583 : string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
16584 : string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
16585 : }
16586 :
16587 : // write buffer and reset index; there must be 13 bytes
16588 : // left, as this is the maximal number of bytes to be
16589 : // written ("\uxxxx\uxxxx\0") for one code point
16590 : if (string_buffer.size() - bytes < 13)
16591 : {
16592 : o->write_characters(string_buffer.data(), bytes);
16593 : bytes = 0;
16594 : }
16595 :
16596 : bytes_after_last_accept = bytes;
16597 : }
16598 :
16599 : undumped_chars = 0;
16600 :
16601 : // continue processing the string
16602 : state = UTF8_ACCEPT;
16603 : break;
16604 : }
16605 :
16606 : default: // LCOV_EXCL_LINE
16607 : JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16608 : }
16609 : break;
16610 : }
16611 :
16612 : default: // decode found yet incomplete multi-byte code point
16613 : {
16614 : if (!ensure_ascii)
16615 : {
16616 : // code point will not be escaped - copy byte to buffer
16617 : string_buffer[bytes++] = s[i];
16618 : }
16619 : ++undumped_chars;
16620 : break;
16621 : }
16622 : }
16623 : }
16624 :
16625 : // we finished processing the string
16626 : if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
16627 : {
16628 : // write buffer
16629 : if (bytes > 0)
16630 : {
16631 : o->write_characters(string_buffer.data(), bytes);
16632 : }
16633 : }
16634 : else
16635 : {
16636 : // we finish reading, but do not accept: string was incomplete
16637 : switch (error_handler)
16638 : {
16639 : case error_handler_t::strict:
16640 : {
16641 : std::stringstream ss;
16642 : ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (static_cast<std::uint8_t>(s.back()) | 0);
16643 : JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + ss.str(), BasicJsonType()));
16644 : }
16645 :
16646 : case error_handler_t::ignore:
16647 : {
16648 : // write all accepted bytes
16649 : o->write_characters(string_buffer.data(), bytes_after_last_accept);
16650 : break;
16651 : }
16652 :
16653 : case error_handler_t::replace:
16654 : {
16655 : // write all accepted bytes
16656 : o->write_characters(string_buffer.data(), bytes_after_last_accept);
16657 : // add a replacement character
16658 : if (ensure_ascii)
16659 : {
16660 : o->write_characters("\\ufffd", 6);
16661 : }
16662 : else
16663 : {
16664 : o->write_characters("\xEF\xBF\xBD", 3);
16665 : }
16666 : break;
16667 : }
16668 :
16669 : default: // LCOV_EXCL_LINE
16670 : JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16671 : }
16672 : }
16673 : }
16674 :
16675 : private:
16676 : /*!
16677 : @brief count digits
16678 :
16679 : Count the number of decimal (base 10) digits for an input unsigned integer.
16680 :
16681 : @param[in] x unsigned integer number to count its digits
16682 : @return number of decimal digits
16683 : */
16684 : inline unsigned int count_digits(number_unsigned_t x) noexcept
16685 : {
16686 : unsigned int n_digits = 1;
16687 : for (;;)
16688 : {
16689 : if (x < 10)
16690 : {
16691 : return n_digits;
16692 : }
16693 : if (x < 100)
16694 : {
16695 : return n_digits + 1;
16696 : }
16697 : if (x < 1000)
16698 : {
16699 : return n_digits + 2;
16700 : }
16701 : if (x < 10000)
16702 : {
16703 : return n_digits + 3;
16704 : }
16705 : x = x / 10000u;
16706 : n_digits += 4;
16707 : }
16708 : }
16709 :
16710 : // templates to avoid warnings about useless casts
16711 : template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
16712 : bool is_negative_number(NumberType x)
16713 : {
16714 : return x < 0;
16715 : }
16716 :
16717 : template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
16718 : bool is_negative_number(NumberType /*unused*/)
16719 : {
16720 : return false;
16721 : }
16722 :
16723 : /*!
16724 : @brief dump an integer
16725 :
16726 : Dump a given integer to output stream @a o. Works internally with
16727 : @a number_buffer.
16728 :
16729 : @param[in] x integer number (signed or unsigned) to dump
16730 : @tparam NumberType either @a number_integer_t or @a number_unsigned_t
16731 : */
16732 : template < typename NumberType, detail::enable_if_t <
16733 : std::is_integral<NumberType>::value ||
16734 : std::is_same<NumberType, number_unsigned_t>::value ||
16735 : std::is_same<NumberType, number_integer_t>::value ||
16736 : std::is_same<NumberType, binary_char_t>::value,
16737 : int > = 0 >
16738 : void dump_integer(NumberType x)
16739 : {
16740 : static constexpr std::array<std::array<char, 2>, 100> digits_to_99
16741 : {
16742 : {
16743 : {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
16744 : {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
16745 : {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
16746 : {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
16747 : {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
16748 : {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
16749 : {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
16750 : {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
16751 : {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
16752 : {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
16753 : }
16754 : };
16755 :
16756 : // special case for "0"
16757 : if (x == 0)
16758 : {
16759 : o->write_character('0');
16760 : return;
16761 : }
16762 :
16763 : // use a pointer to fill the buffer
16764 : auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
16765 :
16766 : number_unsigned_t abs_value;
16767 :
16768 : unsigned int n_chars{};
16769 :
16770 : if (is_negative_number(x))
16771 : {
16772 : *buffer_ptr = '-';
16773 : abs_value = remove_sign(static_cast<number_integer_t>(x));
16774 :
16775 : // account one more byte for the minus sign
16776 : n_chars = 1 + count_digits(abs_value);
16777 : }
16778 : else
16779 : {
16780 : abs_value = static_cast<number_unsigned_t>(x);
16781 : n_chars = count_digits(abs_value);
16782 : }
16783 :
16784 : // spare 1 byte for '\0'
16785 : JSON_ASSERT(n_chars < number_buffer.size() - 1);
16786 :
16787 : // jump to the end to generate the string from backward,
16788 : // so we later avoid reversing the result
16789 : buffer_ptr += n_chars;
16790 :
16791 : // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
16792 : // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
16793 : while (abs_value >= 100)
16794 : {
16795 : const auto digits_index = static_cast<unsigned>((abs_value % 100));
16796 : abs_value /= 100;
16797 : *(--buffer_ptr) = digits_to_99[digits_index][1];
16798 : *(--buffer_ptr) = digits_to_99[digits_index][0];
16799 : }
16800 :
16801 : if (abs_value >= 10)
16802 : {
16803 : const auto digits_index = static_cast<unsigned>(abs_value);
16804 : *(--buffer_ptr) = digits_to_99[digits_index][1];
16805 : *(--buffer_ptr) = digits_to_99[digits_index][0];
16806 : }
16807 : else
16808 : {
16809 : *(--buffer_ptr) = static_cast<char>('0' + abs_value);
16810 : }
16811 :
16812 : o->write_characters(number_buffer.data(), n_chars);
16813 : }
16814 :
16815 : /*!
16816 : @brief dump a floating-point number
16817 :
16818 : Dump a given floating-point number to output stream @a o. Works internally
16819 : with @a number_buffer.
16820 :
16821 : @param[in] x floating-point number to dump
16822 : */
16823 : void dump_float(number_float_t x)
16824 : {
16825 : // NaN / inf
16826 : if (!std::isfinite(x))
16827 : {
16828 : o->write_characters("null", 4);
16829 : return;
16830 : }
16831 :
16832 : // If number_float_t is an IEEE-754 single or double precision number,
16833 : // use the Grisu2 algorithm to produce short numbers which are
16834 : // guaranteed to round-trip, using strtof and strtod, resp.
16835 : //
16836 : // NB: The test below works if <long double> == <double>.
16837 : static constexpr bool is_ieee_single_or_double
16838 : = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
16839 : (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
16840 :
16841 : dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
16842 : }
16843 :
16844 : void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
16845 : {
16846 : auto* begin = number_buffer.data();
16847 : auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
16848 :
16849 : o->write_characters(begin, static_cast<size_t>(end - begin));
16850 : }
16851 :
16852 : void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
16853 : {
16854 : // get number of digits for a float -> text -> float round-trip
16855 : static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
16856 :
16857 : // the actual conversion
16858 : // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
16859 : std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
16860 :
16861 : // negative value indicates an error
16862 : JSON_ASSERT(len > 0);
16863 : // check if buffer was large enough
16864 : JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
16865 :
16866 : // erase thousands separator
16867 : if (thousands_sep != '\0')
16868 : {
16869 : // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
16870 : const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
16871 : std::fill(end, number_buffer.end(), '\0');
16872 : JSON_ASSERT((end - number_buffer.begin()) <= len);
16873 : len = (end - number_buffer.begin());
16874 : }
16875 :
16876 : // convert decimal point to '.'
16877 : if (decimal_point != '\0' && decimal_point != '.')
16878 : {
16879 : // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
16880 : const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
16881 : if (dec_pos != number_buffer.end())
16882 : {
16883 : *dec_pos = '.';
16884 : }
16885 : }
16886 :
16887 : o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
16888 :
16889 : // determine if we need to append ".0"
16890 : const bool value_is_int_like =
16891 : std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
16892 : [](char c)
16893 : {
16894 : return c == '.' || c == 'e';
16895 : });
16896 :
16897 : if (value_is_int_like)
16898 : {
16899 : o->write_characters(".0", 2);
16900 : }
16901 : }
16902 :
16903 : /*!
16904 : @brief check whether a string is UTF-8 encoded
16905 :
16906 : The function checks each byte of a string whether it is UTF-8 encoded. The
16907 : result of the check is stored in the @a state parameter. The function must
16908 : be called initially with state 0 (accept). State 1 means the string must
16909 : be rejected, because the current byte is not allowed. If the string is
16910 : completely processed, but the state is non-zero, the string ended
16911 : prematurely; that is, the last byte indicated more bytes should have
16912 : followed.
16913 :
16914 : @param[in,out] state the state of the decoding
16915 : @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
16916 : @param[in] byte next byte to decode
16917 : @return new state
16918 :
16919 : @note The function has been edited: a std::array is used.
16920 :
16921 : @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
16922 : @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
16923 : */
16924 : static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
16925 : {
16926 : static const std::array<std::uint8_t, 400> utf8d =
16927 : {
16928 : {
16929 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
16930 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
16931 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
16932 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
16933 : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
16934 : 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
16935 : 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
16936 : 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
16937 : 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
16938 : 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
16939 : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
16940 : 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
16941 : 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
16942 : 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
16943 : }
16944 : };
16945 :
16946 : JSON_ASSERT(byte < utf8d.size());
16947 : const std::uint8_t type = utf8d[byte];
16948 :
16949 : codep = (state != UTF8_ACCEPT)
16950 : ? (byte & 0x3fu) | (codep << 6u)
16951 : : (0xFFu >> type) & (byte);
16952 :
16953 : std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
16954 : JSON_ASSERT(index < 400);
16955 : state = utf8d[index];
16956 : return state;
16957 : }
16958 :
16959 : /*
16960 : * Overload to make the compiler happy while it is instantiating
16961 : * dump_integer for number_unsigned_t.
16962 : * Must never be called.
16963 : */
16964 : number_unsigned_t remove_sign(number_unsigned_t x)
16965 : {
16966 : JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16967 : return x; // LCOV_EXCL_LINE
16968 : }
16969 :
16970 : /*
16971 : * Helper function for dump_integer
16972 : *
16973 : * This function takes a negative signed integer and returns its absolute
16974 : * value as unsigned integer. The plus/minus shuffling is necessary as we can
16975 : * not directly remove the sign of an arbitrary signed integer as the
16976 : * absolute values of INT_MIN and INT_MAX are usually not the same. See
16977 : * #1708 for details.
16978 : */
16979 : inline number_unsigned_t remove_sign(number_integer_t x) noexcept
16980 : {
16981 : JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
16982 : return static_cast<number_unsigned_t>(-(x + 1)) + 1;
16983 : }
16984 :
16985 : private:
16986 : /// the output of the serializer
16987 : output_adapter_t<char> o = nullptr;
16988 :
16989 : /// a (hopefully) large enough character buffer
16990 : std::array<char, 64> number_buffer{{}};
16991 :
16992 : /// the locale
16993 : const std::lconv* loc = nullptr;
16994 : /// the locale's thousand separator character
16995 : const char thousands_sep = '\0';
16996 : /// the locale's decimal point character
16997 : const char decimal_point = '\0';
16998 :
16999 : /// string buffer
17000 : std::array<char, 512> string_buffer{{}};
17001 :
17002 : /// the indentation character
17003 : const char indent_char;
17004 : /// the indentation string
17005 : string_t indent_string;
17006 :
17007 : /// error_handler how to react on decoding errors
17008 : const error_handler_t error_handler;
17009 : };
17010 : } // namespace detail
17011 : } // namespace nlohmann
17012 :
17013 : // #include <nlohmann/detail/value_t.hpp>
17014 :
17015 : // #include <nlohmann/json_fwd.hpp>
17016 :
17017 : // #include <nlohmann/ordered_map.hpp>
17018 :
17019 :
17020 : #include <functional> // less
17021 : #include <initializer_list> // initializer_list
17022 : #include <iterator> // input_iterator_tag, iterator_traits
17023 : #include <memory> // allocator
17024 : #include <stdexcept> // for out_of_range
17025 : #include <type_traits> // enable_if, is_convertible
17026 : #include <utility> // pair
17027 : #include <vector> // vector
17028 :
17029 : // #include <nlohmann/detail/macro_scope.hpp>
17030 :
17031 :
17032 : namespace nlohmann
17033 : {
17034 :
17035 : /// ordered_map: a minimal map-like container that preserves insertion order
17036 : /// for use within nlohmann::basic_json<ordered_map>
17037 : template <class Key, class T, class IgnoredLess = std::less<Key>,
17038 : class Allocator = std::allocator<std::pair<const Key, T>>>
17039 : struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
17040 : {
17041 : using key_type = Key;
17042 : using mapped_type = T;
17043 : using Container = std::vector<std::pair<const Key, T>, Allocator>;
17044 : using iterator = typename Container::iterator;
17045 : using const_iterator = typename Container::const_iterator;
17046 : using size_type = typename Container::size_type;
17047 : using value_type = typename Container::value_type;
17048 :
17049 : // Explicit constructors instead of `using Container::Container`
17050 : // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
17051 : ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {}
17052 : template <class It>
17053 : ordered_map(It first, It last, const Allocator& alloc = Allocator())
17054 : : Container{first, last, alloc} {}
17055 : ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator() )
17056 : : Container{init, alloc} {}
17057 :
17058 : std::pair<iterator, bool> emplace(const key_type& key, T&& t)
17059 : {
17060 : for (auto it = this->begin(); it != this->end(); ++it)
17061 : {
17062 : if (it->first == key)
17063 : {
17064 : return {it, false};
17065 : }
17066 : }
17067 : Container::emplace_back(key, t);
17068 : return {--this->end(), true};
17069 : }
17070 :
17071 : T& operator[](const Key& key)
17072 : {
17073 : return emplace(key, T{}).first->second;
17074 : }
17075 :
17076 : const T& operator[](const Key& key) const
17077 : {
17078 : return at(key);
17079 : }
17080 :
17081 : T& at(const Key& key)
17082 : {
17083 : for (auto it = this->begin(); it != this->end(); ++it)
17084 : {
17085 : if (it->first == key)
17086 : {
17087 : return it->second;
17088 : }
17089 : }
17090 :
17091 : JSON_THROW(std::out_of_range("key not found"));
17092 : }
17093 :
17094 : const T& at(const Key& key) const
17095 : {
17096 : for (auto it = this->begin(); it != this->end(); ++it)
17097 : {
17098 : if (it->first == key)
17099 : {
17100 : return it->second;
17101 : }
17102 : }
17103 :
17104 : JSON_THROW(std::out_of_range("key not found"));
17105 : }
17106 :
17107 : size_type erase(const Key& key)
17108 : {
17109 : for (auto it = this->begin(); it != this->end(); ++it)
17110 : {
17111 : if (it->first == key)
17112 : {
17113 : // Since we cannot move const Keys, re-construct them in place
17114 : for (auto next = it; ++next != this->end(); ++it)
17115 : {
17116 : it->~value_type(); // Destroy but keep allocation
17117 : new (&*it) value_type{std::move(*next)};
17118 : }
17119 : Container::pop_back();
17120 : return 1;
17121 : }
17122 : }
17123 : return 0;
17124 : }
17125 :
17126 : iterator erase(iterator pos)
17127 : {
17128 : return erase(pos, std::next(pos));
17129 : }
17130 :
17131 : iterator erase(iterator first, iterator last)
17132 : {
17133 : const auto elements_affected = std::distance(first, last);
17134 : const auto offset = std::distance(Container::begin(), first);
17135 :
17136 : // This is the start situation. We need to delete elements_affected
17137 : // elements (3 in this example: e, f, g), and need to return an
17138 : // iterator past the last deleted element (h in this example).
17139 : // Note that offset is the distance from the start of the vector
17140 : // to first. We will need this later.
17141 :
17142 : // [ a, b, c, d, e, f, g, h, i, j ]
17143 : // ^ ^
17144 : // first last
17145 :
17146 : // Since we cannot move const Keys, we re-construct them in place.
17147 : // We start at first and re-construct (viz. copy) the elements from
17148 : // the back of the vector. Example for first iteration:
17149 :
17150 : // ,--------.
17151 : // v | destroy e and re-construct with h
17152 : // [ a, b, c, d, e, f, g, h, i, j ]
17153 : // ^ ^
17154 : // it it + elements_affected
17155 :
17156 : for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
17157 : {
17158 : it->~value_type(); // destroy but keep allocation
17159 : new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
17160 : }
17161 :
17162 : // [ a, b, c, d, h, i, j, h, i, j ]
17163 : // ^ ^
17164 : // first last
17165 :
17166 : // remove the unneeded elements at the end of the vector
17167 : Container::resize(this->size() - static_cast<size_type>(elements_affected));
17168 :
17169 : // [ a, b, c, d, h, i, j ]
17170 : // ^ ^
17171 : // first last
17172 :
17173 : // first is now pointing past the last deleted element, but we cannot
17174 : // use this iterator, because it may have been invalidated by the
17175 : // resize call. Instead, we can return begin() + offset.
17176 : return Container::begin() + offset;
17177 : }
17178 :
17179 : size_type count(const Key& key) const
17180 : {
17181 : for (auto it = this->begin(); it != this->end(); ++it)
17182 : {
17183 : if (it->first == key)
17184 : {
17185 : return 1;
17186 : }
17187 : }
17188 : return 0;
17189 : }
17190 :
17191 : iterator find(const Key& key)
17192 : {
17193 : for (auto it = this->begin(); it != this->end(); ++it)
17194 : {
17195 : if (it->first == key)
17196 : {
17197 : return it;
17198 : }
17199 : }
17200 : return Container::end();
17201 : }
17202 :
17203 : const_iterator find(const Key& key) const
17204 : {
17205 : for (auto it = this->begin(); it != this->end(); ++it)
17206 : {
17207 : if (it->first == key)
17208 : {
17209 : return it;
17210 : }
17211 : }
17212 : return Container::end();
17213 : }
17214 :
17215 : std::pair<iterator, bool> insert( value_type&& value )
17216 : {
17217 : return emplace(value.first, std::move(value.second));
17218 : }
17219 :
17220 : std::pair<iterator, bool> insert( const value_type& value )
17221 : {
17222 : for (auto it = this->begin(); it != this->end(); ++it)
17223 : {
17224 : if (it->first == value.first)
17225 : {
17226 : return {it, false};
17227 : }
17228 : }
17229 : Container::push_back(value);
17230 : return {--this->end(), true};
17231 : }
17232 :
17233 : template<typename InputIt>
17234 : using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
17235 : std::input_iterator_tag>::value>::type;
17236 :
17237 : template<typename InputIt, typename = require_input_iter<InputIt>>
17238 : void insert(InputIt first, InputIt last)
17239 : {
17240 : for (auto it = first; it != last; ++it)
17241 : {
17242 : insert(*it);
17243 : }
17244 : }
17245 : };
17246 :
17247 : } // namespace nlohmann
17248 :
17249 :
17250 : #if defined(JSON_HAS_CPP_17)
17251 : #include <string_view>
17252 : #endif
17253 :
17254 : /*!
17255 : @brief namespace for Niels Lohmann
17256 : @see https://github.com/nlohmann
17257 : @since version 1.0.0
17258 : */
17259 : namespace nlohmann
17260 : {
17261 :
17262 : /*!
17263 : @brief a class to store JSON values
17264 :
17265 : @internal
17266 : @invariant The member variables @a m_value and @a m_type have the following
17267 : relationship:
17268 : - If `m_type == value_t::object`, then `m_value.object != nullptr`.
17269 : - If `m_type == value_t::array`, then `m_value.array != nullptr`.
17270 : - If `m_type == value_t::string`, then `m_value.string != nullptr`.
17271 : The invariants are checked by member function assert_invariant().
17272 :
17273 : @note ObjectType trick from https://stackoverflow.com/a/9860911
17274 : @endinternal
17275 :
17276 : @since version 1.0.0
17277 :
17278 : @nosubgrouping
17279 : */
17280 : NLOHMANN_BASIC_JSON_TPL_DECLARATION
17281 : class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
17282 : {
17283 : private:
17284 : template<detail::value_t> friend struct detail::external_constructor;
17285 : friend ::nlohmann::json_pointer<basic_json>;
17286 :
17287 : template<typename BasicJsonType, typename InputType>
17288 : friend class ::nlohmann::detail::parser;
17289 : friend ::nlohmann::detail::serializer<basic_json>;
17290 : template<typename BasicJsonType>
17291 : friend class ::nlohmann::detail::iter_impl;
17292 : template<typename BasicJsonType, typename CharType>
17293 : friend class ::nlohmann::detail::binary_writer;
17294 : template<typename BasicJsonType, typename InputType, typename SAX>
17295 : friend class ::nlohmann::detail::binary_reader;
17296 : template<typename BasicJsonType>
17297 : friend class ::nlohmann::detail::json_sax_dom_parser;
17298 : template<typename BasicJsonType>
17299 : friend class ::nlohmann::detail::json_sax_dom_callback_parser;
17300 : friend class ::nlohmann::detail::exception;
17301 :
17302 : /// workaround type for MSVC
17303 : using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
17304 :
17305 : JSON_PRIVATE_UNLESS_TESTED:
17306 : // convenience aliases for types residing in namespace detail;
17307 : using lexer = ::nlohmann::detail::lexer_base<basic_json>;
17308 :
17309 : template<typename InputAdapterType>
17310 34 : static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
17311 : InputAdapterType adapter,
17312 : detail::parser_callback_t<basic_json>cb = nullptr,
17313 : const bool allow_exceptions = true,
17314 : const bool ignore_comments = false
17315 : )
17316 : {
17317 : return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
17318 68 : std::move(cb), allow_exceptions, ignore_comments);
17319 : }
17320 :
17321 : private:
17322 : using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
17323 : template<typename BasicJsonType>
17324 : using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
17325 : template<typename BasicJsonType>
17326 : using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
17327 : template<typename Iterator>
17328 : using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
17329 : template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
17330 :
17331 : template<typename CharType>
17332 : using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
17333 :
17334 : template<typename InputType>
17335 : using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
17336 : template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
17337 :
17338 : JSON_PRIVATE_UNLESS_TESTED:
17339 : using serializer = ::nlohmann::detail::serializer<basic_json>;
17340 :
17341 : public:
17342 : using value_t = detail::value_t;
17343 : /// JSON Pointer, see @ref nlohmann::json_pointer
17344 : using json_pointer = ::nlohmann::json_pointer<basic_json>;
17345 : template<typename T, typename SFINAE>
17346 : using json_serializer = JSONSerializer<T, SFINAE>;
17347 : /// how to treat decoding errors
17348 : using error_handler_t = detail::error_handler_t;
17349 : /// how to treat CBOR tags
17350 : using cbor_tag_handler_t = detail::cbor_tag_handler_t;
17351 : /// helper type for initializer lists of basic_json values
17352 : using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
17353 :
17354 : using input_format_t = detail::input_format_t;
17355 : /// SAX interface type, see @ref nlohmann::json_sax
17356 : using json_sax_t = json_sax<basic_json>;
17357 :
17358 : ////////////////
17359 : // exceptions //
17360 : ////////////////
17361 :
17362 : /// @name exceptions
17363 : /// Classes to implement user-defined exceptions.
17364 : /// @{
17365 :
17366 : using exception = detail::exception;
17367 : using parse_error = detail::parse_error;
17368 : using invalid_iterator = detail::invalid_iterator;
17369 : using type_error = detail::type_error;
17370 : using out_of_range = detail::out_of_range;
17371 : using other_error = detail::other_error;
17372 :
17373 : /// @}
17374 :
17375 :
17376 : /////////////////////
17377 : // container types //
17378 : /////////////////////
17379 :
17380 : /// @name container types
17381 : /// The canonic container types to use @ref basic_json like any other STL
17382 : /// container.
17383 : /// @{
17384 :
17385 : /// the type of elements in a basic_json container
17386 : using value_type = basic_json;
17387 :
17388 : /// the type of an element reference
17389 : using reference = value_type&;
17390 : /// the type of an element const reference
17391 : using const_reference = const value_type&;
17392 :
17393 : /// a type to represent differences between iterators
17394 : using difference_type = std::ptrdiff_t;
17395 : /// a type to represent container sizes
17396 : using size_type = std::size_t;
17397 :
17398 : /// the allocator type
17399 : using allocator_type = AllocatorType<basic_json>;
17400 :
17401 : /// the type of an element pointer
17402 : using pointer = typename std::allocator_traits<allocator_type>::pointer;
17403 : /// the type of an element const pointer
17404 : using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
17405 :
17406 : /// an iterator for a basic_json container
17407 : using iterator = iter_impl<basic_json>;
17408 : /// a const iterator for a basic_json container
17409 : using const_iterator = iter_impl<const basic_json>;
17410 : /// a reverse iterator for a basic_json container
17411 : using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
17412 : /// a const reverse iterator for a basic_json container
17413 : using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
17414 :
17415 : /// @}
17416 :
17417 :
17418 : /// @brief returns the allocator associated with the container
17419 : /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
17420 : static allocator_type get_allocator()
17421 : {
17422 : return allocator_type();
17423 : }
17424 :
17425 : /// @brief returns version information on the library
17426 : /// @sa https://json.nlohmann.me/api/basic_json/meta/
17427 : JSON_HEDLEY_WARN_UNUSED_RESULT
17428 : static basic_json meta()
17429 : {
17430 : basic_json result;
17431 :
17432 : result["copyright"] = "(C) 2013-2022 Niels Lohmann";
17433 : result["name"] = "JSON for Modern C++";
17434 : result["url"] = "https://github.com/nlohmann/json";
17435 : result["version"]["string"] =
17436 : std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
17437 : std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
17438 : std::to_string(NLOHMANN_JSON_VERSION_PATCH);
17439 : result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
17440 : result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
17441 : result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
17442 :
17443 : #ifdef _WIN32
17444 : result["platform"] = "win32";
17445 : #elif defined __linux__
17446 : result["platform"] = "linux";
17447 : #elif defined __APPLE__
17448 : result["platform"] = "apple";
17449 : #elif defined __unix__
17450 : result["platform"] = "unix";
17451 : #else
17452 : result["platform"] = "unknown";
17453 : #endif
17454 :
17455 : #if defined(__ICC) || defined(__INTEL_COMPILER)
17456 : result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
17457 : #elif defined(__clang__)
17458 : result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
17459 : #elif defined(__GNUC__) || defined(__GNUG__)
17460 : result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
17461 : #elif defined(__HP_cc) || defined(__HP_aCC)
17462 : result["compiler"] = "hp"
17463 : #elif defined(__IBMCPP__)
17464 : result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
17465 : #elif defined(_MSC_VER)
17466 : result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
17467 : #elif defined(__PGI)
17468 : result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
17469 : #elif defined(__SUNPRO_CC)
17470 : result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
17471 : #else
17472 : result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
17473 : #endif
17474 :
17475 : #ifdef __cplusplus
17476 : result["compiler"]["c++"] = std::to_string(__cplusplus);
17477 : #else
17478 : result["compiler"]["c++"] = "unknown";
17479 : #endif
17480 : return result;
17481 : }
17482 :
17483 :
17484 : ///////////////////////////
17485 : // JSON value data types //
17486 : ///////////////////////////
17487 :
17488 : /// @name JSON value data types
17489 : /// The data types to store a JSON value. These types are derived from
17490 : /// the template arguments passed to class @ref basic_json.
17491 : /// @{
17492 :
17493 : /// @brief object key comparator type
17494 : /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
17495 : #if defined(JSON_HAS_CPP_14)
17496 : // Use transparent comparator if possible, combined with perfect forwarding
17497 : // on find() and count() calls prevents unnecessary string construction.
17498 : using object_comparator_t = std::less<>;
17499 : #else
17500 : using object_comparator_t = std::less<StringType>;
17501 : #endif
17502 :
17503 : /// @brief a type for an object
17504 : /// @sa https://json.nlohmann.me/api/basic_json/object_t/
17505 : using object_t = ObjectType<StringType,
17506 : basic_json,
17507 : object_comparator_t,
17508 : AllocatorType<std::pair<const StringType,
17509 : basic_json>>>;
17510 :
17511 : /// @brief a type for an array
17512 : /// @sa https://json.nlohmann.me/api/basic_json/array_t/
17513 : using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
17514 :
17515 : /// @brief a type for a string
17516 : /// @sa https://json.nlohmann.me/api/basic_json/string_t/
17517 : using string_t = StringType;
17518 :
17519 : /// @brief a type for a boolean
17520 : /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
17521 : using boolean_t = BooleanType;
17522 :
17523 : /// @brief a type for a number (integer)
17524 : /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
17525 : using number_integer_t = NumberIntegerType;
17526 :
17527 : /// @brief a type for a number (unsigned)
17528 : /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
17529 : using number_unsigned_t = NumberUnsignedType;
17530 :
17531 : /// @brief a type for a number (floating-point)
17532 : /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
17533 : using number_float_t = NumberFloatType;
17534 :
17535 : /// @brief a type for a packed binary type
17536 : /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
17537 : using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
17538 :
17539 : /// @}
17540 :
17541 : private:
17542 :
17543 : /// helper for exception-safe object creation
17544 : template<typename T, typename... Args>
17545 : JSON_HEDLEY_RETURNS_NON_NULL
17546 152 : static T* create(Args&& ... args)
17547 : {
17548 : AllocatorType<T> alloc;
17549 : using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
17550 :
17551 : auto deleter = [&](T * obj)
17552 : {
17553 : AllocatorTraits::deallocate(alloc, obj, 1);
17554 : };
17555 : std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
17556 : AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
17557 : JSON_ASSERT(obj != nullptr);
17558 152 : return obj.release();
17559 : }
17560 :
17561 : ////////////////////////
17562 : // JSON value storage //
17563 : ////////////////////////
17564 :
17565 : JSON_PRIVATE_UNLESS_TESTED:
17566 : /*!
17567 : @brief a JSON value
17568 :
17569 : The actual storage for a JSON value of the @ref basic_json class. This
17570 : union combines the different storage types for the JSON value types
17571 : defined in @ref value_t.
17572 :
17573 : JSON type | value_t type | used type
17574 : --------- | --------------- | ------------------------
17575 : object | object | pointer to @ref object_t
17576 : array | array | pointer to @ref array_t
17577 : string | string | pointer to @ref string_t
17578 : boolean | boolean | @ref boolean_t
17579 : number | number_integer | @ref number_integer_t
17580 : number | number_unsigned | @ref number_unsigned_t
17581 : number | number_float | @ref number_float_t
17582 : binary | binary | pointer to @ref binary_t
17583 : null | null | *no value is stored*
17584 :
17585 : @note Variable-length types (objects, arrays, and strings) are stored as
17586 : pointers. The size of the union should not exceed 64 bits if the default
17587 : value types are used.
17588 :
17589 : @since version 1.0.0
17590 : */
17591 : union json_value
17592 : {
17593 : /// object (stored with pointer to save storage)
17594 : object_t* object;
17595 : /// array (stored with pointer to save storage)
17596 : array_t* array;
17597 : /// string (stored with pointer to save storage)
17598 : string_t* string;
17599 : /// binary (stored with pointer to save storage)
17600 : binary_t* binary;
17601 : /// boolean
17602 : boolean_t boolean;
17603 : /// number (integer)
17604 : number_integer_t number_integer;
17605 : /// number (unsigned integer)
17606 : number_unsigned_t number_unsigned;
17607 : /// number (floating-point)
17608 : number_float_t number_float;
17609 :
17610 : /// default constructor (for null values)
17611 : json_value() = default;
17612 : /// constructor for booleans
17613 0 : json_value(boolean_t v) noexcept : boolean(v) {}
17614 : /// constructor for numbers (integer)
17615 : json_value(number_integer_t v) noexcept : number_integer(v) {}
17616 : /// constructor for numbers (unsigned)
17617 : json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
17618 : /// constructor for numbers (floating-point)
17619 : json_value(number_float_t v) noexcept : number_float(v) {}
17620 : /// constructor for empty values of a given type
17621 3254 : json_value(value_t t)
17622 : {
17623 3254 : switch (t)
17624 : {
17625 : case value_t::object:
17626 : {
17627 596 : object = create<object_t>();
17628 596 : break;
17629 : }
17630 :
17631 : case value_t::array:
17632 : {
17633 620 : array = create<array_t>();
17634 620 : break;
17635 : }
17636 :
17637 0 : case value_t::string:
17638 : {
17639 0 : string = create<string_t>("");
17640 0 : break;
17641 : }
17642 :
17643 : case value_t::binary:
17644 : {
17645 0 : binary = create<binary_t>();
17646 0 : break;
17647 : }
17648 :
17649 0 : case value_t::boolean:
17650 : {
17651 0 : boolean = static_cast<boolean_t>(false);
17652 0 : break;
17653 : }
17654 :
17655 0 : case value_t::number_integer:
17656 : {
17657 0 : number_integer = static_cast<number_integer_t>(0);
17658 0 : break;
17659 : }
17660 :
17661 0 : case value_t::number_unsigned:
17662 : {
17663 0 : number_unsigned = static_cast<number_unsigned_t>(0);
17664 0 : break;
17665 : }
17666 :
17667 0 : case value_t::number_float:
17668 : {
17669 0 : number_float = static_cast<number_float_t>(0.0);
17670 0 : break;
17671 : }
17672 :
17673 2038 : case value_t::null:
17674 : {
17675 2038 : object = nullptr; // silence warning, see #821
17676 2038 : break;
17677 : }
17678 :
17679 0 : case value_t::discarded:
17680 : default:
17681 : {
17682 0 : object = nullptr; // silence warning, see #821
17683 : if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
17684 : {
17685 : JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5", basic_json())); // LCOV_EXCL_LINE
17686 : }
17687 : break;
17688 : }
17689 : }
17690 3254 : }
17691 :
17692 : /// constructor for strings
17693 152 : json_value(const string_t& value) : string(create<string_t>(value)) {}
17694 :
17695 : /// constructor for rvalue strings
17696 : json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
17697 :
17698 : /// constructor for objects
17699 0 : json_value(const object_t& value) : object(create<object_t>(value)) {}
17700 :
17701 : /// constructor for rvalue objects
17702 : json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
17703 :
17704 : /// constructor for arrays
17705 0 : json_value(const array_t& value) : array(create<array_t>(value)) {}
17706 :
17707 : /// constructor for rvalue arrays
17708 : json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
17709 :
17710 : /// constructor for binary arrays
17711 : json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
17712 :
17713 : /// constructor for rvalue binary arrays
17714 : json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
17715 :
17716 : /// constructor for binary arrays (internal type)
17717 0 : json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
17718 :
17719 : /// constructor for rvalue binary arrays (internal type)
17720 : json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
17721 :
17722 20894 : void destroy(value_t t)
17723 : {
17724 20894 : if (t == value_t::array || t == value_t::object)
17725 : {
17726 : // flatten the current json_value to a heap-allocated stack
17727 : std::vector<basic_json> stack;
17728 :
17729 : // move the top-level items to stack
17730 448 : if (t == value_t::array)
17731 : {
17732 140 : stack.reserve(array->size());
17733 140 : std::move(array->begin(), array->end(), std::back_inserter(stack));
17734 : }
17735 : else
17736 : {
17737 308 : stack.reserve(object->size());
17738 532 : for (auto&& it : *object)
17739 : {
17740 224 : stack.push_back(std::move(it.second));
17741 : }
17742 : }
17743 :
17744 6394 : while (!stack.empty())
17745 : {
17746 : // move the last item to local variable to be processed
17747 : basic_json current_item(std::move(stack.back()));
17748 : stack.pop_back();
17749 :
17750 : // if current_item is array/object, move
17751 : // its children to the stack to be processed later
17752 2973 : if (current_item.is_array())
17753 : {
17754 140 : std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack));
17755 :
17756 140 : current_item.m_value.array->clear();
17757 : }
17758 2833 : else if (current_item.is_object())
17759 : {
17760 1232 : for (auto&& it : *current_item.m_value.object)
17761 : {
17762 952 : stack.push_back(std::move(it.second));
17763 : }
17764 :
17765 280 : current_item.m_value.object->clear();
17766 : }
17767 :
17768 : // it's now safe that current_item get destructed
17769 : // since it doesn't have any children
17770 : }
17771 448 : }
17772 :
17773 20894 : switch (t)
17774 : {
17775 : case value_t::object:
17776 : {
17777 : AllocatorType<object_t> alloc;
17778 308 : std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
17779 308 : std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
17780 : break;
17781 : }
17782 :
17783 : case value_t::array:
17784 : {
17785 : AllocatorType<array_t> alloc;
17786 140 : std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
17787 140 : std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
17788 : break;
17789 : }
17790 :
17791 : case value_t::string:
17792 : {
17793 : AllocatorType<string_t> alloc;
17794 140 : std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
17795 140 : std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
17796 : break;
17797 : }
17798 :
17799 : case value_t::binary:
17800 : {
17801 : AllocatorType<binary_t> alloc;
17802 0 : std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
17803 0 : std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
17804 : break;
17805 : }
17806 :
17807 : case value_t::null:
17808 : case value_t::boolean:
17809 : case value_t::number_integer:
17810 : case value_t::number_unsigned:
17811 : case value_t::number_float:
17812 : case value_t::discarded:
17813 : default:
17814 : {
17815 : break;
17816 : }
17817 : }
17818 20894 : }
17819 : };
17820 :
17821 : private:
17822 : /*!
17823 : @brief checks the class invariants
17824 :
17825 : This function asserts the class invariants. It needs to be called at the
17826 : end of every constructor to make sure that created objects respect the
17827 : invariant. Furthermore, it has to be called each time the type of a JSON
17828 : value is changed, because the invariant expresses a relationship between
17829 : @a m_type and @a m_value.
17830 :
17831 : Furthermore, the parent relation is checked for arrays and objects: If
17832 : @a check_parents true and the value is an array or object, then the
17833 : container's elements must have the current value as parent.
17834 :
17835 : @param[in] check_parents whether the parent relation should be checked.
17836 : The value is true by default and should only be set to false
17837 : during destruction of objects when the invariant does not
17838 : need to hold.
17839 : */
17840 : void assert_invariant(bool check_parents = true) const noexcept
17841 : {
17842 : JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
17843 : JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
17844 : JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
17845 : JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
17846 :
17847 : #if JSON_DIAGNOSTICS
17848 : JSON_TRY
17849 : {
17850 : // cppcheck-suppress assertWithSideEffect
17851 : JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
17852 : {
17853 : return j.m_parent == this;
17854 : }));
17855 : }
17856 : JSON_CATCH(...) {} // LCOV_EXCL_LINE
17857 : #endif
17858 : static_cast<void>(check_parents);
17859 0 : }
17860 :
17861 : void set_parents()
17862 : {
17863 : #if JSON_DIAGNOSTICS
17864 : switch (m_type)
17865 : {
17866 : case value_t::array:
17867 : {
17868 : for (auto& element : *m_value.array)
17869 : {
17870 : element.m_parent = this;
17871 : }
17872 : break;
17873 : }
17874 :
17875 : case value_t::object:
17876 : {
17877 : for (auto& element : *m_value.object)
17878 : {
17879 : element.second.m_parent = this;
17880 : }
17881 : break;
17882 : }
17883 :
17884 : case value_t::null:
17885 : case value_t::string:
17886 : case value_t::boolean:
17887 : case value_t::number_integer:
17888 : case value_t::number_unsigned:
17889 : case value_t::number_float:
17890 : case value_t::binary:
17891 : case value_t::discarded:
17892 : default:
17893 : break;
17894 : }
17895 : #endif
17896 : }
17897 :
17898 : iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
17899 : {
17900 : #if JSON_DIAGNOSTICS
17901 : for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
17902 : {
17903 : (it + i)->m_parent = this;
17904 : }
17905 : #else
17906 : static_cast<void>(count_set_parents);
17907 : #endif
17908 : return it;
17909 : }
17910 :
17911 : reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
17912 : {
17913 : #if JSON_DIAGNOSTICS
17914 : if (old_capacity != static_cast<std::size_t>(-1))
17915 : {
17916 : // see https://github.com/nlohmann/json/issues/2838
17917 : JSON_ASSERT(type() == value_t::array);
17918 : if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
17919 : {
17920 : // capacity has changed: update all parents
17921 : set_parents();
17922 : return j;
17923 : }
17924 : }
17925 :
17926 : // ordered_json uses a vector internally, so pointers could have
17927 : // been invalidated; see https://github.com/nlohmann/json/issues/2962
17928 : #ifdef JSON_HEDLEY_MSVC_VERSION
17929 : #pragma warning(push )
17930 : #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
17931 : #endif
17932 : if (detail::is_ordered_map<object_t>::value)
17933 : {
17934 : set_parents();
17935 : return j;
17936 : }
17937 : #ifdef JSON_HEDLEY_MSVC_VERSION
17938 : #pragma warning( pop )
17939 : #endif
17940 :
17941 : j.m_parent = this;
17942 : #else
17943 : static_cast<void>(j);
17944 : static_cast<void>(old_capacity);
17945 : #endif
17946 : return j;
17947 : }
17948 :
17949 : public:
17950 : //////////////////////////
17951 : // JSON parser callback //
17952 : //////////////////////////
17953 :
17954 : /// @brief parser event types
17955 : /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
17956 : using parse_event_t = detail::parse_event_t;
17957 :
17958 : /// @brief per-element parser callback type
17959 : /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
17960 : using parser_callback_t = detail::parser_callback_t<basic_json>;
17961 :
17962 : //////////////////
17963 : // constructors //
17964 : //////////////////
17965 :
17966 : /// @name constructors and destructors
17967 : /// Constructors of class @ref basic_json, copy/move constructor, copy
17968 : /// assignment, static functions creating objects, and the destructor.
17969 : /// @{
17970 :
17971 : /// @brief create an empty value with a given type
17972 : /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
17973 3254 : basic_json(const value_t v)
17974 3246 : : m_type(v), m_value(v)
17975 : {
17976 : assert_invariant();
17977 0 : }
17978 :
17979 : /// @brief create a null object
17980 : /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
17981 0 : basic_json(std::nullptr_t = nullptr) noexcept
17982 : : basic_json(value_t::null)
17983 : {
17984 : assert_invariant();
17985 0 : }
17986 :
17987 : /// @brief create a JSON value from compatible types
17988 : /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
17989 : template < typename CompatibleType,
17990 : typename U = detail::uncvref_t<CompatibleType>,
17991 : detail::enable_if_t <
17992 : !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
17993 4694 : basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
17994 : JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
17995 : std::forward<CompatibleType>(val))))
17996 4693 : {
17997 : JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
17998 : set_parents();
17999 : assert_invariant();
18000 3877 : }
18001 :
18002 : /// @brief create a JSON value from an existing one
18003 : /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18004 : template < typename BasicJsonType,
18005 : detail::enable_if_t <
18006 : detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
18007 : basic_json(const BasicJsonType& val)
18008 : {
18009 : using other_boolean_t = typename BasicJsonType::boolean_t;
18010 : using other_number_float_t = typename BasicJsonType::number_float_t;
18011 : using other_number_integer_t = typename BasicJsonType::number_integer_t;
18012 : using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18013 : using other_string_t = typename BasicJsonType::string_t;
18014 : using other_object_t = typename BasicJsonType::object_t;
18015 : using other_array_t = typename BasicJsonType::array_t;
18016 : using other_binary_t = typename BasicJsonType::binary_t;
18017 :
18018 : switch (val.type())
18019 : {
18020 : case value_t::boolean:
18021 : JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
18022 : break;
18023 : case value_t::number_float:
18024 : JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
18025 : break;
18026 : case value_t::number_integer:
18027 : JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
18028 : break;
18029 : case value_t::number_unsigned:
18030 : JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
18031 : break;
18032 : case value_t::string:
18033 : JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
18034 : break;
18035 : case value_t::object:
18036 : JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
18037 : break;
18038 : case value_t::array:
18039 : JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
18040 : break;
18041 : case value_t::binary:
18042 : JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
18043 : break;
18044 : case value_t::null:
18045 : *this = nullptr;
18046 : break;
18047 : case value_t::discarded:
18048 : m_type = value_t::discarded;
18049 : break;
18050 : default: // LCOV_EXCL_LINE
18051 : JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18052 : }
18053 : set_parents();
18054 : assert_invariant();
18055 : }
18056 :
18057 : /// @brief create a container (array or object) from an initializer list
18058 : /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18059 : basic_json(initializer_list_t init,
18060 : bool type_deduction = true,
18061 : value_t manual_type = value_t::array)
18062 : {
18063 : // check if each element is an array with two elements whose first
18064 : // element is a string
18065 : bool is_an_object = std::all_of(init.begin(), init.end(),
18066 : [](const detail::json_ref<basic_json>& element_ref)
18067 : {
18068 : return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
18069 : });
18070 :
18071 : // adjust type if type deduction is not wanted
18072 : if (!type_deduction)
18073 : {
18074 : // if array is wanted, do not create an object though possible
18075 : if (manual_type == value_t::array)
18076 : {
18077 : is_an_object = false;
18078 : }
18079 :
18080 : // if object is wanted but impossible, throw an exception
18081 : if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
18082 : {
18083 : JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json()));
18084 : }
18085 : }
18086 :
18087 : if (is_an_object)
18088 : {
18089 : // the initializer list is a list of pairs -> create object
18090 : m_type = value_t::object;
18091 : m_value = value_t::object;
18092 :
18093 : for (auto& element_ref : init)
18094 : {
18095 : auto element = element_ref.moved_or_copied();
18096 : m_value.object->emplace(
18097 : std::move(*((*element.m_value.array)[0].m_value.string)),
18098 : std::move((*element.m_value.array)[1]));
18099 : }
18100 : }
18101 : else
18102 : {
18103 : // the initializer list describes an array -> create array
18104 : m_type = value_t::array;
18105 : m_value.array = create<array_t>(init.begin(), init.end());
18106 : }
18107 :
18108 : set_parents();
18109 : assert_invariant();
18110 : }
18111 :
18112 : /// @brief explicitly create a binary array (without subtype)
18113 : /// @sa https://json.nlohmann.me/api/basic_json/binary/
18114 : JSON_HEDLEY_WARN_UNUSED_RESULT
18115 : static basic_json binary(const typename binary_t::container_type& init)
18116 : {
18117 : auto res = basic_json();
18118 : res.m_type = value_t::binary;
18119 : res.m_value = init;
18120 : return res;
18121 : }
18122 :
18123 : /// @brief explicitly create a binary array (with subtype)
18124 : /// @sa https://json.nlohmann.me/api/basic_json/binary/
18125 : JSON_HEDLEY_WARN_UNUSED_RESULT
18126 : static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
18127 : {
18128 : auto res = basic_json();
18129 : res.m_type = value_t::binary;
18130 : res.m_value = binary_t(init, subtype);
18131 : return res;
18132 : }
18133 :
18134 : /// @brief explicitly create a binary array
18135 : /// @sa https://json.nlohmann.me/api/basic_json/binary/
18136 : JSON_HEDLEY_WARN_UNUSED_RESULT
18137 : static basic_json binary(typename binary_t::container_type&& init)
18138 : {
18139 : auto res = basic_json();
18140 : res.m_type = value_t::binary;
18141 : res.m_value = std::move(init);
18142 : return res;
18143 : }
18144 :
18145 : /// @brief explicitly create a binary array (with subtype)
18146 : /// @sa https://json.nlohmann.me/api/basic_json/binary/
18147 : JSON_HEDLEY_WARN_UNUSED_RESULT
18148 : static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
18149 : {
18150 : auto res = basic_json();
18151 : res.m_type = value_t::binary;
18152 : res.m_value = binary_t(std::move(init), subtype);
18153 : return res;
18154 : }
18155 :
18156 : /// @brief explicitly create an array from an initializer list
18157 : /// @sa https://json.nlohmann.me/api/basic_json/array/
18158 : JSON_HEDLEY_WARN_UNUSED_RESULT
18159 : static basic_json array(initializer_list_t init = {})
18160 : {
18161 : return basic_json(init, false, value_t::array);
18162 : }
18163 :
18164 : /// @brief explicitly create an object from an initializer list
18165 : /// @sa https://json.nlohmann.me/api/basic_json/object/
18166 : JSON_HEDLEY_WARN_UNUSED_RESULT
18167 : static basic_json object(initializer_list_t init = {})
18168 : {
18169 : return basic_json(init, false, value_t::object);
18170 : }
18171 :
18172 : /// @brief construct an array with count copies of given value
18173 : /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18174 : basic_json(size_type cnt, const basic_json& val)
18175 : : m_type(value_t::array)
18176 : {
18177 : m_value.array = create<array_t>(cnt, val);
18178 : set_parents();
18179 : assert_invariant();
18180 : }
18181 :
18182 : /// @brief construct a JSON container given an iterator range
18183 : /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18184 : template < class InputIT, typename std::enable_if <
18185 : std::is_same<InputIT, typename basic_json_t::iterator>::value ||
18186 : std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
18187 : basic_json(InputIT first, InputIT last)
18188 : {
18189 : JSON_ASSERT(first.m_object != nullptr);
18190 : JSON_ASSERT(last.m_object != nullptr);
18191 :
18192 : // make sure iterator fits the current value
18193 : if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
18194 : {
18195 : JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json()));
18196 : }
18197 :
18198 : // copy type from first iterator
18199 : m_type = first.m_object->m_type;
18200 :
18201 : // check if iterator range is complete for primitive values
18202 : switch (m_type)
18203 : {
18204 : case value_t::boolean:
18205 : case value_t::number_float:
18206 : case value_t::number_integer:
18207 : case value_t::number_unsigned:
18208 : case value_t::string:
18209 : {
18210 : if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
18211 : || !last.m_it.primitive_iterator.is_end()))
18212 : {
18213 : JSON_THROW(invalid_iterator::create(204, "iterators out of range", *first.m_object));
18214 : }
18215 : break;
18216 : }
18217 :
18218 : case value_t::null:
18219 : case value_t::object:
18220 : case value_t::array:
18221 : case value_t::binary:
18222 : case value_t::discarded:
18223 : default:
18224 : break;
18225 : }
18226 :
18227 : switch (m_type)
18228 : {
18229 : case value_t::number_integer:
18230 : {
18231 : m_value.number_integer = first.m_object->m_value.number_integer;
18232 : break;
18233 : }
18234 :
18235 : case value_t::number_unsigned:
18236 : {
18237 : m_value.number_unsigned = first.m_object->m_value.number_unsigned;
18238 : break;
18239 : }
18240 :
18241 : case value_t::number_float:
18242 : {
18243 : m_value.number_float = first.m_object->m_value.number_float;
18244 : break;
18245 : }
18246 :
18247 : case value_t::boolean:
18248 : {
18249 : m_value.boolean = first.m_object->m_value.boolean;
18250 : break;
18251 : }
18252 :
18253 : case value_t::string:
18254 : {
18255 : m_value = *first.m_object->m_value.string;
18256 : break;
18257 : }
18258 :
18259 : case value_t::object:
18260 : {
18261 : m_value.object = create<object_t>(first.m_it.object_iterator,
18262 : last.m_it.object_iterator);
18263 : break;
18264 : }
18265 :
18266 : case value_t::array:
18267 : {
18268 : m_value.array = create<array_t>(first.m_it.array_iterator,
18269 : last.m_it.array_iterator);
18270 : break;
18271 : }
18272 :
18273 : case value_t::binary:
18274 : {
18275 : m_value = *first.m_object->m_value.binary;
18276 : break;
18277 : }
18278 :
18279 : case value_t::null:
18280 : case value_t::discarded:
18281 : default:
18282 : JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), *first.m_object));
18283 : }
18284 :
18285 : set_parents();
18286 : assert_invariant();
18287 : }
18288 :
18289 :
18290 : ///////////////////////////////////////
18291 : // other constructors and destructor //
18292 : ///////////////////////////////////////
18293 :
18294 : template<typename JsonRef,
18295 : detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
18296 : std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
18297 : basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
18298 :
18299 : /// @brief copy constructor
18300 : /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18301 0 : basic_json(const basic_json& other)
18302 0 : : m_type(other.m_type)
18303 : {
18304 : // check of passed value is valid
18305 : other.assert_invariant();
18306 :
18307 0 : switch (m_type)
18308 : {
18309 0 : case value_t::object:
18310 : {
18311 0 : m_value = *other.m_value.object;
18312 0 : break;
18313 : }
18314 :
18315 0 : case value_t::array:
18316 : {
18317 0 : m_value = *other.m_value.array;
18318 0 : break;
18319 : }
18320 :
18321 0 : case value_t::string:
18322 : {
18323 0 : m_value = *other.m_value.string;
18324 0 : break;
18325 : }
18326 :
18327 0 : case value_t::boolean:
18328 : {
18329 0 : m_value = other.m_value.boolean;
18330 0 : break;
18331 : }
18332 :
18333 0 : case value_t::number_integer:
18334 : {
18335 0 : m_value = other.m_value.number_integer;
18336 0 : break;
18337 : }
18338 :
18339 0 : case value_t::number_unsigned:
18340 : {
18341 0 : m_value = other.m_value.number_unsigned;
18342 0 : break;
18343 : }
18344 :
18345 0 : case value_t::number_float:
18346 : {
18347 0 : m_value = other.m_value.number_float;
18348 0 : break;
18349 : }
18350 :
18351 0 : case value_t::binary:
18352 : {
18353 0 : m_value = *other.m_value.binary;
18354 0 : break;
18355 : }
18356 :
18357 : case value_t::null:
18358 : case value_t::discarded:
18359 : default:
18360 : break;
18361 : }
18362 :
18363 : set_parents();
18364 : assert_invariant();
18365 0 : }
18366 :
18367 : /// @brief move constructor
18368 : /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18369 11166 : basic_json(basic_json&& other) noexcept
18370 11166 : : m_type(std::move(other.m_type)),
18371 11166 : m_value(std::move(other.m_value))
18372 : {
18373 : // check that passed value is valid
18374 : other.assert_invariant(false);
18375 :
18376 : // invalidate payload
18377 11166 : other.m_type = value_t::null;
18378 11166 : other.m_value = {};
18379 :
18380 : set_parents();
18381 : assert_invariant();
18382 : }
18383 :
18384 : /// @brief copy assignment
18385 : /// @sa https://json.nlohmann.me/api/basic_json/operator=/
18386 : basic_json& operator=(basic_json other) noexcept (
18387 : std::is_nothrow_move_constructible<value_t>::value&&
18388 : std::is_nothrow_move_assignable<value_t>::value&&
18389 : std::is_nothrow_move_constructible<json_value>::value&&
18390 : std::is_nothrow_move_assignable<json_value>::value
18391 : )
18392 : {
18393 : // check that passed value is valid
18394 : other.assert_invariant();
18395 :
18396 : using std::swap;
18397 : swap(m_type, other.m_type);
18398 : swap(m_value, other.m_value);
18399 :
18400 : set_parents();
18401 : assert_invariant();
18402 : return *this;
18403 : }
18404 :
18405 : /// @brief destructor
18406 : /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
18407 11166 : ~basic_json() noexcept
18408 : {
18409 : assert_invariant(false);
18410 15024 : m_value.destroy(m_type);
18411 3857 : }
18412 :
18413 : /// @}
18414 :
18415 : public:
18416 : ///////////////////////
18417 : // object inspection //
18418 : ///////////////////////
18419 :
18420 : /// @name object inspection
18421 : /// Functions to inspect the type of a JSON value.
18422 : /// @{
18423 :
18424 : /// @brief serialization
18425 : /// @sa https://json.nlohmann.me/api/basic_json/dump/
18426 : string_t dump(const int indent = -1,
18427 : const char indent_char = ' ',
18428 : const bool ensure_ascii = false,
18429 : const error_handler_t error_handler = error_handler_t::strict) const
18430 : {
18431 : string_t result;
18432 : serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
18433 :
18434 : if (indent >= 0)
18435 : {
18436 : s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
18437 : }
18438 : else
18439 : {
18440 : s.dump(*this, false, ensure_ascii, 0);
18441 : }
18442 :
18443 : return result;
18444 : }
18445 :
18446 : /// @brief return the type of the JSON value (explicit)
18447 : /// @sa https://json.nlohmann.me/api/basic_json/type/
18448 : constexpr value_t type() const noexcept
18449 : {
18450 6 : return m_type;
18451 : }
18452 :
18453 : /// @brief return whether type is primitive
18454 : /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
18455 : constexpr bool is_primitive() const noexcept
18456 : {
18457 : return is_null() || is_string() || is_boolean() || is_number() || is_binary();
18458 : }
18459 :
18460 : /// @brief return whether type is structured
18461 : /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
18462 : constexpr bool is_structured() const noexcept
18463 : {
18464 0 : return is_array() || is_object();
18465 : }
18466 :
18467 : /// @brief return whether value is null
18468 : /// @sa https://json.nlohmann.me/api/basic_json/is_null/
18469 : constexpr bool is_null() const noexcept
18470 : {
18471 56 : return m_type == value_t::null;
18472 : }
18473 :
18474 : /// @brief return whether value is a boolean
18475 : /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
18476 : constexpr bool is_boolean() const noexcept
18477 : {
18478 : return m_type == value_t::boolean;
18479 : }
18480 :
18481 : /// @brief return whether value is a number
18482 : /// @sa https://json.nlohmann.me/api/basic_json/is_number/
18483 : constexpr bool is_number() const noexcept
18484 : {
18485 : return is_number_integer() || is_number_float();
18486 : }
18487 :
18488 : /// @brief return whether value is an integer number
18489 : /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
18490 : constexpr bool is_number_integer() const noexcept
18491 : {
18492 : return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
18493 : }
18494 :
18495 : /// @brief return whether value is an unsigned integer number
18496 : /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
18497 : constexpr bool is_number_unsigned() const noexcept
18498 : {
18499 : return m_type == value_t::number_unsigned;
18500 : }
18501 :
18502 : /// @brief return whether value is a floating-point number
18503 : /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
18504 : constexpr bool is_number_float() const noexcept
18505 : {
18506 : return m_type == value_t::number_float;
18507 : }
18508 :
18509 : /// @brief return whether value is an object
18510 : /// @sa https://json.nlohmann.me/api/basic_json/is_object/
18511 : constexpr bool is_object() const noexcept
18512 : {
18513 62 : return m_type == value_t::object;
18514 : }
18515 :
18516 : /// @brief return whether value is an array
18517 : /// @sa https://json.nlohmann.me/api/basic_json/is_array/
18518 : constexpr bool is_array() const noexcept
18519 : {
18520 9000 : return m_type == value_t::array;
18521 : }
18522 :
18523 : /// @brief return whether value is a string
18524 : /// @sa https://json.nlohmann.me/api/basic_json/is_string/
18525 : constexpr bool is_string() const noexcept
18526 : {
18527 84 : return m_type == value_t::string;
18528 : }
18529 :
18530 : /// @brief return whether value is a binary array
18531 : /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
18532 : constexpr bool is_binary() const noexcept
18533 : {
18534 : return m_type == value_t::binary;
18535 : }
18536 :
18537 : /// @brief return whether value is discarded
18538 : /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
18539 : constexpr bool is_discarded() const noexcept
18540 : {
18541 0 : return m_type == value_t::discarded;
18542 : }
18543 :
18544 : /// @brief return the type of the JSON value (implicit)
18545 : /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
18546 : constexpr operator value_t() const noexcept
18547 : {
18548 2476 : return m_type;
18549 : }
18550 :
18551 : /// @}
18552 :
18553 : private:
18554 : //////////////////
18555 : // value access //
18556 : //////////////////
18557 :
18558 : /// get a boolean (explicit)
18559 : boolean_t get_impl(boolean_t* /*unused*/) const
18560 : {
18561 : if (JSON_HEDLEY_LIKELY(is_boolean()))
18562 : {
18563 : return m_value.boolean;
18564 : }
18565 :
18566 : JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this));
18567 : }
18568 :
18569 : /// get a pointer to the value (object)
18570 : object_t* get_impl_ptr(object_t* /*unused*/) noexcept
18571 : {
18572 : return is_object() ? m_value.object : nullptr;
18573 : }
18574 :
18575 : /// get a pointer to the value (object)
18576 : constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
18577 : {
18578 56 : return is_object() ? m_value.object : nullptr;
18579 : }
18580 :
18581 : /// get a pointer to the value (array)
18582 : array_t* get_impl_ptr(array_t* /*unused*/) noexcept
18583 : {
18584 : return is_array() ? m_value.array : nullptr;
18585 : }
18586 :
18587 : /// get a pointer to the value (array)
18588 : constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
18589 : {
18590 : return is_array() ? m_value.array : nullptr;
18591 : }
18592 :
18593 : /// get a pointer to the value (string)
18594 : string_t* get_impl_ptr(string_t* /*unused*/) noexcept
18595 : {
18596 : return is_string() ? m_value.string : nullptr;
18597 : }
18598 :
18599 : /// get a pointer to the value (string)
18600 : constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
18601 : {
18602 84 : return is_string() ? m_value.string : nullptr;
18603 : }
18604 :
18605 : /// get a pointer to the value (boolean)
18606 : boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
18607 : {
18608 : return is_boolean() ? &m_value.boolean : nullptr;
18609 : }
18610 :
18611 : /// get a pointer to the value (boolean)
18612 : constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
18613 : {
18614 : return is_boolean() ? &m_value.boolean : nullptr;
18615 : }
18616 :
18617 : /// get a pointer to the value (integer number)
18618 : number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
18619 : {
18620 : return is_number_integer() ? &m_value.number_integer : nullptr;
18621 : }
18622 :
18623 : /// get a pointer to the value (integer number)
18624 : constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
18625 : {
18626 0 : return is_number_integer() ? &m_value.number_integer : nullptr;
18627 : }
18628 :
18629 : /// get a pointer to the value (unsigned number)
18630 : number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
18631 : {
18632 : return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
18633 : }
18634 :
18635 : /// get a pointer to the value (unsigned number)
18636 : constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
18637 : {
18638 31 : return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
18639 : }
18640 :
18641 : /// get a pointer to the value (floating-point number)
18642 : number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
18643 : {
18644 : return is_number_float() ? &m_value.number_float : nullptr;
18645 : }
18646 :
18647 : /// get a pointer to the value (floating-point number)
18648 : constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
18649 : {
18650 2445 : return is_number_float() ? &m_value.number_float : nullptr;
18651 : }
18652 :
18653 : /// get a pointer to the value (binary)
18654 : binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
18655 : {
18656 : return is_binary() ? m_value.binary : nullptr;
18657 : }
18658 :
18659 : /// get a pointer to the value (binary)
18660 : constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
18661 : {
18662 : return is_binary() ? m_value.binary : nullptr;
18663 : }
18664 :
18665 : /*!
18666 : @brief helper function to implement get_ref()
18667 :
18668 : This function helps to implement get_ref() without code duplication for
18669 : const and non-const overloads
18670 :
18671 : @tparam ThisType will be deduced as `basic_json` or `const basic_json`
18672 :
18673 : @throw type_error.303 if ReferenceType does not match underlying value
18674 : type of the current JSON
18675 : */
18676 : template<typename ReferenceType, typename ThisType>
18677 : static ReferenceType get_ref_impl(ThisType& obj)
18678 : {
18679 : // delegate the call to get_ptr<>()
18680 : auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
18681 :
18682 : if (JSON_HEDLEY_LIKELY(ptr != nullptr))
18683 : {
18684 : return *ptr;
18685 : }
18686 :
18687 : JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj));
18688 : }
18689 :
18690 : public:
18691 : /// @name value access
18692 : /// Direct access to the stored value of a JSON value.
18693 : /// @{
18694 :
18695 : /// @brief get a pointer value (implicit)
18696 : /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
18697 : template<typename PointerType, typename std::enable_if<
18698 : std::is_pointer<PointerType>::value, int>::type = 0>
18699 : auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
18700 : {
18701 : // delegate the call to get_impl_ptr<>()
18702 : return get_impl_ptr(static_cast<PointerType>(nullptr));
18703 : }
18704 :
18705 : /// @brief get a pointer value (implicit)
18706 : /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
18707 : template < typename PointerType, typename std::enable_if <
18708 : std::is_pointer<PointerType>::value&&
18709 : std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
18710 : constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
18711 : {
18712 : // delegate the call to get_impl_ptr<>() const
18713 : return get_impl_ptr(static_cast<PointerType>(nullptr));
18714 : }
18715 :
18716 : private:
18717 : /*!
18718 : @brief get a value (explicit)
18719 :
18720 : Explicit type conversion between the JSON value and a compatible value
18721 : which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
18722 : and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
18723 : The value is converted by calling the @ref json_serializer<ValueType>
18724 : `from_json()` method.
18725 :
18726 : The function is equivalent to executing
18727 : @code {.cpp}
18728 : ValueType ret;
18729 : JSONSerializer<ValueType>::from_json(*this, ret);
18730 : return ret;
18731 : @endcode
18732 :
18733 : This overloads is chosen if:
18734 : - @a ValueType is not @ref basic_json,
18735 : - @ref json_serializer<ValueType> has a `from_json()` method of the form
18736 : `void from_json(const basic_json&, ValueType&)`, and
18737 : - @ref json_serializer<ValueType> does not have a `from_json()` method of
18738 : the form `ValueType from_json(const basic_json&)`
18739 :
18740 : @tparam ValueType the returned value type
18741 :
18742 : @return copy of the JSON value, converted to @a ValueType
18743 :
18744 : @throw what @ref json_serializer<ValueType> `from_json()` method throws
18745 :
18746 : @liveexample{The example below shows several conversions from JSON values
18747 : to other types. There a few things to note: (1) Floating-point numbers can
18748 : be converted to integers\, (2) A JSON array can be converted to a standard
18749 : `std::vector<short>`\, (3) A JSON object can be converted to C++
18750 : associative containers such as `std::unordered_map<std::string\,
18751 : json>`.,get__ValueType_const}
18752 :
18753 : @since version 2.1.0
18754 : */
18755 : template < typename ValueType,
18756 : detail::enable_if_t <
18757 : detail::is_default_constructible<ValueType>::value&&
18758 : detail::has_from_json<basic_json_t, ValueType>::value,
18759 : int > = 0 >
18760 56 : ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
18761 : JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
18762 : {
18763 2532 : auto ret = ValueType();
18764 : JSONSerializer<ValueType>::from_json(*this, ret);
18765 2532 : return ret;
18766 0 : }
18767 :
18768 : /*!
18769 : @brief get a value (explicit); special case
18770 :
18771 : Explicit type conversion between the JSON value and a compatible value
18772 : which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
18773 : and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
18774 : The value is converted by calling the @ref json_serializer<ValueType>
18775 : `from_json()` method.
18776 :
18777 : The function is equivalent to executing
18778 : @code {.cpp}
18779 : return JSONSerializer<ValueType>::from_json(*this);
18780 : @endcode
18781 :
18782 : This overloads is chosen if:
18783 : - @a ValueType is not @ref basic_json and
18784 : - @ref json_serializer<ValueType> has a `from_json()` method of the form
18785 : `ValueType from_json(const basic_json&)`
18786 :
18787 : @note If @ref json_serializer<ValueType> has both overloads of
18788 : `from_json()`, this one is chosen.
18789 :
18790 : @tparam ValueType the returned value type
18791 :
18792 : @return copy of the JSON value, converted to @a ValueType
18793 :
18794 : @throw what @ref json_serializer<ValueType> `from_json()` method throws
18795 :
18796 : @since version 2.1.0
18797 : */
18798 : template < typename ValueType,
18799 : detail::enable_if_t <
18800 : detail::has_non_default_from_json<basic_json_t, ValueType>::value,
18801 : int > = 0 >
18802 : ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
18803 : JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
18804 : {
18805 : return JSONSerializer<ValueType>::from_json(*this);
18806 : }
18807 :
18808 : /*!
18809 : @brief get special-case overload
18810 :
18811 : This overloads converts the current @ref basic_json in a different
18812 : @ref basic_json type
18813 :
18814 : @tparam BasicJsonType == @ref basic_json
18815 :
18816 : @return a copy of *this, converted into @a BasicJsonType
18817 :
18818 : @complexity Depending on the implementation of the called `from_json()`
18819 : method.
18820 :
18821 : @since version 3.2.0
18822 : */
18823 : template < typename BasicJsonType,
18824 : detail::enable_if_t <
18825 : detail::is_basic_json<BasicJsonType>::value,
18826 : int > = 0 >
18827 : BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
18828 : {
18829 : return *this;
18830 : }
18831 :
18832 : /*!
18833 : @brief get special-case overload
18834 :
18835 : This overloads avoids a lot of template boilerplate, it can be seen as the
18836 : identity method
18837 :
18838 : @tparam BasicJsonType == @ref basic_json
18839 :
18840 : @return a copy of *this
18841 :
18842 : @complexity Constant.
18843 :
18844 : @since version 2.1.0
18845 : */
18846 : template<typename BasicJsonType,
18847 : detail::enable_if_t<
18848 : std::is_same<BasicJsonType, basic_json_t>::value,
18849 : int> = 0>
18850 : basic_json get_impl(detail::priority_tag<3> /*unused*/) const
18851 : {
18852 : return *this;
18853 : }
18854 :
18855 : /*!
18856 : @brief get a pointer value (explicit)
18857 : @copydoc get()
18858 : */
18859 : template<typename PointerType,
18860 : detail::enable_if_t<
18861 : std::is_pointer<PointerType>::value,
18862 : int> = 0>
18863 : constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
18864 : -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
18865 : {
18866 : // delegate the call to get_ptr
18867 : return get_ptr<PointerType>();
18868 : }
18869 :
18870 : public:
18871 : /*!
18872 : @brief get a (pointer) value (explicit)
18873 :
18874 : Performs explicit type conversion between the JSON value and a compatible value if required.
18875 :
18876 : - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
18877 : No copies are made.
18878 :
18879 : - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
18880 : from the current @ref basic_json.
18881 :
18882 : - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
18883 : method.
18884 :
18885 : @tparam ValueTypeCV the provided value type
18886 : @tparam ValueType the returned value type
18887 :
18888 : @return copy of the JSON value, converted to @tparam ValueType if necessary
18889 :
18890 : @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
18891 :
18892 : @since version 2.1.0
18893 : */
18894 : template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
18895 : #if defined(JSON_HAS_CPP_14)
18896 : constexpr
18897 : #endif
18898 236 : auto get() const noexcept(
18899 : noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
18900 : -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
18901 : {
18902 : // we cannot static_assert on ValueTypeCV being non-const, because
18903 : // there is support for get<const basic_json_t>(), which is why we
18904 : // still need the uncvref
18905 : static_assert(!std::is_reference<ValueTypeCV>::value,
18906 : "get() cannot be used with reference types, you might want to use get_ref()");
18907 292 : return get_impl<ValueType>(detail::priority_tag<4> {});
18908 : }
18909 :
18910 : /*!
18911 : @brief get a pointer value (explicit)
18912 :
18913 : Explicit pointer access to the internally stored JSON value. No copies are
18914 : made.
18915 :
18916 : @warning The pointer becomes invalid if the underlying JSON object
18917 : changes.
18918 :
18919 : @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
18920 : object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
18921 : @ref number_unsigned_t, or @ref number_float_t.
18922 :
18923 : @return pointer to the internally stored JSON value if the requested
18924 : pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
18925 :
18926 : @complexity Constant.
18927 :
18928 : @liveexample{The example below shows how pointers to internal values of a
18929 : JSON value can be requested. Note that no type conversions are made and a
18930 : `nullptr` is returned if the value and the requested pointer type does not
18931 : match.,get__PointerType}
18932 :
18933 : @sa see @ref get_ptr() for explicit pointer-member access
18934 :
18935 : @since version 1.0.0
18936 : */
18937 : template<typename PointerType, typename std::enable_if<
18938 : std::is_pointer<PointerType>::value, int>::type = 0>
18939 : auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
18940 : {
18941 : // delegate the call to get_ptr
18942 : return get_ptr<PointerType>();
18943 : }
18944 :
18945 : /// @brief get a value (explicit)
18946 : /// @sa https://json.nlohmann.me/api/basic_json/get_to/
18947 : template < typename ValueType,
18948 : detail::enable_if_t <
18949 : !detail::is_basic_json<ValueType>::value&&
18950 : detail::has_from_json<basic_json_t, ValueType>::value,
18951 : int > = 0 >
18952 : ValueType & get_to(ValueType& v) const noexcept(noexcept(
18953 : JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
18954 : {
18955 : JSONSerializer<ValueType>::from_json(*this, v);
18956 : return v;
18957 : }
18958 :
18959 : // specialization to allow calling get_to with a basic_json value
18960 : // see https://github.com/nlohmann/json/issues/2175
18961 : template<typename ValueType,
18962 : detail::enable_if_t <
18963 : detail::is_basic_json<ValueType>::value,
18964 : int> = 0>
18965 : ValueType & get_to(ValueType& v) const
18966 : {
18967 : v = *this;
18968 : return v;
18969 : }
18970 :
18971 : template <
18972 : typename T, std::size_t N,
18973 : typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
18974 : detail::enable_if_t <
18975 : detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
18976 : Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
18977 : noexcept(noexcept(JSONSerializer<Array>::from_json(
18978 : std::declval<const basic_json_t&>(), v)))
18979 : {
18980 : JSONSerializer<Array>::from_json(*this, v);
18981 : return v;
18982 : }
18983 :
18984 : /// @brief get a reference value (implicit)
18985 : /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
18986 : template<typename ReferenceType, typename std::enable_if<
18987 : std::is_reference<ReferenceType>::value, int>::type = 0>
18988 : ReferenceType get_ref()
18989 : {
18990 : // delegate call to get_ref_impl
18991 : return get_ref_impl<ReferenceType>(*this);
18992 : }
18993 :
18994 : /// @brief get a reference value (implicit)
18995 : /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
18996 : template < typename ReferenceType, typename std::enable_if <
18997 : std::is_reference<ReferenceType>::value&&
18998 : std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
18999 : ReferenceType get_ref() const
19000 : {
19001 : // delegate call to get_ref_impl
19002 : return get_ref_impl<ReferenceType>(*this);
19003 : }
19004 :
19005 : /*!
19006 : @brief get a value (implicit)
19007 :
19008 : Implicit type conversion between the JSON value and a compatible value.
19009 : The call is realized by calling @ref get() const.
19010 :
19011 : @tparam ValueType non-pointer type compatible to the JSON value, for
19012 : instance `int` for JSON integer numbers, `bool` for JSON booleans, or
19013 : `std::vector` types for JSON arrays. The character type of @ref string_t
19014 : as well as an initializer list of this type is excluded to avoid
19015 : ambiguities as these types implicitly convert to `std::string`.
19016 :
19017 : @return copy of the JSON value, converted to type @a ValueType
19018 :
19019 : @throw type_error.302 in case passed type @a ValueType is incompatible
19020 : to the JSON value type (e.g., the JSON value is of type boolean, but a
19021 : string is requested); see example below
19022 :
19023 : @complexity Linear in the size of the JSON value.
19024 :
19025 : @liveexample{The example below shows several conversions from JSON values
19026 : to other types. There a few things to note: (1) Floating-point numbers can
19027 : be converted to integers\, (2) A JSON array can be converted to a standard
19028 : `std::vector<short>`\, (3) A JSON object can be converted to C++
19029 : associative containers such as `std::unordered_map<std::string\,
19030 : json>`.,operator__ValueType}
19031 :
19032 : @since version 1.0.0
19033 : */
19034 : template < typename ValueType, typename std::enable_if <
19035 : detail::conjunction <
19036 : detail::negation<std::is_pointer<ValueType>>,
19037 : detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
19038 : detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
19039 : detail::negation<detail::is_basic_json<ValueType>>,
19040 : detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
19041 :
19042 : #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
19043 : detail::negation<std::is_same<ValueType, std::string_view>>,
19044 : #endif
19045 : detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
19046 : >::value, int >::type = 0 >
19047 : JSON_EXPLICIT operator ValueType() const
19048 : {
19049 : // delegate the call to get<>() const
19050 12 : return get<ValueType>();
19051 : }
19052 :
19053 : /// @brief get a binary value
19054 : /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
19055 : binary_t& get_binary()
19056 : {
19057 : if (!is_binary())
19058 : {
19059 : JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
19060 : }
19061 :
19062 : return *get_ptr<binary_t*>();
19063 : }
19064 :
19065 : /// @brief get a binary value
19066 : /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
19067 : const binary_t& get_binary() const
19068 : {
19069 : if (!is_binary())
19070 : {
19071 : JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
19072 : }
19073 :
19074 : return *get_ptr<const binary_t*>();
19075 : }
19076 :
19077 : /// @}
19078 :
19079 :
19080 : ////////////////////
19081 : // element access //
19082 : ////////////////////
19083 :
19084 : /// @name element access
19085 : /// Access to the JSON value.
19086 : /// @{
19087 :
19088 : /// @brief access specified array element with bounds checking
19089 : /// @sa https://json.nlohmann.me/api/basic_json/at/
19090 : reference at(size_type idx)
19091 : {
19092 : // at only works for arrays
19093 : if (JSON_HEDLEY_LIKELY(is_array()))
19094 : {
19095 : JSON_TRY
19096 : {
19097 : return set_parent(m_value.array->at(idx));
19098 : }
19099 : JSON_CATCH (std::out_of_range&)
19100 : {
19101 : // create better exception explanation
19102 : JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
19103 : }
19104 : }
19105 : else
19106 : {
19107 : JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
19108 : }
19109 : }
19110 :
19111 : /// @brief access specified array element with bounds checking
19112 : /// @sa https://json.nlohmann.me/api/basic_json/at/
19113 : const_reference at(size_type idx) const
19114 : {
19115 : // at only works for arrays
19116 : if (JSON_HEDLEY_LIKELY(is_array()))
19117 : {
19118 : JSON_TRY
19119 : {
19120 : return m_value.array->at(idx);
19121 : }
19122 : JSON_CATCH (std::out_of_range&)
19123 : {
19124 : // create better exception explanation
19125 : JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
19126 : }
19127 : }
19128 : else
19129 : {
19130 : JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
19131 : }
19132 : }
19133 :
19134 : /// @brief access specified object element with bounds checking
19135 : /// @sa https://json.nlohmann.me/api/basic_json/at/
19136 108 : reference at(const typename object_t::key_type& key)
19137 : {
19138 : // at only works for objects
19139 108 : if (JSON_HEDLEY_LIKELY(is_object()))
19140 : {
19141 : JSON_TRY
19142 : {
19143 108 : return set_parent(m_value.object->at(key));
19144 : }
19145 0 : JSON_CATCH (std::out_of_range&)
19146 : {
19147 : // create better exception explanation
19148 0 : JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
19149 : }
19150 : }
19151 : else
19152 : {
19153 0 : JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
19154 : }
19155 : }
19156 :
19157 : /// @brief access specified object element with bounds checking
19158 : /// @sa https://json.nlohmann.me/api/basic_json/at/
19159 676 : const_reference at(const typename object_t::key_type& key) const
19160 : {
19161 : // at only works for objects
19162 676 : if (JSON_HEDLEY_LIKELY(is_object()))
19163 : {
19164 : JSON_TRY
19165 : {
19166 676 : return m_value.object->at(key);
19167 : }
19168 0 : JSON_CATCH (std::out_of_range&)
19169 : {
19170 : // create better exception explanation
19171 0 : JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
19172 : }
19173 : }
19174 : else
19175 : {
19176 0 : JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
19177 : }
19178 : }
19179 :
19180 : /// @brief access specified array element
19181 : /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19182 : reference operator[](size_type idx)
19183 : {
19184 : // implicitly convert null value to an empty array
19185 : if (is_null())
19186 : {
19187 : m_type = value_t::array;
19188 : m_value.array = create<array_t>();
19189 : assert_invariant();
19190 : }
19191 :
19192 : // operator[] only works for arrays
19193 : if (JSON_HEDLEY_LIKELY(is_array()))
19194 : {
19195 : // fill up array with null values if given idx is outside range
19196 : if (idx >= m_value.array->size())
19197 : {
19198 : #if JSON_DIAGNOSTICS
19199 : // remember array size & capacity before resizing
19200 : const auto old_size = m_value.array->size();
19201 : const auto old_capacity = m_value.array->capacity();
19202 : #endif
19203 : m_value.array->resize(idx + 1);
19204 :
19205 : #if JSON_DIAGNOSTICS
19206 : if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
19207 : {
19208 : // capacity has changed: update all parents
19209 : set_parents();
19210 : }
19211 : else
19212 : {
19213 : // set parent for values added above
19214 : set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
19215 : }
19216 : #endif
19217 : assert_invariant();
19218 : }
19219 :
19220 : return m_value.array->operator[](idx);
19221 : }
19222 :
19223 : JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
19224 : }
19225 :
19226 : /// @brief access specified array element
19227 : /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19228 2 : const_reference operator[](size_type idx) const
19229 : {
19230 : // const operator[] only works for arrays
19231 2 : if (JSON_HEDLEY_LIKELY(is_array()))
19232 : {
19233 2 : return m_value.array->operator[](idx);
19234 : }
19235 :
19236 0 : JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
19237 : }
19238 :
19239 : /// @brief access specified object element
19240 : /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19241 : reference operator[](const typename object_t::key_type& key)
19242 : {
19243 : // implicitly convert null value to an empty object
19244 : if (is_null())
19245 : {
19246 : m_type = value_t::object;
19247 : m_value.object = create<object_t>();
19248 : assert_invariant();
19249 : }
19250 :
19251 : // operator[] only works for objects
19252 : if (JSON_HEDLEY_LIKELY(is_object()))
19253 : {
19254 : return set_parent(m_value.object->operator[](key));
19255 : }
19256 :
19257 : JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
19258 : }
19259 :
19260 : /// @brief access specified object element
19261 : /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19262 : const_reference operator[](const typename object_t::key_type& key) const
19263 : {
19264 : // const operator[] only works for objects
19265 : if (JSON_HEDLEY_LIKELY(is_object()))
19266 : {
19267 : JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
19268 : return m_value.object->find(key)->second;
19269 : }
19270 :
19271 : JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
19272 : }
19273 :
19274 : /// @brief access specified object element
19275 : /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19276 : template<typename T>
19277 : JSON_HEDLEY_NON_NULL(2)
19278 56 : reference operator[](T* key)
19279 : {
19280 : // implicitly convert null to object
19281 56 : if (is_null())
19282 : {
19283 0 : m_type = value_t::object;
19284 0 : m_value = value_t::object;
19285 : assert_invariant();
19286 : }
19287 :
19288 : // at only works for objects
19289 56 : if (JSON_HEDLEY_LIKELY(is_object()))
19290 : {
19291 112 : return set_parent(m_value.object->operator[](key));
19292 : }
19293 :
19294 0 : JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
19295 : }
19296 :
19297 : /// @brief access specified object element
19298 : /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19299 : template<typename T>
19300 : JSON_HEDLEY_NON_NULL(2)
19301 : const_reference operator[](T* key) const
19302 : {
19303 : // at only works for objects
19304 : if (JSON_HEDLEY_LIKELY(is_object()))
19305 : {
19306 : JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
19307 : return m_value.object->find(key)->second;
19308 : }
19309 :
19310 : JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
19311 : }
19312 :
19313 : /// @brief access specified object element with default value
19314 : /// @sa https://json.nlohmann.me/api/basic_json/value/
19315 : /// using std::is_convertible in a std::enable_if will fail when using explicit conversions
19316 : template < class ValueType, typename std::enable_if <
19317 : detail::is_getable<basic_json_t, ValueType>::value
19318 : && !std::is_same<value_t, ValueType>::value, int >::type = 0 >
19319 : ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
19320 : {
19321 : // at only works for objects
19322 : if (JSON_HEDLEY_LIKELY(is_object()))
19323 : {
19324 : // if key is found, return value and given default value otherwise
19325 : const auto it = find(key);
19326 : if (it != end())
19327 : {
19328 : return it->template get<ValueType>();
19329 : }
19330 :
19331 : return default_value;
19332 : }
19333 :
19334 : JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
19335 : }
19336 :
19337 : /// @brief access specified object element with default value
19338 : /// @sa https://json.nlohmann.me/api/basic_json/value/
19339 : /// overload for a default value of type const char*
19340 : string_t value(const typename object_t::key_type& key, const char* default_value) const
19341 : {
19342 : return value(key, string_t(default_value));
19343 : }
19344 :
19345 : /// @brief access specified object element via JSON Pointer with default value
19346 : /// @sa https://json.nlohmann.me/api/basic_json/value/
19347 : template<class ValueType, typename std::enable_if<
19348 : detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
19349 : ValueType value(const json_pointer& ptr, const ValueType& default_value) const
19350 : {
19351 : // at only works for objects
19352 : if (JSON_HEDLEY_LIKELY(is_object()))
19353 : {
19354 : // if pointer resolves a value, return it or use default value
19355 : JSON_TRY
19356 : {
19357 : return ptr.get_checked(this).template get<ValueType>();
19358 : }
19359 : JSON_INTERNAL_CATCH (out_of_range&)
19360 : {
19361 : return default_value;
19362 : }
19363 : }
19364 :
19365 : JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
19366 : }
19367 :
19368 : /// @brief access specified object element via JSON Pointer with default value
19369 : /// @sa https://json.nlohmann.me/api/basic_json/value/
19370 : /// overload for a default value of type const char*
19371 : JSON_HEDLEY_NON_NULL(3)
19372 : string_t value(const json_pointer& ptr, const char* default_value) const
19373 : {
19374 : return value(ptr, string_t(default_value));
19375 : }
19376 :
19377 : /// @brief access the first element
19378 : /// @sa https://json.nlohmann.me/api/basic_json/front/
19379 : reference front()
19380 : {
19381 : return *begin();
19382 : }
19383 :
19384 : /// @brief access the first element
19385 : /// @sa https://json.nlohmann.me/api/basic_json/front/
19386 : const_reference front() const
19387 : {
19388 : return *cbegin();
19389 : }
19390 :
19391 : /// @brief access the last element
19392 : /// @sa https://json.nlohmann.me/api/basic_json/back/
19393 : reference back()
19394 : {
19395 : auto tmp = end();
19396 : --tmp;
19397 : return *tmp;
19398 : }
19399 :
19400 : /// @brief access the last element
19401 : /// @sa https://json.nlohmann.me/api/basic_json/back/
19402 : const_reference back() const
19403 : {
19404 : auto tmp = cend();
19405 : --tmp;
19406 : return *tmp;
19407 : }
19408 :
19409 : /// @brief remove element given an iterator
19410 : /// @sa https://json.nlohmann.me/api/basic_json/erase/
19411 : template < class IteratorType, typename std::enable_if <
19412 : std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
19413 : std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
19414 : = 0 >
19415 0 : IteratorType erase(IteratorType pos)
19416 : {
19417 : // make sure iterator fits the current value
19418 0 : if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
19419 : {
19420 0 : JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
19421 : }
19422 :
19423 0 : IteratorType result = end();
19424 :
19425 0 : switch (m_type)
19426 : {
19427 0 : case value_t::boolean:
19428 : case value_t::number_float:
19429 : case value_t::number_integer:
19430 : case value_t::number_unsigned:
19431 : case value_t::string:
19432 : case value_t::binary:
19433 : {
19434 0 : if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
19435 : {
19436 0 : JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this));
19437 : }
19438 :
19439 0 : if (is_string())
19440 : {
19441 : AllocatorType<string_t> alloc;
19442 0 : std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
19443 0 : std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
19444 0 : m_value.string = nullptr;
19445 : }
19446 0 : else if (is_binary())
19447 : {
19448 : AllocatorType<binary_t> alloc;
19449 0 : std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
19450 0 : std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
19451 0 : m_value.binary = nullptr;
19452 : }
19453 :
19454 0 : m_type = value_t::null;
19455 : assert_invariant();
19456 : break;
19457 : }
19458 :
19459 0 : case value_t::object:
19460 : {
19461 0 : result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
19462 0 : break;
19463 : }
19464 :
19465 0 : case value_t::array:
19466 : {
19467 0 : result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
19468 0 : break;
19469 : }
19470 :
19471 0 : case value_t::null:
19472 : case value_t::discarded:
19473 : default:
19474 0 : JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
19475 : }
19476 :
19477 0 : return result;
19478 : }
19479 :
19480 : /// @brief remove elements given an iterator range
19481 : /// @sa https://json.nlohmann.me/api/basic_json/erase/
19482 : template < class IteratorType, typename std::enable_if <
19483 : std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
19484 : std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
19485 : = 0 >
19486 : IteratorType erase(IteratorType first, IteratorType last)
19487 : {
19488 : // make sure iterator fits the current value
19489 : if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
19490 : {
19491 : JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this));
19492 : }
19493 :
19494 : IteratorType result = end();
19495 :
19496 : switch (m_type)
19497 : {
19498 : case value_t::boolean:
19499 : case value_t::number_float:
19500 : case value_t::number_integer:
19501 : case value_t::number_unsigned:
19502 : case value_t::string:
19503 : case value_t::binary:
19504 : {
19505 : if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
19506 : || !last.m_it.primitive_iterator.is_end()))
19507 : {
19508 : JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this));
19509 : }
19510 :
19511 : if (is_string())
19512 : {
19513 : AllocatorType<string_t> alloc;
19514 : std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
19515 : std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
19516 : m_value.string = nullptr;
19517 : }
19518 : else if (is_binary())
19519 : {
19520 : AllocatorType<binary_t> alloc;
19521 : std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
19522 : std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
19523 : m_value.binary = nullptr;
19524 : }
19525 :
19526 : m_type = value_t::null;
19527 : assert_invariant();
19528 : break;
19529 : }
19530 :
19531 : case value_t::object:
19532 : {
19533 : result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
19534 : last.m_it.object_iterator);
19535 : break;
19536 : }
19537 :
19538 : case value_t::array:
19539 : {
19540 : result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
19541 : last.m_it.array_iterator);
19542 : break;
19543 : }
19544 :
19545 : case value_t::null:
19546 : case value_t::discarded:
19547 : default:
19548 : JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
19549 : }
19550 :
19551 : return result;
19552 : }
19553 :
19554 : /// @brief remove element from a JSON object given a key
19555 : /// @sa https://json.nlohmann.me/api/basic_json/erase/
19556 : size_type erase(const typename object_t::key_type& key)
19557 : {
19558 : // this erase only works for objects
19559 : if (JSON_HEDLEY_LIKELY(is_object()))
19560 : {
19561 : return m_value.object->erase(key);
19562 : }
19563 :
19564 : JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
19565 : }
19566 :
19567 : /// @brief remove element from a JSON array given an index
19568 : /// @sa https://json.nlohmann.me/api/basic_json/erase/
19569 : void erase(const size_type idx)
19570 : {
19571 : // this erase only works for arrays
19572 : if (JSON_HEDLEY_LIKELY(is_array()))
19573 : {
19574 : if (JSON_HEDLEY_UNLIKELY(idx >= size()))
19575 : {
19576 : JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
19577 : }
19578 :
19579 : m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
19580 : }
19581 : else
19582 : {
19583 : JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
19584 : }
19585 : }
19586 :
19587 : /// @}
19588 :
19589 :
19590 : ////////////
19591 : // lookup //
19592 : ////////////
19593 :
19594 : /// @name lookup
19595 : /// @{
19596 :
19597 : /// @brief find an element in a JSON object
19598 : /// @sa https://json.nlohmann.me/api/basic_json/find/
19599 : template<typename KeyT>
19600 224 : iterator find(KeyT&& key)
19601 : {
19602 224 : auto result = end();
19603 :
19604 224 : if (is_object())
19605 : {
19606 224 : result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
19607 : }
19608 :
19609 224 : return result;
19610 : }
19611 :
19612 : /// @brief find an element in a JSON object
19613 : /// @sa https://json.nlohmann.me/api/basic_json/find/
19614 : template<typename KeyT>
19615 : const_iterator find(KeyT&& key) const
19616 : {
19617 : auto result = cend();
19618 :
19619 : if (is_object())
19620 : {
19621 : result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
19622 : }
19623 :
19624 : return result;
19625 : }
19626 :
19627 : /// @brief returns the number of occurrences of a key in a JSON object
19628 : /// @sa https://json.nlohmann.me/api/basic_json/count/
19629 : template<typename KeyT>
19630 : size_type count(KeyT&& key) const
19631 : {
19632 : // return 0 for all nonobject types
19633 : return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
19634 : }
19635 :
19636 : /// @brief check the existence of an element in a JSON object
19637 : /// @sa https://json.nlohmann.me/api/basic_json/contains/
19638 : template < typename KeyT, typename std::enable_if <
19639 : !std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int >::type = 0 >
19640 : bool contains(KeyT && key) const
19641 : {
19642 944 : return is_object() && m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
19643 : }
19644 :
19645 : /// @brief check the existence of an element in a JSON object given a JSON pointer
19646 : /// @sa https://json.nlohmann.me/api/basic_json/contains/
19647 : bool contains(const json_pointer& ptr) const
19648 : {
19649 : return ptr.contains(this);
19650 : }
19651 :
19652 : /// @}
19653 :
19654 :
19655 : ///////////////
19656 : // iterators //
19657 : ///////////////
19658 :
19659 : /// @name iterators
19660 : /// @{
19661 :
19662 : /// @brief returns an iterator to the first element
19663 : /// @sa https://json.nlohmann.me/api/basic_json/begin/
19664 2 : iterator begin() noexcept
19665 : {
19666 : iterator result(this);
19667 : result.set_begin();
19668 2 : return result;
19669 : }
19670 :
19671 : /// @brief returns an iterator to the first element
19672 : /// @sa https://json.nlohmann.me/api/basic_json/begin/
19673 : const_iterator begin() const noexcept
19674 : {
19675 152 : return cbegin();
19676 : }
19677 :
19678 : /// @brief returns a const iterator to the first element
19679 : /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
19680 152 : const_iterator cbegin() const noexcept
19681 : {
19682 : const_iterator result(this);
19683 : result.set_begin();
19684 152 : return result;
19685 : }
19686 :
19687 : /// @brief returns an iterator to one past the last element
19688 : /// @sa https://json.nlohmann.me/api/basic_json/end/
19689 450 : iterator end() noexcept
19690 : {
19691 : iterator result(this);
19692 : result.set_end();
19693 450 : return result;
19694 : }
19695 :
19696 : /// @brief returns an iterator to one past the last element
19697 : /// @sa https://json.nlohmann.me/api/basic_json/end/
19698 : const_iterator end() const noexcept
19699 : {
19700 152 : return cend();
19701 : }
19702 :
19703 : /// @brief returns an iterator to one past the last element
19704 : /// @sa https://json.nlohmann.me/api/basic_json/cend/
19705 152 : const_iterator cend() const noexcept
19706 : {
19707 : const_iterator result(this);
19708 : result.set_end();
19709 152 : return result;
19710 : }
19711 :
19712 : /// @brief returns an iterator to the reverse-beginning
19713 : /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
19714 : reverse_iterator rbegin() noexcept
19715 : {
19716 : return reverse_iterator(end());
19717 : }
19718 :
19719 : /// @brief returns an iterator to the reverse-beginning
19720 : /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
19721 : const_reverse_iterator rbegin() const noexcept
19722 : {
19723 : return crbegin();
19724 : }
19725 :
19726 : /// @brief returns an iterator to the reverse-end
19727 : /// @sa https://json.nlohmann.me/api/basic_json/rend/
19728 : reverse_iterator rend() noexcept
19729 : {
19730 : return reverse_iterator(begin());
19731 : }
19732 :
19733 : /// @brief returns an iterator to the reverse-end
19734 : /// @sa https://json.nlohmann.me/api/basic_json/rend/
19735 : const_reverse_iterator rend() const noexcept
19736 : {
19737 : return crend();
19738 : }
19739 :
19740 : /// @brief returns a const reverse iterator to the last element
19741 : /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
19742 : const_reverse_iterator crbegin() const noexcept
19743 : {
19744 : return const_reverse_iterator(cend());
19745 : }
19746 :
19747 : /// @brief returns a const reverse iterator to one before the first
19748 : /// @sa https://json.nlohmann.me/api/basic_json/crend/
19749 : const_reverse_iterator crend() const noexcept
19750 : {
19751 : return const_reverse_iterator(cbegin());
19752 : }
19753 :
19754 : public:
19755 : /// @brief wrapper to access iterator member functions in range-based for
19756 : /// @sa https://json.nlohmann.me/api/basic_json/items/
19757 : /// @deprecated This function is deprecated since 3.1.0 and will be removed in
19758 : /// version 4.0.0 of the library. Please use @ref items() instead;
19759 : /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
19760 : JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
19761 : static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
19762 : {
19763 : return ref.items();
19764 : }
19765 :
19766 : /// @brief wrapper to access iterator member functions in range-based for
19767 : /// @sa https://json.nlohmann.me/api/basic_json/items/
19768 : /// @deprecated This function is deprecated since 3.1.0 and will be removed in
19769 : /// version 4.0.0 of the library. Please use @ref items() instead;
19770 : /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
19771 : JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
19772 : static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
19773 : {
19774 : return ref.items();
19775 : }
19776 :
19777 : /// @brief helper to access iterator member functions in range-based for
19778 : /// @sa https://json.nlohmann.me/api/basic_json/items/
19779 : iteration_proxy<iterator> items() noexcept
19780 : {
19781 : return iteration_proxy<iterator>(*this);
19782 : }
19783 :
19784 : /// @brief helper to access iterator member functions in range-based for
19785 : /// @sa https://json.nlohmann.me/api/basic_json/items/
19786 : iteration_proxy<const_iterator> items() const noexcept
19787 : {
19788 : return iteration_proxy<const_iterator>(*this);
19789 : }
19790 :
19791 : /// @}
19792 :
19793 :
19794 : //////////////
19795 : // capacity //
19796 : //////////////
19797 :
19798 : /// @name capacity
19799 : /// @{
19800 :
19801 : /// @brief checks whether the container is empty.
19802 : /// @sa https://json.nlohmann.me/api/basic_json/empty/
19803 : bool empty() const noexcept
19804 : {
19805 : switch (m_type)
19806 : {
19807 : case value_t::null:
19808 : {
19809 : // null values are empty
19810 : return true;
19811 : }
19812 :
19813 : case value_t::array:
19814 : {
19815 : // delegate call to array_t::empty()
19816 : return m_value.array->empty();
19817 : }
19818 :
19819 : case value_t::object:
19820 : {
19821 : // delegate call to object_t::empty()
19822 : return m_value.object->empty();
19823 : }
19824 :
19825 : case value_t::string:
19826 : case value_t::boolean:
19827 : case value_t::number_integer:
19828 : case value_t::number_unsigned:
19829 : case value_t::number_float:
19830 : case value_t::binary:
19831 : case value_t::discarded:
19832 : default:
19833 : {
19834 : // all other types are nonempty
19835 : return false;
19836 : }
19837 : }
19838 : }
19839 :
19840 : /// @brief returns the number of elements
19841 : /// @sa https://json.nlohmann.me/api/basic_json/size/
19842 : size_type size() const noexcept
19843 : {
19844 152 : switch (m_type)
19845 : {
19846 : case value_t::null:
19847 : {
19848 : // null values are empty
19849 : return 0;
19850 : }
19851 :
19852 152 : case value_t::array:
19853 : {
19854 : // delegate call to array_t::size()
19855 152 : return m_value.array->size();
19856 : }
19857 :
19858 0 : case value_t::object:
19859 : {
19860 : // delegate call to object_t::size()
19861 0 : return m_value.object->size();
19862 : }
19863 :
19864 0 : case value_t::string:
19865 : case value_t::boolean:
19866 : case value_t::number_integer:
19867 : case value_t::number_unsigned:
19868 : case value_t::number_float:
19869 : case value_t::binary:
19870 : case value_t::discarded:
19871 : default:
19872 : {
19873 : // all other types have size 1
19874 0 : return 1;
19875 : }
19876 : }
19877 : }
19878 :
19879 : /// @brief returns the maximum possible number of elements
19880 : /// @sa https://json.nlohmann.me/api/basic_json/max_size/
19881 : size_type max_size() const noexcept
19882 : {
19883 0 : switch (m_type)
19884 : {
19885 : case value_t::array:
19886 : {
19887 : // delegate call to array_t::max_size()
19888 : return m_value.array->max_size();
19889 : }
19890 :
19891 0 : case value_t::object:
19892 : {
19893 : // delegate call to object_t::max_size()
19894 0 : return m_value.object->max_size();
19895 : }
19896 :
19897 : case value_t::null:
19898 : case value_t::string:
19899 : case value_t::boolean:
19900 : case value_t::number_integer:
19901 : case value_t::number_unsigned:
19902 : case value_t::number_float:
19903 : case value_t::binary:
19904 : case value_t::discarded:
19905 : default:
19906 : {
19907 : // all other types have max_size() == size()
19908 : return size();
19909 : }
19910 : }
19911 : }
19912 :
19913 : /// @}
19914 :
19915 :
19916 : ///////////////
19917 : // modifiers //
19918 : ///////////////
19919 :
19920 : /// @name modifiers
19921 : /// @{
19922 :
19923 : /// @brief clears the contents
19924 : /// @sa https://json.nlohmann.me/api/basic_json/clear/
19925 : void clear() noexcept
19926 : {
19927 : switch (m_type)
19928 : {
19929 : case value_t::number_integer:
19930 : {
19931 : m_value.number_integer = 0;
19932 : break;
19933 : }
19934 :
19935 : case value_t::number_unsigned:
19936 : {
19937 : m_value.number_unsigned = 0;
19938 : break;
19939 : }
19940 :
19941 : case value_t::number_float:
19942 : {
19943 : m_value.number_float = 0.0;
19944 : break;
19945 : }
19946 :
19947 : case value_t::boolean:
19948 : {
19949 : m_value.boolean = false;
19950 : break;
19951 : }
19952 :
19953 : case value_t::string:
19954 : {
19955 : m_value.string->clear();
19956 : break;
19957 : }
19958 :
19959 : case value_t::binary:
19960 : {
19961 : m_value.binary->clear();
19962 : break;
19963 : }
19964 :
19965 : case value_t::array:
19966 : {
19967 : m_value.array->clear();
19968 : break;
19969 : }
19970 :
19971 : case value_t::object:
19972 : {
19973 : m_value.object->clear();
19974 : break;
19975 : }
19976 :
19977 : case value_t::null:
19978 : case value_t::discarded:
19979 : default:
19980 : break;
19981 : }
19982 : }
19983 :
19984 : /// @brief add an object to an array
19985 : /// @sa https://json.nlohmann.me/api/basic_json/push_back/
19986 : void push_back(basic_json&& val)
19987 : {
19988 : // push_back only works for null objects or arrays
19989 : if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
19990 : {
19991 : JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
19992 : }
19993 :
19994 : // transform null object into an array
19995 : if (is_null())
19996 : {
19997 : m_type = value_t::array;
19998 : m_value = value_t::array;
19999 : assert_invariant();
20000 : }
20001 :
20002 : // add element to array (move semantics)
20003 : const auto old_capacity = m_value.array->capacity();
20004 : m_value.array->push_back(std::move(val));
20005 : set_parent(m_value.array->back(), old_capacity);
20006 : // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
20007 : }
20008 :
20009 : /// @brief add an object to an array
20010 : /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
20011 : reference operator+=(basic_json&& val)
20012 : {
20013 : push_back(std::move(val));
20014 : return *this;
20015 : }
20016 :
20017 : /// @brief add an object to an array
20018 : /// @sa https://json.nlohmann.me/api/basic_json/push_back/
20019 : void push_back(const basic_json& val)
20020 : {
20021 : // push_back only works for null objects or arrays
20022 : if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
20023 : {
20024 : JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
20025 : }
20026 :
20027 : // transform null object into an array
20028 : if (is_null())
20029 : {
20030 : m_type = value_t::array;
20031 : m_value = value_t::array;
20032 : assert_invariant();
20033 : }
20034 :
20035 : // add element to array
20036 : const auto old_capacity = m_value.array->capacity();
20037 : m_value.array->push_back(val);
20038 : set_parent(m_value.array->back(), old_capacity);
20039 : }
20040 :
20041 : /// @brief add an object to an array
20042 : /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
20043 : reference operator+=(const basic_json& val)
20044 : {
20045 : push_back(val);
20046 : return *this;
20047 : }
20048 :
20049 : /// @brief add an object to an object
20050 : /// @sa https://json.nlohmann.me/api/basic_json/push_back/
20051 : void push_back(const typename object_t::value_type& val)
20052 : {
20053 : // push_back only works for null objects or objects
20054 : if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
20055 : {
20056 : JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
20057 : }
20058 :
20059 : // transform null object into an object
20060 : if (is_null())
20061 : {
20062 : m_type = value_t::object;
20063 : m_value = value_t::object;
20064 : assert_invariant();
20065 : }
20066 :
20067 : // add element to object
20068 : auto res = m_value.object->insert(val);
20069 : set_parent(res.first->second);
20070 : }
20071 :
20072 : /// @brief add an object to an object
20073 : /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
20074 : reference operator+=(const typename object_t::value_type& val)
20075 : {
20076 : push_back(val);
20077 : return *this;
20078 : }
20079 :
20080 : /// @brief add an object to an object
20081 : /// @sa https://json.nlohmann.me/api/basic_json/push_back/
20082 : void push_back(initializer_list_t init)
20083 : {
20084 : if (is_object() && init.size() == 2 && (*init.begin())->is_string())
20085 : {
20086 : basic_json&& key = init.begin()->moved_or_copied();
20087 : push_back(typename object_t::value_type(
20088 : std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
20089 : }
20090 : else
20091 : {
20092 : push_back(basic_json(init));
20093 : }
20094 : }
20095 :
20096 : /// @brief add an object to an object
20097 : /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
20098 : reference operator+=(initializer_list_t init)
20099 : {
20100 : push_back(init);
20101 : return *this;
20102 : }
20103 :
20104 : /// @brief add an object to an array
20105 : /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
20106 : template<class... Args>
20107 : reference emplace_back(Args&& ... args)
20108 : {
20109 : // emplace_back only works for null objects or arrays
20110 : if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
20111 : {
20112 : JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this));
20113 : }
20114 :
20115 : // transform null object into an array
20116 : if (is_null())
20117 : {
20118 : m_type = value_t::array;
20119 : m_value = value_t::array;
20120 : assert_invariant();
20121 : }
20122 :
20123 : // add element to array (perfect forwarding)
20124 : const auto old_capacity = m_value.array->capacity();
20125 : m_value.array->emplace_back(std::forward<Args>(args)...);
20126 : return set_parent(m_value.array->back(), old_capacity);
20127 : }
20128 :
20129 : /// @brief add an object to an object if key does not exist
20130 : /// @sa https://json.nlohmann.me/api/basic_json/emplace/
20131 : template<class... Args>
20132 : std::pair<iterator, bool> emplace(Args&& ... args)
20133 : {
20134 : // emplace only works for null objects or arrays
20135 : if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
20136 : {
20137 : JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this));
20138 : }
20139 :
20140 : // transform null object into an object
20141 : if (is_null())
20142 : {
20143 : m_type = value_t::object;
20144 : m_value = value_t::object;
20145 : assert_invariant();
20146 : }
20147 :
20148 : // add element to array (perfect forwarding)
20149 : auto res = m_value.object->emplace(std::forward<Args>(args)...);
20150 : set_parent(res.first->second);
20151 :
20152 : // create result iterator and set iterator to the result of emplace
20153 : auto it = begin();
20154 : it.m_it.object_iterator = res.first;
20155 :
20156 : // return pair of iterator and boolean
20157 : return {it, res.second};
20158 : }
20159 :
20160 : /// Helper for insertion of an iterator
20161 : /// @note: This uses std::distance to support GCC 4.8,
20162 : /// see https://github.com/nlohmann/json/pull/1257
20163 : template<typename... Args>
20164 : iterator insert_iterator(const_iterator pos, Args&& ... args)
20165 : {
20166 : iterator result(this);
20167 : JSON_ASSERT(m_value.array != nullptr);
20168 :
20169 : auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
20170 : m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
20171 : result.m_it.array_iterator = m_value.array->begin() + insert_pos;
20172 :
20173 : // This could have been written as:
20174 : // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
20175 : // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
20176 :
20177 : set_parents();
20178 : return result;
20179 : }
20180 :
20181 : /// @brief inserts element into array
20182 : /// @sa https://json.nlohmann.me/api/basic_json/insert/
20183 : iterator insert(const_iterator pos, const basic_json& val)
20184 : {
20185 : // insert only works for arrays
20186 : if (JSON_HEDLEY_LIKELY(is_array()))
20187 : {
20188 : // check if iterator pos fits to this JSON value
20189 : if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
20190 : {
20191 : JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
20192 : }
20193 :
20194 : // insert to array and return iterator
20195 : return insert_iterator(pos, val);
20196 : }
20197 :
20198 : JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20199 : }
20200 :
20201 : /// @brief inserts element into array
20202 : /// @sa https://json.nlohmann.me/api/basic_json/insert/
20203 : iterator insert(const_iterator pos, basic_json&& val)
20204 : {
20205 : return insert(pos, val);
20206 : }
20207 :
20208 : /// @brief inserts copies of element into array
20209 : /// @sa https://json.nlohmann.me/api/basic_json/insert/
20210 : iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
20211 : {
20212 : // insert only works for arrays
20213 : if (JSON_HEDLEY_LIKELY(is_array()))
20214 : {
20215 : // check if iterator pos fits to this JSON value
20216 : if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
20217 : {
20218 : JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
20219 : }
20220 :
20221 : // insert to array and return iterator
20222 : return insert_iterator(pos, cnt, val);
20223 : }
20224 :
20225 : JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20226 : }
20227 :
20228 : /// @brief inserts range of elements into array
20229 : /// @sa https://json.nlohmann.me/api/basic_json/insert/
20230 : iterator insert(const_iterator pos, const_iterator first, const_iterator last)
20231 : {
20232 : // insert only works for arrays
20233 : if (JSON_HEDLEY_UNLIKELY(!is_array()))
20234 : {
20235 : JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20236 : }
20237 :
20238 : // check if iterator pos fits to this JSON value
20239 : if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
20240 : {
20241 : JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
20242 : }
20243 :
20244 : // check if range iterators belong to the same JSON object
20245 : if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20246 : {
20247 : JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
20248 : }
20249 :
20250 : if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
20251 : {
20252 : JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this));
20253 : }
20254 :
20255 : // insert to array and return iterator
20256 : return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
20257 : }
20258 :
20259 : /// @brief inserts elements from initializer list into array
20260 : /// @sa https://json.nlohmann.me/api/basic_json/insert/
20261 : iterator insert(const_iterator pos, initializer_list_t ilist)
20262 : {
20263 : // insert only works for arrays
20264 : if (JSON_HEDLEY_UNLIKELY(!is_array()))
20265 : {
20266 : JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20267 : }
20268 :
20269 : // check if iterator pos fits to this JSON value
20270 : if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
20271 : {
20272 : JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
20273 : }
20274 :
20275 : // insert to array and return iterator
20276 : return insert_iterator(pos, ilist.begin(), ilist.end());
20277 : }
20278 :
20279 : /// @brief inserts range of elements into object
20280 : /// @sa https://json.nlohmann.me/api/basic_json/insert/
20281 : void insert(const_iterator first, const_iterator last)
20282 : {
20283 : // insert only works for objects
20284 : if (JSON_HEDLEY_UNLIKELY(!is_object()))
20285 : {
20286 : JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20287 : }
20288 :
20289 : // check if range iterators belong to the same JSON object
20290 : if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20291 : {
20292 : JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
20293 : }
20294 :
20295 : // passed iterators must belong to objects
20296 : if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
20297 : {
20298 : JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this));
20299 : }
20300 :
20301 : m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
20302 : }
20303 :
20304 : /// @brief updates a JSON object from another object, overwriting existing keys
20305 : /// @sa https://json.nlohmann.me/api/basic_json/update/
20306 : void update(const_reference j, bool merge_objects = false)
20307 : {
20308 : update(j.begin(), j.end(), merge_objects);
20309 : }
20310 :
20311 : /// @brief updates a JSON object from another object, overwriting existing keys
20312 : /// @sa https://json.nlohmann.me/api/basic_json/update/
20313 : void update(const_iterator first, const_iterator last, bool merge_objects = false)
20314 : {
20315 : // implicitly convert null value to an empty object
20316 : if (is_null())
20317 : {
20318 : m_type = value_t::object;
20319 : m_value.object = create<object_t>();
20320 : assert_invariant();
20321 : }
20322 :
20323 : if (JSON_HEDLEY_UNLIKELY(!is_object()))
20324 : {
20325 : JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this));
20326 : }
20327 :
20328 : // check if range iterators belong to the same JSON object
20329 : if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20330 : {
20331 : JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
20332 : }
20333 :
20334 : // passed iterators must belong to objects
20335 : if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
20336 : {
20337 : JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(first.m_object->type_name()), *first.m_object));
20338 : }
20339 :
20340 : for (auto it = first; it != last; ++it)
20341 : {
20342 : if (merge_objects && it.value().is_object())
20343 : {
20344 : auto it2 = m_value.object->find(it.key());
20345 : if (it2 != m_value.object->end())
20346 : {
20347 : it2->second.update(it.value(), true);
20348 : continue;
20349 : }
20350 : }
20351 : m_value.object->operator[](it.key()) = it.value();
20352 : #if JSON_DIAGNOSTICS
20353 : m_value.object->operator[](it.key()).m_parent = this;
20354 : #endif
20355 : }
20356 : }
20357 :
20358 : /// @brief exchanges the values
20359 : /// @sa https://json.nlohmann.me/api/basic_json/swap/
20360 : void swap(reference other) noexcept (
20361 : std::is_nothrow_move_constructible<value_t>::value&&
20362 : std::is_nothrow_move_assignable<value_t>::value&&
20363 : std::is_nothrow_move_constructible<json_value>::value&&
20364 : std::is_nothrow_move_assignable<json_value>::value
20365 : )
20366 : {
20367 : std::swap(m_type, other.m_type);
20368 : std::swap(m_value, other.m_value);
20369 :
20370 : set_parents();
20371 : other.set_parents();
20372 : assert_invariant();
20373 : }
20374 :
20375 : /// @brief exchanges the values
20376 : /// @sa https://json.nlohmann.me/api/basic_json/swap/
20377 : friend void swap(reference left, reference right) noexcept (
20378 : std::is_nothrow_move_constructible<value_t>::value&&
20379 : std::is_nothrow_move_assignable<value_t>::value&&
20380 : std::is_nothrow_move_constructible<json_value>::value&&
20381 : std::is_nothrow_move_assignable<json_value>::value
20382 : )
20383 : {
20384 : left.swap(right);
20385 : }
20386 :
20387 : /// @brief exchanges the values
20388 : /// @sa https://json.nlohmann.me/api/basic_json/swap/
20389 : void swap(array_t& other) // NOLINT(bugprone-exception-escape)
20390 : {
20391 : // swap only works for arrays
20392 : if (JSON_HEDLEY_LIKELY(is_array()))
20393 : {
20394 : std::swap(*(m_value.array), other);
20395 : }
20396 : else
20397 : {
20398 : JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20399 : }
20400 : }
20401 :
20402 : /// @brief exchanges the values
20403 : /// @sa https://json.nlohmann.me/api/basic_json/swap/
20404 : void swap(object_t& other) // NOLINT(bugprone-exception-escape)
20405 : {
20406 : // swap only works for objects
20407 : if (JSON_HEDLEY_LIKELY(is_object()))
20408 : {
20409 : std::swap(*(m_value.object), other);
20410 : }
20411 : else
20412 : {
20413 : JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20414 : }
20415 : }
20416 :
20417 : /// @brief exchanges the values
20418 : /// @sa https://json.nlohmann.me/api/basic_json/swap/
20419 : void swap(string_t& other) // NOLINT(bugprone-exception-escape)
20420 : {
20421 : // swap only works for strings
20422 : if (JSON_HEDLEY_LIKELY(is_string()))
20423 : {
20424 : std::swap(*(m_value.string), other);
20425 : }
20426 : else
20427 : {
20428 : JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20429 : }
20430 : }
20431 :
20432 : /// @brief exchanges the values
20433 : /// @sa https://json.nlohmann.me/api/basic_json/swap/
20434 : void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
20435 : {
20436 : // swap only works for strings
20437 : if (JSON_HEDLEY_LIKELY(is_binary()))
20438 : {
20439 : std::swap(*(m_value.binary), other);
20440 : }
20441 : else
20442 : {
20443 : JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20444 : }
20445 : }
20446 :
20447 : /// @brief exchanges the values
20448 : /// @sa https://json.nlohmann.me/api/basic_json/swap/
20449 : void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
20450 : {
20451 : // swap only works for strings
20452 : if (JSON_HEDLEY_LIKELY(is_binary()))
20453 : {
20454 : std::swap(*(m_value.binary), other);
20455 : }
20456 : else
20457 : {
20458 : JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20459 : }
20460 : }
20461 :
20462 : /// @}
20463 :
20464 : public:
20465 : //////////////////////////////////////////
20466 : // lexicographical comparison operators //
20467 : //////////////////////////////////////////
20468 :
20469 : /// @name lexicographical comparison operators
20470 : /// @{
20471 :
20472 : /// @brief comparison: equal
20473 : /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
20474 : friend bool operator==(const_reference lhs, const_reference rhs) noexcept
20475 : {
20476 : #ifdef __GNUC__
20477 : #pragma GCC diagnostic push
20478 : #pragma GCC diagnostic ignored "-Wfloat-equal"
20479 : #endif
20480 : const auto lhs_type = lhs.type();
20481 : const auto rhs_type = rhs.type();
20482 :
20483 : if (lhs_type == rhs_type)
20484 : {
20485 : switch (lhs_type)
20486 : {
20487 : case value_t::array:
20488 : return *lhs.m_value.array == *rhs.m_value.array;
20489 :
20490 : case value_t::object:
20491 : return *lhs.m_value.object == *rhs.m_value.object;
20492 :
20493 : case value_t::null:
20494 : return true;
20495 :
20496 : case value_t::string:
20497 : return *lhs.m_value.string == *rhs.m_value.string;
20498 :
20499 : case value_t::boolean:
20500 : return lhs.m_value.boolean == rhs.m_value.boolean;
20501 :
20502 : case value_t::number_integer:
20503 : return lhs.m_value.number_integer == rhs.m_value.number_integer;
20504 :
20505 : case value_t::number_unsigned:
20506 : return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
20507 :
20508 : case value_t::number_float:
20509 : return lhs.m_value.number_float == rhs.m_value.number_float;
20510 :
20511 : case value_t::binary:
20512 : return *lhs.m_value.binary == *rhs.m_value.binary;
20513 :
20514 : case value_t::discarded:
20515 : default:
20516 : return false;
20517 : }
20518 : }
20519 : else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
20520 : {
20521 : return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
20522 : }
20523 : else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
20524 : {
20525 : return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
20526 : }
20527 : else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
20528 : {
20529 : return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
20530 : }
20531 : else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
20532 : {
20533 : return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
20534 : }
20535 : else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
20536 : {
20537 : return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
20538 : }
20539 : else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
20540 : {
20541 : return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
20542 : }
20543 :
20544 : return false;
20545 : #ifdef __GNUC__
20546 : #pragma GCC diagnostic pop
20547 : #endif
20548 : }
20549 :
20550 : /// @brief comparison: equal
20551 : /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
20552 : template<typename ScalarType, typename std::enable_if<
20553 : std::is_scalar<ScalarType>::value, int>::type = 0>
20554 : friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
20555 : {
20556 : return lhs == basic_json(rhs);
20557 : }
20558 :
20559 : /// @brief comparison: equal
20560 : /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
20561 : template<typename ScalarType, typename std::enable_if<
20562 : std::is_scalar<ScalarType>::value, int>::type = 0>
20563 : friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
20564 : {
20565 : return basic_json(lhs) == rhs;
20566 : }
20567 :
20568 : /// @brief comparison: not equal
20569 : /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
20570 : friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
20571 : {
20572 : return !(lhs == rhs);
20573 : }
20574 :
20575 : /// @brief comparison: not equal
20576 : /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
20577 : template<typename ScalarType, typename std::enable_if<
20578 : std::is_scalar<ScalarType>::value, int>::type = 0>
20579 : friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
20580 : {
20581 : return lhs != basic_json(rhs);
20582 : }
20583 :
20584 : /// @brief comparison: not equal
20585 : /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
20586 : template<typename ScalarType, typename std::enable_if<
20587 : std::is_scalar<ScalarType>::value, int>::type = 0>
20588 : friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
20589 : {
20590 : return basic_json(lhs) != rhs;
20591 : }
20592 :
20593 : /// @brief comparison: less than
20594 : /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
20595 1 : friend bool operator<(const_reference lhs, const_reference rhs) noexcept
20596 : {
20597 : const auto lhs_type = lhs.type();
20598 : const auto rhs_type = rhs.type();
20599 :
20600 1 : if (lhs_type == rhs_type)
20601 : {
20602 0 : switch (lhs_type)
20603 : {
20604 0 : case value_t::array:
20605 : // note parentheses are necessary, see
20606 : // https://github.com/nlohmann/json/issues/1530
20607 0 : return (*lhs.m_value.array) < (*rhs.m_value.array);
20608 :
20609 0 : case value_t::object:
20610 0 : return (*lhs.m_value.object) < (*rhs.m_value.object);
20611 :
20612 : case value_t::null:
20613 : return false;
20614 :
20615 0 : case value_t::string:
20616 0 : return (*lhs.m_value.string) < (*rhs.m_value.string);
20617 :
20618 0 : case value_t::boolean:
20619 0 : return (lhs.m_value.boolean) < (rhs.m_value.boolean);
20620 :
20621 0 : case value_t::number_integer:
20622 0 : return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
20623 :
20624 0 : case value_t::number_unsigned:
20625 0 : return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned);
20626 :
20627 0 : case value_t::number_float:
20628 0 : return (lhs.m_value.number_float) < (rhs.m_value.number_float);
20629 :
20630 0 : case value_t::binary:
20631 0 : return (*lhs.m_value.binary) < (*rhs.m_value.binary);
20632 :
20633 : case value_t::discarded:
20634 : default:
20635 : return false;
20636 : }
20637 : }
20638 1 : else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
20639 : {
20640 0 : return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
20641 : }
20642 1 : else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
20643 : {
20644 0 : return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
20645 : }
20646 1 : else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
20647 : {
20648 1 : return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
20649 : }
20650 0 : else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
20651 : {
20652 0 : return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
20653 : }
20654 0 : else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
20655 : {
20656 0 : return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
20657 : }
20658 0 : else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
20659 : {
20660 0 : return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
20661 : }
20662 :
20663 : // We only reach this line if we cannot compare values. In that case,
20664 : // we compare types. Note we have to call the operator explicitly,
20665 : // because MSVC has problems otherwise.
20666 : return operator<(lhs_type, rhs_type);
20667 : }
20668 :
20669 : /// @brief comparison: less than
20670 : /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
20671 : template<typename ScalarType, typename std::enable_if<
20672 : std::is_scalar<ScalarType>::value, int>::type = 0>
20673 : friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
20674 : {
20675 : return lhs < basic_json(rhs);
20676 : }
20677 :
20678 : /// @brief comparison: less than
20679 : /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
20680 : template<typename ScalarType, typename std::enable_if<
20681 : std::is_scalar<ScalarType>::value, int>::type = 0>
20682 : friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
20683 : {
20684 : return basic_json(lhs) < rhs;
20685 : }
20686 :
20687 : /// @brief comparison: less than or equal
20688 : /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
20689 : friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
20690 : {
20691 1 : return !(rhs < lhs);
20692 : }
20693 :
20694 : /// @brief comparison: less than or equal
20695 : /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
20696 : template<typename ScalarType, typename std::enable_if<
20697 : std::is_scalar<ScalarType>::value, int>::type = 0>
20698 : friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
20699 : {
20700 : return lhs <= basic_json(rhs);
20701 : }
20702 :
20703 : /// @brief comparison: less than or equal
20704 : /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
20705 : template<typename ScalarType, typename std::enable_if<
20706 : std::is_scalar<ScalarType>::value, int>::type = 0>
20707 : friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
20708 : {
20709 : return basic_json(lhs) <= rhs;
20710 : }
20711 :
20712 : /// @brief comparison: greater than
20713 : /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
20714 : friend bool operator>(const_reference lhs, const_reference rhs) noexcept
20715 : {
20716 : return !(lhs <= rhs);
20717 : }
20718 :
20719 : /// @brief comparison: greater than
20720 : /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
20721 : template<typename ScalarType, typename std::enable_if<
20722 : std::is_scalar<ScalarType>::value, int>::type = 0>
20723 : friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
20724 : {
20725 : return lhs > basic_json(rhs);
20726 : }
20727 :
20728 : /// @brief comparison: greater than
20729 : /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
20730 : template<typename ScalarType, typename std::enable_if<
20731 : std::is_scalar<ScalarType>::value, int>::type = 0>
20732 1 : friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
20733 : {
20734 1 : return basic_json(lhs) > rhs;
20735 : }
20736 :
20737 : /// @brief comparison: greater than or equal
20738 : /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
20739 : friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
20740 : {
20741 : return !(lhs < rhs);
20742 : }
20743 :
20744 : /// @brief comparison: greater than or equal
20745 : /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
20746 : template<typename ScalarType, typename std::enable_if<
20747 : std::is_scalar<ScalarType>::value, int>::type = 0>
20748 : friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
20749 : {
20750 : return lhs >= basic_json(rhs);
20751 : }
20752 :
20753 : /// @brief comparison: greater than or equal
20754 : /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
20755 : template<typename ScalarType, typename std::enable_if<
20756 : std::is_scalar<ScalarType>::value, int>::type = 0>
20757 : friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
20758 : {
20759 : return basic_json(lhs) >= rhs;
20760 : }
20761 :
20762 : /// @}
20763 :
20764 : ///////////////////
20765 : // serialization //
20766 : ///////////////////
20767 :
20768 : /// @name serialization
20769 : /// @{
20770 : #ifndef JSON_NO_IO
20771 : /// @brief serialize to stream
20772 : /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
20773 : friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
20774 : {
20775 : // read width member and use it as indentation parameter if nonzero
20776 : const bool pretty_print = o.width() > 0;
20777 : const auto indentation = pretty_print ? o.width() : 0;
20778 :
20779 : // reset width to 0 for subsequent calls to this stream
20780 : o.width(0);
20781 :
20782 : // do the actual serialization
20783 : serializer s(detail::output_adapter<char>(o), o.fill());
20784 : s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
20785 : return o;
20786 : }
20787 :
20788 : /// @brief serialize to stream
20789 : /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
20790 : /// @deprecated This function is deprecated since 3.0.0 and will be removed in
20791 : /// version 4.0.0 of the library. Please use
20792 : /// operator<<(std::ostream&, const basic_json&) instead; that is,
20793 : /// replace calls like `j >> o;` with `o << j;`.
20794 : JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
20795 : friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
20796 : {
20797 : return o << j;
20798 : }
20799 : #endif // JSON_NO_IO
20800 : /// @}
20801 :
20802 :
20803 : /////////////////////
20804 : // deserialization //
20805 : /////////////////////
20806 :
20807 : /// @name deserialization
20808 : /// @{
20809 :
20810 : /// @brief deserialize from a compatible input
20811 : /// @sa https://json.nlohmann.me/api/basic_json/parse/
20812 : template<typename InputType>
20813 : JSON_HEDLEY_WARN_UNUSED_RESULT
20814 : static basic_json parse(InputType&& i,
20815 : const parser_callback_t cb = nullptr,
20816 : const bool allow_exceptions = true,
20817 : const bool ignore_comments = false)
20818 : {
20819 : basic_json result;
20820 : parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
20821 : return result;
20822 : }
20823 :
20824 : /// @brief deserialize from a pair of character iterators
20825 : /// @sa https://json.nlohmann.me/api/basic_json/parse/
20826 : template<typename IteratorType>
20827 : JSON_HEDLEY_WARN_UNUSED_RESULT
20828 : static basic_json parse(IteratorType first,
20829 : IteratorType last,
20830 : const parser_callback_t cb = nullptr,
20831 : const bool allow_exceptions = true,
20832 : const bool ignore_comments = false)
20833 : {
20834 : basic_json result;
20835 : parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
20836 : return result;
20837 : }
20838 :
20839 : JSON_HEDLEY_WARN_UNUSED_RESULT
20840 : JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
20841 : static basic_json parse(detail::span_input_adapter&& i,
20842 : const parser_callback_t cb = nullptr,
20843 : const bool allow_exceptions = true,
20844 : const bool ignore_comments = false)
20845 : {
20846 : basic_json result;
20847 : parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
20848 : return result;
20849 : }
20850 :
20851 : /// @brief check if the input is valid JSON
20852 : /// @sa https://json.nlohmann.me/api/basic_json/accept/
20853 : template<typename InputType>
20854 : static bool accept(InputType&& i,
20855 : const bool ignore_comments = false)
20856 : {
20857 : return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
20858 : }
20859 :
20860 : /// @brief check if the input is valid JSON
20861 : /// @sa https://json.nlohmann.me/api/basic_json/accept/
20862 : template<typename IteratorType>
20863 : static bool accept(IteratorType first, IteratorType last,
20864 : const bool ignore_comments = false)
20865 : {
20866 : return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
20867 : }
20868 :
20869 : JSON_HEDLEY_WARN_UNUSED_RESULT
20870 : JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
20871 : static bool accept(detail::span_input_adapter&& i,
20872 : const bool ignore_comments = false)
20873 : {
20874 : return parser(i.get(), nullptr, false, ignore_comments).accept(true);
20875 : }
20876 :
20877 : /// @brief generate SAX events
20878 : /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
20879 : template <typename InputType, typename SAX>
20880 : JSON_HEDLEY_NON_NULL(2)
20881 : static bool sax_parse(InputType&& i, SAX* sax,
20882 : input_format_t format = input_format_t::json,
20883 : const bool strict = true,
20884 : const bool ignore_comments = false)
20885 : {
20886 : auto ia = detail::input_adapter(std::forward<InputType>(i));
20887 : return format == input_format_t::json
20888 : ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
20889 : : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
20890 : }
20891 :
20892 : /// @brief generate SAX events
20893 : /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
20894 : template<class IteratorType, class SAX>
20895 : JSON_HEDLEY_NON_NULL(3)
20896 : static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
20897 : input_format_t format = input_format_t::json,
20898 : const bool strict = true,
20899 : const bool ignore_comments = false)
20900 : {
20901 : auto ia = detail::input_adapter(std::move(first), std::move(last));
20902 : return format == input_format_t::json
20903 : ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
20904 : : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
20905 : }
20906 :
20907 : /// @brief generate SAX events
20908 : /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
20909 : /// @deprecated This function is deprecated since 3.8.0 and will be removed in
20910 : /// version 4.0.0 of the library. Please use
20911 : /// sax_parse(ptr, ptr + len) instead.
20912 : template <typename SAX>
20913 : JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
20914 : JSON_HEDLEY_NON_NULL(2)
20915 : static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
20916 : input_format_t format = input_format_t::json,
20917 : const bool strict = true,
20918 : const bool ignore_comments = false)
20919 : {
20920 : auto ia = i.get();
20921 : return format == input_format_t::json
20922 : // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
20923 : ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
20924 : // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
20925 : : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
20926 : }
20927 : #ifndef JSON_NO_IO
20928 : /// @brief deserialize from stream
20929 : /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
20930 : /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
20931 : /// version 4.0.0 of the library. Please use
20932 : /// operator>>(std::istream&, basic_json&) instead; that is,
20933 : /// replace calls like `j << i;` with `i >> j;`.
20934 : JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
20935 : friend std::istream& operator<<(basic_json& j, std::istream& i)
20936 : {
20937 : return operator>>(i, j);
20938 : }
20939 :
20940 : /// @brief deserialize from stream
20941 : /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
20942 34 : friend std::istream& operator>>(std::istream& i, basic_json& j)
20943 : {
20944 34 : parser(detail::input_adapter(i)).parse(false, j);
20945 34 : return i;
20946 : }
20947 : #endif // JSON_NO_IO
20948 : /// @}
20949 :
20950 : ///////////////////////////
20951 : // convenience functions //
20952 : ///////////////////////////
20953 :
20954 : /// @brief return the type as string
20955 : /// @sa https://json.nlohmann.me/api/basic_json/type_name/
20956 : JSON_HEDLEY_RETURNS_NON_NULL
20957 : const char* type_name() const noexcept
20958 : {
20959 0 : switch (m_type)
20960 : {
20961 : case value_t::null:
20962 : return "null";
20963 0 : case value_t::object:
20964 0 : return "object";
20965 0 : case value_t::array:
20966 0 : return "array";
20967 0 : case value_t::string:
20968 0 : return "string";
20969 0 : case value_t::boolean:
20970 0 : return "boolean";
20971 0 : case value_t::binary:
20972 0 : return "binary";
20973 0 : case value_t::discarded:
20974 0 : return "discarded";
20975 0 : case value_t::number_integer:
20976 : case value_t::number_unsigned:
20977 : case value_t::number_float:
20978 : default:
20979 0 : return "number";
20980 : }
20981 : }
20982 :
20983 :
20984 : JSON_PRIVATE_UNLESS_TESTED:
20985 : //////////////////////
20986 : // member variables //
20987 : //////////////////////
20988 :
20989 : /// the type of the current element
20990 : value_t m_type = value_t::null;
20991 :
20992 : /// the value of the current element
20993 : json_value m_value = {};
20994 :
20995 : #if JSON_DIAGNOSTICS
20996 : /// a pointer to a parent value (for debugging purposes)
20997 : basic_json* m_parent = nullptr;
20998 : #endif
20999 :
21000 : //////////////////////////////////////////
21001 : // binary serialization/deserialization //
21002 : //////////////////////////////////////////
21003 :
21004 : /// @name binary serialization/deserialization support
21005 : /// @{
21006 :
21007 : public:
21008 : /// @brief create a CBOR serialization of a given JSON value
21009 : /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
21010 : static std::vector<std::uint8_t> to_cbor(const basic_json& j)
21011 : {
21012 : std::vector<std::uint8_t> result;
21013 : to_cbor(j, result);
21014 : return result;
21015 : }
21016 :
21017 : /// @brief create a CBOR serialization of a given JSON value
21018 : /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
21019 : static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
21020 : {
21021 : binary_writer<std::uint8_t>(o).write_cbor(j);
21022 : }
21023 :
21024 : /// @brief create a CBOR serialization of a given JSON value
21025 : /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
21026 : static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
21027 : {
21028 : binary_writer<char>(o).write_cbor(j);
21029 : }
21030 :
21031 : /// @brief create a MessagePack serialization of a given JSON value
21032 : /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
21033 : static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
21034 : {
21035 : std::vector<std::uint8_t> result;
21036 : to_msgpack(j, result);
21037 : return result;
21038 : }
21039 :
21040 : /// @brief create a MessagePack serialization of a given JSON value
21041 : /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
21042 : static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
21043 : {
21044 : binary_writer<std::uint8_t>(o).write_msgpack(j);
21045 : }
21046 :
21047 : /// @brief create a MessagePack serialization of a given JSON value
21048 : /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
21049 : static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
21050 : {
21051 : binary_writer<char>(o).write_msgpack(j);
21052 : }
21053 :
21054 : /// @brief create a UBJSON serialization of a given JSON value
21055 : /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
21056 : static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
21057 : const bool use_size = false,
21058 : const bool use_type = false)
21059 : {
21060 : std::vector<std::uint8_t> result;
21061 : to_ubjson(j, result, use_size, use_type);
21062 : return result;
21063 : }
21064 :
21065 : /// @brief create a UBJSON serialization of a given JSON value
21066 : /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
21067 : static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
21068 : const bool use_size = false, const bool use_type = false)
21069 : {
21070 : binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
21071 : }
21072 :
21073 : /// @brief create a UBJSON serialization of a given JSON value
21074 : /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
21075 : static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
21076 : const bool use_size = false, const bool use_type = false)
21077 : {
21078 : binary_writer<char>(o).write_ubjson(j, use_size, use_type);
21079 : }
21080 :
21081 : /// @brief create a BSON serialization of a given JSON value
21082 : /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
21083 : static std::vector<std::uint8_t> to_bson(const basic_json& j)
21084 : {
21085 : std::vector<std::uint8_t> result;
21086 : to_bson(j, result);
21087 : return result;
21088 : }
21089 :
21090 : /// @brief create a BSON serialization of a given JSON value
21091 : /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
21092 : static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
21093 : {
21094 : binary_writer<std::uint8_t>(o).write_bson(j);
21095 : }
21096 :
21097 : /// @brief create a BSON serialization of a given JSON value
21098 : /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
21099 : static void to_bson(const basic_json& j, detail::output_adapter<char> o)
21100 : {
21101 : binary_writer<char>(o).write_bson(j);
21102 : }
21103 :
21104 : /// @brief create a JSON value from an input in CBOR format
21105 : /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
21106 : template<typename InputType>
21107 : JSON_HEDLEY_WARN_UNUSED_RESULT
21108 : static basic_json from_cbor(InputType&& i,
21109 : const bool strict = true,
21110 : const bool allow_exceptions = true,
21111 : const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
21112 : {
21113 : basic_json result;
21114 : detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21115 : auto ia = detail::input_adapter(std::forward<InputType>(i));
21116 : const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
21117 : return res ? result : basic_json(value_t::discarded);
21118 : }
21119 :
21120 : /// @brief create a JSON value from an input in CBOR format
21121 : /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
21122 : template<typename IteratorType>
21123 : JSON_HEDLEY_WARN_UNUSED_RESULT
21124 : static basic_json from_cbor(IteratorType first, IteratorType last,
21125 : const bool strict = true,
21126 : const bool allow_exceptions = true,
21127 : const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
21128 : {
21129 : basic_json result;
21130 : detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21131 : auto ia = detail::input_adapter(std::move(first), std::move(last));
21132 : const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
21133 : return res ? result : basic_json(value_t::discarded);
21134 : }
21135 :
21136 : template<typename T>
21137 : JSON_HEDLEY_WARN_UNUSED_RESULT
21138 : JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
21139 : static basic_json from_cbor(const T* ptr, std::size_t len,
21140 : const bool strict = true,
21141 : const bool allow_exceptions = true,
21142 : const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
21143 : {
21144 : return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
21145 : }
21146 :
21147 :
21148 : JSON_HEDLEY_WARN_UNUSED_RESULT
21149 : JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
21150 : static basic_json from_cbor(detail::span_input_adapter&& i,
21151 : const bool strict = true,
21152 : const bool allow_exceptions = true,
21153 : const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
21154 : {
21155 : basic_json result;
21156 : detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21157 : auto ia = i.get();
21158 : // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21159 : const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
21160 : return res ? result : basic_json(value_t::discarded);
21161 : }
21162 :
21163 : /// @brief create a JSON value from an input in MessagePack format
21164 : /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
21165 : template<typename InputType>
21166 : JSON_HEDLEY_WARN_UNUSED_RESULT
21167 : static basic_json from_msgpack(InputType&& i,
21168 : const bool strict = true,
21169 : const bool allow_exceptions = true)
21170 : {
21171 : basic_json result;
21172 : detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21173 : auto ia = detail::input_adapter(std::forward<InputType>(i));
21174 : const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
21175 : return res ? result : basic_json(value_t::discarded);
21176 : }
21177 :
21178 : /// @brief create a JSON value from an input in MessagePack format
21179 : /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
21180 : template<typename IteratorType>
21181 : JSON_HEDLEY_WARN_UNUSED_RESULT
21182 : static basic_json from_msgpack(IteratorType first, IteratorType last,
21183 : const bool strict = true,
21184 : const bool allow_exceptions = true)
21185 : {
21186 : basic_json result;
21187 : detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21188 : auto ia = detail::input_adapter(std::move(first), std::move(last));
21189 : const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
21190 : return res ? result : basic_json(value_t::discarded);
21191 : }
21192 :
21193 : template<typename T>
21194 : JSON_HEDLEY_WARN_UNUSED_RESULT
21195 : JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
21196 : static basic_json from_msgpack(const T* ptr, std::size_t len,
21197 : const bool strict = true,
21198 : const bool allow_exceptions = true)
21199 : {
21200 : return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
21201 : }
21202 :
21203 : JSON_HEDLEY_WARN_UNUSED_RESULT
21204 : JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
21205 : static basic_json from_msgpack(detail::span_input_adapter&& i,
21206 : const bool strict = true,
21207 : const bool allow_exceptions = true)
21208 : {
21209 : basic_json result;
21210 : detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21211 : auto ia = i.get();
21212 : // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21213 : const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
21214 : return res ? result : basic_json(value_t::discarded);
21215 : }
21216 :
21217 : /// @brief create a JSON value from an input in UBJSON format
21218 : /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
21219 : template<typename InputType>
21220 : JSON_HEDLEY_WARN_UNUSED_RESULT
21221 : static basic_json from_ubjson(InputType&& i,
21222 : const bool strict = true,
21223 : const bool allow_exceptions = true)
21224 : {
21225 : basic_json result;
21226 : detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21227 : auto ia = detail::input_adapter(std::forward<InputType>(i));
21228 : const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
21229 : return res ? result : basic_json(value_t::discarded);
21230 : }
21231 :
21232 : /// @brief create a JSON value from an input in UBJSON format
21233 : /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
21234 : template<typename IteratorType>
21235 : JSON_HEDLEY_WARN_UNUSED_RESULT
21236 : static basic_json from_ubjson(IteratorType first, IteratorType last,
21237 : const bool strict = true,
21238 : const bool allow_exceptions = true)
21239 : {
21240 : basic_json result;
21241 : detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21242 : auto ia = detail::input_adapter(std::move(first), std::move(last));
21243 : const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
21244 : return res ? result : basic_json(value_t::discarded);
21245 : }
21246 :
21247 : template<typename T>
21248 : JSON_HEDLEY_WARN_UNUSED_RESULT
21249 : JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
21250 : static basic_json from_ubjson(const T* ptr, std::size_t len,
21251 : const bool strict = true,
21252 : const bool allow_exceptions = true)
21253 : {
21254 : return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
21255 : }
21256 :
21257 : JSON_HEDLEY_WARN_UNUSED_RESULT
21258 : JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
21259 : static basic_json from_ubjson(detail::span_input_adapter&& i,
21260 : const bool strict = true,
21261 : const bool allow_exceptions = true)
21262 : {
21263 : basic_json result;
21264 : detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21265 : auto ia = i.get();
21266 : // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21267 : const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
21268 : return res ? result : basic_json(value_t::discarded);
21269 : }
21270 :
21271 : /// @brief create a JSON value from an input in BSON format
21272 : /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
21273 : template<typename InputType>
21274 : JSON_HEDLEY_WARN_UNUSED_RESULT
21275 : static basic_json from_bson(InputType&& i,
21276 : const bool strict = true,
21277 : const bool allow_exceptions = true)
21278 : {
21279 : basic_json result;
21280 : detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21281 : auto ia = detail::input_adapter(std::forward<InputType>(i));
21282 : const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
21283 : return res ? result : basic_json(value_t::discarded);
21284 : }
21285 :
21286 : /// @brief create a JSON value from an input in BSON format
21287 : /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
21288 : template<typename IteratorType>
21289 : JSON_HEDLEY_WARN_UNUSED_RESULT
21290 : static basic_json from_bson(IteratorType first, IteratorType last,
21291 : const bool strict = true,
21292 : const bool allow_exceptions = true)
21293 : {
21294 : basic_json result;
21295 : detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21296 : auto ia = detail::input_adapter(std::move(first), std::move(last));
21297 : const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
21298 : return res ? result : basic_json(value_t::discarded);
21299 : }
21300 :
21301 : template<typename T>
21302 : JSON_HEDLEY_WARN_UNUSED_RESULT
21303 : JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
21304 : static basic_json from_bson(const T* ptr, std::size_t len,
21305 : const bool strict = true,
21306 : const bool allow_exceptions = true)
21307 : {
21308 : return from_bson(ptr, ptr + len, strict, allow_exceptions);
21309 : }
21310 :
21311 : JSON_HEDLEY_WARN_UNUSED_RESULT
21312 : JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
21313 : static basic_json from_bson(detail::span_input_adapter&& i,
21314 : const bool strict = true,
21315 : const bool allow_exceptions = true)
21316 : {
21317 : basic_json result;
21318 : detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21319 : auto ia = i.get();
21320 : // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21321 : const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
21322 : return res ? result : basic_json(value_t::discarded);
21323 : }
21324 : /// @}
21325 :
21326 : //////////////////////////
21327 : // JSON Pointer support //
21328 : //////////////////////////
21329 :
21330 : /// @name JSON Pointer functions
21331 : /// @{
21332 :
21333 : /// @brief access specified element via JSON Pointer
21334 : /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21335 : reference operator[](const json_pointer& ptr)
21336 : {
21337 : return ptr.get_unchecked(this);
21338 : }
21339 :
21340 : /// @brief access specified element via JSON Pointer
21341 : /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21342 : const_reference operator[](const json_pointer& ptr) const
21343 : {
21344 : return ptr.get_unchecked(this);
21345 : }
21346 :
21347 : /// @brief access specified element via JSON Pointer
21348 : /// @sa https://json.nlohmann.me/api/basic_json/at/
21349 : reference at(const json_pointer& ptr)
21350 : {
21351 : return ptr.get_checked(this);
21352 : }
21353 :
21354 : /// @brief access specified element via JSON Pointer
21355 : /// @sa https://json.nlohmann.me/api/basic_json/at/
21356 : const_reference at(const json_pointer& ptr) const
21357 : {
21358 : return ptr.get_checked(this);
21359 : }
21360 :
21361 : /// @brief return flattened JSON value
21362 : /// @sa https://json.nlohmann.me/api/basic_json/flatten/
21363 : basic_json flatten() const
21364 : {
21365 : basic_json result(value_t::object);
21366 : json_pointer::flatten("", *this, result);
21367 : return result;
21368 : }
21369 :
21370 : /// @brief unflatten a previously flattened JSON value
21371 : /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
21372 : basic_json unflatten() const
21373 : {
21374 : return json_pointer::unflatten(*this);
21375 : }
21376 :
21377 : /// @}
21378 :
21379 : //////////////////////////
21380 : // JSON Patch functions //
21381 : //////////////////////////
21382 :
21383 : /// @name JSON Patch functions
21384 : /// @{
21385 :
21386 : /// @brief applies a JSON patch
21387 : /// @sa https://json.nlohmann.me/api/basic_json/patch/
21388 : basic_json patch(const basic_json& json_patch) const
21389 : {
21390 : // make a working copy to apply the patch to
21391 : basic_json result = *this;
21392 :
21393 : // the valid JSON Patch operations
21394 : enum class patch_operations {add, remove, replace, move, copy, test, invalid};
21395 :
21396 : const auto get_op = [](const std::string & op)
21397 : {
21398 : if (op == "add")
21399 : {
21400 : return patch_operations::add;
21401 : }
21402 : if (op == "remove")
21403 : {
21404 : return patch_operations::remove;
21405 : }
21406 : if (op == "replace")
21407 : {
21408 : return patch_operations::replace;
21409 : }
21410 : if (op == "move")
21411 : {
21412 : return patch_operations::move;
21413 : }
21414 : if (op == "copy")
21415 : {
21416 : return patch_operations::copy;
21417 : }
21418 : if (op == "test")
21419 : {
21420 : return patch_operations::test;
21421 : }
21422 :
21423 : return patch_operations::invalid;
21424 : };
21425 :
21426 : // wrapper for "add" operation; add value at ptr
21427 : const auto operation_add = [&result](json_pointer & ptr, basic_json val)
21428 : {
21429 : // adding to the root of the target document means replacing it
21430 : if (ptr.empty())
21431 : {
21432 : result = val;
21433 : return;
21434 : }
21435 :
21436 : // make sure the top element of the pointer exists
21437 : json_pointer top_pointer = ptr.top();
21438 : if (top_pointer != ptr)
21439 : {
21440 : result.at(top_pointer);
21441 : }
21442 :
21443 : // get reference to parent of JSON pointer ptr
21444 : const auto last_path = ptr.back();
21445 : ptr.pop_back();
21446 : basic_json& parent = result[ptr];
21447 :
21448 : switch (parent.m_type)
21449 : {
21450 : case value_t::null:
21451 : case value_t::object:
21452 : {
21453 : // use operator[] to add value
21454 : parent[last_path] = val;
21455 : break;
21456 : }
21457 :
21458 : case value_t::array:
21459 : {
21460 : if (last_path == "-")
21461 : {
21462 : // special case: append to back
21463 : parent.push_back(val);
21464 : }
21465 : else
21466 : {
21467 : const auto idx = json_pointer::array_index(last_path);
21468 : if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
21469 : {
21470 : // avoid undefined behavior
21471 : JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", parent));
21472 : }
21473 :
21474 : // default case: insert add offset
21475 : parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
21476 : }
21477 : break;
21478 : }
21479 :
21480 : // if there exists a parent it cannot be primitive
21481 : case value_t::string: // LCOV_EXCL_LINE
21482 : case value_t::boolean: // LCOV_EXCL_LINE
21483 : case value_t::number_integer: // LCOV_EXCL_LINE
21484 : case value_t::number_unsigned: // LCOV_EXCL_LINE
21485 : case value_t::number_float: // LCOV_EXCL_LINE
21486 : case value_t::binary: // LCOV_EXCL_LINE
21487 : case value_t::discarded: // LCOV_EXCL_LINE
21488 : default: // LCOV_EXCL_LINE
21489 : JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
21490 : }
21491 : };
21492 :
21493 : // wrapper for "remove" operation; remove value at ptr
21494 : const auto operation_remove = [this, &result](json_pointer & ptr)
21495 : {
21496 : // get reference to parent of JSON pointer ptr
21497 : const auto last_path = ptr.back();
21498 : ptr.pop_back();
21499 : basic_json& parent = result.at(ptr);
21500 :
21501 : // remove child
21502 : if (parent.is_object())
21503 : {
21504 : // perform range check
21505 : auto it = parent.find(last_path);
21506 : if (JSON_HEDLEY_LIKELY(it != parent.end()))
21507 : {
21508 : parent.erase(it);
21509 : }
21510 : else
21511 : {
21512 : JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", *this));
21513 : }
21514 : }
21515 : else if (parent.is_array())
21516 : {
21517 : // note erase performs range check
21518 : parent.erase(json_pointer::array_index(last_path));
21519 : }
21520 : };
21521 :
21522 : // type check: top level value must be an array
21523 : if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
21524 : {
21525 : JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", json_patch));
21526 : }
21527 :
21528 : // iterate and apply the operations
21529 : for (const auto& val : json_patch)
21530 : {
21531 : // wrapper to get a value for an operation
21532 : const auto get_value = [&val](const std::string & op,
21533 : const std::string & member,
21534 : bool string_type) -> basic_json &
21535 : {
21536 : // find value
21537 : auto it = val.m_value.object->find(member);
21538 :
21539 : // context-sensitive error message
21540 : const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
21541 :
21542 : // check if desired value is present
21543 : if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
21544 : {
21545 : // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
21546 : JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", val));
21547 : }
21548 :
21549 : // check if result is of type string
21550 : if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
21551 : {
21552 : // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
21553 : JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", val));
21554 : }
21555 :
21556 : // no error: return value
21557 : return it->second;
21558 : };
21559 :
21560 : // type check: every element of the array must be an object
21561 : if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
21562 : {
21563 : JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", val));
21564 : }
21565 :
21566 : // collect mandatory members
21567 : const auto op = get_value("op", "op", true).template get<std::string>();
21568 : const auto path = get_value(op, "path", true).template get<std::string>();
21569 : json_pointer ptr(path);
21570 :
21571 : switch (get_op(op))
21572 : {
21573 : case patch_operations::add:
21574 : {
21575 : operation_add(ptr, get_value("add", "value", false));
21576 : break;
21577 : }
21578 :
21579 : case patch_operations::remove:
21580 : {
21581 : operation_remove(ptr);
21582 : break;
21583 : }
21584 :
21585 : case patch_operations::replace:
21586 : {
21587 : // the "path" location must exist - use at()
21588 : result.at(ptr) = get_value("replace", "value", false);
21589 : break;
21590 : }
21591 :
21592 : case patch_operations::move:
21593 : {
21594 : const auto from_path = get_value("move", "from", true).template get<std::string>();
21595 : json_pointer from_ptr(from_path);
21596 :
21597 : // the "from" location must exist - use at()
21598 : basic_json v = result.at(from_ptr);
21599 :
21600 : // The move operation is functionally identical to a
21601 : // "remove" operation on the "from" location, followed
21602 : // immediately by an "add" operation at the target
21603 : // location with the value that was just removed.
21604 : operation_remove(from_ptr);
21605 : operation_add(ptr, v);
21606 : break;
21607 : }
21608 :
21609 : case patch_operations::copy:
21610 : {
21611 : const auto from_path = get_value("copy", "from", true).template get<std::string>();
21612 : const json_pointer from_ptr(from_path);
21613 :
21614 : // the "from" location must exist - use at()
21615 : basic_json v = result.at(from_ptr);
21616 :
21617 : // The copy is functionally identical to an "add"
21618 : // operation at the target location using the value
21619 : // specified in the "from" member.
21620 : operation_add(ptr, v);
21621 : break;
21622 : }
21623 :
21624 : case patch_operations::test:
21625 : {
21626 : bool success = false;
21627 : JSON_TRY
21628 : {
21629 : // check if "value" matches the one at "path"
21630 : // the "path" location must exist - use at()
21631 : success = (result.at(ptr) == get_value("test", "value", false));
21632 : }
21633 : JSON_INTERNAL_CATCH (out_of_range&)
21634 : {
21635 : // ignore out of range errors: success remains false
21636 : }
21637 :
21638 : // throw an exception if test fails
21639 : if (JSON_HEDLEY_UNLIKELY(!success))
21640 : {
21641 : JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), val));
21642 : }
21643 :
21644 : break;
21645 : }
21646 :
21647 : case patch_operations::invalid:
21648 : default:
21649 : {
21650 : // op must be "add", "remove", "replace", "move", "copy", or
21651 : // "test"
21652 : JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid", val));
21653 : }
21654 : }
21655 : }
21656 :
21657 : return result;
21658 : }
21659 :
21660 : /// @brief creates a diff as a JSON patch
21661 : /// @sa https://json.nlohmann.me/api/basic_json/diff/
21662 : JSON_HEDLEY_WARN_UNUSED_RESULT
21663 : static basic_json diff(const basic_json& source, const basic_json& target,
21664 : const std::string& path = "")
21665 : {
21666 : // the patch
21667 : basic_json result(value_t::array);
21668 :
21669 : // if the values are the same, return empty patch
21670 : if (source == target)
21671 : {
21672 : return result;
21673 : }
21674 :
21675 : if (source.type() != target.type())
21676 : {
21677 : // different types: replace value
21678 : result.push_back(
21679 : {
21680 : {"op", "replace"}, {"path", path}, {"value", target}
21681 : });
21682 : return result;
21683 : }
21684 :
21685 : switch (source.type())
21686 : {
21687 : case value_t::array:
21688 : {
21689 : // first pass: traverse common elements
21690 : std::size_t i = 0;
21691 : while (i < source.size() && i < target.size())
21692 : {
21693 : // recursive call to compare array values at index i
21694 : auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
21695 : result.insert(result.end(), temp_diff.begin(), temp_diff.end());
21696 : ++i;
21697 : }
21698 :
21699 : // We now reached the end of at least one array
21700 : // in a second pass, traverse the remaining elements
21701 :
21702 : // remove my remaining elements
21703 : const auto end_index = static_cast<difference_type>(result.size());
21704 : while (i < source.size())
21705 : {
21706 : // add operations in reverse order to avoid invalid
21707 : // indices
21708 : result.insert(result.begin() + end_index, object(
21709 : {
21710 : {"op", "remove"},
21711 : {"path", path + "/" + std::to_string(i)}
21712 : }));
21713 : ++i;
21714 : }
21715 :
21716 : // add other remaining elements
21717 : while (i < target.size())
21718 : {
21719 : result.push_back(
21720 : {
21721 : {"op", "add"},
21722 : {"path", path + "/-"},
21723 : {"value", target[i]}
21724 : });
21725 : ++i;
21726 : }
21727 :
21728 : break;
21729 : }
21730 :
21731 : case value_t::object:
21732 : {
21733 : // first pass: traverse this object's elements
21734 : for (auto it = source.cbegin(); it != source.cend(); ++it)
21735 : {
21736 : // escape the key name to be used in a JSON patch
21737 : const auto path_key = path + "/" + detail::escape(it.key());
21738 :
21739 : if (target.find(it.key()) != target.end())
21740 : {
21741 : // recursive call to compare object values at key it
21742 : auto temp_diff = diff(it.value(), target[it.key()], path_key);
21743 : result.insert(result.end(), temp_diff.begin(), temp_diff.end());
21744 : }
21745 : else
21746 : {
21747 : // found a key that is not in o -> remove it
21748 : result.push_back(object(
21749 : {
21750 : {"op", "remove"}, {"path", path_key}
21751 : }));
21752 : }
21753 : }
21754 :
21755 : // second pass: traverse other object's elements
21756 : for (auto it = target.cbegin(); it != target.cend(); ++it)
21757 : {
21758 : if (source.find(it.key()) == source.end())
21759 : {
21760 : // found a key that is not in this -> add it
21761 : const auto path_key = path + "/" + detail::escape(it.key());
21762 : result.push_back(
21763 : {
21764 : {"op", "add"}, {"path", path_key},
21765 : {"value", it.value()}
21766 : });
21767 : }
21768 : }
21769 :
21770 : break;
21771 : }
21772 :
21773 : case value_t::null:
21774 : case value_t::string:
21775 : case value_t::boolean:
21776 : case value_t::number_integer:
21777 : case value_t::number_unsigned:
21778 : case value_t::number_float:
21779 : case value_t::binary:
21780 : case value_t::discarded:
21781 : default:
21782 : {
21783 : // both primitive type: replace value
21784 : result.push_back(
21785 : {
21786 : {"op", "replace"}, {"path", path}, {"value", target}
21787 : });
21788 : break;
21789 : }
21790 : }
21791 :
21792 : return result;
21793 : }
21794 :
21795 : /// @}
21796 :
21797 : ////////////////////////////////
21798 : // JSON Merge Patch functions //
21799 : ////////////////////////////////
21800 :
21801 : /// @name JSON Merge Patch functions
21802 : /// @{
21803 :
21804 : /// @brief applies a JSON Merge Patch
21805 : /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
21806 : void merge_patch(const basic_json& apply_patch)
21807 : {
21808 : if (apply_patch.is_object())
21809 : {
21810 : if (!is_object())
21811 : {
21812 : *this = object();
21813 : }
21814 : for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
21815 : {
21816 : if (it.value().is_null())
21817 : {
21818 : erase(it.key());
21819 : }
21820 : else
21821 : {
21822 : operator[](it.key()).merge_patch(it.value());
21823 : }
21824 : }
21825 : }
21826 : else
21827 : {
21828 : *this = apply_patch;
21829 : }
21830 : }
21831 :
21832 : /// @}
21833 : };
21834 :
21835 : /// @brief user-defined to_string function for JSON values
21836 : /// @sa https://json.nlohmann.me/api/basic_json/to_string/
21837 : NLOHMANN_BASIC_JSON_TPL_DECLARATION
21838 : std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
21839 : {
21840 : return j.dump();
21841 : }
21842 :
21843 : } // namespace nlohmann
21844 :
21845 : ///////////////////////
21846 : // nonmember support //
21847 : ///////////////////////
21848 :
21849 : namespace std // NOLINT(cert-dcl58-cpp)
21850 : {
21851 :
21852 : /// @brief hash value for JSON objects
21853 : /// @sa https://json.nlohmann.me/api/basic_json/std_hash/
21854 : NLOHMANN_BASIC_JSON_TPL_DECLARATION
21855 : struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL>
21856 : {
21857 : std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
21858 : {
21859 : return nlohmann::detail::hash(j);
21860 : }
21861 : };
21862 :
21863 : // specialization for std::less<value_t>
21864 : template<>
21865 : struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
21866 : {
21867 : /*!
21868 : @brief compare two value_t enum values
21869 : @since version 3.0.0
21870 : */
21871 : bool operator()(nlohmann::detail::value_t lhs,
21872 : nlohmann::detail::value_t rhs) const noexcept
21873 : {
21874 : return nlohmann::detail::operator<(lhs, rhs);
21875 : }
21876 : };
21877 :
21878 : // C++20 prohibit function specialization in the std namespace.
21879 : #ifndef JSON_HAS_CPP_20
21880 :
21881 : /// @brief exchanges the values of two JSON objects
21882 : /// @sa https://json.nlohmann.me/api/basic_json/std_swap/
21883 : NLOHMANN_BASIC_JSON_TPL_DECLARATION
21884 : inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name)
21885 : is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression)
21886 : is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
21887 : {
21888 : j1.swap(j2);
21889 : }
21890 :
21891 : #endif
21892 :
21893 : } // namespace std
21894 :
21895 : /// @brief user-defined string literal for JSON values
21896 : /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
21897 : JSON_HEDLEY_NON_NULL(1)
21898 : inline nlohmann::json operator "" _json(const char* s, std::size_t n)
21899 : {
21900 : return nlohmann::json::parse(s, s + n);
21901 : }
21902 :
21903 : /// @brief user-defined string literal for JSON pointer
21904 : /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
21905 : JSON_HEDLEY_NON_NULL(1)
21906 : inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
21907 : {
21908 : return nlohmann::json::json_pointer(std::string(s, n));
21909 : }
21910 :
21911 : // #include <nlohmann/detail/macro_unscope.hpp>
21912 :
21913 :
21914 : // restore clang diagnostic settings
21915 : #if defined(__clang__)
21916 : #pragma clang diagnostic pop
21917 : #endif
21918 :
21919 : // clean up
21920 : #undef JSON_ASSERT
21921 : #undef JSON_INTERNAL_CATCH
21922 : #undef JSON_CATCH
21923 : #undef JSON_THROW
21924 : #undef JSON_TRY
21925 : #undef JSON_PRIVATE_UNLESS_TESTED
21926 : #undef JSON_HAS_CPP_11
21927 : #undef JSON_HAS_CPP_14
21928 : #undef JSON_HAS_CPP_17
21929 : #undef JSON_HAS_CPP_20
21930 : #undef JSON_HAS_FILESYSTEM
21931 : #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
21932 : #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
21933 : #undef NLOHMANN_BASIC_JSON_TPL
21934 : #undef JSON_EXPLICIT
21935 : #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
21936 :
21937 : // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
21938 :
21939 :
21940 : #undef JSON_HEDLEY_ALWAYS_INLINE
21941 : #undef JSON_HEDLEY_ARM_VERSION
21942 : #undef JSON_HEDLEY_ARM_VERSION_CHECK
21943 : #undef JSON_HEDLEY_ARRAY_PARAM
21944 : #undef JSON_HEDLEY_ASSUME
21945 : #undef JSON_HEDLEY_BEGIN_C_DECLS
21946 : #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
21947 : #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
21948 : #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
21949 : #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
21950 : #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
21951 : #undef JSON_HEDLEY_CLANG_HAS_FEATURE
21952 : #undef JSON_HEDLEY_CLANG_HAS_WARNING
21953 : #undef JSON_HEDLEY_COMPCERT_VERSION
21954 : #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
21955 : #undef JSON_HEDLEY_CONCAT
21956 : #undef JSON_HEDLEY_CONCAT3
21957 : #undef JSON_HEDLEY_CONCAT3_EX
21958 : #undef JSON_HEDLEY_CONCAT_EX
21959 : #undef JSON_HEDLEY_CONST
21960 : #undef JSON_HEDLEY_CONSTEXPR
21961 : #undef JSON_HEDLEY_CONST_CAST
21962 : #undef JSON_HEDLEY_CPP_CAST
21963 : #undef JSON_HEDLEY_CRAY_VERSION
21964 : #undef JSON_HEDLEY_CRAY_VERSION_CHECK
21965 : #undef JSON_HEDLEY_C_DECL
21966 : #undef JSON_HEDLEY_DEPRECATED
21967 : #undef JSON_HEDLEY_DEPRECATED_FOR
21968 : #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
21969 : #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
21970 : #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
21971 : #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
21972 : #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
21973 : #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
21974 : #undef JSON_HEDLEY_DIAGNOSTIC_POP
21975 : #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
21976 : #undef JSON_HEDLEY_DMC_VERSION
21977 : #undef JSON_HEDLEY_DMC_VERSION_CHECK
21978 : #undef JSON_HEDLEY_EMPTY_BASES
21979 : #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
21980 : #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
21981 : #undef JSON_HEDLEY_END_C_DECLS
21982 : #undef JSON_HEDLEY_FLAGS
21983 : #undef JSON_HEDLEY_FLAGS_CAST
21984 : #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
21985 : #undef JSON_HEDLEY_GCC_HAS_BUILTIN
21986 : #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
21987 : #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
21988 : #undef JSON_HEDLEY_GCC_HAS_EXTENSION
21989 : #undef JSON_HEDLEY_GCC_HAS_FEATURE
21990 : #undef JSON_HEDLEY_GCC_HAS_WARNING
21991 : #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
21992 : #undef JSON_HEDLEY_GCC_VERSION
21993 : #undef JSON_HEDLEY_GCC_VERSION_CHECK
21994 : #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
21995 : #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
21996 : #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
21997 : #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
21998 : #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
21999 : #undef JSON_HEDLEY_GNUC_HAS_FEATURE
22000 : #undef JSON_HEDLEY_GNUC_HAS_WARNING
22001 : #undef JSON_HEDLEY_GNUC_VERSION
22002 : #undef JSON_HEDLEY_GNUC_VERSION_CHECK
22003 : #undef JSON_HEDLEY_HAS_ATTRIBUTE
22004 : #undef JSON_HEDLEY_HAS_BUILTIN
22005 : #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
22006 : #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
22007 : #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
22008 : #undef JSON_HEDLEY_HAS_EXTENSION
22009 : #undef JSON_HEDLEY_HAS_FEATURE
22010 : #undef JSON_HEDLEY_HAS_WARNING
22011 : #undef JSON_HEDLEY_IAR_VERSION
22012 : #undef JSON_HEDLEY_IAR_VERSION_CHECK
22013 : #undef JSON_HEDLEY_IBM_VERSION
22014 : #undef JSON_HEDLEY_IBM_VERSION_CHECK
22015 : #undef JSON_HEDLEY_IMPORT
22016 : #undef JSON_HEDLEY_INLINE
22017 : #undef JSON_HEDLEY_INTEL_CL_VERSION
22018 : #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
22019 : #undef JSON_HEDLEY_INTEL_VERSION
22020 : #undef JSON_HEDLEY_INTEL_VERSION_CHECK
22021 : #undef JSON_HEDLEY_IS_CONSTANT
22022 : #undef JSON_HEDLEY_IS_CONSTEXPR_
22023 : #undef JSON_HEDLEY_LIKELY
22024 : #undef JSON_HEDLEY_MALLOC
22025 : #undef JSON_HEDLEY_MCST_LCC_VERSION
22026 : #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
22027 : #undef JSON_HEDLEY_MESSAGE
22028 : #undef JSON_HEDLEY_MSVC_VERSION
22029 : #undef JSON_HEDLEY_MSVC_VERSION_CHECK
22030 : #undef JSON_HEDLEY_NEVER_INLINE
22031 : #undef JSON_HEDLEY_NON_NULL
22032 : #undef JSON_HEDLEY_NO_ESCAPE
22033 : #undef JSON_HEDLEY_NO_RETURN
22034 : #undef JSON_HEDLEY_NO_THROW
22035 : #undef JSON_HEDLEY_NULL
22036 : #undef JSON_HEDLEY_PELLES_VERSION
22037 : #undef JSON_HEDLEY_PELLES_VERSION_CHECK
22038 : #undef JSON_HEDLEY_PGI_VERSION
22039 : #undef JSON_HEDLEY_PGI_VERSION_CHECK
22040 : #undef JSON_HEDLEY_PREDICT
22041 : #undef JSON_HEDLEY_PRINTF_FORMAT
22042 : #undef JSON_HEDLEY_PRIVATE
22043 : #undef JSON_HEDLEY_PUBLIC
22044 : #undef JSON_HEDLEY_PURE
22045 : #undef JSON_HEDLEY_REINTERPRET_CAST
22046 : #undef JSON_HEDLEY_REQUIRE
22047 : #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
22048 : #undef JSON_HEDLEY_REQUIRE_MSG
22049 : #undef JSON_HEDLEY_RESTRICT
22050 : #undef JSON_HEDLEY_RETURNS_NON_NULL
22051 : #undef JSON_HEDLEY_SENTINEL
22052 : #undef JSON_HEDLEY_STATIC_ASSERT
22053 : #undef JSON_HEDLEY_STATIC_CAST
22054 : #undef JSON_HEDLEY_STRINGIFY
22055 : #undef JSON_HEDLEY_STRINGIFY_EX
22056 : #undef JSON_HEDLEY_SUNPRO_VERSION
22057 : #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
22058 : #undef JSON_HEDLEY_TINYC_VERSION
22059 : #undef JSON_HEDLEY_TINYC_VERSION_CHECK
22060 : #undef JSON_HEDLEY_TI_ARMCL_VERSION
22061 : #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
22062 : #undef JSON_HEDLEY_TI_CL2000_VERSION
22063 : #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
22064 : #undef JSON_HEDLEY_TI_CL430_VERSION
22065 : #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
22066 : #undef JSON_HEDLEY_TI_CL6X_VERSION
22067 : #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
22068 : #undef JSON_HEDLEY_TI_CL7X_VERSION
22069 : #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
22070 : #undef JSON_HEDLEY_TI_CLPRU_VERSION
22071 : #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
22072 : #undef JSON_HEDLEY_TI_VERSION
22073 : #undef JSON_HEDLEY_TI_VERSION_CHECK
22074 : #undef JSON_HEDLEY_UNAVAILABLE
22075 : #undef JSON_HEDLEY_UNLIKELY
22076 : #undef JSON_HEDLEY_UNPREDICTABLE
22077 : #undef JSON_HEDLEY_UNREACHABLE
22078 : #undef JSON_HEDLEY_UNREACHABLE_RETURN
22079 : #undef JSON_HEDLEY_VERSION
22080 : #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
22081 : #undef JSON_HEDLEY_VERSION_DECODE_MINOR
22082 : #undef JSON_HEDLEY_VERSION_DECODE_REVISION
22083 : #undef JSON_HEDLEY_VERSION_ENCODE
22084 : #undef JSON_HEDLEY_WARNING
22085 : #undef JSON_HEDLEY_WARN_UNUSED_RESULT
22086 : #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
22087 : #undef JSON_HEDLEY_FALL_THROUGH
22088 :
22089 :
22090 :
22091 : #endif // INCLUDE_NLOHMANN_JSON_HPP_
|