BmnRoot 26.10.0-18-g4e3414f9
Software framework of the BM@N experiment
Loading...
Searching...
No Matches
json.hpp
Go to the documentation of this file.
1/*
2 __ _____ _____ _____
3 __| | __| | | | JSON for Modern C++
4| | |__ | | | | | | version 3.10.5
5|_____|_____|_____|_|___| https://github.com/nlohmann/json
6
7Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8SPDX-License-Identifier: MIT
9Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
10
11Permission is hereby granted, free of charge, to any person obtaining a copy
12of this software and associated documentation files (the "Software"), to deal
13in the Software without restriction, including without limitation the rights
14to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15copies of the Software, and to permit persons to whom the Software is
16furnished to do so, subject to the following conditions:
17
18The above copyright notice and this permission notice shall be included in all
19copies or substantial portions of the Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27SOFTWARE.
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#include <type_traits>
63#include <utility>
64
65// #include <nlohmann/detail/conversions/from_json.hpp>
66
67#include <algorithm> // transform
68#include <array> // array
69#include <forward_list> // forward_list
70#include <iterator> // inserter, front_inserter, end
71#include <map> // map
72#include <string> // string
73#include <tuple> // tuple, make_tuple
74#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
75#include <unordered_map> // unordered_map
76#include <utility> // pair, declval
77#include <valarray> // valarray
78
79// #include <nlohmann/detail/exceptions.hpp>
80
81#include <exception> // exception
82#include <stdexcept> // runtime_error
83#include <string> // to_string
84#include <vector> // vector
85
86// #include <nlohmann/detail/value_t.hpp>
87
88#include <array> // array
89#include <cstddef> // size_t
90#include <cstdint> // uint8_t
91#include <string> // string
92
93namespace nlohmann
94{
95namespace detail
96{
97///////////////////////////
98// JSON type enumeration //
99///////////////////////////
100
101/*!
102@brief the JSON type enumeration
103
104This enumeration collects the different JSON types. It is internally used to
105distinguish the stored values, and the functions @ref basic_json::is_null(),
106@ref basic_json::is_object(), @ref basic_json::is_array(),
107@ref basic_json::is_string(), @ref basic_json::is_boolean(),
108@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
109@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
110@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
111@ref basic_json::is_structured() rely on it.
112
113@note There are three enumeration entries (number_integer, number_unsigned, and
114number_float), because the library distinguishes these three types for numbers:
115@ref basic_json::number_unsigned_t is used for unsigned integers,
116@ref basic_json::number_integer_t is used for signed integers, and
117@ref basic_json::number_float_t is used for floating-point numbers or to
118approximate integers which do not fit in the limits of their respective type.
119
120@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
121value with the default value for a given type
122
123@since version 1.0.0
124*/
125enum class value_t : std::uint8_t
126{
127 null, ///< null value
128 object, ///< object (unordered set of name/value pairs)
129 array, ///< array (ordered collection of values)
130 string, ///< string value
131 boolean, ///< boolean value
132 number_integer, ///< number value (signed integer)
133 number_unsigned, ///< number value (unsigned integer)
134 number_float, ///< number value (floating-point)
135 binary, ///< binary array (ordered collection of bytes)
136 discarded ///< discarded by the parser callback function
137};
138
139/*!
140@brief comparison operator for JSON types
141
142Returns an ordering that is similar to Python:
143- order: null < boolean < number < object < array < string < binary
144- furthermore, each type is not smaller than itself
145- discarded values are not comparable
146- binary is represented as a b"" string in python and directly comparable to a
147 string; however, making a binary array directly comparable with a string would
148 be surprising behavior in a JSON file.
149
150@since version 1.0.0
151*/
152inline bool operator<(const value_t lhs, const value_t rhs) noexcept
153{
154 static constexpr std::array<std::uint8_t, 9> order = {{
155 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, 1 /* boolean */, 2 /* integer */, 2 /* unsigned */,
156 2 /* float */, 6 /* binary */
157 }};
158
159 const auto l_index = static_cast<std::size_t>(lhs);
160 const auto r_index = static_cast<std::size_t>(rhs);
161 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
162}
163} // namespace detail
164} // namespace nlohmann
165
166// #include <nlohmann/detail/string_escape.hpp>
167
168#include <string>
169// #include <nlohmann/detail/macro_scope.hpp>
170
171#include <utility> // declval, pair
172// #include <nlohmann/thirdparty/hedley/hedley.hpp>
173
174/* Hedley - https://nemequ.github.io/hedley
175 * Created by Evan Nemerson <evan@nemerson.com>
176 *
177 * To the extent possible under law, the author(s) have dedicated all
178 * copyright and related and neighboring rights to this software to
179 * the public domain worldwide. This software is distributed without
180 * any warranty.
181 *
182 * For details, see <http://creativecommons.org/publicdomain/zero/1.0/>.
183 * SPDX-License-Identifier: CC0-1.0
184 */
185
186#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
187#if defined(JSON_HEDLEY_VERSION)
188#undef JSON_HEDLEY_VERSION
189#endif
190#define JSON_HEDLEY_VERSION 15
191
192#if defined(JSON_HEDLEY_STRINGIFY_EX)
193#undef JSON_HEDLEY_STRINGIFY_EX
194#endif
195#define JSON_HEDLEY_STRINGIFY_EX(x) #x
196
197#if defined(JSON_HEDLEY_STRINGIFY)
198#undef JSON_HEDLEY_STRINGIFY
199#endif
200#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
201
202#if defined(JSON_HEDLEY_CONCAT_EX)
203#undef JSON_HEDLEY_CONCAT_EX
204#endif
205#define JSON_HEDLEY_CONCAT_EX(a, b) a##b
206
207#if defined(JSON_HEDLEY_CONCAT)
208#undef JSON_HEDLEY_CONCAT
209#endif
210#define JSON_HEDLEY_CONCAT(a, b) JSON_HEDLEY_CONCAT_EX(a, b)
211
212#if defined(JSON_HEDLEY_CONCAT3_EX)
213#undef JSON_HEDLEY_CONCAT3_EX
214#endif
215#define JSON_HEDLEY_CONCAT3_EX(a, b, c) a##b##c
216
217#if defined(JSON_HEDLEY_CONCAT3)
218#undef JSON_HEDLEY_CONCAT3
219#endif
220#define JSON_HEDLEY_CONCAT3(a, b, c) JSON_HEDLEY_CONCAT3_EX(a, b, c)
221
222#if defined(JSON_HEDLEY_VERSION_ENCODE)
223#undef JSON_HEDLEY_VERSION_ENCODE
224#endif
225#define JSON_HEDLEY_VERSION_ENCODE(major, minor, revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
226
227#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
228#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
229#endif
230#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
231
232#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
233#undef JSON_HEDLEY_VERSION_DECODE_MINOR
234#endif
235#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
236
237#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
238#undef JSON_HEDLEY_VERSION_DECODE_REVISION
239#endif
240#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
241
242#if defined(JSON_HEDLEY_GNUC_VERSION)
243#undef JSON_HEDLEY_GNUC_VERSION
244#endif
245#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
246#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
247#elif defined(__GNUC__)
248#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
249#endif
250
251#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
252#undef JSON_HEDLEY_GNUC_VERSION_CHECK
253#endif
254#if defined(JSON_HEDLEY_GNUC_VERSION)
255#define JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) \
256 (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
257#else
258#define JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) (0)
259#endif
260
261#if defined(JSON_HEDLEY_MSVC_VERSION)
262#undef JSON_HEDLEY_MSVC_VERSION
263#endif
264#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
265#define JSON_HEDLEY_MSVC_VERSION \
266 JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, \
267 (_MSC_FULL_VER % 100000) / 100)
268#elif defined(_MSC_FULL_VER) && !defined(__ICL)
269#define JSON_HEDLEY_MSVC_VERSION \
270 JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
271#elif defined(_MSC_VER) && !defined(__ICL)
272#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
273#endif
274
275#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
276#undef JSON_HEDLEY_MSVC_VERSION_CHECK
277#endif
278#if !defined(JSON_HEDLEY_MSVC_VERSION)
279#define JSON_HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) (0)
280#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
281#define JSON_HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) \
282 (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
283#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
284#define JSON_HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) \
285 (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
286#else
287#define JSON_HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) (_MSC_VER >= ((major * 100) + (minor)))
288#endif
289
290#if defined(JSON_HEDLEY_INTEL_VERSION)
291#undef JSON_HEDLEY_INTEL_VERSION
292#endif
293#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
294#define JSON_HEDLEY_INTEL_VERSION \
295 JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
296#elif defined(__INTEL_COMPILER) && !defined(__ICL)
297#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
298#endif
299
300#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
301#undef JSON_HEDLEY_INTEL_VERSION_CHECK
302#endif
303#if defined(JSON_HEDLEY_INTEL_VERSION)
304#define JSON_HEDLEY_INTEL_VERSION_CHECK(major, minor, patch) \
305 (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
306#else
307#define JSON_HEDLEY_INTEL_VERSION_CHECK(major, minor, patch) (0)
308#endif
309
310#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
311#undef JSON_HEDLEY_INTEL_CL_VERSION
312#endif
313#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
314#define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
315#endif
316
317#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
318#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
319#endif
320#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
321#define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major, minor, patch) \
322 (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) \
339 (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
340#else
341#define JSON_HEDLEY_PGI_VERSION_CHECK(major, minor, patch) (0)
342#endif
343
344#if defined(JSON_HEDLEY_SUNPRO_VERSION)
345#undef JSON_HEDLEY_SUNPRO_VERSION
346#endif
347#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
348#define JSON_HEDLEY_SUNPRO_VERSION \
349 JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), \
350 (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
351#elif defined(__SUNPRO_C)
352#define JSON_HEDLEY_SUNPRO_VERSION \
353 JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
354#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
355#define JSON_HEDLEY_SUNPRO_VERSION \
356 JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), \
357 (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), \
358 (__SUNPRO_CC & 0xf) * 10)
359#elif defined(__SUNPRO_CC)
360#define JSON_HEDLEY_SUNPRO_VERSION \
361 JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
362#endif
363
364#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
365#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
366#endif
367#if defined(JSON_HEDLEY_SUNPRO_VERSION)
368#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major, minor, patch) \
369 (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
370#else
371#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major, minor, patch) (0)
372#endif
373
374#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
375#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
376#endif
377#if defined(__EMSCRIPTEN__)
378#define JSON_HEDLEY_EMSCRIPTEN_VERSION \
379 JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
380#endif
381
382#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
383#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
384#endif
385#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
386#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major, minor, patch) \
387 (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
388#else
389#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major, minor, patch) (0)
390#endif
391
392#if defined(JSON_HEDLEY_ARM_VERSION)
393#undef JSON_HEDLEY_ARM_VERSION
394#endif
395#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
396#define JSON_HEDLEY_ARM_VERSION \
397 JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, \
398 (__ARMCOMPILER_VERSION % 10000) / 100)
399#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
400#define JSON_HEDLEY_ARM_VERSION \
401 JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, \
402 (__ARMCC_VERSION % 10000) / 100)
403#endif
404
405#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
406#undef JSON_HEDLEY_ARM_VERSION_CHECK
407#endif
408#if defined(JSON_HEDLEY_ARM_VERSION)
409#define JSON_HEDLEY_ARM_VERSION_CHECK(major, minor, patch) \
410 (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
411#else
412#define JSON_HEDLEY_ARM_VERSION_CHECK(major, minor, patch) (0)
413#endif
414
415#if defined(JSON_HEDLEY_IBM_VERSION)
416#undef JSON_HEDLEY_IBM_VERSION
417#endif
418#if defined(__ibmxl__)
419#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
420#elif defined(__xlC__) && defined(__xlC_ver__)
421#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
422#elif defined(__xlC__)
423#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
424#endif
425
426#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
427#undef JSON_HEDLEY_IBM_VERSION_CHECK
428#endif
429#if defined(JSON_HEDLEY_IBM_VERSION)
430#define JSON_HEDLEY_IBM_VERSION_CHECK(major, minor, patch) \
431 (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
432#else
433#define JSON_HEDLEY_IBM_VERSION_CHECK(major, minor, patch) (0)
434#endif
435
436#if defined(JSON_HEDLEY_TI_VERSION)
437#undef JSON_HEDLEY_TI_VERSION
438#endif
439#if defined(__TI_COMPILER_VERSION__) \
440 && (defined(__TMS470__) || defined(__TI_ARM__) || defined(__MSP430__) || defined(__TMS320C2000__))
441#if (__TI_COMPILER_VERSION__ >= 16000000)
442#define JSON_HEDLEY_TI_VERSION \
443 JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, \
444 (__TI_COMPILER_VERSION__ % 1000))
445#endif
446#endif
447
448#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
449#undef JSON_HEDLEY_TI_VERSION_CHECK
450#endif
451#if defined(JSON_HEDLEY_TI_VERSION)
452#define JSON_HEDLEY_TI_VERSION_CHECK(major, minor, patch) \
453 (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
454#else
455#define JSON_HEDLEY_TI_VERSION_CHECK(major, minor, patch) (0)
456#endif
457
458#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
459#undef JSON_HEDLEY_TI_CL2000_VERSION
460#endif
461#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
462#define JSON_HEDLEY_TI_CL2000_VERSION \
463 JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, \
464 (__TI_COMPILER_VERSION__ % 1000))
465#endif
466
467#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
468#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
469#endif
470#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
471#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major, minor, patch) \
472 (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
473#else
474#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major, minor, patch) (0)
475#endif
476
477#if defined(JSON_HEDLEY_TI_CL430_VERSION)
478#undef JSON_HEDLEY_TI_CL430_VERSION
479#endif
480#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
481#define JSON_HEDLEY_TI_CL430_VERSION \
482 JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, \
483 (__TI_COMPILER_VERSION__ % 1000))
484#endif
485
486#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
487#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
488#endif
489#if defined(JSON_HEDLEY_TI_CL430_VERSION)
490#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major, minor, patch) \
491 (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
492#else
493#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major, minor, patch) (0)
494#endif
495
496#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
497#undef JSON_HEDLEY_TI_ARMCL_VERSION
498#endif
499#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
500#define JSON_HEDLEY_TI_ARMCL_VERSION \
501 JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, \
502 (__TI_COMPILER_VERSION__ % 1000))
503#endif
504
505#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
506#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
507#endif
508#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
509#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major, minor, patch) \
510 (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
511#else
512#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major, minor, patch) (0)
513#endif
514
515#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
516#undef JSON_HEDLEY_TI_CL6X_VERSION
517#endif
518#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
519#define JSON_HEDLEY_TI_CL6X_VERSION \
520 JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, \
521 (__TI_COMPILER_VERSION__ % 1000))
522#endif
523
524#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
525#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
526#endif
527#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
528#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major, minor, patch) \
529 (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
530#else
531#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major, minor, patch) (0)
532#endif
533
534#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
535#undef JSON_HEDLEY_TI_CL7X_VERSION
536#endif
537#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
538#define JSON_HEDLEY_TI_CL7X_VERSION \
539 JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, \
540 (__TI_COMPILER_VERSION__ % 1000))
541#endif
542
543#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
544#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
545#endif
546#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
547#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major, minor, patch) \
548 (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
549#else
550#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major, minor, patch) (0)
551#endif
552
553#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
554#undef JSON_HEDLEY_TI_CLPRU_VERSION
555#endif
556#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
557#define JSON_HEDLEY_TI_CLPRU_VERSION \
558 JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, \
559 (__TI_COMPILER_VERSION__ % 1000))
560#endif
561
562#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
563#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
564#endif
565#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
566#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major, minor, patch) \
567 (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
568#else
569#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major, minor, patch) (0)
570#endif
571
572#if defined(JSON_HEDLEY_CRAY_VERSION)
573#undef JSON_HEDLEY_CRAY_VERSION
574#endif
575#if defined(_CRAYC)
576#if defined(_RELEASE_PATCHLEVEL)
577#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
578#else
579#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
580#endif
581#endif
582
583#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
584#undef JSON_HEDLEY_CRAY_VERSION_CHECK
585#endif
586#if defined(JSON_HEDLEY_CRAY_VERSION)
587#define JSON_HEDLEY_CRAY_VERSION_CHECK(major, minor, patch) \
588 (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
589#else
590#define JSON_HEDLEY_CRAY_VERSION_CHECK(major, minor, patch) (0)
591#endif
592
593#if defined(JSON_HEDLEY_IAR_VERSION)
594#undef JSON_HEDLEY_IAR_VERSION
595#endif
596#if defined(__IAR_SYSTEMS_ICC__)
597#if __VER__ > 1000
598#define JSON_HEDLEY_IAR_VERSION \
599 JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
600#else
601#define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
602#endif
603#endif
604
605#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
606#undef JSON_HEDLEY_IAR_VERSION_CHECK
607#endif
608#if defined(JSON_HEDLEY_IAR_VERSION)
609#define JSON_HEDLEY_IAR_VERSION_CHECK(major, minor, patch) \
610 (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
611#else
612#define JSON_HEDLEY_IAR_VERSION_CHECK(major, minor, patch) (0)
613#endif
614
615#if defined(JSON_HEDLEY_TINYC_VERSION)
616#undef JSON_HEDLEY_TINYC_VERSION
617#endif
618#if defined(__TINYC__)
619#define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
620#endif
621
622#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
623#undef JSON_HEDLEY_TINYC_VERSION_CHECK
624#endif
625#if defined(JSON_HEDLEY_TINYC_VERSION)
626#define JSON_HEDLEY_TINYC_VERSION_CHECK(major, minor, patch) \
627 (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
628#else
629#define JSON_HEDLEY_TINYC_VERSION_CHECK(major, minor, patch) (0)
630#endif
631
632#if defined(JSON_HEDLEY_DMC_VERSION)
633#undef JSON_HEDLEY_DMC_VERSION
634#endif
635#if defined(__DMC__)
636#define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
637#endif
638
639#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
640#undef JSON_HEDLEY_DMC_VERSION_CHECK
641#endif
642#if defined(JSON_HEDLEY_DMC_VERSION)
643#define JSON_HEDLEY_DMC_VERSION_CHECK(major, minor, patch) \
644 (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
645#else
646#define JSON_HEDLEY_DMC_VERSION_CHECK(major, minor, patch) (0)
647#endif
648
649#if defined(JSON_HEDLEY_COMPCERT_VERSION)
650#undef JSON_HEDLEY_COMPCERT_VERSION
651#endif
652#if defined(__COMPCERT_VERSION__)
653#define JSON_HEDLEY_COMPCERT_VERSION \
654 JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, \
655 __COMPCERT_VERSION__ % 100)
656#endif
657
658#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
659#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
660#endif
661#if defined(JSON_HEDLEY_COMPCERT_VERSION)
662#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major, minor, patch) \
663 (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
664#else
665#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major, minor, patch) (0)
666#endif
667
668#if defined(JSON_HEDLEY_PELLES_VERSION)
669#undef JSON_HEDLEY_PELLES_VERSION
670#endif
671#if defined(__POCC__)
672#define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
673#endif
674
675#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
676#undef JSON_HEDLEY_PELLES_VERSION_CHECK
677#endif
678#if defined(JSON_HEDLEY_PELLES_VERSION)
679#define JSON_HEDLEY_PELLES_VERSION_CHECK(major, minor, patch) \
680 (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
681#else
682#define JSON_HEDLEY_PELLES_VERSION_CHECK(major, minor, patch) (0)
683#endif
684
685#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
686#undef JSON_HEDLEY_MCST_LCC_VERSION
687#endif
688#if defined(__LCC__) && defined(__LCC_MINOR__)
689#define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
690#endif
691
692#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
693#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
694#endif
695#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
696#define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major, minor, patch) \
697 (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
698#else
699#define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major, minor, patch) (0)
700#endif
701
702#if defined(JSON_HEDLEY_GCC_VERSION)
703#undef JSON_HEDLEY_GCC_VERSION
704#endif
705#if defined(JSON_HEDLEY_GNUC_VERSION) && !defined(__clang__) && !defined(JSON_HEDLEY_INTEL_VERSION) \
706 && !defined(JSON_HEDLEY_PGI_VERSION) && !defined(JSON_HEDLEY_ARM_VERSION) && !defined(JSON_HEDLEY_CRAY_VERSION) \
707 && !defined(JSON_HEDLEY_TI_VERSION) && !defined(JSON_HEDLEY_TI_ARMCL_VERSION) \
708 && !defined(JSON_HEDLEY_TI_CL430_VERSION) && !defined(JSON_HEDLEY_TI_CL2000_VERSION) \
709 && !defined(JSON_HEDLEY_TI_CL6X_VERSION) && !defined(JSON_HEDLEY_TI_CL7X_VERSION) \
710 && !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && !defined(__COMPCERT__) && !defined(JSON_HEDLEY_MCST_LCC_VERSION)
711#define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
712#endif
713
714#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
715#undef JSON_HEDLEY_GCC_VERSION_CHECK
716#endif
717#if defined(JSON_HEDLEY_GCC_VERSION)
718#define JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch) \
719 (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
720#else
721#define JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch) (0)
722#endif
723
724#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
725#undef JSON_HEDLEY_HAS_ATTRIBUTE
726#endif
727#if defined(__has_attribute) && ((!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8, 5, 9)))
728#define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
729#else
730#define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
731#endif
732
733#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
734#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
735#endif
736#if defined(__has_attribute)
737#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
738#else
739#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \
740 JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch)
741#endif
742
743#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
744#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
745#endif
746#if defined(__has_attribute)
747#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute, major, minor, patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
748#else
749#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute, major, minor, patch) JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch)
750#endif
751
752#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
753#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
754#endif
755#if defined(__has_cpp_attribute) && defined(__cplusplus) \
756 && (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0))
757#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
758#else
759#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
760#endif
761
762#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
763#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
764#endif
765#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
766#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns, attribute) (0)
767#elif !defined(JSON_HEDLEY_PGI_VERSION) && !defined(JSON_HEDLEY_IAR_VERSION) \
768 && (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0)) \
769 && (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19, 20, 0))
770#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns, attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
771#else
772#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns, attribute) (0)
773#endif
774
775#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
776#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
777#endif
778#if defined(__has_cpp_attribute) && defined(__cplusplus)
779#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) __has_cpp_attribute(attribute)
780#else
781#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) \
782 JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch)
783#endif
784
785#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
786#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
787#endif
788#if defined(__has_cpp_attribute) && defined(__cplusplus)
789#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) __has_cpp_attribute(attribute)
790#else
791#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) \
792 JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch)
793#endif
794
795#if defined(JSON_HEDLEY_HAS_BUILTIN)
796#undef JSON_HEDLEY_HAS_BUILTIN
797#endif
798#if defined(__has_builtin)
799#define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
800#else
801#define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
802#endif
803
804#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
805#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
806#endif
807#if defined(__has_builtin)
808#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin, major, minor, patch) __has_builtin(builtin)
809#else
810#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin, major, minor, patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch)
811#endif
812
813#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
814#undef JSON_HEDLEY_GCC_HAS_BUILTIN
815#endif
816#if defined(__has_builtin)
817#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin, major, minor, patch) __has_builtin(builtin)
818#else
819#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin, major, minor, patch) JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch)
820#endif
821
822#if defined(JSON_HEDLEY_HAS_FEATURE)
823#undef JSON_HEDLEY_HAS_FEATURE
824#endif
825#if defined(__has_feature)
826#define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
827#else
828#define JSON_HEDLEY_HAS_FEATURE(feature) (0)
829#endif
830
831#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
832#undef JSON_HEDLEY_GNUC_HAS_FEATURE
833#endif
834#if defined(__has_feature)
835#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature, major, minor, patch) __has_feature(feature)
836#else
837#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature, major, minor, patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch)
838#endif
839
840#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
841#undef JSON_HEDLEY_GCC_HAS_FEATURE
842#endif
843#if defined(__has_feature)
844#define JSON_HEDLEY_GCC_HAS_FEATURE(feature, major, minor, patch) __has_feature(feature)
845#else
846#define JSON_HEDLEY_GCC_HAS_FEATURE(feature, major, minor, patch) JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch)
847#endif
848
849#if defined(JSON_HEDLEY_HAS_EXTENSION)
850#undef JSON_HEDLEY_HAS_EXTENSION
851#endif
852#if defined(__has_extension)
853#define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
854#else
855#define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
856#endif
857
858#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
859#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
860#endif
861#if defined(__has_extension)
862#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension, major, minor, patch) __has_extension(extension)
863#else
864#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension, major, minor, patch) \
865 JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch)
866#endif
867
868#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
869#undef JSON_HEDLEY_GCC_HAS_EXTENSION
870#endif
871#if defined(__has_extension)
872#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension, major, minor, patch) __has_extension(extension)
873#else
874#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension, major, minor, patch) JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch)
875#endif
876
877#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
878#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
879#endif
880#if defined(__has_declspec_attribute)
881#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
882#else
883#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
884#endif
885
886#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
887#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
888#endif
889#if defined(__has_declspec_attribute)
890#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute, major, minor, patch) __has_declspec_attribute(attribute)
891#else
892#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute, major, minor, patch) \
893 JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch)
894#endif
895
896#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
897#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
898#endif
899#if defined(__has_declspec_attribute)
900#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute, major, minor, patch) __has_declspec_attribute(attribute)
901#else
902#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute, major, minor, patch) \
903 JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch)
904#endif
905
906#if defined(JSON_HEDLEY_HAS_WARNING)
907#undef JSON_HEDLEY_HAS_WARNING
908#endif
909#if defined(__has_warning)
910#define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
911#else
912#define JSON_HEDLEY_HAS_WARNING(warning) (0)
913#endif
914
915#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
916#undef JSON_HEDLEY_GNUC_HAS_WARNING
917#endif
918#if defined(__has_warning)
919#define JSON_HEDLEY_GNUC_HAS_WARNING(warning, major, minor, patch) __has_warning(warning)
920#else
921#define JSON_HEDLEY_GNUC_HAS_WARNING(warning, major, minor, patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch)
922#endif
923
924#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
925#undef JSON_HEDLEY_GCC_HAS_WARNING
926#endif
927#if defined(__has_warning)
928#define JSON_HEDLEY_GCC_HAS_WARNING(warning, major, minor, patch) __has_warning(warning)
929#else
930#define JSON_HEDLEY_GCC_HAS_WARNING(warning, major, minor, patch) JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch)
931#endif
932
933#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || defined(__clang__) \
934 || JSON_HEDLEY_GCC_VERSION_CHECK(3, 0, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) \
935 || JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) || JSON_HEDLEY_PGI_VERSION_CHECK(18, 4, 0) \
936 || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) \
937 || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 7, 0) || JSON_HEDLEY_TI_CL430_VERSION_CHECK(2, 0, 1) \
938 || JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 1, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 0, 0) \
939 || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) \
940 || JSON_HEDLEY_CRAY_VERSION_CHECK(5, 0, 0) || JSON_HEDLEY_TINYC_VERSION_CHECK(0, 9, 17) \
941 || JSON_HEDLEY_SUNPRO_VERSION_CHECK(8, 0, 0) \
942 || (JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) && defined(__C99_PRAGMA_OPERATOR))
943#define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
944#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0)
945#define JSON_HEDLEY_PRAGMA(value) __pragma(value)
946#else
947#define JSON_HEDLEY_PRAGMA(value)
948#endif
949
950#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
951#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
952#endif
953#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
954#undef JSON_HEDLEY_DIAGNOSTIC_POP
955#endif
956#if defined(__clang__)
957#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
958#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
959#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0)
960#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
961#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
962#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 6, 0)
963#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
964#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
965#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
966#define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
967#define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
968#elif JSON_HEDLEY_ARM_VERSION_CHECK(5, 6, 0)
969#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
970#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
971#elif JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) \
972 || JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 4, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 1, 0) \
973 || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0)
974#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
975#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
976#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2, 90, 0)
977#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
978#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
979#else
980#define JSON_HEDLEY_DIAGNOSTIC_PUSH
981#define JSON_HEDLEY_DIAGNOSTIC_POP
982#endif
983
984/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
985 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
986#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
987#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
988#endif
989#if defined(__cplusplus)
990#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
991#if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
992#if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
993#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
994 JSON_HEDLEY_DIAGNOSTIC_PUSH \
995 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
996 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") xpr JSON_HEDLEY_DIAGNOSTIC_POP
997#else
998#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
999 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1000 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1001 xpr JSON_HEDLEY_DIAGNOSTIC_POP
1002#endif
1003#else
1004#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1005 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1006 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") xpr JSON_HEDLEY_DIAGNOSTIC_POP
1007#endif
1008#endif
1009#endif
1010#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1011#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1012#endif
1013
1014#if defined(JSON_HEDLEY_CONST_CAST)
1015#undef JSON_HEDLEY_CONST_CAST
1016#endif
1017#if defined(__cplusplus)
1018#define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1019#elif JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || JSON_HEDLEY_GCC_VERSION_CHECK(4, 6, 0) \
1020 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0)
1021#define JSON_HEDLEY_CONST_CAST(T, expr) \
1022 (__extension__({ \
1023 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1024 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL((T)(expr)); \
1025 JSON_HEDLEY_DIAGNOSTIC_POP \
1026 }))
1027#else
1028#define JSON_HEDLEY_CONST_CAST(T, expr) ((T)(expr))
1029#endif
1030
1031#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1032#undef JSON_HEDLEY_REINTERPRET_CAST
1033#endif
1034#if defined(__cplusplus)
1035#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1036#else
1037#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T)(expr))
1038#endif
1039
1040#if defined(JSON_HEDLEY_STATIC_CAST)
1041#undef JSON_HEDLEY_STATIC_CAST
1042#endif
1043#if defined(__cplusplus)
1044#define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1045#else
1046#define JSON_HEDLEY_STATIC_CAST(T, expr) ((T)(expr))
1047#endif
1048
1049#if defined(JSON_HEDLEY_CPP_CAST)
1050#undef JSON_HEDLEY_CPP_CAST
1051#endif
1052#if defined(__cplusplus)
1053#if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1054#define JSON_HEDLEY_CPP_CAST(T, expr) \
1055 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1056 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"")((T)(expr)) JSON_HEDLEY_DIAGNOSTIC_POP
1057#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 3, 0)
1058#define JSON_HEDLEY_CPP_CAST(T, expr) \
1059 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1060 _Pragma("diag_suppress=Pe137") JSON_HEDLEY_DIAGNOSTIC_POP
1061#else
1062#define JSON_HEDLEY_CPP_CAST(T, expr) ((T)(expr))
1063#endif
1064#else
1065#define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1066#endif
1067
1068#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1069#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1070#endif
1071#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1072#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1073#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0)
1074#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1075#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1076#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable : 1478 1786))
1077#elif JSON_HEDLEY_PGI_VERSION_CHECK(20, 7, 0)
1078#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1079#elif JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0)
1080#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1081#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 3, 0)
1082#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1083#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0)
1084#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable : 4996))
1085#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1086#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1087#elif JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) \
1088 || (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1089 || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) \
1090 || (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1091 || JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) \
1092 || (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1093 || JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) \
1094 || (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1095 || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) \
1096 || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0)
1097#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1098#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 13, 0) && !defined(__cplusplus)
1099#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1100#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 13, 0) && defined(__cplusplus)
1101#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1102#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0)
1103#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1104#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2, 90, 0)
1105#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1106#else
1107#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1108#endif
1109
1110#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1111#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1112#endif
1113#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1114#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1115#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0)
1116#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1117#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1118#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable : 161))
1119#elif JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0)
1120#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1121#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 3, 0)
1122#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1123#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0)
1124#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable : 4068))
1125#elif JSON_HEDLEY_TI_VERSION_CHECK(16, 9, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 0, 0) \
1126 || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || 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 \
1143 _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1144#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 6, 0)
1145#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES \
1146 _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1147#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17, 0, 0)
1148#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1149#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1150#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable : 1292))
1151#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19, 0, 0)
1152#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable : 5030))
1153#elif JSON_HEDLEY_PGI_VERSION_CHECK(20, 7, 0)
1154#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1155#elif JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0)
1156#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1157#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 14, 0) && defined(__cplusplus)
1158#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1159#elif JSON_HEDLEY_TI_VERSION_CHECK(18, 1, 0) || 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 JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1205#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " #since))
1206#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1207#elif (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) \
1208 || JSON_HEDLEY_GCC_VERSION_CHECK(4, 5, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) \
1209 || JSON_HEDLEY_ARM_VERSION_CHECK(5, 6, 0) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 13, 0) \
1210 || JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || JSON_HEDLEY_TI_VERSION_CHECK(18, 1, 0) \
1211 || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18, 1, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 3, 0) \
1212 || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 3, 0) \
1213 || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1214#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1215#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) \
1216 __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1217#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1218#define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1219#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) \
1220 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1221#elif JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 1, 0) \
1222 || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) \
1223 || (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1224 || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) \
1225 || (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1226 || JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) \
1227 || (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1228 || JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) \
1229 || (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1230 || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) \
1231 || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) \
1232 || JSON_HEDLEY_IAR_VERSION_CHECK(8, 10, 0)
1233#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1234#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1235#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || JSON_HEDLEY_PELLES_VERSION_CHECK(6, 50, 0) \
1236 || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1237#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1238#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1239#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0)
1240#define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1241#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1242#else
1243#define JSON_HEDLEY_DEPRECATED(since)
1244#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1245#endif
1246
1247#if defined(JSON_HEDLEY_UNAVAILABLE)
1248#undef JSON_HEDLEY_UNAVAILABLE
1249#endif
1250#if JSON_HEDLEY_HAS_ATTRIBUTE(warning) || JSON_HEDLEY_GCC_VERSION_CHECK(4, 3, 0) \
1251 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1252#define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1253#else
1254#define JSON_HEDLEY_UNAVAILABLE(available_since)
1255#endif
1256
1257#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1258#undef JSON_HEDLEY_WARN_UNUSED_RESULT
1259#endif
1260#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1261#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1262#endif
1263#if JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 4, 0) \
1264 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) \
1265 || (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1266 || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) \
1267 || (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1268 || JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) \
1269 || (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1270 || JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) \
1271 || (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1272 || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) \
1273 || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) \
1274 || (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0) && defined(__cplusplus)) \
1275 || JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1276#define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1277#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1278#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1279#define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1280#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1281#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1282#define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1283#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1284#elif defined(_Check_return_) /* SAL */
1285#define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1286#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1287#else
1288#define JSON_HEDLEY_WARN_UNUSED_RESULT
1289#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1290#endif
1291
1292#if defined(JSON_HEDLEY_SENTINEL)
1293#undef JSON_HEDLEY_SENTINEL
1294#endif
1295#if JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || JSON_HEDLEY_GCC_VERSION_CHECK(4, 0, 0) \
1296 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_ARM_VERSION_CHECK(5, 4, 0) \
1297 || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1298#define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1299#else
1300#define JSON_HEDLEY_SENTINEL(position)
1301#endif
1302
1303#if defined(JSON_HEDLEY_NO_RETURN)
1304#undef JSON_HEDLEY_NO_RETURN
1305#endif
1306#if JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0)
1307#define JSON_HEDLEY_NO_RETURN __noreturn
1308#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1309#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1310#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1311#define JSON_HEDLEY_NO_RETURN _Noreturn
1312#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1313#define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1314#elif JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 2, 0) \
1315 || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) \
1316 || JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) \
1317 || (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1318 || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) \
1319 || (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1320 || JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) \
1321 || (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1322 || JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) \
1323 || (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1324 || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) \
1325 || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || JSON_HEDLEY_IAR_VERSION_CHECK(8, 10, 0)
1326#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1327#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0)
1328#define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1329#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1330#define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1331#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 0, 0) && defined(__cplusplus)
1332#define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1333#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3, 2, 0)
1334#define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1335#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9, 0, 0)
1336#define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1337#else
1338#define JSON_HEDLEY_NO_RETURN
1339#endif
1340
1341#if defined(JSON_HEDLEY_NO_ESCAPE)
1342#undef JSON_HEDLEY_NO_ESCAPE
1343#endif
1344#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1345#define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1346#else
1347#define JSON_HEDLEY_NO_ESCAPE
1348#endif
1349
1350#if defined(JSON_HEDLEY_UNREACHABLE)
1351#undef JSON_HEDLEY_UNREACHABLE
1352#endif
1353#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1354#undef JSON_HEDLEY_UNREACHABLE_RETURN
1355#endif
1356#if defined(JSON_HEDLEY_ASSUME)
1357#undef JSON_HEDLEY_ASSUME
1358#endif
1359#if JSON_HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) \
1360 || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1361#define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1362#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1363#define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1364#elif JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4, 0, 0)
1365#if defined(__cplusplus)
1366#define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1367#else
1368#define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1369#endif
1370#endif
1371#if (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) \
1372 || JSON_HEDLEY_GCC_VERSION_CHECK(4, 5, 0) || JSON_HEDLEY_PGI_VERSION_CHECK(18, 10, 0) \
1373 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(13, 1, 5) \
1374 || JSON_HEDLEY_CRAY_VERSION_CHECK(10, 0, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1375#define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1376#elif defined(JSON_HEDLEY_ASSUME)
1377#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1378#endif
1379#if !defined(JSON_HEDLEY_ASSUME)
1380#if defined(JSON_HEDLEY_UNREACHABLE)
1381#define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1382#else
1383#define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1384#endif
1385#endif
1386#if defined(JSON_HEDLEY_UNREACHABLE)
1387#if JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4, 0, 0)
1388#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1389#else
1390#define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1391#endif
1392#else
1393#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1394#endif
1395#if !defined(JSON_HEDLEY_UNREACHABLE)
1396#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1397#endif
1398
1400#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1401#pragma clang diagnostic ignored "-Wpedantic"
1402#endif
1403#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1404#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1405#endif
1406#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros", 4, 0, 0)
1407#if defined(__clang__)
1408#pragma clang diagnostic ignored "-Wvariadic-macros"
1409#elif defined(JSON_HEDLEY_GCC_VERSION)
1410#pragma GCC diagnostic ignored "-Wvariadic-macros"
1411#endif
1412#endif
1413#if defined(JSON_HEDLEY_NON_NULL)
1414#undef JSON_HEDLEY_NON_NULL
1415#endif
1416#if JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 3, 0) \
1417 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0)
1418#define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1419#else
1420#define JSON_HEDLEY_NON_NULL(...)
1421#endif
1423
1424#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1425#undef JSON_HEDLEY_PRINTF_FORMAT
1426#endif
1427#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format, 4, 4, 0) && !defined(__USE_MINGW_ANSI_STDIO)
1428#define JSON_HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) \
1429 __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1430#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format, 4, 4, 0) && defined(__USE_MINGW_ANSI_STDIO)
1431#define JSON_HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) \
1432 __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1433#elif JSON_HEDLEY_HAS_ATTRIBUTE(format) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 1, 0) \
1434 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_ARM_VERSION_CHECK(5, 6, 0) \
1435 || JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) \
1436 || (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1437 || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) \
1438 || (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1439 || JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) \
1440 || (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1441 || JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) \
1442 || (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1443 || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) \
1444 || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1445#define JSON_HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) \
1446 __attribute__((__format__(__printf__, string_idx, first_to_check)))
1447#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6, 0, 0)
1448#define JSON_HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) __declspec(vaformat(printf, string_idx, first_to_check))
1449#else
1450#define JSON_HEDLEY_PRINTF_FORMAT(string_idx, first_to_check)
1451#endif
1452
1453#if defined(JSON_HEDLEY_CONSTEXPR)
1454#undef JSON_HEDLEY_CONSTEXPR
1455#endif
1456#if defined(__cplusplus)
1457#if __cplusplus >= 201103L
1458#define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1459#endif
1460#endif
1461#if !defined(JSON_HEDLEY_CONSTEXPR)
1462#define JSON_HEDLEY_CONSTEXPR
1463#endif
1464
1465#if defined(JSON_HEDLEY_PREDICT)
1466#undef JSON_HEDLEY_PREDICT
1467#endif
1468#if defined(JSON_HEDLEY_LIKELY)
1469#undef JSON_HEDLEY_LIKELY
1470#endif
1471#if defined(JSON_HEDLEY_UNLIKELY)
1472#undef JSON_HEDLEY_UNLIKELY
1473#endif
1474#if defined(JSON_HEDLEY_UNPREDICTABLE)
1475#undef JSON_HEDLEY_UNPREDICTABLE
1476#endif
1477#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1478#define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1479#endif
1480#if (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) \
1481 || JSON_HEDLEY_GCC_VERSION_CHECK(9, 0, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1482#define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability((expr), (value), (probability))
1483#define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1, (probability))
1484#define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0, (probability))
1485#define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1486#define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1487#elif (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) \
1488 || JSON_HEDLEY_GCC_VERSION_CHECK(3, 0, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) \
1489 || (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0) && defined(__cplusplus)) || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) \
1490 || JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) \
1491 || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 7, 0) || JSON_HEDLEY_TI_CL430_VERSION_CHECK(3, 1, 0) \
1492 || JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 1, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 1, 0) \
1493 || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) \
1494 || JSON_HEDLEY_TINYC_VERSION_CHECK(0, 9, 27) || JSON_HEDLEY_CRAY_VERSION_CHECK(8, 1, 0) \
1495 || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1496#define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1497 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1498#define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1499 (__extension__({ \
1500 double hedley_probability_ = (probability); \
1501 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) \
1502 : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1503 }))
1504#define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1505 (__extension__({ \
1506 double hedley_probability_ = (probability); \
1507 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) \
1508 : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1509 }))
1510#define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1511#define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1512#else
1513#define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1514#define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1515#define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1516#define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1517#define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1518#endif
1519#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1520#define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1521#endif
1522
1523#if defined(JSON_HEDLEY_MALLOC)
1524#undef JSON_HEDLEY_MALLOC
1525#endif
1526#if JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 1, 0) \
1527 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) \
1528 || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(12, 1, 0) \
1529 || JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) \
1530 || (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1531 || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) \
1532 || (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1533 || JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) \
1534 || (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1535 || JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) \
1536 || (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1537 || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) \
1538 || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1539#define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1540#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0)
1541#define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1542#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1543#define JSON_HEDLEY_MALLOC __declspec(restrict)
1544#else
1545#define JSON_HEDLEY_MALLOC
1546#endif
1547
1548#if defined(JSON_HEDLEY_PURE)
1549#undef JSON_HEDLEY_PURE
1550#endif
1551#if JSON_HEDLEY_HAS_ATTRIBUTE(pure) || JSON_HEDLEY_GCC_VERSION_CHECK(2, 96, 0) \
1552 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) \
1553 || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) \
1554 || JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) \
1555 || (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1556 || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) \
1557 || (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1558 || JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) \
1559 || (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1560 || JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) \
1561 || (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1562 || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) \
1563 || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) \
1564 || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1565#define JSON_HEDLEY_PURE __attribute__((__pure__))
1566#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0)
1567#define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1568#elif defined(__cplusplus) \
1569 && (JSON_HEDLEY_TI_CL430_VERSION_CHECK(2, 0, 1) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4, 0, 0) \
1570 || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0))
1571#define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1572#else
1573#define JSON_HEDLEY_PURE
1574#endif
1575
1576#if defined(JSON_HEDLEY_CONST)
1577#undef JSON_HEDLEY_CONST
1578#endif
1579#if JSON_HEDLEY_HAS_ATTRIBUTE(const) || JSON_HEDLEY_GCC_VERSION_CHECK(2, 5, 0) \
1580 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) \
1581 || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) \
1582 || JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) \
1583 || (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1584 || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) \
1585 || (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1586 || JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) \
1587 || (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1588 || JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) \
1589 || (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1590 || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) \
1591 || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) \
1592 || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1593#define JSON_HEDLEY_CONST __attribute__((__const__))
1594#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0)
1595#define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1596#else
1597#define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1598#endif
1599
1600#if defined(JSON_HEDLEY_RESTRICT)
1601#undef JSON_HEDLEY_RESTRICT
1602#endif
1603#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1604#define JSON_HEDLEY_RESTRICT restrict
1605#elif JSON_HEDLEY_GCC_VERSION_CHECK(3, 1, 0) || JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) \
1606 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) \
1607 || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) \
1608 || JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) \
1609 || JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 4) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 1, 0) \
1610 || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) \
1611 || (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 14, 0) && defined(__cplusplus)) || JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) \
1612 || defined(__clang__) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1613#define JSON_HEDLEY_RESTRICT __restrict
1614#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 3, 0) && !defined(__cplusplus)
1615#define JSON_HEDLEY_RESTRICT _Restrict
1616#else
1617#define JSON_HEDLEY_RESTRICT
1618#endif
1619
1620#if defined(JSON_HEDLEY_INLINE)
1621#undef JSON_HEDLEY_INLINE
1622#endif
1623#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined(__cplusplus) && (__cplusplus >= 199711L))
1624#define JSON_HEDLEY_INLINE inline
1625#elif defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_ARM_VERSION_CHECK(6, 2, 0)
1626#define JSON_HEDLEY_INLINE __inline__
1627#elif JSON_HEDLEY_MSVC_VERSION_CHECK(12, 0, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) \
1628 || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 1, 0) \
1629 || JSON_HEDLEY_TI_CL430_VERSION_CHECK(3, 1, 0) || JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 0) \
1630 || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 0, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) \
1631 || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1632#define JSON_HEDLEY_INLINE __inline
1633#else
1634#define JSON_HEDLEY_INLINE
1635#endif
1636
1637#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1638#undef JSON_HEDLEY_ALWAYS_INLINE
1639#endif
1640#if JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || JSON_HEDLEY_GCC_VERSION_CHECK(4, 0, 0) \
1641 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) \
1642 || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) \
1643 || JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) \
1644 || (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1645 || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) \
1646 || (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1647 || JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) \
1648 || (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1649 || JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) \
1650 || (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1651 || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) \
1652 || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) \
1653 || JSON_HEDLEY_IAR_VERSION_CHECK(8, 10, 0)
1654#define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1655#elif JSON_HEDLEY_MSVC_VERSION_CHECK(12, 0, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1656#define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1657#elif defined(__cplusplus) \
1658 && (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) \
1659 || JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 1, 0) \
1660 || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0))
1661#define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1662#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0)
1663#define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1664#else
1665#define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1666#endif
1667
1668#if defined(JSON_HEDLEY_NEVER_INLINE)
1669#undef JSON_HEDLEY_NEVER_INLINE
1670#endif
1671#if JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || JSON_HEDLEY_GCC_VERSION_CHECK(4, 0, 0) \
1672 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) \
1673 || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) \
1674 || JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) \
1675 || (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1676 || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) \
1677 || (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1678 || JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) \
1679 || (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1680 || JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) \
1681 || (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1682 || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) \
1683 || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) \
1684 || JSON_HEDLEY_IAR_VERSION_CHECK(8, 10, 0)
1685#define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1686#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1687#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1688#elif JSON_HEDLEY_PGI_VERSION_CHECK(10, 2, 0)
1689#define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1690#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 0, 0) && defined(__cplusplus)
1691#define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1692#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0)
1693#define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1694#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3, 2, 0)
1695#define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1696#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9, 0, 0)
1697#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1698#else
1699#define JSON_HEDLEY_NEVER_INLINE
1700#endif
1701
1702#if defined(JSON_HEDLEY_PRIVATE)
1703#undef JSON_HEDLEY_PRIVATE
1704#endif
1705#if defined(JSON_HEDLEY_PUBLIC)
1706#undef JSON_HEDLEY_PUBLIC
1707#endif
1708#if defined(JSON_HEDLEY_IMPORT)
1709#undef JSON_HEDLEY_IMPORT
1710#endif
1711#if defined(_WIN32) || defined(__CYGWIN__)
1712#define JSON_HEDLEY_PRIVATE
1713#define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1714#define JSON_HEDLEY_IMPORT __declspec(dllimport)
1715#else
1716#if JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 3, 0) \
1717 || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) \
1718 || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(13, 1, 0) \
1719 || (defined(__TI_EABI__) \
1720 && ((JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) \
1721 || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0))) \
1722 || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1723#define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1724#define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1725#else
1726#define JSON_HEDLEY_PRIVATE
1727#define JSON_HEDLEY_PUBLIC
1728#endif
1729#define JSON_HEDLEY_IMPORT extern
1730#endif
1731
1732#if defined(JSON_HEDLEY_NO_THROW)
1733#undef JSON_HEDLEY_NO_THROW
1734#endif
1735#if JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 3, 0) \
1736 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1737#define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
1738#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13, 1, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) \
1739 || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0)
1740#define JSON_HEDLEY_NO_THROW __declspec(nothrow)
1741#else
1742#define JSON_HEDLEY_NO_THROW
1743#endif
1744
1745#if defined(JSON_HEDLEY_FALL_THROUGH)
1746#undef JSON_HEDLEY_FALL_THROUGH
1747#endif
1748#if JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || JSON_HEDLEY_GCC_VERSION_CHECK(7, 0, 0) \
1749 || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1750#define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
1751#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang, fallthrough)
1752#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
1753#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
1754#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
1755#elif defined(__fallthrough) /* SAL */
1756#define JSON_HEDLEY_FALL_THROUGH __fallthrough
1757#else
1758#define JSON_HEDLEY_FALL_THROUGH
1759#endif
1760
1761#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
1762#undef JSON_HEDLEY_RETURNS_NON_NULL
1763#endif
1764#if JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || JSON_HEDLEY_GCC_VERSION_CHECK(4, 9, 0) \
1765 || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1766#define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
1767#elif defined(_Ret_notnull_) /* SAL */
1768#define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
1769#else
1770#define JSON_HEDLEY_RETURNS_NON_NULL
1771#endif
1772
1773#if defined(JSON_HEDLEY_ARRAY_PARAM)
1774#undef JSON_HEDLEY_ARRAY_PARAM
1775#endif
1776#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__STDC_NO_VLA__) && !defined(__cplusplus) \
1777 && !defined(JSON_HEDLEY_PGI_VERSION) && !defined(JSON_HEDLEY_TINYC_VERSION)
1778#define JSON_HEDLEY_ARRAY_PARAM(name) (name)
1779#else
1780#define JSON_HEDLEY_ARRAY_PARAM(name)
1781#endif
1782
1783#if defined(JSON_HEDLEY_IS_CONSTANT)
1784#undef JSON_HEDLEY_IS_CONSTANT
1785#endif
1786#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
1787#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
1788#endif
1789/* JSON_HEDLEY_IS_CONSTEXPR_ is for
1790 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1791#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1792#undef JSON_HEDLEY_IS_CONSTEXPR_
1793#endif
1794#if JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 4, 0) \
1795 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_TINYC_VERSION_CHECK(0, 9, 19) \
1796 || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(13, 1, 0) \
1797 || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 1, 0) \
1798 || (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0) && !defined(__cplusplus)) \
1799 || JSON_HEDLEY_CRAY_VERSION_CHECK(8, 1, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1800#define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
1801#endif
1802#if !defined(__cplusplus)
1803#if JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 4, 0) \
1804 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(13, 1, 0) \
1805 || JSON_HEDLEY_CRAY_VERSION_CHECK(8, 1, 0) || JSON_HEDLEY_ARM_VERSION_CHECK(5, 4, 0) \
1806 || JSON_HEDLEY_TINYC_VERSION_CHECK(0, 9, 24)
1807#if defined(__INTPTR_TYPE__)
1808#define JSON_HEDLEY_IS_CONSTEXPR_(expr) \
1809 __builtin_types_compatible_p(__typeof__((1 ? (void*)((__INTPTR_TYPE__)((expr) * 0)) : (int*)0)), int*)
1810#else
1811#include <stdint.h>
1812#define JSON_HEDLEY_IS_CONSTEXPR_(expr) \
1813 __builtin_types_compatible_p(__typeof__((1 ? (void*)((intptr_t)((expr) * 0)) : (int*)0)), int*)
1814#endif
1815#elif (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(JSON_HEDLEY_SUNPRO_VERSION) \
1816 && !defined(JSON_HEDLEY_PGI_VERSION) && !defined(JSON_HEDLEY_IAR_VERSION)) \
1817 || (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) \
1818 || JSON_HEDLEY_GCC_VERSION_CHECK(4, 9, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(17, 0, 0) \
1819 || JSON_HEDLEY_IBM_VERSION_CHECK(12, 1, 0) || JSON_HEDLEY_ARM_VERSION_CHECK(5, 3, 0)
1820#if defined(__INTPTR_TYPE__)
1821#define JSON_HEDLEY_IS_CONSTEXPR_(expr) \
1822 _Generic((1 ? (void*)((__INTPTR_TYPE__)((expr) * 0)) : (int*)0), int*: 1, void*: 0)
1823#else
1824#include <stdint.h>
1825#define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*)((intptr_t)*0) : (int*)0), int*: 1, void*: 0)
1826#endif
1827#elif defined(JSON_HEDLEY_GCC_VERSION) || defined(JSON_HEDLEY_INTEL_VERSION) || defined(JSON_HEDLEY_TINYC_VERSION) \
1828 || defined(JSON_HEDLEY_TI_ARMCL_VERSION) || JSON_HEDLEY_TI_CL430_VERSION_CHECK(18, 12, 0) \
1829 || defined(JSON_HEDLEY_TI_CL2000_VERSION) || defined(JSON_HEDLEY_TI_CL6X_VERSION) \
1830 || defined(JSON_HEDLEY_TI_CL7X_VERSION) || defined(JSON_HEDLEY_TI_CLPRU_VERSION) || defined(__clang__)
1831#define JSON_HEDLEY_IS_CONSTEXPR_(expr) \
1832 (sizeof(void) != sizeof(*(1 ? ((void*)((expr) * 0L)) : ((struct { char v[sizeof(void) * 2]; }*)1))))
1833#endif
1834#endif
1835#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1836#if !defined(JSON_HEDLEY_IS_CONSTANT)
1837#define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
1838#endif
1839#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
1840#else
1841#if !defined(JSON_HEDLEY_IS_CONSTANT)
1842#define JSON_HEDLEY_IS_CONSTANT(expr) (0)
1843#endif
1844#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
1845#endif
1846
1847#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
1848#undef JSON_HEDLEY_BEGIN_C_DECLS
1849#endif
1850#if defined(JSON_HEDLEY_END_C_DECLS)
1851#undef JSON_HEDLEY_END_C_DECLS
1852#endif
1853#if defined(JSON_HEDLEY_C_DECL)
1854#undef JSON_HEDLEY_C_DECL
1855#endif
1856#if defined(__cplusplus)
1857#define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
1858#define JSON_HEDLEY_END_C_DECLS }
1859#define JSON_HEDLEY_C_DECL extern "C"
1860#else
1861#define JSON_HEDLEY_BEGIN_C_DECLS
1862#define JSON_HEDLEY_END_C_DECLS
1863#define JSON_HEDLEY_C_DECL
1864#endif
1865
1866#if defined(JSON_HEDLEY_STATIC_ASSERT)
1867#undef JSON_HEDLEY_STATIC_ASSERT
1868#endif
1869#if !defined(__cplusplus) \
1870 && ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) \
1871 || (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) \
1872 || JSON_HEDLEY_GCC_VERSION_CHECK(6, 0, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) \
1873 || defined(_Static_assert))
1874#define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
1875#elif (defined(__cplusplus) && (__cplusplus >= 201103L)) || JSON_HEDLEY_MSVC_VERSION_CHECK(16, 0, 0) \
1876 || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1877#define JSON_HEDLEY_STATIC_ASSERT(expr, message) \
1878 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
1879#else
1880#define JSON_HEDLEY_STATIC_ASSERT(expr, message)
1881#endif
1882
1883#if defined(JSON_HEDLEY_NULL)
1884#undef JSON_HEDLEY_NULL
1885#endif
1886#if defined(__cplusplus)
1887#if __cplusplus >= 201103L
1888#define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
1889#elif defined(NULL)
1890#define JSON_HEDLEY_NULL NULL
1891#else
1892#define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
1893#endif
1894#elif defined(NULL)
1895#define JSON_HEDLEY_NULL NULL
1896#else
1897#define JSON_HEDLEY_NULL ((void*)0)
1898#endif
1899
1900#if defined(JSON_HEDLEY_MESSAGE)
1901#undef JSON_HEDLEY_MESSAGE
1902#endif
1903#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1904#define JSON_HEDLEY_MESSAGE(msg) \
1905 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1906 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
1907 JSON_HEDLEY_PRAGMA(message msg) \
1908 JSON_HEDLEY_DIAGNOSTIC_POP
1909#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 4, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0)
1910#define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
1911#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5, 0, 0)
1912#define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
1913#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0)
1914#define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
1915#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2, 0, 0)
1916#define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
1917#else
1918#define JSON_HEDLEY_MESSAGE(msg)
1919#endif
1920
1921#if defined(JSON_HEDLEY_WARNING)
1922#undef JSON_HEDLEY_WARNING
1923#endif
1924#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1925#define JSON_HEDLEY_WARNING(msg) \
1926 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1927 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
1928 JSON_HEDLEY_PRAGMA(clang warning msg) \
1929 JSON_HEDLEY_DIAGNOSTIC_POP
1930#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 8, 0) || JSON_HEDLEY_PGI_VERSION_CHECK(18, 4, 0) \
1931 || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0)
1932#define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
1933#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1934#define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
1935#else
1936#define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
1937#endif
1938
1939#if defined(JSON_HEDLEY_REQUIRE)
1940#undef JSON_HEDLEY_REQUIRE
1941#endif
1942#if defined(JSON_HEDLEY_REQUIRE_MSG)
1943#undef JSON_HEDLEY_REQUIRE_MSG
1944#endif
1945#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
1946#if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
1947#define JSON_HEDLEY_REQUIRE(expr) \
1948 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1949 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
1950 __attribute__((diagnose_if(!(expr), #expr, "error"))) JSON_HEDLEY_DIAGNOSTIC_POP
1951#define JSON_HEDLEY_REQUIRE_MSG(expr, msg) \
1952 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1953 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
1954 __attribute__((diagnose_if(!(expr), msg, "error"))) JSON_HEDLEY_DIAGNOSTIC_POP
1955#else
1956#define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
1957#define JSON_HEDLEY_REQUIRE_MSG(expr, msg) __attribute__((diagnose_if(!(expr), msg, "error")))
1958#endif
1959#else
1960#define JSON_HEDLEY_REQUIRE(expr)
1961#define JSON_HEDLEY_REQUIRE_MSG(expr, msg)
1962#endif
1963
1964#if defined(JSON_HEDLEY_FLAGS)
1965#undef JSON_HEDLEY_FLAGS
1966#endif
1967#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) \
1968 && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
1969#define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
1970#else
1971#define JSON_HEDLEY_FLAGS
1972#endif
1973
1974#if defined(JSON_HEDLEY_FLAGS_CAST)
1975#undef JSON_HEDLEY_FLAGS_CAST
1976#endif
1977#if JSON_HEDLEY_INTEL_VERSION_CHECK(19, 0, 0)
1978#define JSON_HEDLEY_FLAGS_CAST(T, expr) \
1979 (__extension__({ \
1980 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1981 _Pragma("warning(disable:188)")((T)(expr)); \
1982 JSON_HEDLEY_DIAGNOSTIC_POP \
1983 }))
1984#else
1985#define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
1986#endif
1987
1988#if defined(JSON_HEDLEY_EMPTY_BASES)
1989#undef JSON_HEDLEY_EMPTY_BASES
1990#endif
1991#if (JSON_HEDLEY_MSVC_VERSION_CHECK(19, 0, 23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20, 0, 0)) \
1992 || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1993#define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
1994#else
1995#define JSON_HEDLEY_EMPTY_BASES
1996#endif
1997
1998/* Remaining macros are deprecated. */
1999
2000#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2001#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2002#endif
2003#if defined(__clang__)
2004#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major, minor, patch) (0)
2005#else
2006#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major, minor, patch) JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch)
2007#endif
2008
2009#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2010#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2011#endif
2012#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2013
2014#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2015#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2016#endif
2017#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2018
2019#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2020#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2021#endif
2022#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2023
2024#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2025#undef JSON_HEDLEY_CLANG_HAS_FEATURE
2026#endif
2027#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2028
2029#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2030#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2031#endif
2032#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2033
2034#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2035#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2036#endif
2037#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2038
2039#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2040#undef JSON_HEDLEY_CLANG_HAS_WARNING
2041#endif
2042#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2043
2044#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2045
2046// #include <nlohmann/detail/meta/detected.hpp>
2047
2048#include <type_traits>
2049
2050// #include <nlohmann/detail/meta/void_t.hpp>
2051
2052namespace nlohmann
2053{
2054namespace detail
2055{
2056template<typename... Ts>
2058{
2059 using type = void;
2060};
2061template<typename... Ts>
2062using void_t = typename make_void<Ts...>::type;
2063} // namespace detail
2064} // namespace nlohmann
2065
2066// https://en.cppreference.com/w/cpp/experimental/is_detected
2067namespace nlohmann
2068{
2069namespace detail
2070{
2072{
2073 nonesuch() = delete;
2074 ~nonesuch() = delete;
2075 nonesuch(nonesuch const&) = delete;
2076 nonesuch(nonesuch const&&) = delete;
2077 void operator=(nonesuch const&) = delete;
2078 void operator=(nonesuch&&) = delete;
2079};
2080
2081template<class Default, class AlwaysVoid, template<class...> class Op, class... Args>
2083{
2084 using value_t = std::false_type;
2085 using type = Default;
2086};
2087
2088template<class Default, template<class...> class Op, class... Args>
2089struct detector<Default, void_t<Op<Args...>>, Op, Args...>
2090{
2091 using value_t = std::true_type;
2092 using type = Op<Args...>;
2093};
2094
2095template<template<class...> class Op, class... Args>
2096using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
2097
2098template<template<class...> class Op, class... Args>
2099struct is_detected_lazy : is_detected<Op, Args...>
2100{};
2101
2102template<template<class...> class Op, class... Args>
2103using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
2104
2105template<class Default, template<class...> class Op, class... Args>
2106using detected_or = detector<Default, void, Op, Args...>;
2107
2108template<class Default, template<class...> class Op, class... Args>
2109using detected_or_t = typename detected_or<Default, Op, Args...>::type;
2110
2111template<class Expected, template<class...> class Op, class... Args>
2112using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
2113
2114template<class To, template<class...> class Op, class... Args>
2115using is_detected_convertible = std::is_convertible<detected_t<Op, Args...>, To>;
2116} // namespace detail
2117} // namespace nlohmann
2118
2119// This file contains all internal macro definitions
2120// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2121
2122// exclude unsupported compilers
2123#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2124#if defined(__clang__)
2125#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2126#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2127#endif
2128#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2129#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2130#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2131#endif
2132#endif
2133#endif
2134
2135// C++ language standard detection
2136// if the user manually specified the used c++ version this is skipped
2137#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2138#if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2139#define JSON_HAS_CPP_20
2140#define JSON_HAS_CPP_17
2141#define JSON_HAS_CPP_14
2142#elif (defined(__cplusplus) && __cplusplus >= 201703L) \
2143 || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2144#define JSON_HAS_CPP_17
2145#define JSON_HAS_CPP_14
2146#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2147#define JSON_HAS_CPP_14
2148#endif
2149 // the cpp 11 flag is always specified because it is the minimal required version
2150#define JSON_HAS_CPP_11
2151#endif
2152
2153#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2154#ifdef JSON_HAS_CPP_17
2155#if defined(__cpp_lib_filesystem)
2156#define JSON_HAS_FILESYSTEM 1
2157#elif defined(__cpp_lib_experimental_filesystem)
2158#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2159#elif !defined(__has_include)
2160#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2161#elif __has_include(<filesystem>)
2162#define JSON_HAS_FILESYSTEM 1
2163#elif __has_include(<experimental/filesystem>)
2164#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2165#endif
2166
2167// std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2168#if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2169#undef JSON_HAS_FILESYSTEM
2170#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2171#endif
2172
2173// no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2174#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2175#undef JSON_HAS_FILESYSTEM
2176#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2177#endif
2178
2179// no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2180#if defined(__clang_major__) && __clang_major__ < 7
2181#undef JSON_HAS_FILESYSTEM
2182#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2183#endif
2184
2185// no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2186#if defined(_MSC_VER) && _MSC_VER < 1940
2187#undef JSON_HAS_FILESYSTEM
2188#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2189#endif
2190
2191// no filesystem support before iOS 13
2192#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2193#undef JSON_HAS_FILESYSTEM
2194#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2195#endif
2196
2197// no filesystem support before macOS Catalina
2198#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2199#undef JSON_HAS_FILESYSTEM
2200#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2201#endif
2202#endif
2203#endif
2204
2205#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2206#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2207#endif
2208
2209#ifndef JSON_HAS_FILESYSTEM
2210#define JSON_HAS_FILESYSTEM 0
2211#endif
2212
2213// disable documentation warnings on clang
2214#if defined(__clang__)
2215#pragma clang diagnostic push
2216#pragma clang diagnostic ignored "-Wdocumentation"
2217#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2218#endif
2219
2220// allow disabling exceptions
2221#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2222#define JSON_THROW(exception) throw exception
2223#define JSON_TRY try
2224#define JSON_CATCH(exception) catch (exception)
2225#define JSON_INTERNAL_CATCH(exception) catch (exception)
2226#else
2227#include <cstdlib>
2228#define JSON_THROW(exception) std::abort()
2229#define JSON_TRY if (true)
2230#define JSON_CATCH(exception) if (false)
2231#define JSON_INTERNAL_CATCH(exception) if (false)
2232#endif
2233
2234// override exception macros
2235#if defined(JSON_THROW_USER)
2236#undef JSON_THROW
2237#define JSON_THROW JSON_THROW_USER
2238#endif
2239#if defined(JSON_TRY_USER)
2240#undef JSON_TRY
2241#define JSON_TRY JSON_TRY_USER
2242#endif
2243#if defined(JSON_CATCH_USER)
2244#undef JSON_CATCH
2245#define JSON_CATCH JSON_CATCH_USER
2246#undef JSON_INTERNAL_CATCH
2247#define JSON_INTERNAL_CATCH JSON_CATCH_USER
2248#endif
2249#if defined(JSON_INTERNAL_CATCH_USER)
2250#undef JSON_INTERNAL_CATCH
2251#define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2252#endif
2253
2254// allow overriding assert
2255#if !defined(JSON_ASSERT)
2256#include <cassert> // assert
2257#define JSON_ASSERT(x) assert(x)
2258#endif
2259
2260// allow to access some private functions (needed by the test suite)
2261#if defined(JSON_TESTS_PRIVATE)
2262#define JSON_PRIVATE_UNLESS_TESTED public
2263#else
2264#define JSON_PRIVATE_UNLESS_TESTED private
2265#endif
2266
2267/*!
2268@brief macro to briefly define a mapping between an enum and JSON
2269@def NLOHMANN_JSON_SERIALIZE_ENUM
2270@since version 3.4.0
2271*/
2272#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2273 template<typename BasicJsonType> \
2274 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2275 { \
2276 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2277 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2278 auto it = \
2279 std::find_if(std::begin(m), std::end(m), [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool { \
2280 return ej_pair.first == e; \
2281 }); \
2282 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2283 } \
2284 template<typename BasicJsonType> \
2285 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2286 { \
2287 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2288 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2289 auto it = std::find_if( \
2290 std::begin(m), std::end(m), \
2291 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool { return ej_pair.second == j; }); \
2292 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2293 }
2294
2295// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2296// may be removed in the future once the class is split.
2297
2298#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2299 template<template<typename, typename, typename...> class ObjectType, \
2300 template<typename, typename...> class ArrayType, class StringType, class BooleanType, \
2301 class NumberIntegerType, class NumberUnsignedType, class NumberFloatType, \
2302 template<typename> class AllocatorType, template<typename, typename = void> class JSONSerializer, \
2303 class BinaryType>
2304
2305#define NLOHMANN_BASIC_JSON_TPL \
2306 basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2307 AllocatorType, JSONSerializer, BinaryType>
2308
2309// Macros to simplify conversion from/to types
2310
2311#define NLOHMANN_JSON_EXPAND(x) x
2312#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \
2313 _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, \
2314 _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, \
2315 _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME, ...) \
2316 NAME
2317#define NLOHMANN_JSON_PASTE(...) \
2318 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO( \
2319 __VA_ARGS__, NLOHMANN_JSON_PASTE64, NLOHMANN_JSON_PASTE63, NLOHMANN_JSON_PASTE62, NLOHMANN_JSON_PASTE61, \
2320 NLOHMANN_JSON_PASTE60, NLOHMANN_JSON_PASTE59, NLOHMANN_JSON_PASTE58, NLOHMANN_JSON_PASTE57, \
2321 NLOHMANN_JSON_PASTE56, NLOHMANN_JSON_PASTE55, NLOHMANN_JSON_PASTE54, NLOHMANN_JSON_PASTE53, \
2322 NLOHMANN_JSON_PASTE52, NLOHMANN_JSON_PASTE51, NLOHMANN_JSON_PASTE50, NLOHMANN_JSON_PASTE49, \
2323 NLOHMANN_JSON_PASTE48, NLOHMANN_JSON_PASTE47, NLOHMANN_JSON_PASTE46, NLOHMANN_JSON_PASTE45, \
2324 NLOHMANN_JSON_PASTE44, NLOHMANN_JSON_PASTE43, NLOHMANN_JSON_PASTE42, NLOHMANN_JSON_PASTE41, \
2325 NLOHMANN_JSON_PASTE40, NLOHMANN_JSON_PASTE39, NLOHMANN_JSON_PASTE38, NLOHMANN_JSON_PASTE37, \
2326 NLOHMANN_JSON_PASTE36, NLOHMANN_JSON_PASTE35, NLOHMANN_JSON_PASTE34, NLOHMANN_JSON_PASTE33, \
2327 NLOHMANN_JSON_PASTE32, NLOHMANN_JSON_PASTE31, NLOHMANN_JSON_PASTE30, NLOHMANN_JSON_PASTE29, \
2328 NLOHMANN_JSON_PASTE28, NLOHMANN_JSON_PASTE27, NLOHMANN_JSON_PASTE26, NLOHMANN_JSON_PASTE25, \
2329 NLOHMANN_JSON_PASTE24, NLOHMANN_JSON_PASTE23, NLOHMANN_JSON_PASTE22, NLOHMANN_JSON_PASTE21, \
2330 NLOHMANN_JSON_PASTE20, NLOHMANN_JSON_PASTE19, NLOHMANN_JSON_PASTE18, NLOHMANN_JSON_PASTE17, \
2331 NLOHMANN_JSON_PASTE16, NLOHMANN_JSON_PASTE15, NLOHMANN_JSON_PASTE14, NLOHMANN_JSON_PASTE13, \
2332 NLOHMANN_JSON_PASTE12, NLOHMANN_JSON_PASTE11, NLOHMANN_JSON_PASTE10, NLOHMANN_JSON_PASTE9, \
2333 NLOHMANN_JSON_PASTE8, NLOHMANN_JSON_PASTE7, NLOHMANN_JSON_PASTE6, NLOHMANN_JSON_PASTE5, NLOHMANN_JSON_PASTE4, \
2334 NLOHMANN_JSON_PASTE3, NLOHMANN_JSON_PASTE2, NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2335#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2336#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2337#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2338#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2339#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) \
2340 NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2341#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) \
2342 NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2343#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) \
2344 NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2345#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) \
2346 NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2347#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) \
2348 NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2349#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) \
2350 NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2351#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) \
2352 NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2353#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) \
2354 NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2355#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) \
2356 NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2357#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) \
2358 NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2359#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \
2360 NLOHMANN_JSON_PASTE2(func, v1) \
2361 NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2362#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) \
2363 NLOHMANN_JSON_PASTE2(func, v1) \
2364 NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2365#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) \
2366 NLOHMANN_JSON_PASTE2(func, v1) \
2367 NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
2368#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) \
2369 NLOHMANN_JSON_PASTE2(func, v1) \
2370 NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
2371#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2372 v19) \
2373 NLOHMANN_JSON_PASTE2(func, v1) \
2374 NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
2375#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2376 v19, v20) \
2377 NLOHMANN_JSON_PASTE2(func, v1) \
2378 NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
2379#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2380 v19, v20, v21) \
2381 NLOHMANN_JSON_PASTE2(func, v1) \
2382 NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2383 v21)
2384#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2385 v19, v20, v21, v22) \
2386 NLOHMANN_JSON_PASTE2(func, v1) \
2387 NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2388 v21, v22)
2389#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2390 v19, v20, v21, v22, v23) \
2391 NLOHMANN_JSON_PASTE2(func, v1) \
2392 NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2393 v21, v22, v23)
2394#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2395 v19, v20, v21, v22, v23, v24) \
2396 NLOHMANN_JSON_PASTE2(func, v1) \
2397 NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2398 v21, v22, v23, v24)
2399#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2400 v19, v20, v21, v22, v23, v24, v25) \
2401 NLOHMANN_JSON_PASTE2(func, v1) \
2402 NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2403 v21, v22, v23, v24, v25)
2404#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2405 v19, v20, v21, v22, v23, v24, v25, v26) \
2406 NLOHMANN_JSON_PASTE2(func, v1) \
2407 NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2408 v21, v22, v23, v24, v25, v26)
2409#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2410 v19, v20, v21, v22, v23, v24, v25, v26, v27) \
2411 NLOHMANN_JSON_PASTE2(func, v1) \
2412 NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2413 v21, v22, v23, v24, v25, v26, v27)
2414#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2415 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) \
2416 NLOHMANN_JSON_PASTE2(func, v1) \
2417 NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2418 v21, v22, v23, v24, v25, v26, v27, v28)
2419#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2420 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) \
2421 NLOHMANN_JSON_PASTE2(func, v1) \
2422 NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2423 v21, v22, v23, v24, v25, v26, v27, v28, v29)
2424#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2425 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) \
2426 NLOHMANN_JSON_PASTE2(func, v1) \
2427 NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2428 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2429#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2430 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) \
2431 NLOHMANN_JSON_PASTE2(func, v1) \
2432 NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2433 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
2434#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2435 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) \
2436 NLOHMANN_JSON_PASTE2(func, v1) \
2437 NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2438 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
2439#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2440 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) \
2441 NLOHMANN_JSON_PASTE2(func, v1) \
2442 NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2443 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
2444#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2445 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) \
2446 NLOHMANN_JSON_PASTE2(func, v1) \
2447 NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2448 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
2449#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2450 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) \
2451 NLOHMANN_JSON_PASTE2(func, v1) \
2452 NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2453 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
2454#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2455 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2456 v36) \
2457 NLOHMANN_JSON_PASTE2(func, v1) \
2458 NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2459 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
2460#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2461 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2462 v36, v37) \
2463 NLOHMANN_JSON_PASTE2(func, v1) \
2464 NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2465 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
2466#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2467 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2468 v36, v37, v38) \
2469 NLOHMANN_JSON_PASTE2(func, v1) \
2470 NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2471 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
2472#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2473 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2474 v36, v37, v38, v39) \
2475 NLOHMANN_JSON_PASTE2(func, v1) \
2476 NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2477 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2478 v39)
2479#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2480 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2481 v36, v37, v38, v39, v40) \
2482 NLOHMANN_JSON_PASTE2(func, v1) \
2483 NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2484 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2485 v39, v40)
2486#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2487 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2488 v36, v37, v38, v39, v40, v41) \
2489 NLOHMANN_JSON_PASTE2(func, v1) \
2490 NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2491 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2492 v39, v40, v41)
2493#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2494 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2495 v36, v37, v38, v39, v40, v41, v42) \
2496 NLOHMANN_JSON_PASTE2(func, v1) \
2497 NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2498 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2499 v39, v40, v41, v42)
2500#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2501 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2502 v36, v37, v38, v39, v40, v41, v42, v43) \
2503 NLOHMANN_JSON_PASTE2(func, v1) \
2504 NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2505 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2506 v39, v40, v41, v42, v43)
2507#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2508 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2509 v36, v37, v38, v39, v40, v41, v42, v43, v44) \
2510 NLOHMANN_JSON_PASTE2(func, v1) \
2511 NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2512 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2513 v39, v40, v41, v42, v43, v44)
2514#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2515 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2516 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) \
2517 NLOHMANN_JSON_PASTE2(func, v1) \
2518 NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2519 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2520 v39, v40, v41, v42, v43, v44, v45)
2521#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2522 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2523 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) \
2524 NLOHMANN_JSON_PASTE2(func, v1) \
2525 NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2526 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2527 v39, v40, v41, v42, v43, v44, v45, v46)
2528#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2529 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2530 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) \
2531 NLOHMANN_JSON_PASTE2(func, v1) \
2532 NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2533 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2534 v39, v40, v41, v42, v43, v44, v45, v46, v47)
2535#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2536 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2537 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) \
2538 NLOHMANN_JSON_PASTE2(func, v1) \
2539 NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2540 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2541 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
2542#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2543 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2544 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) \
2545 NLOHMANN_JSON_PASTE2(func, v1) \
2546 NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2547 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2548 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
2549#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2550 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2551 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) \
2552 NLOHMANN_JSON_PASTE2(func, v1) \
2553 NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2554 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2555 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
2556#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2557 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2558 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) \
2559 NLOHMANN_JSON_PASTE2(func, v1) \
2560 NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2561 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2562 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
2563#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2564 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2565 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) \
2566 NLOHMANN_JSON_PASTE2(func, v1) \
2567 NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2568 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2569 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
2570#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2571 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2572 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, \
2573 v53) \
2574 NLOHMANN_JSON_PASTE2(func, v1) \
2575 NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2576 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2577 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
2578#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2579 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2580 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, \
2581 v53, v54) \
2582 NLOHMANN_JSON_PASTE2(func, v1) \
2583 NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2584 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2585 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2586#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2587 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2588 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, \
2589 v53, v54, v55) \
2590 NLOHMANN_JSON_PASTE2(func, v1) \
2591 NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2592 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2593 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2594#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2595 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2596 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, \
2597 v53, v54, v55, v56) \
2598 NLOHMANN_JSON_PASTE2(func, v1) \
2599 NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2600 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2601 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2602#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2603 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2604 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, \
2605 v53, v54, v55, v56, v57) \
2606 NLOHMANN_JSON_PASTE2(func, v1) \
2607 NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2608 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2609 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, \
2610 v57)
2611#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2612 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2613 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, \
2614 v53, v54, v55, v56, v57, v58) \
2615 NLOHMANN_JSON_PASTE2(func, v1) \
2616 NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2617 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2618 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, \
2619 v57, v58)
2620#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2621 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2622 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, \
2623 v53, v54, v55, v56, v57, v58, v59) \
2624 NLOHMANN_JSON_PASTE2(func, v1) \
2625 NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2626 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2627 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, \
2628 v57, v58, v59)
2629#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2630 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2631 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, \
2632 v53, v54, v55, v56, v57, v58, v59, v60) \
2633 NLOHMANN_JSON_PASTE2(func, v1) \
2634 NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2635 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2636 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, \
2637 v57, v58, v59, v60)
2638#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2639 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2640 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, \
2641 v53, v54, v55, v56, v57, v58, v59, v60, v61) \
2642 NLOHMANN_JSON_PASTE2(func, v1) \
2643 NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2644 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2645 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, \
2646 v57, v58, v59, v60, v61)
2647#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2648 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2649 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, \
2650 v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) \
2651 NLOHMANN_JSON_PASTE2(func, v1) \
2652 NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2653 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2654 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, \
2655 v57, v58, v59, v60, v61, v62)
2656#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, \
2657 v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, \
2658 v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, \
2659 v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) \
2660 NLOHMANN_JSON_PASTE2(func, v1) \
2661 NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
2662 v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2663 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, \
2664 v57, v58, v59, v60, v61, v62, v63)
2665
2666#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2667#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2668
2669/*!
2670@brief macro
2671@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
2672@since version 3.9.0
2673*/
2674#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2675 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) \
2676 { \
2677 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \
2678 } \
2679 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) \
2680 { \
2681 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) \
2682 }
2683
2684/*!
2685@brief macro
2686@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
2687@since version 3.9.0
2688*/
2689#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2690 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) \
2691 { \
2692 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \
2693 } \
2694 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) \
2695 { \
2696 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) \
2697 }
2698
2699// inspired from https://stackoverflow.com/a/26745591
2700// allows to call any std function as if (e.g. with begin):
2701// using std::begin; begin(x);
2702//
2703// it allows using the detected idiom to retrieve the return type
2704// of such an expression
2705#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2706 namespace detail \
2707 { \
2708 using std::std_name; \
2709 \
2710 template<typename... T> \
2711 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2712 } \
2713 \
2714 namespace detail2 \
2715 { \
2716 struct std_name##_tag \
2717 {}; \
2718 \
2719 template<typename... T> \
2720 std_name##_tag std_name(T&&...); \
2721 \
2722 template<typename... T> \
2723 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2724 \
2725 template<typename... T> \
2726 struct would_call_std_##std_name \
2727 { \
2728 static constexpr auto const value = \
2729 ::nlohmann::detail::is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2730 }; \
2731 } /* namespace detail2 */ \
2732 \
2733 template<typename... T> \
2734 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2735 {}
2736
2737#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2738#define JSON_USE_IMPLICIT_CONVERSIONS 1
2739#endif
2740
2741#if JSON_USE_IMPLICIT_CONVERSIONS
2742#define JSON_EXPLICIT
2743#else
2744#define JSON_EXPLICIT explicit
2745#endif
2746
2747#ifndef JSON_DIAGNOSTICS
2748#define JSON_DIAGNOSTICS 0
2749#endif
2750
2751namespace nlohmann
2752{
2753namespace detail
2754{
2755
2756/*!
2757@brief replace all occurrences of a substring by another string
2758
2759@param[in,out] s the string to manipulate; changed so that all
2760 occurrences of @a f are replaced with @a t
2761@param[in] f the substring to replace with @a t
2762@param[in] t the string to replace @a f
2763
2764@pre The search string @a f must not be empty. **This precondition is
2765enforced with an assertion.**
2766
2767@since version 2.0.0
2768*/
2769inline void replace_substring(std::string& s, const std::string& f, const std::string& t)
2770{
2771 JSON_ASSERT(!f.empty());
2772 for (auto pos = s.find(f); // find first occurrence of f
2773 pos != std::string::npos; // make sure f was found
2774 s.replace(pos, f.size(), t), // replace with t, and
2775 pos = s.find(f, pos + t.size())) // find next occurrence of f
2776 {}
2777}
2778
2779/*!
2780 * @brief string escaping as described in RFC 6901 (Sect. 4)
2781 * @param[in] s string to escape
2782 * @return escaped string
2783 *
2784 * Note the order of escaping "~" to "~0" and "/" to "~1" is important.
2785 */
2786inline std::string escape(std::string s)
2787{
2788 replace_substring(s, "~", "~0");
2789 replace_substring(s, "/", "~1");
2790 return s;
2791}
2792
2793/*!
2794 * @brief string unescaping as described in RFC 6901 (Sect. 4)
2795 * @param[in] s string to unescape
2796 * @return unescaped string
2797 *
2798 * Note the order of escaping "~1" to "/" and "~0" to "~" is important.
2799 */
2800static void unescape(std::string& s)
2801{
2802 replace_substring(s, "~1", "/");
2803 replace_substring(s, "~0", "~");
2804}
2805
2806} // namespace detail
2807} // namespace nlohmann
2808
2809// #include <nlohmann/detail/input/position_t.hpp>
2810
2811#include <cstddef> // size_t
2812
2813namespace nlohmann
2814{
2815namespace detail
2816{
2817/// struct to capture the start position of the current token
2819{
2820 /// the total number of characters read
2821 std::size_t chars_read_total = 0;
2822 /// the number of characters read in the current line
2824 /// the number of lines read
2825 std::size_t lines_read = 0;
2826
2827 /// conversion to size_t to preserve SAX interface
2828 constexpr operator size_t() const { return chars_read_total; }
2829};
2830
2831} // namespace detail
2832} // namespace nlohmann
2833
2834// #include <nlohmann/detail/macro_scope.hpp>
2835
2836namespace nlohmann
2837{
2838namespace detail
2839{
2840////////////////
2841// exceptions //
2842////////////////
2843
2844/// @brief general exception of the @ref basic_json class
2845/// @sa https://json.nlohmann.me/api/basic_json/exception/
2846class exception : public std::exception
2847{
2848 public:
2849 /// returns the explanatory string
2850 const char* what() const noexcept override { return m.what(); }
2851
2852 /// the id of the exception
2853 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
2854
2855 protected:
2857 exception(int id_, const char* what_arg)
2858 : id(id_)
2859 , m(what_arg)
2860 {} // NOLINT(bugprone-throw-keyword-missing)
2861
2862 static std::string name(const std::string& ename, int id_)
2863 {
2864 return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
2865 }
2866
2867 template<typename BasicJsonType>
2868 static std::string diagnostics(const BasicJsonType& leaf_element)
2869 {
2870#if JSON_DIAGNOSTICS
2871 std::vector<std::string> tokens;
2872 for (const auto* current = &leaf_element; current->m_parent != nullptr; current = current->m_parent) {
2873 switch (current->m_parent->type()) {
2874 case value_t::array: {
2875 for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i) {
2876 if (&current->m_parent->m_value.array->operator[](i) == current) {
2877 tokens.emplace_back(std::to_string(i));
2878 break;
2879 }
2880 }
2881 break;
2882 }
2883
2884 case value_t::object: {
2885 for (const auto& element : *current->m_parent->m_value.object) {
2886 if (&element.second == current) {
2887 tokens.emplace_back(element.first.c_str());
2888 break;
2889 }
2890 }
2891 break;
2892 }
2893
2894 case value_t::null: // LCOV_EXCL_LINE
2895 case value_t::string: // LCOV_EXCL_LINE
2896 case value_t::boolean: // LCOV_EXCL_LINE
2897 case value_t::number_integer: // LCOV_EXCL_LINE
2898 case value_t::number_unsigned: // LCOV_EXCL_LINE
2899 case value_t::number_float: // LCOV_EXCL_LINE
2900 case value_t::binary: // LCOV_EXCL_LINE
2901 case value_t::discarded: // LCOV_EXCL_LINE
2902 default: // LCOV_EXCL_LINE
2903 break; // LCOV_EXCL_LINE
2904 }
2905 }
2906
2907 if (tokens.empty()) {
2908 return "";
2909 }
2910
2911 return "("
2912 + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
2913 [](const std::string& a, const std::string& b) { return a + "/" + detail::escape(b); })
2914 + ") ";
2915#else
2916 static_cast<void>(leaf_element);
2917 return "";
2918#endif
2919 }
2920
2921 private:
2922 /// an exception object as storage for error messages
2923 std::runtime_error m;
2924};
2925
2926/// @brief exception indicating a parse error
2927/// @sa https://json.nlohmann.me/api/basic_json/parse_error/
2929{
2930 public:
2931 /*!
2932 @brief create a parse error exception
2933 @param[in] id_ the id of the exception
2934 @param[in] pos the position where the error occurred (or with
2935 chars_read_total=0 if the position cannot be
2936 determined)
2937 @param[in] what_arg the explanatory string
2938 @return parse_error object
2939 */
2940 template<typename BasicJsonType>
2941 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context)
2942 {
2943 std::string w = exception::name("parse_error", id_) + "parse error" + position_string(pos) + ": "
2944 + exception::diagnostics(context) + what_arg;
2945 return {id_, pos.chars_read_total, w.c_str()};
2946 }
2947
2948 template<typename BasicJsonType>
2949 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context)
2950 {
2951 std::string w = exception::name("parse_error", id_) + "parse error"
2952 + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + ": "
2953 + exception::diagnostics(context) + what_arg;
2954 return {id_, byte_, w.c_str()};
2955 }
2956
2957 /*!
2958 @brief byte index of the parse error
2959
2960 The byte index of the last read character in the input file.
2961
2962 @note For an input with n bytes, 1 is the index of the first character and
2963 n+1 is the index of the terminating null byte or the end of file.
2964 This also holds true when reading a byte vector (CBOR or MessagePack).
2965 */
2966 const std::size_t byte;
2967
2968 private:
2969 parse_error(int id_, std::size_t byte_, const char* what_arg)
2970 : exception(id_, what_arg)
2971 , byte(byte_)
2972 {}
2973
2974 static std::string position_string(const position_t& pos)
2975 {
2976 return " at line " + std::to_string(pos.lines_read + 1) + ", column "
2977 + std::to_string(pos.chars_read_current_line);
2978 }
2979};
2980
2981/// @brief exception indicating errors with iterators
2982/// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
2984{
2985 public:
2986 template<typename BasicJsonType>
2987 static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context)
2988 {
2989 std::string w = exception::name("invalid_iterator", id_) + exception::diagnostics(context) + what_arg;
2990 return {id_, w.c_str()};
2991 }
2992
2993 private:
2995 invalid_iterator(int id_, const char* what_arg)
2996 : exception(id_, what_arg)
2997 {}
2998};
2999
3000/// @brief exception indicating executing a member function with a wrong type
3001/// @sa https://json.nlohmann.me/api/basic_json/type_error/
3002class type_error : public exception
3003{
3004 public:
3005 template<typename BasicJsonType>
3006 static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
3007 {
3008 std::string w = exception::name("type_error", id_) + exception::diagnostics(context) + what_arg;
3009 return {id_, w.c_str()};
3010 }
3011
3012 private:
3014 type_error(int id_, const char* what_arg)
3015 : exception(id_, what_arg)
3016 {}
3017};
3018
3019/// @brief exception indicating access out of the defined range
3020/// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
3022{
3023 public:
3024 template<typename BasicJsonType>
3025 static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context)
3026 {
3027 std::string w = exception::name("out_of_range", id_) + exception::diagnostics(context) + what_arg;
3028 return {id_, w.c_str()};
3029 }
3030
3031 private:
3033 out_of_range(int id_, const char* what_arg)
3034 : exception(id_, what_arg)
3035 {}
3036};
3037
3038/// @brief exception indicating other library errors
3039/// @sa https://json.nlohmann.me/api/basic_json/other_error/
3041{
3042 public:
3043 template<typename BasicJsonType>
3044 static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
3045 {
3046 std::string w = exception::name("other_error", id_) + exception::diagnostics(context) + what_arg;
3047 return {id_, w.c_str()};
3048 }
3049
3050 private:
3052 other_error(int id_, const char* what_arg)
3053 : exception(id_, what_arg)
3054 {}
3055};
3056
3057} // namespace detail
3058} // namespace nlohmann
3059
3060// #include <nlohmann/detail/macro_scope.hpp>
3061
3062// #include <nlohmann/detail/meta/cpp_future.hpp>
3063
3064#include <cstddef> // size_t
3065#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3066#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3067
3068// #include <nlohmann/detail/macro_scope.hpp>
3069
3070namespace nlohmann
3071{
3072namespace detail
3073{
3074
3075template<typename T>
3076using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3077
3078#ifdef JSON_HAS_CPP_14
3079
3080// the following utilities are natively available in C++14
3081using std::enable_if_t;
3082using std::index_sequence;
3083using std::index_sequence_for;
3084using std::make_index_sequence;
3085
3086#else
3087
3088// alias templates to reduce boilerplate
3089template<bool B, typename T = void>
3090using enable_if_t = typename std::enable_if<B, T>::type;
3091
3092// The following code is taken from
3093// https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h which is
3094// part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3095
3096//// START OF CODE FROM GOOGLE ABSEIL
3097
3098// integer_sequence
3099//
3100// Class template representing a compile-time integer sequence. An instantiation
3101// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3102// type through its template arguments (which is a common need when
3103// working with C++11 variadic templates). `absl::integer_sequence` is designed
3104// to be a drop-in replacement for C++14's `std::integer_sequence`.
3105//
3106// Example:
3107//
3108// template< class T, T... Ints >
3109// void user_function(integer_sequence<T, Ints...>);
3110//
3111// int main()
3112// {
3113// // user_function's `T` will be deduced to `int` and `Ints...`
3114// // will be deduced to `0, 1, 2, 3, 4`.
3115// user_function(make_integer_sequence<int, 5>());
3116// }
3117template<typename T, T... Ints>
3119{
3120 using value_type = T;
3121 static constexpr std::size_t size() noexcept { return sizeof...(Ints); }
3122};
3123
3124// index_sequence
3125//
3126// A helper template for an `integer_sequence` of `size_t`,
3127// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3128// `std::index_sequence`.
3129template<size_t... Ints>
3130using index_sequence = integer_sequence<size_t, Ints...>;
3131
3133{
3134
3135template<typename Seq, size_t SeqSize, size_t Rem>
3136struct Extend;
3137
3138// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3139template<typename T, T... Ints, size_t SeqSize>
3140struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3141{
3142 using type = integer_sequence<T, Ints..., (Ints + SeqSize)...>;
3143};
3144
3145template<typename T, T... Ints, size_t SeqSize>
3146struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3147{
3148 using type = integer_sequence<T, Ints..., (Ints + SeqSize)..., 2 * SeqSize>;
3149};
3150
3151// Recursion helper for 'make_integer_sequence<T, N>'.
3152// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3153template<typename T, size_t N>
3154struct Gen
3155{
3156 using type = typename Extend<typename Gen<T, N / 2>::type, N / 2, N % 2>::type;
3157};
3158
3159template<typename T>
3160struct Gen<T, 0>
3161{
3163};
3164
3165} // namespace utility_internal
3166
3167// Compile-time sequences of integers
3168
3169// make_integer_sequence
3170//
3171// This template alias is equivalent to
3172// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3173// replacement for C++14's `std::make_integer_sequence`.
3174template<typename T, T N>
3176
3177// make_index_sequence
3178//
3179// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3180// and is designed to be a drop-in replacement for C++14's
3181// `std::make_index_sequence`.
3182template<size_t N>
3184
3185// index_sequence_for
3186//
3187// Converts a typename pack into an index sequence of the same length, and
3188// is designed to be a drop-in replacement for C++14's
3189// `std::index_sequence_for()`
3190template<typename... Ts>
3192
3193//// END OF CODE FROM GOOGLE ABSEIL
3194
3195#endif
3196
3197// dispatch utility (taken from ranges-v3)
3198template<unsigned N>
3200{};
3201template<>
3203{};
3204
3205// taken from ranges-v3
3206template<typename T>
3208{
3209 static constexpr T value{};
3210};
3211
3212template<typename T>
3213constexpr T static_const<T>::value; // NOLINT(readability-redundant-declaration)
3214
3215} // namespace detail
3216} // namespace nlohmann
3217
3218// #include <nlohmann/detail/meta/identity_tag.hpp>
3219
3220namespace nlohmann
3221{
3222namespace detail
3223{
3224// dispatching helper struct
3225template<class T>
3227{};
3228} // namespace detail
3229} // namespace nlohmann
3230
3231// #include <nlohmann/detail/meta/type_traits.hpp>
3232
3233#include <limits> // numeric_limits
3234#include <tuple> // tuple
3235#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3236#include <utility> // declval
3237
3238// #include <nlohmann/detail/macro_scope.hpp>
3239
3240// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3241
3242#include <iterator> // random_access_iterator_tag
3243
3244// #include <nlohmann/detail/meta/void_t.hpp>
3245
3246// #include <nlohmann/detail/meta/cpp_future.hpp>
3247
3248namespace nlohmann
3249{
3250namespace detail
3251{
3252template<typename It, typename = void>
3254{};
3255
3256template<typename It>
3258 void_t<typename It::difference_type,
3259 typename It::value_type,
3260 typename It::pointer,
3261 typename It::reference,
3262 typename It::iterator_category>>
3263{
3264 using difference_type = typename It::difference_type;
3265 using value_type = typename It::value_type;
3266 using pointer = typename It::pointer;
3267 using reference = typename It::reference;
3268 using iterator_category = typename It::iterator_category;
3269};
3270
3271// This is required as some compilers implement std::iterator_traits in a way that
3272// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3273template<typename T, typename = void>
3275{};
3276
3277template<typename T>
3279{};
3280
3281template<typename T>
3283{
3284 using iterator_category = std::random_access_iterator_tag;
3285 using value_type = T;
3286 using difference_type = ptrdiff_t;
3287 using pointer = T*;
3288 using reference = T&;
3289};
3290} // namespace detail
3291} // namespace nlohmann
3292
3293// #include <nlohmann/detail/meta/call_std/begin.hpp>
3294
3295// #include <nlohmann/detail/macro_scope.hpp>
3296
3297namespace nlohmann
3298{
3300} // namespace nlohmann
3301
3302// #include <nlohmann/detail/meta/call_std/end.hpp>
3303
3304// #include <nlohmann/detail/macro_scope.hpp>
3305
3306namespace nlohmann
3307{
3309} // namespace nlohmann
3310
3311// #include <nlohmann/detail/meta/cpp_future.hpp>
3312
3313// #include <nlohmann/detail/meta/detected.hpp>
3314
3315// #include <nlohmann/json_fwd.hpp>
3316#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3317#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3318
3319#include <cstdint> // int64_t, uint64_t
3320#include <map> // map
3321#include <memory> // allocator
3322#include <string> // string
3323#include <vector> // vector
3324
3325/*!
3326@brief namespace for Niels Lohmann
3327@see https://github.com/nlohmann
3328@since version 1.0.0
3329*/
3330namespace nlohmann
3331{
3332/*!
3333@brief default JSONSerializer template argument
3334
3335This serializer ignores the template arguments and uses ADL
3336([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
3337for serialization.
3338*/
3339template<typename T = void, typename SFINAE = void>
3340struct adl_serializer;
3341
3342/// a class to store JSON values
3343/// @sa https://json.nlohmann.me/api/basic_json/
3344template<template<typename U, typename V, typename... Args> class ObjectType = std::map,
3345 template<typename U, typename... Args> class ArrayType = std::vector,
3346 class StringType = std::string,
3347 class BooleanType = bool,
3348 class NumberIntegerType = std::int64_t,
3349 class NumberUnsignedType = std::uint64_t,
3350 class NumberFloatType = double,
3351 template<typename U> class AllocatorType = std::allocator,
3352 template<typename T, typename SFINAE = void> class JSONSerializer = adl_serializer,
3353 class BinaryType = std::vector<std::uint8_t>>
3354class basic_json;
3355
3356/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
3357/// @sa https://json.nlohmann.me/api/json_pointer/
3358template<typename BasicJsonType>
3360
3361/*!
3362@brief default specialization
3363@sa https://json.nlohmann.me/api/json/
3364*/
3365using json = basic_json<>;
3366
3367/// @brief a minimal map-like container that preserves insertion order
3368/// @sa https://json.nlohmann.me/api/ordered_map/
3369template<class Key, class T, class IgnoredLess, class Allocator>
3371
3372/// @brief specialization that maintains the insertion order of object keys
3373/// @sa https://json.nlohmann.me/api/ordered_json/
3375
3376} // namespace nlohmann
3377
3378#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3379
3380namespace nlohmann
3381{
3382/*!
3383@brief detail namespace with internal helper functions
3384
3385This namespace collects functions that should not be exposed,
3386implementations of some @ref basic_json methods, and meta-programming helpers.
3387
3388@since version 2.1.0
3389*/
3390namespace detail
3391{
3392/////////////
3393// helpers //
3394/////////////
3395
3396// Note to maintainers:
3397//
3398// Every trait in this file expects a non CV-qualified type.
3399// The only exceptions are in the 'aliases for detected' section
3400// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3401//
3402// In this case, T has to be properly CV-qualified to constraint the function arguments
3403// (e.g. to_json(BasicJsonType&, const T&))
3404
3405template<typename>
3406struct is_basic_json : std::false_type
3407{};
3408
3411{};
3412
3413//////////////////////
3414// json_ref helpers //
3415//////////////////////
3416
3417template<typename>
3418class json_ref;
3419
3420template<typename>
3421struct is_json_ref : std::false_type
3422{};
3423
3424template<typename T>
3425struct is_json_ref<json_ref<T>> : std::true_type
3426{};
3427
3428//////////////////////////
3429// aliases for detected //
3430//////////////////////////
3431
3432template<typename T>
3433using mapped_type_t = typename T::mapped_type;
3434
3435template<typename T>
3436using key_type_t = typename T::key_type;
3437
3438template<typename T>
3439using value_type_t = typename T::value_type;
3440
3441template<typename T>
3442using difference_type_t = typename T::difference_type;
3443
3444template<typename T>
3445using pointer_t = typename T::pointer;
3446
3447template<typename T>
3448using reference_t = typename T::reference;
3449
3450template<typename T>
3451using iterator_category_t = typename T::iterator_category;
3452
3453template<typename T, typename... Args>
3454using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3455
3456template<typename T, typename... Args>
3457using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3458
3459template<typename T, typename U>
3460using get_template_function = decltype(std::declval<T>().template get<U>());
3461
3462// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3463template<typename BasicJsonType, typename T, typename = void>
3464struct has_from_json : std::false_type
3465{};
3466
3467// trait checking if j.get<T> is valid
3468// use this trait instead of std::is_constructible or std::is_convertible,
3469// both rely on, or make use of implicit conversions, and thus fail when T
3470// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3471template<typename BasicJsonType, typename T>
3476
3477template<typename BasicJsonType, typename T>
3479{
3480 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3481
3482 static constexpr bool value =
3484};
3485
3486// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3487// this overload is used for non-default-constructible user-defined-types
3488template<typename BasicJsonType, typename T, typename = void>
3489struct has_non_default_from_json : std::false_type
3490{};
3491
3492template<typename BasicJsonType, typename T>
3494{
3495 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3496
3498};
3499
3500// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3501// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3502template<typename BasicJsonType, typename T, typename = void>
3503struct has_to_json : std::false_type
3504{};
3505
3506template<typename BasicJsonType, typename T>
3508{
3509 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3510
3512};
3513
3514///////////////////
3515// is_ functions //
3516///////////////////
3517
3518// https://en.cppreference.com/w/cpp/types/conjunction
3519template<class...>
3520struct conjunction : std::true_type
3521{};
3522template<class B1>
3524{};
3525template<class B1, class... Bn>
3526struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type
3527{};
3528
3529// https://en.cppreference.com/w/cpp/types/negation
3530template<class B>
3531struct negation : std::integral_constant<bool, !B::value>
3532{};
3533
3534// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3535// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3536// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3537template<typename T>
3538struct is_default_constructible : std::is_default_constructible<T>
3539{};
3540
3541template<typename T1, typename T2>
3542struct is_default_constructible<std::pair<T1, T2>>
3543 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>>
3544{};
3545
3546template<typename T1, typename T2>
3547struct is_default_constructible<const std::pair<T1, T2>>
3548 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>>
3549{};
3550
3551template<typename... Ts>
3552struct is_default_constructible<std::tuple<Ts...>> : conjunction<is_default_constructible<Ts>...>
3553{};
3554
3555template<typename... Ts>
3556struct is_default_constructible<const std::tuple<Ts...>> : conjunction<is_default_constructible<Ts>...>
3557{};
3558
3559template<typename T, typename... Args>
3560struct is_constructible : std::is_constructible<T, Args...>
3561{};
3562
3563template<typename T1, typename T2>
3564struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>>
3565{};
3566
3567template<typename T1, typename T2>
3568struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>>
3569{};
3570
3571template<typename... Ts>
3572struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>>
3573{};
3574
3575template<typename... Ts>
3576struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>>
3577{};
3578
3579template<typename T, typename = void>
3580struct is_iterator_traits : std::false_type
3581{};
3582
3583template<typename T>
3595
3596template<typename T>
3598{
3599 private:
3600 using t_ref = typename std::add_lvalue_reference<T>::type;
3601
3604
3605 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3606 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3607 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3609
3610 public:
3611 static constexpr bool value =
3612 !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3613};
3614
3615template<typename R>
3616using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3617
3618template<typename T>
3620
3621// The following implementation of is_complete_type is taken from
3622// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3623// and is written by Xiang Fan who agreed to using it in this library.
3624
3625template<typename T, typename = void>
3626struct is_complete_type : std::false_type
3627{};
3628
3629template<typename T>
3630struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type
3631{};
3632
3633template<typename BasicJsonType, typename CompatibleObjectType, typename = void>
3634struct is_compatible_object_type_impl : std::false_type
3635{};
3636
3637template<typename BasicJsonType, typename CompatibleObjectType>
3639 CompatibleObjectType,
3640 enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value
3641 && is_detected<key_type_t, CompatibleObjectType>::value>>
3642{
3643 using object_t = typename BasicJsonType::object_t;
3644
3645 // macOS's is_constructible does not play well with nonesuch...
3646 static constexpr bool value =
3649};
3650
3651template<typename BasicJsonType, typename CompatibleObjectType>
3652struct is_compatible_object_type : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType>
3653{};
3654
3655template<typename BasicJsonType, typename ConstructibleObjectType, typename = void>
3657{};
3658
3659template<typename BasicJsonType, typename ConstructibleObjectType>
3661 ConstructibleObjectType,
3662 enable_if_t<is_detected<mapped_type_t, ConstructibleObjectType>::value
3663 && is_detected<key_type_t, ConstructibleObjectType>::value>>
3664{
3665 using object_t = typename BasicJsonType::object_t;
3666
3667 static constexpr bool value =
3669 && (std::is_move_assignable<ConstructibleObjectType>::value
3670 || std::is_copy_assignable<ConstructibleObjectType>::value)
3672 && std::is_same<typename object_t::mapped_type, typename ConstructibleObjectType::mapped_type>::value))
3675};
3676
3677template<typename BasicJsonType, typename ConstructibleObjectType>
3678struct is_constructible_object_type : is_constructible_object_type_impl<BasicJsonType, ConstructibleObjectType>
3679{};
3680
3681template<typename BasicJsonType, typename CompatibleStringType>
3686
3687template<typename BasicJsonType, typename ConstructibleStringType>
3692
3693template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3694struct is_compatible_array_type_impl : std::false_type
3695{};
3696
3697template<typename BasicJsonType, typename CompatibleArrayType>
3700 CompatibleArrayType,
3701 enable_if_t<is_detected<iterator_t, CompatibleArrayType>::value
3702 && is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value &&
3703 // special case for types like std::filesystem::path whose iterator's value_type are themselves
3704 // c.f. https://github.com/nlohmann/json/pull/3073
3705 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value>>
3706{
3708};
3709
3710template<typename BasicJsonType, typename CompatibleArrayType>
3711struct is_compatible_array_type : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType>
3712{};
3713
3714template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3715struct is_constructible_array_type_impl : std::false_type
3716{};
3717
3718template<typename BasicJsonType, typename ConstructibleArrayType>
3721 ConstructibleArrayType,
3722 enable_if_t<std::is_same<ConstructibleArrayType, typename BasicJsonType::value_type>::value>> : std::true_type
3723{};
3724
3725template<typename BasicJsonType, typename ConstructibleArrayType>
3728 ConstructibleArrayType,
3729 enable_if_t<!std::is_same<ConstructibleArrayType, typename BasicJsonType::value_type>::value
3730 && !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value
3731 && is_default_constructible<ConstructibleArrayType>::value
3732 && (std::is_move_assignable<ConstructibleArrayType>::value
3733 || std::is_copy_assignable<ConstructibleArrayType>::value)
3734 && is_detected<iterator_t, ConstructibleArrayType>::value
3735 && is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value
3736 && is_detected<range_value_t, ConstructibleArrayType>::value &&
3737 // special case for types like std::filesystem::path whose iterator's value_type are themselves
3738 // c.f. https://github.com/nlohmann/json/pull/3073
3739 !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value
3740 && is_complete_type<detected_t<range_value_t, ConstructibleArrayType>>::value>>
3741{
3743
3744 static constexpr bool value = std::is_same<value_type, typename BasicJsonType::array_t::value_type>::value
3747};
3748
3749template<typename BasicJsonType, typename ConstructibleArrayType>
3750struct is_constructible_array_type : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType>
3751{};
3752
3753template<typename RealIntegerType, typename CompatibleNumberIntegerType, typename = void>
3754struct is_compatible_integer_type_impl : std::false_type
3755{};
3756
3757template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3759 RealIntegerType,
3760 CompatibleNumberIntegerType,
3761 enable_if_t<std::is_integral<RealIntegerType>::value && std::is_integral<CompatibleNumberIntegerType>::value
3762 && !std::is_same<bool, CompatibleNumberIntegerType>::value>>
3763{
3764 // is there an assert somewhere on overflows?
3765 using RealLimits = std::numeric_limits<RealIntegerType>;
3766 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3767
3769 && CompatibleLimits::is_integer
3770 && RealLimits::is_signed == CompatibleLimits::is_signed;
3771};
3772
3773template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3774struct is_compatible_integer_type : is_compatible_integer_type_impl<RealIntegerType, CompatibleNumberIntegerType>
3775{};
3776
3777template<typename BasicJsonType, typename CompatibleType, typename = void>
3778struct is_compatible_type_impl : std::false_type
3779{};
3780
3781template<typename BasicJsonType, typename CompatibleType>
3783{
3785};
3786
3787template<typename BasicJsonType, typename CompatibleType>
3788struct is_compatible_type : is_compatible_type_impl<BasicJsonType, CompatibleType>
3789{};
3790
3791template<typename T1, typename T2>
3792struct is_constructible_tuple : std::false_type
3793{};
3794
3795template<typename T1, typename... Args>
3796struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...>
3797{};
3798
3799// a naive helper to check if a type is an ordered_map (exploits the fact that
3800// ordered_map inherits capacity() from std::vector)
3801template<typename T>
3803{
3804 using one = char;
3805
3806 struct two
3807 {
3808 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3809 };
3810
3811 template<typename C>
3812 static one test(decltype(&C::capacity));
3813 template<typename C>
3814 static two test(...);
3815
3816 enum
3817 {
3818 value = sizeof(test<T>(nullptr)) == sizeof(char)
3819 }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
3820};
3821
3822// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
3823template<typename T, typename U, enable_if_t<!std::is_same<T, U>::value, int> = 0>
3825{
3826 return static_cast<T>(value);
3827}
3828
3829template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
3831{
3832 return value;
3833}
3834
3835} // namespace detail
3836} // namespace nlohmann
3837
3838// #include <nlohmann/detail/value_t.hpp>
3839
3840#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
3841#include <experimental/filesystem>
3842namespace nlohmann::detail
3843{
3844namespace std_fs = std::experimental::filesystem;
3845} // namespace nlohmann::detail
3846#elif JSON_HAS_FILESYSTEM
3847#include <filesystem>
3848namespace nlohmann::detail
3849{
3850namespace std_fs = std::filesystem;
3851} // namespace nlohmann::detail
3852#endif
3853
3854namespace nlohmann
3855{
3856namespace detail
3857{
3858template<typename BasicJsonType>
3859void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
3860{
3861 if (JSON_HEDLEY_UNLIKELY(!j.is_null())) {
3862 JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j));
3863 }
3864 n = nullptr;
3865}
3866
3867// overloads for basic_json template parameters
3868template<typename BasicJsonType,
3869 typename ArithmeticType,
3870 enable_if_t<std::is_arithmetic<ArithmeticType>::value
3871 && !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
3872 int> = 0>
3873void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
3874{
3875 switch (static_cast<value_t>(j)) {
3877 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
3878 break;
3879 }
3881 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
3882 break;
3883 }
3884 case value_t::number_float: {
3885 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
3886 break;
3887 }
3888
3889 case value_t::null:
3890 case value_t::object:
3891 case value_t::array:
3892 case value_t::string:
3893 case value_t::boolean:
3894 case value_t::binary:
3895 case value_t::discarded:
3896 default:
3897 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
3898 }
3899}
3900
3901template<typename BasicJsonType>
3902void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
3903{
3904 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) {
3905 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j));
3906 }
3907 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
3908}
3909
3910template<typename BasicJsonType>
3911void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
3912{
3913 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) {
3914 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
3915 }
3916 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
3917}
3918
3919template<typename BasicJsonType,
3920 typename ConstructibleStringType,
3921 enable_if_t<is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value
3922 && !std::is_same<typename BasicJsonType::string_t, ConstructibleStringType>::value,
3923 int> = 0>
3924void from_json(const BasicJsonType& j, ConstructibleStringType& s)
3925{
3926 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) {
3927 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
3928 }
3929
3930 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
3931}
3932
3933template<typename BasicJsonType>
3934void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
3935{
3936 get_arithmetic_value(j, val);
3937}
3938
3939template<typename BasicJsonType>
3940void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
3941{
3942 get_arithmetic_value(j, val);
3943}
3944
3945template<typename BasicJsonType>
3946void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
3947{
3948 get_arithmetic_value(j, val);
3949}
3950
3951template<typename BasicJsonType, typename EnumType, enable_if_t<std::is_enum<EnumType>::value, int> = 0>
3952void from_json(const BasicJsonType& j, EnumType& e)
3953{
3954 typename std::underlying_type<EnumType>::type val;
3955 get_arithmetic_value(j, val);
3956 e = static_cast<EnumType>(val);
3957}
3958
3959// forward_list doesn't have an insert method
3960template<typename BasicJsonType,
3961 typename T,
3962 typename Allocator,
3963 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
3964void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
3965{
3966 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
3967 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
3968 }
3969 l.clear();
3970 std::transform(j.rbegin(), j.rend(), std::front_inserter(l),
3971 [](const BasicJsonType& i) { return i.template get<T>(); });
3972}
3973
3974// valarray doesn't have an insert method
3975template<typename BasicJsonType, typename T, enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
3976void from_json(const BasicJsonType& j, std::valarray<T>& l)
3977{
3978 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
3979 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
3980 }
3981 l.resize(j.size());
3982 std::transform(j.begin(), j.end(), std::begin(l), [](const BasicJsonType& elem) { return elem.template get<T>(); });
3983}
3984
3985template<typename BasicJsonType, typename T, std::size_t N>
3987 T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3988 -> decltype(j.template get<T>(), void())
3989{
3990 for (std::size_t i = 0; i < N; ++i) {
3991 arr[i] = j.at(i).template get<T>();
3992 }
3993}
3994
3995template<typename BasicJsonType>
3996void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
3997{
3998 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
3999}
4000
4001template<typename BasicJsonType, typename T, std::size_t N>
4002auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/)
4003 -> decltype(j.template get<T>(), void())
4004{
4005 for (std::size_t i = 0; i < N; ++i) {
4006 arr[i] = j.at(i).template get<T>();
4007 }
4008}
4009
4010template<typename BasicJsonType,
4011 typename ConstructibleArrayType,
4012 enable_if_t<std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, int> = 0>
4013auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4014 -> decltype(arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4016 void())
4017{
4018 using std::end;
4019
4020 ConstructibleArrayType ret;
4021 ret.reserve(j.size());
4022 std::transform(j.begin(), j.end(), std::inserter(ret, end(ret)), [](const BasicJsonType& i) {
4023 // get<BasicJsonType>() returns *this, this won't call a from_json
4024 // method when value_type is BasicJsonType
4026 });
4027 arr = std::move(ret);
4028}
4029
4030template<typename BasicJsonType,
4031 typename ConstructibleArrayType,
4032 enable_if_t<std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, int> = 0>
4033void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<0> /*unused*/)
4034{
4035 using std::end;
4036
4037 ConstructibleArrayType ret;
4038 std::transform(j.begin(), j.end(), std::inserter(ret, end(ret)), [](const BasicJsonType& i) {
4039 // get<BasicJsonType>() returns *this, this won't call a from_json
4040 // method when value_type is BasicJsonType
4042 });
4043 arr = std::move(ret);
4044}
4045
4046template<typename BasicJsonType,
4047 typename ConstructibleArrayType,
4048 enable_if_t<is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value
4049 && !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value
4051 && !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value
4052 && !is_basic_json<ConstructibleArrayType>::value,
4053 int> = 0>
4054auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4055 -> decltype(from_json_array_impl(j, arr, priority_tag<3>{}),
4057 void())
4058{
4059 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
4060 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4061 }
4062
4063 from_json_array_impl(j, arr, priority_tag<3>{});
4064}
4065
4066template<typename BasicJsonType, typename T, std::size_t... Idx>
4067std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4068 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/,
4069 index_sequence<Idx...> /*unused*/)
4070{
4071 return {{std::forward<BasicJsonType>(j).at(Idx).template get<T>()...}};
4072}
4073
4074template<typename BasicJsonType, typename T, std::size_t N>
4075auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4076 -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N>{}))
4077{
4078 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
4079 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4080 }
4081
4082 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N>{});
4083}
4084
4085template<typename BasicJsonType>
4086void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4087{
4088 if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) {
4089 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j));
4090 }
4091
4092 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4093}
4094
4095template<typename BasicJsonType,
4096 typename ConstructibleObjectType,
4097 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
4098void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
4099{
4100 if (JSON_HEDLEY_UNLIKELY(!j.is_object())) {
4101 JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j));
4102 }
4103
4104 ConstructibleObjectType ret;
4105 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4106 using value_type = typename ConstructibleObjectType::value_type;
4107 std::transform(inner_object->begin(), inner_object->end(), std::inserter(ret, ret.begin()),
4108 [](typename BasicJsonType::object_t::value_type const& p) {
4109 return value_type(p.first,
4110 p.second.template get<typename ConstructibleObjectType::mapped_type>());
4111 });
4112 obj = std::move(ret);
4113}
4114
4115// overload for arithmetic types, not chosen for basic_json template arguments
4116// (BooleanType, etc..); note: Is it really necessary to provide explicit
4117// overloads for boolean_t etc. in case of a custom BooleanType which is not
4118// an arithmetic type?
4119template<typename BasicJsonType,
4120 typename ArithmeticType,
4121 enable_if_t<std::is_arithmetic<ArithmeticType>::value
4122 && !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value
4123 && !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value
4124 && !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value
4125 && !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4126 int> = 0>
4127void from_json(const BasicJsonType& j, ArithmeticType& val)
4128{
4129 switch (static_cast<value_t>(j)) {
4131 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4132 break;
4133 }
4135 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4136 break;
4137 }
4138 case value_t::number_float: {
4139 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4140 break;
4141 }
4142 case value_t::boolean: {
4143 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
4144 break;
4145 }
4146
4147 case value_t::null:
4148 case value_t::object:
4149 case value_t::array:
4150 case value_t::string:
4151 case value_t::binary:
4152 case value_t::discarded:
4153 default:
4154 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
4155 }
4156}
4157
4158template<typename BasicJsonType, typename... Args, std::size_t... Idx>
4160{
4161 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
4162}
4163
4164template<typename BasicJsonType, class A1, class A2>
4166 identity_tag<std::pair<A1, A2>> /*unused*/,
4167 priority_tag<0> /*unused*/)
4168{
4169 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
4170 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
4171}
4172
4173template<typename BasicJsonType, typename A1, typename A2>
4174void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
4175{
4176 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>>{}, priority_tag<0>{});
4177}
4178
4179template<typename BasicJsonType, typename... Args>
4180std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j,
4181 identity_tag<std::tuple<Args...>> /*unused*/,
4182 priority_tag<2> /*unused*/)
4183{
4184 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j),
4185 index_sequence_for<Args...>{});
4186}
4187
4188template<typename BasicJsonType, typename... Args>
4189void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
4190{
4191 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j),
4192 index_sequence_for<Args...>{});
4193}
4194
4195template<typename BasicJsonType, typename TupleRelated>
4196auto from_json(BasicJsonType&& j, TupleRelated&& t)
4197 -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3>{}))
4198{
4199 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
4200 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4201 }
4202
4203 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3>{});
4204}
4205
4206template<typename BasicJsonType,
4207 typename Key,
4208 typename Value,
4209 typename Compare,
4210 typename Allocator,
4212void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
4213{
4214 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
4215 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4216 }
4217 m.clear();
4218 for (const auto& p : j) {
4219 if (JSON_HEDLEY_UNLIKELY(!p.is_array())) {
4220 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
4221 }
4222 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4223 }
4224}
4225
4226template<typename BasicJsonType,
4227 typename Key,
4228 typename Value,
4229 typename Hash,
4230 typename KeyEqual,
4231 typename Allocator,
4232 typename = enable_if_t<!std::is_constructible<typename BasicJsonType::string_t, Key>::value>>
4233void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
4234{
4235 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
4236 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4237 }
4238 m.clear();
4239 for (const auto& p : j) {
4240 if (JSON_HEDLEY_UNLIKELY(!p.is_array())) {
4241 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
4242 }
4243 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4244 }
4245}
4246
4247#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4248template<typename BasicJsonType>
4249void from_json(const BasicJsonType& j, std_fs::path& p)
4250{
4251 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) {
4252 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
4253 }
4254 p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4255}
4256#endif
4257
4259{
4260 template<typename BasicJsonType, typename T>
4261 auto operator()(const BasicJsonType& j, T&& val) const noexcept(noexcept(from_json(j, std::forward<T>(val))))
4262 -> decltype(from_json(j, std::forward<T>(val)))
4263 {
4264 return from_json(j, std::forward<T>(val));
4265 }
4266};
4267} // namespace detail
4268
4269/// namespace to hold default `from_json` function
4270/// to see why this is required:
4271/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
4272namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
4273{
4274constexpr const auto& from_json =
4275 detail::static_const<detail::from_json_fn>::value; // NOLINT(misc-definitions-in-headers)
4276} // namespace
4277} // namespace nlohmann
4278
4279// #include <nlohmann/detail/conversions/to_json.hpp>
4280
4281#include <algorithm> // copy
4282#include <iterator> // begin, end
4283#include <string> // string
4284#include <tuple> // tuple, get
4285#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
4286#include <utility> // move, forward, declval, pair
4287#include <valarray> // valarray
4288#include <vector> // vector
4289
4290// #include <nlohmann/detail/macro_scope.hpp>
4291
4292// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
4293
4294#include <cstddef> // size_t
4295#include <iterator> // input_iterator_tag
4296#include <string> // string, to_string
4297#include <tuple> // tuple_size, get, tuple_element
4298#include <utility> // move
4299
4300// #include <nlohmann/detail/meta/type_traits.hpp>
4301
4302// #include <nlohmann/detail/value_t.hpp>
4303
4304namespace nlohmann
4305{
4306namespace detail
4307{
4308template<typename string_type>
4309void int_to_string(string_type& target, std::size_t value)
4310{
4311 // For ADL
4312 using std::to_string;
4313 target = to_string(value);
4314}
4315template<typename IteratorType>
4317{
4318 public:
4319 using difference_type = std::ptrdiff_t;
4323 using iterator_category = std::input_iterator_tag;
4324 using string_type = typename std::remove_cv<
4325 typename std::remove_reference<decltype(std::declval<IteratorType>().key())>::type>::type;
4326
4327 private:
4328 /// the iterator
4329 IteratorType anchor;
4330 /// an index for arrays (used to create key names)
4331 std::size_t array_index = 0;
4332 /// last stringified array index
4333 mutable std::size_t array_index_last = 0;
4334 /// a string representation of the array index
4336 /// an empty string (to return a reference for primitive values)
4338
4339 public:
4340 explicit iteration_proxy_value(IteratorType it) noexcept
4341 : anchor(std::move(it))
4342 {}
4343
4344 /// dereference operator (needed for range-based for)
4346
4347 /// increment operator (needed for range-based for)
4349 {
4350 ++anchor;
4351 ++array_index;
4352
4353 return *this;
4354 }
4355
4356 /// equality operator (needed for InputIterator)
4357 bool operator==(const iteration_proxy_value& o) const { return anchor == o.anchor; }
4358
4359 /// inequality operator (needed for range-based for)
4360 bool operator!=(const iteration_proxy_value& o) const { return anchor != o.anchor; }
4361
4362 /// return key of the iterator
4363 const string_type& key() const
4364 {
4365 JSON_ASSERT(anchor.m_object != nullptr);
4366
4367 switch (anchor.m_object->type()) {
4368 // use integer array index as key
4369 case value_t::array: {
4373 }
4374 return array_index_str;
4375 }
4376
4377 // use key from the object
4378 case value_t::object:
4379 return anchor.key();
4380
4381 // use an empty key for all primitive types
4382 case value_t::null:
4383 case value_t::string:
4384 case value_t::boolean:
4388 case value_t::binary:
4389 case value_t::discarded:
4390 default:
4391 return empty_str;
4392 }
4393 }
4394
4395 /// return value of the iterator
4396 typename IteratorType::reference value() const { return anchor.value(); }
4397};
4398
4399/// proxy class for the items() function
4400template<typename IteratorType>
4402{
4403 private:
4404 /// the container to iterate
4405 typename IteratorType::reference container;
4406
4407 public:
4408 /// construct iteration proxy from a container
4409 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
4410 : container(cont)
4411 {}
4412
4413 /// return iterator begin (needed for range-based for)
4418
4419 /// return iterator end (needed for range-based for)
4421};
4422// Structured Bindings Support
4423// For further reference see https://blog.tartanllama.xyz/structured-bindings/
4424// And see https://github.com/nlohmann/json/pull/1391
4425template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
4427{
4428 return i.key();
4429}
4430// Structured Bindings Support
4431// For further reference see https://blog.tartanllama.xyz/structured-bindings/
4432// And see https://github.com/nlohmann/json/pull/1391
4433template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
4435{
4436 return i.value();
4437}
4438} // namespace detail
4439} // namespace nlohmann
4440
4441// The Addition to the STD Namespace is required to add
4442// Structured Bindings Support to the iteration_proxy_value class
4443// For further reference see https://blog.tartanllama.xyz/structured-bindings/
4444// And see https://github.com/nlohmann/json/pull/1391
4445namespace std
4446{
4447#if defined(__clang__)
4448// Fix: https://github.com/nlohmann/json/issues/1401
4449#pragma clang diagnostic push
4450#pragma clang diagnostic ignored "-Wmismatched-tags"
4451#endif
4452template<typename IteratorType>
4453class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
4454 : public std::integral_constant<std::size_t, 2>
4455{};
4456
4457template<std::size_t N, typename IteratorType>
4458class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType>>
4459{
4460 public:
4461 using type = decltype(get<N>(std::declval<::nlohmann::detail::iteration_proxy_value<IteratorType>>()));
4462};
4463#if defined(__clang__)
4464#pragma clang diagnostic pop
4465#endif
4466} // namespace std
4467
4468// #include <nlohmann/detail/meta/cpp_future.hpp>
4469
4470// #include <nlohmann/detail/meta/type_traits.hpp>
4471
4472// #include <nlohmann/detail/value_t.hpp>
4473
4474#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4475#include <experimental/filesystem>
4476namespace nlohmann::detail
4477{
4478namespace std_fs = std::experimental::filesystem;
4479} // namespace nlohmann::detail
4480#elif JSON_HAS_FILESYSTEM
4481#include <filesystem>
4482namespace nlohmann::detail
4483{
4484namespace std_fs = std::filesystem;
4485} // namespace nlohmann::detail
4486#endif
4487
4488namespace nlohmann
4489{
4490namespace detail
4491{
4492//////////////////
4493// constructors //
4494//////////////////
4495
4496/*
4497 * Note all external_constructor<>::construct functions need to call
4498 * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an
4499 * allocated value (e.g., a string). See bug issue
4500 * https://github.com/nlohmann/json/issues/2865 for more information.
4501 */
4502
4503template<value_t>
4505
4506template<>
4508{
4509 template<typename BasicJsonType>
4510 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
4511 {
4512 j.m_value.destroy(j.m_type);
4513 j.m_type = value_t::boolean;
4514 j.m_value = b;
4515 j.assert_invariant();
4516 }
4517};
4518
4519template<>
4521{
4522 template<typename BasicJsonType>
4523 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
4524 {
4525 j.m_value.destroy(j.m_type);
4526 j.m_type = value_t::string;
4527 j.m_value = s;
4528 j.assert_invariant();
4529 }
4530
4531 template<typename BasicJsonType>
4532 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
4533 {
4534 j.m_value.destroy(j.m_type);
4535 j.m_type = value_t::string;
4536 j.m_value = std::move(s);
4537 j.assert_invariant();
4538 }
4539
4540 template<typename BasicJsonType,
4541 typename CompatibleStringType,
4543 static void construct(BasicJsonType& j, const CompatibleStringType& str)
4544 {
4545 j.m_value.destroy(j.m_type);
4546 j.m_type = value_t::string;
4547 j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
4548 j.assert_invariant();
4549 }
4550};
4551
4552template<>
4554{
4555 template<typename BasicJsonType>
4556 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
4557 {
4558 j.m_value.destroy(j.m_type);
4559 j.m_type = value_t::binary;
4560 j.m_value = typename BasicJsonType::binary_t(b);
4561 j.assert_invariant();
4562 }
4563
4564 template<typename BasicJsonType>
4565 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
4566 {
4567 j.m_value.destroy(j.m_type);
4568 j.m_type = value_t::binary;
4569 j.m_value = typename BasicJsonType::binary_t(std::move(b));
4570 j.assert_invariant();
4571 }
4572};
4573
4574template<>
4576{
4577 template<typename BasicJsonType>
4578 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
4579 {
4580 j.m_value.destroy(j.m_type);
4581 j.m_type = value_t::number_float;
4582 j.m_value = val;
4583 j.assert_invariant();
4584 }
4585};
4586
4587template<>
4589{
4590 template<typename BasicJsonType>
4591 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
4592 {
4593 j.m_value.destroy(j.m_type);
4594 j.m_type = value_t::number_unsigned;
4595 j.m_value = val;
4596 j.assert_invariant();
4597 }
4598};
4599
4600template<>
4602{
4603 template<typename BasicJsonType>
4604 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
4605 {
4606 j.m_value.destroy(j.m_type);
4607 j.m_type = value_t::number_integer;
4608 j.m_value = val;
4609 j.assert_invariant();
4610 }
4611};
4612
4613template<>
4615{
4616 template<typename BasicJsonType>
4617 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
4618 {
4619 j.m_value.destroy(j.m_type);
4620 j.m_type = value_t::array;
4621 j.m_value = arr;
4622 j.set_parents();
4623 j.assert_invariant();
4624 }
4625
4626 template<typename BasicJsonType>
4627 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
4628 {
4629 j.m_value.destroy(j.m_type);
4630 j.m_type = value_t::array;
4631 j.m_value = std::move(arr);
4632 j.set_parents();
4633 j.assert_invariant();
4634 }
4635
4636 template<typename BasicJsonType,
4637 typename CompatibleArrayType,
4639 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
4640 {
4641 using std::begin;
4642 using std::end;
4643
4644 j.m_value.destroy(j.m_type);
4645 j.m_type = value_t::array;
4646 j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
4647 j.set_parents();
4648 j.assert_invariant();
4649 }
4650
4651 template<typename BasicJsonType>
4652 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
4653 {
4654 j.m_value.destroy(j.m_type);
4655 j.m_type = value_t::array;
4656 j.m_value = value_t::array;
4657 j.m_value.array->reserve(arr.size());
4658 for (const bool x : arr) {
4659 j.m_value.array->push_back(x);
4660 j.set_parent(j.m_value.array->back());
4661 }
4662 j.assert_invariant();
4663 }
4664
4665 template<typename BasicJsonType, typename T, enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
4666 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
4667 {
4668 j.m_value.destroy(j.m_type);
4669 j.m_type = value_t::array;
4670 j.m_value = value_t::array;
4671 j.m_value.array->resize(arr.size());
4672 if (arr.size() > 0) {
4673 std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
4674 }
4675 j.set_parents();
4676 j.assert_invariant();
4677 }
4678};
4679
4680template<>
4682{
4683 template<typename BasicJsonType>
4684 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
4685 {
4686 j.m_value.destroy(j.m_type);
4687 j.m_type = value_t::object;
4688 j.m_value = obj;
4689 j.set_parents();
4690 j.assert_invariant();
4691 }
4692
4693 template<typename BasicJsonType>
4694 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
4695 {
4696 j.m_value.destroy(j.m_type);
4697 j.m_type = value_t::object;
4698 j.m_value = std::move(obj);
4699 j.set_parents();
4700 j.assert_invariant();
4701 }
4702
4703 template<typename BasicJsonType,
4704 typename CompatibleObjectType,
4706 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
4707 {
4708 using std::begin;
4709 using std::end;
4710
4711 j.m_value.destroy(j.m_type);
4712 j.m_type = value_t::object;
4713 j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
4714 j.set_parents();
4715 j.assert_invariant();
4716 }
4717};
4718
4719/////////////
4720// to_json //
4721/////////////
4722
4723template<typename BasicJsonType,
4724 typename T,
4725 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
4730
4731template<typename BasicJsonType,
4732 typename CompatibleString,
4733 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
4734void to_json(BasicJsonType& j, const CompatibleString& s)
4735{
4737}
4738
4739template<typename BasicJsonType>
4740void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
4741{
4743}
4744
4745template<typename BasicJsonType, typename FloatType, enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
4746void to_json(BasicJsonType& j, FloatType val) noexcept
4747{
4748 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
4749}
4750
4751template<typename BasicJsonType,
4752 typename CompatibleNumberUnsignedType,
4754 is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value,
4755 int> = 0>
4756void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
4757{
4759 j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
4760}
4761
4762template<typename BasicJsonType,
4763 typename CompatibleNumberIntegerType,
4765 is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value,
4766 int> = 0>
4767void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
4768{
4770 j, static_cast<typename BasicJsonType::number_integer_t>(val));
4771}
4772
4773template<typename BasicJsonType, typename EnumType, enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4774void to_json(BasicJsonType& j, EnumType e) noexcept
4775{
4776 using underlying_type = typename std::underlying_type<EnumType>::type;
4777 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
4778}
4779
4780template<typename BasicJsonType>
4781void to_json(BasicJsonType& j, const std::vector<bool>& e)
4782{
4784}
4785
4786template<typename BasicJsonType,
4787 typename CompatibleArrayType,
4788 enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value
4789 && !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value
4791 && !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value
4792 && !is_basic_json<CompatibleArrayType>::value,
4793 int> = 0>
4794void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
4795{
4797}
4798
4799template<typename BasicJsonType>
4800void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
4801{
4803}
4804
4805template<typename BasicJsonType, typename T, enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
4806void to_json(BasicJsonType& j, const std::valarray<T>& arr)
4807{
4809}
4810
4811template<typename BasicJsonType>
4812void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
4813{
4815}
4816
4817template<typename BasicJsonType,
4818 typename CompatibleObjectType,
4819 enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value
4820 && !is_basic_json<CompatibleObjectType>::value,
4821 int> = 0>
4822void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
4823{
4825}
4826
4827template<typename BasicJsonType>
4828void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
4829{
4831}
4832
4833template<
4834 typename BasicJsonType,
4835 typename T,
4836 std::size_t N,
4837 enable_if_t<!std::is_constructible<typename BasicJsonType::string_t,
4838 const T (&)[N]>::
4839 value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4840 int> = 0>
4842 BasicJsonType& j,
4843 const T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4844{
4846}
4847
4848template<typename BasicJsonType,
4849 typename T1,
4850 typename T2,
4851 enable_if_t<std::is_constructible<BasicJsonType, T1>::value && std::is_constructible<BasicJsonType, T2>::value,
4852 int> = 0>
4853void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
4854{
4855 j = {p.first, p.second};
4856}
4857
4858// for https://github.com/nlohmann/json/pull/1134
4859template<typename BasicJsonType,
4860 typename T,
4862void to_json(BasicJsonType& j, const T& b)
4863{
4864 j = {{b.key(), b.value()}};
4865}
4866
4867template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
4868void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
4869{
4870 j = {std::get<Idx>(t)...};
4871}
4872
4873template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int> = 0>
4874void to_json(BasicJsonType& j, const T& t)
4875{
4876 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value>{});
4877}
4878
4879#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4880template<typename BasicJsonType>
4881void to_json(BasicJsonType& j, const std_fs::path& p)
4882{
4883 j = p.string();
4884}
4885#endif
4886
4888{
4889 template<typename BasicJsonType, typename T>
4890 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
4891 -> decltype(to_json(j, std::forward<T>(val)), void())
4892 {
4893 return to_json(j, std::forward<T>(val));
4894 }
4895};
4896} // namespace detail
4897
4898/// namespace to hold default `to_json` function
4899/// to see why this is required:
4900/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
4901namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
4902{
4903constexpr const auto& to_json =
4904 detail::static_const<detail::to_json_fn>::value; // NOLINT(misc-definitions-in-headers)
4905} // namespace
4906} // namespace nlohmann
4907
4908// #include <nlohmann/detail/meta/identity_tag.hpp>
4909
4910// #include <nlohmann/detail/meta/type_traits.hpp>
4911
4912namespace nlohmann
4913{
4914
4915/// @sa https://json.nlohmann.me/api/adl_serializer/
4916template<typename ValueType, typename>
4918{
4919 /// @brief convert a JSON value to any value type
4920 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
4921 template<typename BasicJsonType, typename TargetType = ValueType>
4922 static auto from_json(BasicJsonType&& j,
4923 TargetType& val) noexcept(noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j),
4924 val)))
4925 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
4926 {
4927 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
4928 }
4929
4930 /// @brief convert a JSON value to any value type
4931 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
4932 template<typename BasicJsonType, typename TargetType = ValueType>
4933 static auto from_json(BasicJsonType&& j) noexcept(
4934 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType>{})))
4935 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType>{}))
4936 {
4937 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType>{});
4938 }
4939
4940 /// @brief convert any value type to a JSON value
4941 /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
4942 template<typename BasicJsonType, typename TargetType = ValueType>
4943 static auto to_json(BasicJsonType& j,
4944 TargetType&& val) noexcept(noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
4945 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
4946 {
4947 ::nlohmann::to_json(j, std::forward<TargetType>(val));
4948 }
4949};
4950} // namespace nlohmann
4951
4952// #include <nlohmann/byte_container_with_subtype.hpp>
4953
4954#include <cstdint> // uint8_t, uint64_t
4955#include <tuple> // tie
4956#include <utility> // move
4957
4958namespace nlohmann
4959{
4960
4961/// @brief an internal type for a backed binary type
4962/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
4963template<typename BinaryType>
4965{
4966 public:
4968 using subtype_type = std::uint64_t;
4969
4970 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4972 : container_type()
4973 {}
4974
4975 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4977 : container_type(b)
4978 {}
4979
4980 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4982 : container_type(std::move(b))
4983 {}
4984
4985 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4987 : container_type(b)
4988 , m_subtype(subtype_)
4989 , m_has_subtype(true)
4990 {}
4991
4992 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4994 subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
4995 : container_type(std::move(b))
4996 , m_subtype(subtype_)
4997 , m_has_subtype(true)
4998 {}
4999
5001 {
5002 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype)
5003 == std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5004 }
5005
5006 bool operator!=(const byte_container_with_subtype& rhs) const { return !(rhs == *this); }
5007
5008 /// @brief sets the binary subtype
5009 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/
5010 void set_subtype(subtype_type subtype_) noexcept
5011 {
5012 m_subtype = subtype_;
5013 m_has_subtype = true;
5014 }
5015
5016 /// @brief return the binary subtype
5017 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/
5018 constexpr subtype_type subtype() const noexcept
5019 {
5020 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
5021 }
5022
5023 /// @brief return whether the value has a subtype
5024 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/
5025 constexpr bool has_subtype() const noexcept { return m_has_subtype; }
5026
5027 /// @brief clears the binary subtype
5028 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/
5029 void clear_subtype() noexcept
5030 {
5031 m_subtype = 0;
5032 m_has_subtype = false;
5033 }
5034
5035 private:
5037 bool m_has_subtype = false;
5038};
5039
5040} // namespace nlohmann
5041
5042// #include <nlohmann/detail/conversions/from_json.hpp>
5043
5044// #include <nlohmann/detail/conversions/to_json.hpp>
5045
5046// #include <nlohmann/detail/exceptions.hpp>
5047
5048// #include <nlohmann/detail/hash.hpp>
5049
5050#include <cstddef> // size_t
5051#include <cstdint> // uint8_t
5052#include <functional> // hash
5053
5054// #include <nlohmann/detail/macro_scope.hpp>
5055
5056// #include <nlohmann/detail/value_t.hpp>
5057
5058namespace nlohmann
5059{
5060namespace detail
5061{
5062
5063// boost::hash_combine
5064inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
5065{
5066 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
5067 return seed;
5068}
5069
5070/*!
5071@brief hash a JSON value
5072
5073The hash function tries to rely on std::hash where possible. Furthermore, the
5074type of the JSON value is taken into account to have different hash values for
5075null, 0, 0U, and false, etc.
5076
5077@tparam BasicJsonType basic_json specialization
5078@param j JSON value to hash
5079@return hash value of j
5080*/
5081template<typename BasicJsonType>
5082std::size_t hash(const BasicJsonType& j)
5083{
5084 using string_t = typename BasicJsonType::string_t;
5085 using number_integer_t = typename BasicJsonType::number_integer_t;
5086 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5087 using number_float_t = typename BasicJsonType::number_float_t;
5088
5089 const auto type = static_cast<std::size_t>(j.type());
5090 switch (j.type()) {
5091 case BasicJsonType::value_t::null:
5092 case BasicJsonType::value_t::discarded: {
5093 return combine(type, 0);
5094 }
5095
5096 case BasicJsonType::value_t::object: {
5097 auto seed = combine(type, j.size());
5098 for (const auto& element : j.items()) {
5099 const auto h = std::hash<string_t>{}(element.key());
5100 seed = combine(seed, h);
5101 seed = combine(seed, hash(element.value()));
5102 }
5103 return seed;
5104 }
5105
5106 case BasicJsonType::value_t::array: {
5107 auto seed = combine(type, j.size());
5108 for (const auto& element : j) {
5109 seed = combine(seed, hash(element));
5110 }
5111 return seed;
5112 }
5113
5114 case BasicJsonType::value_t::string: {
5115 const auto h = std::hash<string_t>{}(j.template get_ref<const string_t&>());
5116 return combine(type, h);
5117 }
5118
5119 case BasicJsonType::value_t::boolean: {
5120 const auto h = std::hash<bool>{}(j.template get<bool>());
5121 return combine(type, h);
5122 }
5123
5124 case BasicJsonType::value_t::number_integer: {
5125 const auto h = std::hash<number_integer_t>{}(j.template get<number_integer_t>());
5126 return combine(type, h);
5127 }
5128
5129 case BasicJsonType::value_t::number_unsigned: {
5130 const auto h = std::hash<number_unsigned_t>{}(j.template get<number_unsigned_t>());
5131 return combine(type, h);
5132 }
5133
5134 case BasicJsonType::value_t::number_float: {
5135 const auto h = std::hash<number_float_t>{}(j.template get<number_float_t>());
5136 return combine(type, h);
5137 }
5138
5139 case BasicJsonType::value_t::binary: {
5140 auto seed = combine(type, j.get_binary().size());
5141 const auto h = std::hash<bool>{}(j.get_binary().has_subtype());
5142 seed = combine(seed, h);
5143 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
5144 for (const auto byte : j.get_binary()) {
5145 seed = combine(seed, std::hash<std::uint8_t>{}(byte));
5146 }
5147 return seed;
5148 }
5149
5150 default: // LCOV_EXCL_LINE
5151 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
5152 return 0; // LCOV_EXCL_LINE
5153 }
5154}
5155
5156} // namespace detail
5157} // namespace nlohmann
5158
5159// #include <nlohmann/detail/input/binary_reader.hpp>
5160
5161#include <algorithm> // generate_n
5162#include <array> // array
5163#include <cmath> // ldexp
5164#include <cstddef> // size_t
5165#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
5166#include <cstdio> // snprintf
5167#include <cstring> // memcpy
5168#include <iterator> // back_inserter
5169#include <limits> // numeric_limits
5170#include <string> // char_traits, string
5171#include <utility> // make_pair, move
5172#include <vector> // vector
5173
5174// #include <nlohmann/detail/exceptions.hpp>
5175
5176// #include <nlohmann/detail/input/input_adapters.hpp>
5177
5178#include <array> // array
5179#include <cstddef> // size_t
5180#include <cstring> // strlen
5181#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
5182#include <memory> // shared_ptr, make_shared, addressof
5183#include <numeric> // accumulate
5184#include <string> // string, char_traits
5185#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
5186#include <utility> // pair, declval
5187
5188#ifndef JSON_NO_IO
5189#include <cstdio> // FILE *
5190#include <istream> // istream
5191#endif // JSON_NO_IO
5192
5193// #include <nlohmann/detail/iterators/iterator_traits.hpp>
5194
5195// #include <nlohmann/detail/macro_scope.hpp>
5196
5197namespace nlohmann
5198{
5199namespace detail
5200{
5201/// the supported input formats
5210
5211////////////////////
5212// input adapters //
5213////////////////////
5214
5215#ifndef JSON_NO_IO
5216/*!
5217Input adapter for stdio file access. This adapter read only 1 byte and do not use any
5218 buffer. This adapter is a very low level adapter.
5219*/
5221{
5222 public:
5223 using char_type = char;
5224
5226 explicit file_input_adapter(std::FILE* f) noexcept
5227 : m_file(f)
5228 {}
5229
5230 // make class move-only
5233 file_input_adapter& operator=(const file_input_adapter&) = delete;
5236
5237 std::char_traits<char>::int_type get_character() noexcept { return std::fgetc(m_file); }
5238
5239 private:
5240 /// the file pointer to read from
5241 std::FILE* m_file;
5242};
5243
5244/*!
5245Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
5246beginning of input. Does not support changing the underlying std::streambuf
5247in mid-input. Maintains underlying std::istream and std::streambuf to support
5248subsequent use of standard std::istream operations to process any input
5249characters following those used in parsing the JSON input. Clears the
5250std::istream flags; any input errors (e.g., EOF) will be detected by the first
5251subsequent call for input from the std::istream.
5252*/
5254{
5255 public:
5256 using char_type = char;
5257
5259 {
5260 // clear stream flags; we use underlying streambuf I/O, do not
5261 // maintain ifstream flags, except eof
5262 if (is != nullptr) {
5263 is->clear(is->rdstate() & std::ios::eofbit);
5264 }
5265 }
5266
5267 explicit input_stream_adapter(std::istream& i)
5268 : is(&i)
5269 , sb(i.rdbuf())
5270 {}
5271
5272 // delete because of pointer members
5276
5278 : is(rhs.is)
5279 , sb(rhs.sb)
5280 {
5281 rhs.is = nullptr;
5282 rhs.sb = nullptr;
5283 }
5284
5285 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
5286 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
5287 // end up as the same value, e.g. 0xFFFFFFFF.
5288 std::char_traits<char>::int_type get_character()
5289 {
5290 auto res = sb->sbumpc();
5291 // set eof manually, as we don't use the istream interface.
5292 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof())) {
5293 is->clear(is->rdstate() | std::ios::eofbit);
5294 }
5295 return res;
5296 }
5297
5298 private:
5299 /// the associated input stream
5300 std::istream* is = nullptr;
5301 std::streambuf* sb = nullptr;
5302};
5303#endif // JSON_NO_IO
5304
5305// General-purpose iterator-based adapter. It might not be as fast as
5306// theoretically possible for some containers, but it is extremely versatile.
5307template<typename IteratorType>
5309{
5310 public:
5311 using char_type = typename std::iterator_traits<IteratorType>::value_type;
5312
5313 iterator_input_adapter(IteratorType first, IteratorType last)
5314 : current(std::move(first))
5315 , end(std::move(last))
5316 {}
5317
5318 typename std::char_traits<char_type>::int_type get_character()
5319 {
5320 if (JSON_HEDLEY_LIKELY(current != end)) {
5321 auto result = std::char_traits<char_type>::to_int_type(*current);
5322 std::advance(current, 1);
5323 return result;
5324 }
5325
5326 return std::char_traits<char_type>::eof();
5327 }
5328
5329 private:
5330 IteratorType current;
5331 IteratorType end;
5332
5333 template<typename BaseInputAdapter, size_t T>
5335
5336 bool empty() const { return current == end; }
5337};
5338
5339template<typename BaseInputAdapter, size_t T>
5341
5342template<typename BaseInputAdapter>
5343struct wide_string_input_helper<BaseInputAdapter, 4>
5344{
5345 // UTF-32
5346 static void fill_buffer(BaseInputAdapter& input,
5347 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
5348 size_t& utf8_bytes_index,
5349 size_t& utf8_bytes_filled)
5350 {
5351 utf8_bytes_index = 0;
5352
5353 if (JSON_HEDLEY_UNLIKELY(input.empty())) {
5354 utf8_bytes[0] = std::char_traits<char>::eof();
5355 utf8_bytes_filled = 1;
5356 } else {
5357 // get the current character
5358 const auto wc = input.get_character();
5359
5360 // UTF-32 to UTF-8 encoding
5361 if (wc < 0x80) {
5362 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5363 utf8_bytes_filled = 1;
5364 } else if (wc <= 0x7FF) {
5365 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(
5366 0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
5367 utf8_bytes[1] =
5368 static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5369 utf8_bytes_filled = 2;
5370 } else if (wc <= 0xFFFF) {
5371 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(
5372 0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
5373 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(
5374 0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5375 utf8_bytes[2] =
5376 static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5377 utf8_bytes_filled = 3;
5378 } else if (wc <= 0x10FFFF) {
5379 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(
5380 0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
5381 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(
5382 0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
5383 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(
5384 0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5385 utf8_bytes[3] =
5386 static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5387 utf8_bytes_filled = 4;
5388 } else {
5389 // unknown character
5390 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5391 utf8_bytes_filled = 1;
5392 }
5393 }
5394 }
5395};
5396
5397template<typename BaseInputAdapter>
5398struct wide_string_input_helper<BaseInputAdapter, 2>
5399{
5400 // UTF-16
5401 static void fill_buffer(BaseInputAdapter& input,
5402 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
5403 size_t& utf8_bytes_index,
5404 size_t& utf8_bytes_filled)
5405 {
5406 utf8_bytes_index = 0;
5407
5408 if (JSON_HEDLEY_UNLIKELY(input.empty())) {
5409 utf8_bytes[0] = std::char_traits<char>::eof();
5410 utf8_bytes_filled = 1;
5411 } else {
5412 // get the current character
5413 const auto wc = input.get_character();
5414
5415 // UTF-16 to UTF-8 encoding
5416 if (wc < 0x80) {
5417 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5418 utf8_bytes_filled = 1;
5419 } else if (wc <= 0x7FF) {
5420 utf8_bytes[0] =
5421 static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
5422 utf8_bytes[1] =
5423 static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5424 utf8_bytes_filled = 2;
5425 } else if (0xD800 > wc || wc >= 0xE000) {
5426 utf8_bytes[0] =
5427 static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
5428 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(
5429 0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5430 utf8_bytes[2] =
5431 static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5432 utf8_bytes_filled = 3;
5433 } else {
5434 if (JSON_HEDLEY_UNLIKELY(!input.empty())) {
5435 const auto wc2 = static_cast<unsigned int>(input.get_character());
5436 const auto charcode =
5437 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
5438 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
5439 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
5440 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
5441 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
5442 utf8_bytes_filled = 4;
5443 } else {
5444 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5445 utf8_bytes_filled = 1;
5446 }
5447 }
5448 }
5449 }
5450};
5451
5452// Wraps another input apdater to convert wide character types into individual bytes.
5453template<typename BaseInputAdapter, typename WideCharType>
5455{
5456 public:
5457 using char_type = char;
5458
5459 wide_string_input_adapter(BaseInputAdapter base)
5460 : base_adapter(base)
5461 {}
5462
5463 typename std::char_traits<char>::int_type get_character() noexcept
5464 {
5465 // check if buffer needs to be filled
5468
5471 }
5472
5473 // use buffer
5476 return utf8_bytes[utf8_bytes_index++];
5477 }
5478
5479 private:
5480 BaseInputAdapter base_adapter;
5481
5482 template<size_t T>
5488
5489 /// a buffer for UTF-8 bytes
5490 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
5491
5492 /// index to the utf8_codes array for the next valid byte
5493 std::size_t utf8_bytes_index = 0;
5494 /// number of valid bytes in the utf8_codes array
5495 std::size_t utf8_bytes_filled = 0;
5496};
5497
5498template<typename IteratorType, typename Enable = void>
5500{
5501 using iterator_type = IteratorType;
5502 using char_type = typename std::iterator_traits<iterator_type>::value_type;
5504
5505 static adapter_type create(IteratorType first, IteratorType last)
5506 {
5507 return adapter_type(std::move(first), std::move(last));
5508 }
5509};
5510
5511template<typename T>
5513{
5514 using value_type = typename std::iterator_traits<T>::value_type;
5515 enum
5516 {
5517 value = sizeof(value_type) > 1
5518 };
5519};
5520
5521template<typename IteratorType>
5523{
5524 using iterator_type = IteratorType;
5525 using char_type = typename std::iterator_traits<iterator_type>::value_type;
5528
5529 static adapter_type create(IteratorType first, IteratorType last)
5530 {
5531 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
5532 }
5533};
5534
5535// General purpose iterator-based input
5536template<typename IteratorType>
5538{
5540 return factory_type::create(first, last);
5541}
5542
5543// Convenience shorthand from container to iterator
5544// Enables ADL on begin(container) and end(container)
5545// Encloses the using declarations in namespace for not to leak them to outside scope
5546
5548{
5549
5550using std::begin;
5551using std::end;
5552
5553template<typename ContainerType, typename Enable = void>
5556
5557template<typename ContainerType>
5559 ContainerType,
5560 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
5561{
5563 decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
5564
5565 static adapter_type create(const ContainerType& container)
5566 {
5567 return input_adapter(begin(container), end(container));
5568 }
5569};
5570
5571} // namespace container_input_adapter_factory_impl
5572
5573template<typename ContainerType>
5574typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type
5579
5580#ifndef JSON_NO_IO
5581// Special cases with fast paths
5582inline file_input_adapter input_adapter(std::FILE* file)
5583{
5584 return file_input_adapter(file);
5585}
5586
5587inline input_stream_adapter input_adapter(std::istream& stream)
5588{
5589 return input_stream_adapter(stream);
5590}
5591
5592inline input_stream_adapter input_adapter(std::istream&& stream)
5593{
5594 return input_stream_adapter(stream);
5595}
5596#endif // JSON_NO_IO
5597
5599 decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
5600
5601// Null-delimited strings, and the like.
5602template<typename CharT,
5603 typename std::enable_if<std::is_pointer<CharT>::value && !std::is_array<CharT>::value
5604 && std::is_integral<typename std::remove_pointer<CharT>::type>::value
5605 && sizeof(typename std::remove_pointer<CharT>::type) == 1,
5606 int>::type = 0>
5608{
5609 auto length = std::strlen(reinterpret_cast<const char*>(b));
5610 const auto* ptr = reinterpret_cast<const char*>(b);
5611 return input_adapter(ptr, ptr + length);
5612}
5613
5614template<typename T, std::size_t N>
5615auto input_adapter(T (&array)[N]) -> decltype(input_adapter(
5616 array,
5617 array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5618{
5619 return input_adapter(array, array + N);
5620}
5621
5622// This class only handles inputs of input_buffer_adapter type.
5623// It's required so that expressions like {ptr, len} can be implicitly cast
5624// to the correct adapter.
5626{
5627 public:
5628 template<typename CharT,
5629 typename std::enable_if<std::is_pointer<CharT>::value
5630 && std::is_integral<typename std::remove_pointer<CharT>::type>::value
5631 && sizeof(typename std::remove_pointer<CharT>::type) == 1,
5632 int>::type = 0>
5633 span_input_adapter(CharT b, std::size_t l)
5634 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l)
5635 {}
5636
5637 template<class IteratorType,
5638 typename std::enable_if<std::is_same<typename iterator_traits<IteratorType>::iterator_category,
5639 std::random_access_iterator_tag>::value,
5640 int>::type = 0>
5641 span_input_adapter(IteratorType first, IteratorType last)
5642 : ia(input_adapter(first, last))
5643 {}
5644
5646 {
5647 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
5648 }
5649
5650 private:
5652};
5653} // namespace detail
5654} // namespace nlohmann
5655
5656// #include <nlohmann/detail/input/json_sax.hpp>
5657
5658#include <cstddef>
5659#include <string> // string
5660#include <utility> // move
5661#include <vector> // vector
5662
5663// #include <nlohmann/detail/exceptions.hpp>
5664
5665// #include <nlohmann/detail/macro_scope.hpp>
5666
5667namespace nlohmann
5668{
5669
5670/*!
5671@brief SAX interface
5672
5673This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
5674Each function is called in different situations while the input is parsed. The
5675boolean return value informs the parser whether to continue processing the
5676input.
5677*/
5678template<typename BasicJsonType>
5680{
5681 using number_integer_t = typename BasicJsonType::number_integer_t;
5682 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5683 using number_float_t = typename BasicJsonType::number_float_t;
5684 using string_t = typename BasicJsonType::string_t;
5685 using binary_t = typename BasicJsonType::binary_t;
5686
5687 /*!
5688 @brief a null value was read
5689 @return whether parsing should proceed
5690 */
5691 virtual bool null() = 0;
5692
5693 /*!
5694 @brief a boolean value was read
5695 @param[in] val boolean value
5696 @return whether parsing should proceed
5697 */
5698 virtual bool boolean(bool val) = 0;
5699
5700 /*!
5701 @brief an integer number was read
5702 @param[in] val integer value
5703 @return whether parsing should proceed
5704 */
5705 virtual bool number_integer(number_integer_t val) = 0;
5706
5707 /*!
5708 @brief an unsigned integer number was read
5709 @param[in] val unsigned integer value
5710 @return whether parsing should proceed
5711 */
5712 virtual bool number_unsigned(number_unsigned_t val) = 0;
5713
5714 /*!
5715 @brief a floating-point number was read
5716 @param[in] val floating-point value
5717 @param[in] s raw token value
5718 @return whether parsing should proceed
5719 */
5720 virtual bool number_float(number_float_t val, const string_t& s) = 0;
5721
5722 /*!
5723 @brief a string value was read
5724 @param[in] val string value
5725 @return whether parsing should proceed
5726 @note It is safe to move the passed string value.
5727 */
5728 virtual bool string(string_t& val) = 0;
5729
5730 /*!
5731 @brief a binary value was read
5732 @param[in] val binary value
5733 @return whether parsing should proceed
5734 @note It is safe to move the passed binary value.
5735 */
5736 virtual bool binary(binary_t& val) = 0;
5737
5738 /*!
5739 @brief the beginning of an object was read
5740 @param[in] elements number of object elements or -1 if unknown
5741 @return whether parsing should proceed
5742 @note binary formats may report the number of elements
5743 */
5744 virtual bool start_object(std::size_t elements) = 0;
5745
5746 /*!
5747 @brief an object key was read
5748 @param[in] val object key
5749 @return whether parsing should proceed
5750 @note It is safe to move the passed string.
5751 */
5752 virtual bool key(string_t& val) = 0;
5753
5754 /*!
5755 @brief the end of an object was read
5756 @return whether parsing should proceed
5757 */
5758 virtual bool end_object() = 0;
5759
5760 /*!
5761 @brief the beginning of an array was read
5762 @param[in] elements number of array elements or -1 if unknown
5763 @return whether parsing should proceed
5764 @note binary formats may report the number of elements
5765 */
5766 virtual bool start_array(std::size_t elements) = 0;
5767
5768 /*!
5769 @brief the end of an array was read
5770 @return whether parsing should proceed
5771 */
5772 virtual bool end_array() = 0;
5773
5774 /*!
5775 @brief a parse error occurred
5776 @param[in] position the position in the input where the error occurs
5777 @param[in] last_token the last read token
5778 @param[in] ex an exception object describing the error
5779 @return whether parsing should proceed (must return false)
5780 */
5781 virtual bool parse_error(std::size_t position, const std::string& last_token, const detail::exception& ex) = 0;
5782
5783 json_sax() = default;
5784 json_sax(const json_sax&) = default;
5785 json_sax(json_sax&&) noexcept = default;
5786 json_sax& operator=(const json_sax&) = default;
5787 json_sax& operator=(json_sax&&) noexcept = default;
5788 virtual ~json_sax() = default;
5789};
5790
5791namespace detail
5792{
5793/*!
5794@brief SAX implementation to create a JSON value from SAX events
5795
5796This class implements the @ref json_sax interface and processes the SAX events
5797to create a JSON value which makes it basically a DOM parser. The structure or
5798hierarchy of the JSON value is managed by the stack `ref_stack` which contains
5799a pointer to the respective array or object for each recursion depth.
5800
5801After successful parsing, the value that is passed by reference to the
5802constructor contains the parsed value.
5803
5804@tparam BasicJsonType the JSON type
5805*/
5806template<typename BasicJsonType>
5808{
5809 public:
5810 using number_integer_t = typename BasicJsonType::number_integer_t;
5811 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5812 using number_float_t = typename BasicJsonType::number_float_t;
5813 using string_t = typename BasicJsonType::string_t;
5814 using binary_t = typename BasicJsonType::binary_t;
5815
5816 /*!
5817 @param[in,out] r reference to a JSON value that is manipulated while
5818 parsing
5819 @param[in] allow_exceptions_ whether parse errors yield exceptions
5820 */
5821 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
5822 : root(r)
5823 , allow_exceptions(allow_exceptions_)
5824 {}
5825
5826 // make class move-only
5829 default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
5832 default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
5834
5835 bool null()
5836 {
5837 handle_value(nullptr);
5838 return true;
5839 }
5840
5841 bool boolean(bool val)
5842 {
5843 handle_value(val);
5844 return true;
5845 }
5846
5848 {
5849 handle_value(val);
5850 return true;
5851 }
5852
5854 {
5855 handle_value(val);
5856 return true;
5857 }
5858
5859 bool number_float(number_float_t val, const string_t& /*unused*/)
5860 {
5861 handle_value(val);
5862 return true;
5863 }
5864
5865 bool string(string_t& val)
5866 {
5867 handle_value(val);
5868 return true;
5869 }
5870
5871 bool binary(binary_t& val)
5872 {
5873 handle_value(std::move(val));
5874 return true;
5875 }
5876
5877 bool start_object(std::size_t len)
5878 {
5879 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
5880
5881 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) {
5882 JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
5883 }
5884
5885 return true;
5886 }
5887
5888 bool key(string_t& val)
5889 {
5890 // add null at given key and store the reference for later
5891 object_element = &(ref_stack.back()->m_value.object->operator[](val));
5892 return true;
5893 }
5894
5896 {
5897 ref_stack.back()->set_parents();
5898 ref_stack.pop_back();
5899 return true;
5900 }
5901
5902 bool start_array(std::size_t len)
5903 {
5904 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
5905
5906 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) {
5907 JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
5908 }
5909
5910 return true;
5911 }
5912
5914 {
5915 ref_stack.back()->set_parents();
5916 ref_stack.pop_back();
5917 return true;
5918 }
5919
5920 template<class Exception>
5921 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const Exception& ex)
5922 {
5923 errored = true;
5924 static_cast<void>(ex);
5925 if (allow_exceptions) {
5926 JSON_THROW(ex);
5927 }
5928 return false;
5929 }
5930
5931 constexpr bool is_errored() const { return errored; }
5932
5933 private:
5934 /*!
5935 @invariant If the ref stack is empty, then the passed value will be the new
5936 root.
5937 @invariant If the ref stack contains a value, then it is an array or an
5938 object to which we can add elements
5939 */
5940 template<typename Value>
5942 {
5943 if (ref_stack.empty()) {
5944 root = BasicJsonType(std::forward<Value>(v));
5945 return &root;
5946 }
5947
5948 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
5949
5950 if (ref_stack.back()->is_array()) {
5951 ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
5952 return &(ref_stack.back()->m_value.array->back());
5953 }
5954
5955 JSON_ASSERT(ref_stack.back()->is_object());
5957 *object_element = BasicJsonType(std::forward<Value>(v));
5958 return object_element;
5959 }
5960
5961 /// the parsed JSON value
5963 /// stack to model hierarchy of values
5964 std::vector<BasicJsonType*> ref_stack{};
5965 /// helper to hold the reference for the next object element
5967 /// whether a syntax error occurred
5968 bool errored = false;
5969 /// whether to throw exceptions in case of errors
5970 const bool allow_exceptions = true;
5971};
5972
5973template<typename BasicJsonType>
5975{
5976 public:
5977 using number_integer_t = typename BasicJsonType::number_integer_t;
5978 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5979 using number_float_t = typename BasicJsonType::number_float_t;
5980 using string_t = typename BasicJsonType::string_t;
5981 using binary_t = typename BasicJsonType::binary_t;
5982 using parser_callback_t = typename BasicJsonType::parser_callback_t;
5983 using parse_event_t = typename BasicJsonType::parse_event_t;
5984
5985 json_sax_dom_callback_parser(BasicJsonType& r, const parser_callback_t cb, const bool allow_exceptions_ = true)
5986 : root(r)
5987 , callback(cb)
5988 , allow_exceptions(allow_exceptions_)
5989 {
5990 keep_stack.push_back(true);
5991 }
5992
5993 // make class move-only
5996 default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
5999 default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6001
6002 bool null()
6003 {
6004 handle_value(nullptr);
6005 return true;
6006 }
6007
6008 bool boolean(bool val)
6009 {
6010 handle_value(val);
6011 return true;
6012 }
6013
6015 {
6016 handle_value(val);
6017 return true;
6018 }
6019
6021 {
6022 handle_value(val);
6023 return true;
6024 }
6025
6026 bool number_float(number_float_t val, const string_t& /*unused*/)
6027 {
6028 handle_value(val);
6029 return true;
6030 }
6031
6032 bool string(string_t& val)
6033 {
6034 handle_value(val);
6035 return true;
6036 }
6037
6038 bool binary(binary_t& val)
6039 {
6040 handle_value(std::move(val));
6041 return true;
6042 }
6043
6044 bool start_object(std::size_t len)
6045 {
6046 // check callback for object start
6047 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
6048 keep_stack.push_back(keep);
6049
6050 auto val = handle_value(BasicJsonType::value_t::object, true);
6051 ref_stack.push_back(val.second);
6052
6053 // check object limit
6054 if (ref_stack.back()
6055 && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6056 {
6057 JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
6058 }
6059
6060 return true;
6061 }
6062
6063 bool key(string_t& val)
6064 {
6066
6067 // check callback for key
6068 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
6069 key_keep_stack.push_back(keep);
6070
6071 // add discarded value at given key and store the reference for later
6072 if (keep && ref_stack.back()) {
6073 object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
6074 }
6075
6076 return true;
6077 }
6078
6080 {
6081 if (ref_stack.back()) {
6082 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) {
6083 // discard object
6084 *ref_stack.back() = discarded;
6085 } else {
6086 ref_stack.back()->set_parents();
6087 }
6088 }
6089
6090 JSON_ASSERT(!ref_stack.empty());
6091 JSON_ASSERT(!keep_stack.empty());
6092 ref_stack.pop_back();
6093 keep_stack.pop_back();
6094
6095 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) {
6096 // remove discarded value
6097 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) {
6098 if (it->is_discarded()) {
6099 ref_stack.back()->erase(it);
6100 break;
6101 }
6102 }
6103 }
6104
6105 return true;
6106 }
6107
6108 bool start_array(std::size_t len)
6109 {
6110 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
6111 keep_stack.push_back(keep);
6112
6113 auto val = handle_value(BasicJsonType::value_t::array, true);
6114 ref_stack.push_back(val.second);
6115
6116 // check array limit
6117 if (ref_stack.back()
6118 && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6119 {
6120 JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
6121 }
6122
6123 return true;
6124 }
6125
6127 {
6128 bool keep = true;
6129
6130 if (ref_stack.back()) {
6131 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
6132 if (keep) {
6133 ref_stack.back()->set_parents();
6134 } else {
6135 // discard array
6136 *ref_stack.back() = discarded;
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 // remove discarded value
6146 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) {
6147 ref_stack.back()->m_value.array->pop_back();
6148 }
6149
6150 return true;
6151 }
6152
6153 template<class Exception>
6154 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const Exception& ex)
6155 {
6156 errored = true;
6157 static_cast<void>(ex);
6158 if (allow_exceptions) {
6159 JSON_THROW(ex);
6160 }
6161 return false;
6162 }
6163
6164 constexpr bool is_errored() const { return errored; }
6165
6166 private:
6167 /*!
6168 @param[in] v value to add to the JSON value we build during parsing
6169 @param[in] skip_callback whether we should skip calling the callback
6170 function; this is required after start_array() and
6171 start_object() SAX events, because otherwise we would call the
6172 callback function with an empty array or object, respectively.
6173
6174 @invariant If the ref stack is empty, then the passed value will be the new
6175 root.
6176 @invariant If the ref stack contains a value, then it is an array or an
6177 object to which we can add elements
6178
6179 @return pair of boolean (whether value should be kept) and pointer (to the
6180 passed value in the ref_stack hierarchy; nullptr if not kept)
6181 */
6182 template<typename Value>
6183 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
6184 {
6185 JSON_ASSERT(!keep_stack.empty());
6186
6187 // do not handle this value if we know it would be added to a discarded
6188 // container
6189 if (!keep_stack.back()) {
6190 return {false, nullptr};
6191 }
6192
6193 // create value
6194 auto value = BasicJsonType(std::forward<Value>(v));
6195
6196 // check callback
6197 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
6198
6199 // do not handle this value if we just learnt it shall be discarded
6200 if (!keep) {
6201 return {false, nullptr};
6202 }
6203
6204 if (ref_stack.empty()) {
6205 root = std::move(value);
6206 return {true, &root};
6207 }
6208
6209 // skip this value if we already decided to skip the parent
6210 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
6211 if (!ref_stack.back()) {
6212 return {false, nullptr};
6213 }
6214
6215 // we now only expect arrays and objects
6216 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6217
6218 // array
6219 if (ref_stack.back()->is_array()) {
6220 ref_stack.back()->m_value.array->emplace_back(std::move(value));
6221 return {true, &(ref_stack.back()->m_value.array->back())};
6222 }
6223
6224 // object
6225 JSON_ASSERT(ref_stack.back()->is_object());
6226 // check if we should store an element for the current key
6227 JSON_ASSERT(!key_keep_stack.empty());
6228 const bool store_element = key_keep_stack.back();
6229 key_keep_stack.pop_back();
6230
6231 if (!store_element) {
6232 return {false, nullptr};
6233 }
6234
6236 *object_element = std::move(value);
6237 return {true, object_element};
6238 }
6239
6240 /// the parsed JSON value
6242 /// stack to model hierarchy of values
6243 std::vector<BasicJsonType*> ref_stack{};
6244 /// stack to manage which values to keep
6245 std::vector<bool> keep_stack{};
6246 /// stack to manage which object keys to keep
6247 std::vector<bool> key_keep_stack{};
6248 /// helper to hold the reference for the next object element
6250 /// whether a syntax error occurred
6251 bool errored = false;
6252 /// callback function
6254 /// whether to throw exceptions in case of errors
6255 const bool allow_exceptions = true;
6256 /// a discarded value for the callback
6257 BasicJsonType discarded = BasicJsonType::value_t::discarded;
6258};
6259
6260template<typename BasicJsonType>
6262{
6263 public:
6264 using number_integer_t = typename BasicJsonType::number_integer_t;
6265 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6266 using number_float_t = typename BasicJsonType::number_float_t;
6267 using string_t = typename BasicJsonType::string_t;
6268 using binary_t = typename BasicJsonType::binary_t;
6269
6270 bool null() { return true; }
6271
6272 bool boolean(bool /*unused*/) { return true; }
6273
6274 bool number_integer(number_integer_t /*unused*/) { return true; }
6275
6276 bool number_unsigned(number_unsigned_t /*unused*/) { return true; }
6277
6278 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) { return true; }
6279
6280 bool string(string_t& /*unused*/) { return true; }
6281
6282 bool binary(binary_t& /*unused*/) { return true; }
6283
6284 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) { return true; }
6285
6286 bool key(string_t& /*unused*/) { return true; }
6287
6288 bool end_object() { return true; }
6289
6290 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) { return true; }
6291
6292 bool end_array() { return true; }
6293
6294 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
6295 {
6296 return false;
6297 }
6298};
6299} // namespace detail
6300
6301} // namespace nlohmann
6302
6303// #include <nlohmann/detail/input/lexer.hpp>
6304
6305#include <array> // array
6306#include <clocale> // localeconv
6307#include <cstddef> // size_t
6308#include <cstdio> // snprintf
6309#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
6310#include <initializer_list> // initializer_list
6311#include <string> // char_traits, string
6312#include <utility> // move
6313#include <vector> // vector
6314
6315// #include <nlohmann/detail/input/input_adapters.hpp>
6316
6317// #include <nlohmann/detail/input/position_t.hpp>
6318
6319// #include <nlohmann/detail/macro_scope.hpp>
6320
6321namespace nlohmann
6322{
6323namespace detail
6324{
6325///////////
6326// lexer //
6327///////////
6328
6329template<typename BasicJsonType>
6331{
6332 public:
6333 /// token types for the parser
6334 enum class token_type
6335 {
6336 uninitialized, ///< indicating the scanner is uninitialized
6337 literal_true, ///< the `true` literal
6338 literal_false, ///< the `false` literal
6339 literal_null, ///< the `null` literal
6340 value_string, ///< a string -- use get_string() for actual value
6341 value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
6342 value_integer, ///< a signed integer -- use get_number_integer() for actual value
6343 value_float, ///< an floating point number -- use get_number_float() for actual value
6344 begin_array, ///< the character for array begin `[`
6345 begin_object, ///< the character for object begin `{`
6346 end_array, ///< the character for array end `]`
6347 end_object, ///< the character for object end `}`
6348 name_separator, ///< the name separator `:`
6349 value_separator, ///< the value separator `,`
6350 parse_error, ///< indicating a parse error
6351 end_of_input, ///< indicating the end of the input buffer
6352 literal_or_value ///< a literal or the begin of a value (only for diagnostics)
6353 };
6354
6355 /// return name of values of type token_type (only used for errors)
6358 static const char* token_type_name(const token_type t) noexcept
6359 {
6360 switch (t) {
6362 return "<uninitialized>";
6364 return "true literal";
6366 return "false literal";
6368 return "null literal";
6370 return "string literal";
6374 return "number literal";
6376 return "'['";
6378 return "'{'";
6380 return "']'";
6382 return "'}'";
6384 return "':'";
6386 return "','";
6388 return "<parse error>";
6390 return "end of input";
6392 return "'[', '{', or a literal";
6393 // LCOV_EXCL_START
6394 default: // catch non-enum values
6395 return "unknown token";
6396 // LCOV_EXCL_STOP
6397 }
6398 }
6399};
6400/*!
6401@brief lexical analysis
6402
6403This class organizes the lexical analysis during JSON deserialization.
6404*/
6405template<typename BasicJsonType, typename InputAdapterType>
6406class lexer : public lexer_base<BasicJsonType>
6407{
6408 using number_integer_t = typename BasicJsonType::number_integer_t;
6409 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6410 using number_float_t = typename BasicJsonType::number_float_t;
6411 using string_t = typename BasicJsonType::string_t;
6412 using char_type = typename InputAdapterType::char_type;
6413 using char_int_type = typename std::char_traits<char_type>::int_type;
6414
6415 public:
6417
6418 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
6419 : ia(std::move(adapter))
6420 , ignore_comments(ignore_comments_)
6422 {}
6423
6424 // delete because of pointer members
6425 lexer(const lexer&) = delete;
6426 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6427 lexer& operator=(lexer&) = delete;
6428 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6429 ~lexer() = default;
6430
6431 private:
6432 /////////////////////
6433 // locales
6434 /////////////////////
6435
6436 /// return the locale-dependent decimal point
6438 static char get_decimal_point() noexcept
6439 {
6440 const auto* loc = localeconv();
6441 JSON_ASSERT(loc != nullptr);
6442 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
6443 }
6444
6445 /////////////////////
6446 // scan functions
6447 /////////////////////
6448
6449 /*!
6450 @brief get codepoint from 4 hex characters following `\u`
6451
6452 For input "\u c1 c2 c3 c4" the codepoint is:
6453 (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
6454 = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
6455
6456 Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
6457 must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
6458 conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
6459 between the ASCII value of the character and the desired integer value.
6460
6461 @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
6462 non-hex character)
6463 */
6465 {
6466 // this function only makes sense after reading `\u`
6467 JSON_ASSERT(current == 'u');
6468 int codepoint = 0;
6469
6470 const auto factors = {12u, 8u, 4u, 0u};
6471 for (const auto factor : factors) {
6472 get();
6473
6474 if (current >= '0' && current <= '9') {
6475 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
6476 } else if (current >= 'A' && current <= 'F') {
6477 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
6478 } else if (current >= 'a' && current <= 'f') {
6479 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
6480 } else {
6481 return -1;
6482 }
6483 }
6484
6485 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
6486 return codepoint;
6487 }
6488
6489 /*!
6490 @brief check if the next byte(s) are inside a given range
6491
6492 Adds the current byte and, for each passed range, reads a new byte and
6493 checks if it is inside the range. If a violation was detected, set up an
6494 error message and return false. Otherwise, return true.
6495
6496 @param[in] ranges list of integers; interpreted as list of pairs of
6497 inclusive lower and upper bound, respectively
6498
6499 @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
6500 1, 2, or 3 pairs. This precondition is enforced by an assertion.
6501
6502 @return true if and only if no range violation was detected
6503 */
6504 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
6505 {
6506 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
6507 add(current);
6508
6509 for (auto range = ranges.begin(); range != ranges.end(); ++range) {
6510 get();
6511 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) {
6512 add(current);
6513 } else {
6514 error_message = "invalid string: ill-formed UTF-8 byte";
6515 return false;
6516 }
6517 }
6518
6519 return true;
6520 }
6521
6522 /*!
6523 @brief scan a string literal
6524
6525 This function scans a string according to Sect. 7 of RFC 8259. While
6526 scanning, bytes are escaped and copied into buffer token_buffer. Then the
6527 function returns successfully, token_buffer is *not* null-terminated (as it
6528 may contain \0 bytes), and token_buffer.size() is the number of bytes in the
6529 string.
6530
6531 @return token_type::value_string if string could be successfully scanned,
6532 token_type::parse_error otherwise
6533
6534 @note In case of errors, variable error_message contains a textual
6535 description.
6536 */
6538 {
6539 // reset token_buffer (ignore opening quote)
6540 reset();
6541
6542 // we entered the function by reading an open quote
6543 JSON_ASSERT(current == '\"');
6544
6545 while (true) {
6546 // get next character
6547 switch (get()) {
6548 // end of file while parsing string
6549 case std::char_traits<char_type>::eof(): {
6550 error_message = "invalid string: missing closing quote";
6551 return token_type::parse_error;
6552 }
6553
6554 // closing quote
6555 case '\"': {
6556 return token_type::value_string;
6557 }
6558
6559 // escapes
6560 case '\\': {
6561 switch (get()) {
6562 // quotation mark
6563 case '\"':
6564 add('\"');
6565 break;
6566 // reverse solidus
6567 case '\\':
6568 add('\\');
6569 break;
6570 // solidus
6571 case '/':
6572 add('/');
6573 break;
6574 // backspace
6575 case 'b':
6576 add('\b');
6577 break;
6578 // form feed
6579 case 'f':
6580 add('\f');
6581 break;
6582 // line feed
6583 case 'n':
6584 add('\n');
6585 break;
6586 // carriage return
6587 case 'r':
6588 add('\r');
6589 break;
6590 // tab
6591 case 't':
6592 add('\t');
6593 break;
6594
6595 // unicode escapes
6596 case 'u': {
6597 const int codepoint1 = get_codepoint();
6598 int codepoint = codepoint1; // start with codepoint1
6599
6600 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) {
6601 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
6602 return token_type::parse_error;
6603 }
6604
6605 // check if code point is a high surrogate
6606 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) {
6607 // expect next \uxxxx entry
6608 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) {
6609 const int codepoint2 = get_codepoint();
6610
6611 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) {
6612 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
6613 return token_type::parse_error;
6614 }
6615
6616 // check if codepoint2 is a low surrogate
6617 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) {
6618 // overwrite codepoint
6619 codepoint = static_cast<int>(
6620 // high surrogate occupies the most significant 22 bits
6621 (static_cast<unsigned int>(codepoint1) << 10u)
6622 // low surrogate occupies the least significant 15 bits
6623 + static_cast<unsigned int>(codepoint2)
6624 // there is still the 0xD800, 0xDC00 and 0x10000 noise
6625 // in the result, so we have to subtract with:
6626 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6627 - 0x35FDC00u);
6628 } else {
6629 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by "
6630 "U+DC00..U+DFFF";
6631 return token_type::parse_error;
6632 }
6633 } else {
6635 "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
6636 return token_type::parse_error;
6637 }
6638 } else {
6639 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) {
6641 "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
6642 return token_type::parse_error;
6643 }
6644 }
6645
6646 // result of the above calculation yields a proper codepoint
6647 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
6648
6649 // translate codepoint into bytes
6650 if (codepoint < 0x80) {
6651 // 1-byte characters: 0xxxxxxx (ASCII)
6652 add(static_cast<char_int_type>(codepoint));
6653 } else if (codepoint <= 0x7FF) {
6654 // 2-byte characters: 110xxxxx 10xxxxxx
6655 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
6656 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6657 } else if (codepoint <= 0xFFFF) {
6658 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6659 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
6660 add(static_cast<char_int_type>(
6661 0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
6662 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6663 } else {
6664 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6665 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
6666 add(static_cast<char_int_type>(
6667 0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
6668 add(static_cast<char_int_type>(
6669 0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
6670 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6671 }
6672
6673 break;
6674 }
6675
6676 // other characters after escape
6677 default:
6678 error_message = "invalid string: forbidden character after backslash";
6679 return token_type::parse_error;
6680 }
6681
6682 break;
6683 }
6684
6685 // invalid control characters
6686 case 0x00: {
6687 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
6688 return token_type::parse_error;
6689 }
6690
6691 case 0x01: {
6692 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
6693 return token_type::parse_error;
6694 }
6695
6696 case 0x02: {
6697 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
6698 return token_type::parse_error;
6699 }
6700
6701 case 0x03: {
6702 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
6703 return token_type::parse_error;
6704 }
6705
6706 case 0x04: {
6707 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
6708 return token_type::parse_error;
6709 }
6710
6711 case 0x05: {
6712 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
6713 return token_type::parse_error;
6714 }
6715
6716 case 0x06: {
6717 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
6718 return token_type::parse_error;
6719 }
6720
6721 case 0x07: {
6722 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
6723 return token_type::parse_error;
6724 }
6725
6726 case 0x08: {
6727 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
6728 return token_type::parse_error;
6729 }
6730
6731 case 0x09: {
6732 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
6733 return token_type::parse_error;
6734 }
6735
6736 case 0x0A: {
6737 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
6738 return token_type::parse_error;
6739 }
6740
6741 case 0x0B: {
6742 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
6743 return token_type::parse_error;
6744 }
6745
6746 case 0x0C: {
6747 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
6748 return token_type::parse_error;
6749 }
6750
6751 case 0x0D: {
6752 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
6753 return token_type::parse_error;
6754 }
6755
6756 case 0x0E: {
6757 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
6758 return token_type::parse_error;
6759 }
6760
6761 case 0x0F: {
6762 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
6763 return token_type::parse_error;
6764 }
6765
6766 case 0x10: {
6767 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
6768 return token_type::parse_error;
6769 }
6770
6771 case 0x11: {
6772 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
6773 return token_type::parse_error;
6774 }
6775
6776 case 0x12: {
6777 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
6778 return token_type::parse_error;
6779 }
6780
6781 case 0x13: {
6782 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
6783 return token_type::parse_error;
6784 }
6785
6786 case 0x14: {
6787 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
6788 return token_type::parse_error;
6789 }
6790
6791 case 0x15: {
6792 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
6793 return token_type::parse_error;
6794 }
6795
6796 case 0x16: {
6797 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
6798 return token_type::parse_error;
6799 }
6800
6801 case 0x17: {
6802 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
6803 return token_type::parse_error;
6804 }
6805
6806 case 0x18: {
6807 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
6808 return token_type::parse_error;
6809 }
6810
6811 case 0x19: {
6812 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
6813 return token_type::parse_error;
6814 }
6815
6816 case 0x1A: {
6817 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
6818 return token_type::parse_error;
6819 }
6820
6821 case 0x1B: {
6822 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
6823 return token_type::parse_error;
6824 }
6825
6826 case 0x1C: {
6827 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
6828 return token_type::parse_error;
6829 }
6830
6831 case 0x1D: {
6832 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
6833 return token_type::parse_error;
6834 }
6835
6836 case 0x1E: {
6837 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
6838 return token_type::parse_error;
6839 }
6840
6841 case 0x1F: {
6842 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
6843 return token_type::parse_error;
6844 }
6845
6846 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
6847 case 0x20:
6848 case 0x21:
6849 case 0x23:
6850 case 0x24:
6851 case 0x25:
6852 case 0x26:
6853 case 0x27:
6854 case 0x28:
6855 case 0x29:
6856 case 0x2A:
6857 case 0x2B:
6858 case 0x2C:
6859 case 0x2D:
6860 case 0x2E:
6861 case 0x2F:
6862 case 0x30:
6863 case 0x31:
6864 case 0x32:
6865 case 0x33:
6866 case 0x34:
6867 case 0x35:
6868 case 0x36:
6869 case 0x37:
6870 case 0x38:
6871 case 0x39:
6872 case 0x3A:
6873 case 0x3B:
6874 case 0x3C:
6875 case 0x3D:
6876 case 0x3E:
6877 case 0x3F:
6878 case 0x40:
6879 case 0x41:
6880 case 0x42:
6881 case 0x43:
6882 case 0x44:
6883 case 0x45:
6884 case 0x46:
6885 case 0x47:
6886 case 0x48:
6887 case 0x49:
6888 case 0x4A:
6889 case 0x4B:
6890 case 0x4C:
6891 case 0x4D:
6892 case 0x4E:
6893 case 0x4F:
6894 case 0x50:
6895 case 0x51:
6896 case 0x52:
6897 case 0x53:
6898 case 0x54:
6899 case 0x55:
6900 case 0x56:
6901 case 0x57:
6902 case 0x58:
6903 case 0x59:
6904 case 0x5A:
6905 case 0x5B:
6906 case 0x5D:
6907 case 0x5E:
6908 case 0x5F:
6909 case 0x60:
6910 case 0x61:
6911 case 0x62:
6912 case 0x63:
6913 case 0x64:
6914 case 0x65:
6915 case 0x66:
6916 case 0x67:
6917 case 0x68:
6918 case 0x69:
6919 case 0x6A:
6920 case 0x6B:
6921 case 0x6C:
6922 case 0x6D:
6923 case 0x6E:
6924 case 0x6F:
6925 case 0x70:
6926 case 0x71:
6927 case 0x72:
6928 case 0x73:
6929 case 0x74:
6930 case 0x75:
6931 case 0x76:
6932 case 0x77:
6933 case 0x78:
6934 case 0x79:
6935 case 0x7A:
6936 case 0x7B:
6937 case 0x7C:
6938 case 0x7D:
6939 case 0x7E:
6940 case 0x7F: {
6941 add(current);
6942 break;
6943 }
6944
6945 // U+0080..U+07FF: bytes C2..DF 80..BF
6946 case 0xC2:
6947 case 0xC3:
6948 case 0xC4:
6949 case 0xC5:
6950 case 0xC6:
6951 case 0xC7:
6952 case 0xC8:
6953 case 0xC9:
6954 case 0xCA:
6955 case 0xCB:
6956 case 0xCC:
6957 case 0xCD:
6958 case 0xCE:
6959 case 0xCF:
6960 case 0xD0:
6961 case 0xD1:
6962 case 0xD2:
6963 case 0xD3:
6964 case 0xD4:
6965 case 0xD5:
6966 case 0xD6:
6967 case 0xD7:
6968 case 0xD8:
6969 case 0xD9:
6970 case 0xDA:
6971 case 0xDB:
6972 case 0xDC:
6973 case 0xDD:
6974 case 0xDE:
6975 case 0xDF: {
6976 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF}))) {
6977 return token_type::parse_error;
6978 }
6979 break;
6980 }
6981
6982 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
6983 case 0xE0: {
6984 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) {
6985 return token_type::parse_error;
6986 }
6987 break;
6988 }
6989
6990 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
6991 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
6992 case 0xE1:
6993 case 0xE2:
6994 case 0xE3:
6995 case 0xE4:
6996 case 0xE5:
6997 case 0xE6:
6998 case 0xE7:
6999 case 0xE8:
7000 case 0xE9:
7001 case 0xEA:
7002 case 0xEB:
7003 case 0xEC:
7004 case 0xEE:
7005 case 0xEF: {
7006 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) {
7007 return token_type::parse_error;
7008 }
7009 break;
7010 }
7011
7012 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7013 case 0xED: {
7014 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) {
7015 return token_type::parse_error;
7016 }
7017 break;
7018 }
7019
7020 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7021 case 0xF0: {
7022 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) {
7023 return token_type::parse_error;
7024 }
7025 break;
7026 }
7027
7028 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7029 case 0xF1:
7030 case 0xF2:
7031 case 0xF3: {
7032 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) {
7033 return token_type::parse_error;
7034 }
7035 break;
7036 }
7037
7038 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7039 case 0xF4: {
7040 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) {
7041 return token_type::parse_error;
7042 }
7043 break;
7044 }
7045
7046 // remaining bytes (80..C1 and F5..FF) are ill-formed
7047 default: {
7048 error_message = "invalid string: ill-formed UTF-8 byte";
7049 return token_type::parse_error;
7050 }
7051 }
7052 }
7053 }
7054
7055 /*!
7056 * @brief scan a comment
7057 * @return whether comment could be scanned successfully
7058 */
7060 {
7061 switch (get()) {
7062 // single-line comments skip input until a newline or EOF is read
7063 case '/': {
7064 while (true) {
7065 switch (get()) {
7066 case '\n':
7067 case '\r':
7068 case std::char_traits<char_type>::eof():
7069 case '\0':
7070 return true;
7071
7072 default:
7073 break;
7074 }
7075 }
7076 }
7077
7078 // multi-line comments skip input until */ is read
7079 case '*': {
7080 while (true) {
7081 switch (get()) {
7082 case std::char_traits<char_type>::eof():
7083 case '\0': {
7084 error_message = "invalid comment; missing closing '*/'";
7085 return false;
7086 }
7087
7088 case '*': {
7089 switch (get()) {
7090 case '/':
7091 return true;
7092
7093 default: {
7094 unget();
7095 continue;
7096 }
7097 }
7098 }
7099
7100 default:
7101 continue;
7102 }
7103 }
7104 }
7105
7106 // unexpected character after reading '/'
7107 default: {
7108 error_message = "invalid comment; expecting '/' or '*' after '/'";
7109 return false;
7110 }
7111 }
7112 }
7113
7115 static void strtof(float& f, const char* str, char** endptr) noexcept { f = std::strtof(str, endptr); }
7116
7118 static void strtof(double& f, const char* str, char** endptr) noexcept { f = std::strtod(str, endptr); }
7119
7121 static void strtof(long double& f, const char* str, char** endptr) noexcept { f = std::strtold(str, endptr); }
7122
7123 /*!
7124 @brief scan a number literal
7125
7126 This function scans a string according to Sect. 6 of RFC 8259.
7127
7128 The function is realized with a deterministic finite state machine derived
7129 from the grammar described in RFC 8259. Starting in state "init", the
7130 input is read and used to determined the next state. Only state "done"
7131 accepts the number. State "error" is a trap state to model errors. In the
7132 table below, "anything" means any character but the ones listed before.
7133
7134 state | 0 | 1-9 | e E | + | - | . | anything
7135 ---------|----------|----------|----------|---------|---------|----------|-----------
7136 init | zero | any1 | [error] | [error] | minus | [error] | [error]
7137 minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
7138 zero | done | done | exponent | done | done | decimal1 | done
7139 any1 | any1 | any1 | exponent | done | done | decimal1 | done
7140 decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error]
7141 decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
7142 exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
7143 sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
7144 any2 | any2 | any2 | done | done | done | done | done
7145
7146 The state machine is realized with one label per state (prefixed with
7147 "scan_number_") and `goto` statements between them. The state machine
7148 contains cycles, but any cycle can be left when EOF is read. Therefore,
7149 the function is guaranteed to terminate.
7150
7151 During scanning, the read bytes are stored in token_buffer. This string is
7152 then converted to a signed integer, an unsigned integer, or a
7153 floating-point number.
7154
7155 @return token_type::value_unsigned, token_type::value_integer, or
7156 token_type::value_float if number could be successfully scanned,
7157 token_type::parse_error otherwise
7158
7159 @note The scanner is independent of the current locale. Internally, the
7160 locale's decimal point is used instead of `.` to work with the
7161 locale-dependent converters.
7162 */
7163 token_type scan_number() // lgtm [cpp/use-of-goto]
7164 {
7165 // reset token_buffer to store the number's bytes
7166 reset();
7167
7168 // the type of the parsed number; initially set to unsigned; will be
7169 // changed if minus sign, decimal point or exponent is read
7170 token_type number_type = token_type::value_unsigned;
7171
7172 // state (init): we just found out we need to scan a number
7173 switch (current) {
7174 case '-': {
7175 add(current);
7176 goto scan_number_minus;
7177 }
7178
7179 case '0': {
7180 add(current);
7181 goto scan_number_zero;
7182 }
7183
7184 case '1':
7185 case '2':
7186 case '3':
7187 case '4':
7188 case '5':
7189 case '6':
7190 case '7':
7191 case '8':
7192 case '9': {
7193 add(current);
7194 goto scan_number_any1;
7195 }
7196
7197 // all other characters are rejected outside scan_number()
7198 default: // LCOV_EXCL_LINE
7199 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
7200 }
7201
7202 scan_number_minus:
7203 // state: we just parsed a leading minus sign
7204 number_type = token_type::value_integer;
7205 switch (get()) {
7206 case '0': {
7207 add(current);
7208 goto scan_number_zero;
7209 }
7210
7211 case '1':
7212 case '2':
7213 case '3':
7214 case '4':
7215 case '5':
7216 case '6':
7217 case '7':
7218 case '8':
7219 case '9': {
7220 add(current);
7221 goto scan_number_any1;
7222 }
7223
7224 default: {
7225 error_message = "invalid number; expected digit after '-'";
7226 return token_type::parse_error;
7227 }
7228 }
7229
7230 scan_number_zero:
7231 // state: we just parse a zero (maybe with a leading minus sign)
7232 switch (get()) {
7233 case '.': {
7235 goto scan_number_decimal1;
7236 }
7237
7238 case 'e':
7239 case 'E': {
7240 add(current);
7241 goto scan_number_exponent;
7242 }
7243
7244 default:
7245 goto scan_number_done;
7246 }
7247
7248 scan_number_any1:
7249 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
7250 switch (get()) {
7251 case '0':
7252 case '1':
7253 case '2':
7254 case '3':
7255 case '4':
7256 case '5':
7257 case '6':
7258 case '7':
7259 case '8':
7260 case '9': {
7261 add(current);
7262 goto scan_number_any1;
7263 }
7264
7265 case '.': {
7267 goto scan_number_decimal1;
7268 }
7269
7270 case 'e':
7271 case 'E': {
7272 add(current);
7273 goto scan_number_exponent;
7274 }
7275
7276 default:
7277 goto scan_number_done;
7278 }
7279
7280 scan_number_decimal1:
7281 // state: we just parsed a decimal point
7282 number_type = token_type::value_float;
7283 switch (get()) {
7284 case '0':
7285 case '1':
7286 case '2':
7287 case '3':
7288 case '4':
7289 case '5':
7290 case '6':
7291 case '7':
7292 case '8':
7293 case '9': {
7294 add(current);
7295 goto scan_number_decimal2;
7296 }
7297
7298 default: {
7299 error_message = "invalid number; expected digit after '.'";
7300 return token_type::parse_error;
7301 }
7302 }
7303
7304 scan_number_decimal2:
7305 // we just parsed at least one number after a decimal point
7306 switch (get()) {
7307 case '0':
7308 case '1':
7309 case '2':
7310 case '3':
7311 case '4':
7312 case '5':
7313 case '6':
7314 case '7':
7315 case '8':
7316 case '9': {
7317 add(current);
7318 goto scan_number_decimal2;
7319 }
7320
7321 case 'e':
7322 case 'E': {
7323 add(current);
7324 goto scan_number_exponent;
7325 }
7326
7327 default:
7328 goto scan_number_done;
7329 }
7330
7331 scan_number_exponent:
7332 // we just parsed an exponent
7333 number_type = token_type::value_float;
7334 switch (get()) {
7335 case '+':
7336 case '-': {
7337 add(current);
7338 goto scan_number_sign;
7339 }
7340
7341 case '0':
7342 case '1':
7343 case '2':
7344 case '3':
7345 case '4':
7346 case '5':
7347 case '6':
7348 case '7':
7349 case '8':
7350 case '9': {
7351 add(current);
7352 goto scan_number_any2;
7353 }
7354
7355 default: {
7356 error_message = "invalid number; expected '+', '-', or digit after exponent";
7357 return token_type::parse_error;
7358 }
7359 }
7360
7361 scan_number_sign:
7362 // we just parsed an exponent sign
7363 switch (get()) {
7364 case '0':
7365 case '1':
7366 case '2':
7367 case '3':
7368 case '4':
7369 case '5':
7370 case '6':
7371 case '7':
7372 case '8':
7373 case '9': {
7374 add(current);
7375 goto scan_number_any2;
7376 }
7377
7378 default: {
7379 error_message = "invalid number; expected digit after exponent sign";
7380 return token_type::parse_error;
7381 }
7382 }
7383
7384 scan_number_any2:
7385 // we just parsed a number after the exponent or exponent sign
7386 switch (get()) {
7387 case '0':
7388 case '1':
7389 case '2':
7390 case '3':
7391 case '4':
7392 case '5':
7393 case '6':
7394 case '7':
7395 case '8':
7396 case '9': {
7397 add(current);
7398 goto scan_number_any2;
7399 }
7400
7401 default:
7402 goto scan_number_done;
7403 }
7404
7405 scan_number_done:
7406 // unget the character after the number (we only read it to know that
7407 // we are done scanning a number)
7408 unget();
7409
7410 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
7411 errno = 0;
7412
7413 // try to parse integers first and fall back to floats
7414 if (number_type == token_type::value_unsigned) {
7415 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
7416
7417 // we checked the number format before
7418 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7419
7420 if (errno == 0) {
7421 value_unsigned = static_cast<number_unsigned_t>(x);
7422 if (value_unsigned == x) {
7423 return token_type::value_unsigned;
7424 }
7425 }
7426 } else if (number_type == token_type::value_integer) {
7427 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
7428
7429 // we checked the number format before
7430 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7431
7432 if (errno == 0) {
7433 value_integer = static_cast<number_integer_t>(x);
7434 if (value_integer == x) {
7435 return token_type::value_integer;
7436 }
7437 }
7438 }
7439
7440 // this code is reached if we parse a floating-point number or if an
7441 // integer conversion above failed
7442 strtof(value_float, token_buffer.data(), &endptr);
7443
7444 // we checked the number format before
7445 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7446
7447 return token_type::value_float;
7448 }
7449
7450 /*!
7451 @param[in] literal_text the literal text to expect
7452 @param[in] length the length of the passed literal text
7453 @param[in] return_type the token type to return on success
7454 */
7456 token_type scan_literal(const char_type* literal_text, const std::size_t length, token_type return_type)
7457 {
7458 JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
7459 for (std::size_t i = 1; i < length; ++i) {
7460 if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i])) {
7461 error_message = "invalid literal";
7462 return token_type::parse_error;
7463 }
7464 }
7465 return return_type;
7466 }
7467
7468 /////////////////////
7469 // input management
7470 /////////////////////
7471
7472 /// reset token_buffer; current character is beginning of token
7473 void reset() noexcept
7474 {
7475 token_buffer.clear();
7476 token_string.clear();
7477 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
7478 }
7479
7480 /*
7481 @brief get next character from the input
7482
7483 This function provides the interface to the used input adapter. It does
7484 not throw in case the input reached EOF, but returns a
7485 `std::char_traits<char>::eof()` in that case. Stores the scanned characters
7486 for use in error messages.
7487
7488 @return character read from the input
7489 */
7491 {
7492 ++position.chars_read_total;
7493 ++position.chars_read_current_line;
7494
7495 if (next_unget) {
7496 // just reset the next_unget variable and work with current
7497 next_unget = false;
7498 } else {
7499 current = ia.get_character();
7500 }
7501
7502 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof())) {
7503 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
7504 }
7505
7506 if (current == '\n') {
7507 ++position.lines_read;
7508 position.chars_read_current_line = 0;
7509 }
7510
7511 return current;
7512 }
7513
7514 /*!
7515 @brief unget current character (read it again on next get)
7516
7517 We implement unget by setting variable next_unget to true. The input is not
7518 changed - we just simulate ungetting by modifying chars_read_total,
7519 chars_read_current_line, and token_string. The next call to get() will
7520 behave as if the unget character is read again.
7521 */
7522 void unget()
7523 {
7524 next_unget = true;
7525
7526 --position.chars_read_total;
7527
7528 // in case we "unget" a newline, we have to also decrement the lines_read
7529 if (position.chars_read_current_line == 0) {
7530 if (position.lines_read > 0) {
7531 --position.lines_read;
7532 }
7533 } else {
7534 --position.chars_read_current_line;
7535 }
7536
7537 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof())) {
7538 JSON_ASSERT(!token_string.empty());
7539 token_string.pop_back();
7540 }
7541 }
7542
7543 /// add a character to token_buffer
7544 void add(char_int_type c) { token_buffer.push_back(static_cast<typename string_t::value_type>(c)); }
7545
7546 public:
7547 /////////////////////
7548 // value getters
7549 /////////////////////
7550
7551 /// return integer value
7552 constexpr number_integer_t get_number_integer() const noexcept { return value_integer; }
7553
7554 /// return unsigned integer value
7555 constexpr number_unsigned_t get_number_unsigned() const noexcept { return value_unsigned; }
7556
7557 /// return floating-point value
7558 constexpr number_float_t get_number_float() const noexcept { return value_float; }
7559
7560 /// return current string value (implicitly resets the token; useful only once)
7562
7563 /////////////////////
7564 // diagnostics
7565 /////////////////////
7566
7567 /// return position of last read token
7568 constexpr position_t get_position() const noexcept { return position; }
7569
7570 /// return the last read token (for errors only). Will never contain EOF
7571 /// (an arbitrary value that is not a valid char value, often -1), because
7572 /// 255 may legitimately occur. May contain NUL, which should be escaped.
7573 std::string get_token_string() const
7574 {
7575 // escape control characters
7576 std::string result;
7577 for (const auto c : token_string) {
7578 if (static_cast<unsigned char>(c) <= '\x1F') {
7579 // escape control characters
7580 std::array<char, 9> cs{{}};
7581 static_cast<void>((std::snprintf)(
7582 cs.data(), cs.size(), "<U+%.4X>",
7583 static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
7584 result += cs.data();
7585 } else {
7586 // add character as is
7587 result.push_back(static_cast<std::string::value_type>(c));
7588 }
7589 }
7590
7591 return result;
7592 }
7593
7594 /// return syntax error message
7596 constexpr const char* get_error_message() const noexcept { return error_message; }
7597
7598 /////////////////////
7599 // actual scanner
7600 /////////////////////
7601
7602 /*!
7603 @brief skip the UTF-8 byte order mark
7604 @return true iff there is no BOM or the correct BOM has been skipped
7605 */
7607 {
7608 if (get() == 0xEF) {
7609 // check if we completely parse the BOM
7610 return get() == 0xBB && get() == 0xBF;
7611 }
7612
7613 // the first character is not the beginning of the BOM; unget it to
7614 // process is later
7615 unget();
7616 return true;
7617 }
7618
7620 {
7621 do {
7622 get();
7623 } while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
7624 }
7625
7627 {
7628 // initially, skip the BOM
7629 if (position.chars_read_total == 0 && !skip_bom()) {
7630 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
7631 return token_type::parse_error;
7632 }
7633
7634 // read next character and ignore whitespace
7636
7637 // ignore comments
7638 while (ignore_comments && current == '/') {
7639 if (!scan_comment()) {
7640 return token_type::parse_error;
7641 }
7642
7643 // skip following whitespace
7645 }
7646
7647 switch (current) {
7648 // structural characters
7649 case '[':
7650 return token_type::begin_array;
7651 case ']':
7652 return token_type::end_array;
7653 case '{':
7654 return token_type::begin_object;
7655 case '}':
7656 return token_type::end_object;
7657 case ':':
7658 return token_type::name_separator;
7659 case ',':
7660 return token_type::value_separator;
7661
7662 // literals
7663 case 't': {
7664 std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'),
7665 static_cast<char_type>('u'), static_cast<char_type>('e')}};
7666 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
7667 }
7668 case 'f': {
7669 std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'),
7670 static_cast<char_type>('l'), static_cast<char_type>('s'),
7671 static_cast<char_type>('e')}};
7672 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
7673 }
7674 case 'n': {
7675 std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'),
7676 static_cast<char_type>('l'), static_cast<char_type>('l')}};
7677 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
7678 }
7679
7680 // string
7681 case '\"':
7682 return scan_string();
7683
7684 // number
7685 case '-':
7686 case '0':
7687 case '1':
7688 case '2':
7689 case '3':
7690 case '4':
7691 case '5':
7692 case '6':
7693 case '7':
7694 case '8':
7695 case '9':
7696 return scan_number();
7697
7698 // end of input (the null byte is needed when parsing from
7699 // string literals)
7700 case '\0':
7701 case std::char_traits<char_type>::eof():
7702 return token_type::end_of_input;
7703
7704 // error
7705 default:
7706 error_message = "invalid literal";
7707 return token_type::parse_error;
7708 }
7709 }
7710
7711 private:
7712 /// input adapter
7713 InputAdapterType ia;
7714
7715 /// whether comments should be ignored (true) or signaled as errors (false)
7716 const bool ignore_comments = false;
7717
7718 /// the current character
7719 char_int_type current = std::char_traits<char_type>::eof();
7720
7721 /// whether the next get() call should just return current
7722 bool next_unget = false;
7723
7724 /// the start position of the current token
7726
7727 /// raw input token string (for error messages)
7728 std::vector<char_type> token_string{};
7729
7730 /// buffer for variable-length tokens (numbers, strings)
7732
7733 /// a description of occurred lexer errors
7734 const char* error_message = "";
7735
7736 // number values
7740
7741 /// the decimal point
7743};
7744} // namespace detail
7745} // namespace nlohmann
7746
7747// #include <nlohmann/detail/macro_scope.hpp>
7748
7749// #include <nlohmann/detail/meta/is_sax.hpp>
7750
7751#include <cstdint> // size_t
7752#include <string> // string
7753#include <utility> // declval
7754
7755// #include <nlohmann/detail/meta/detected.hpp>
7756
7757// #include <nlohmann/detail/meta/type_traits.hpp>
7758
7759namespace nlohmann
7760{
7761namespace detail
7762{
7763template<typename T>
7764using null_function_t = decltype(std::declval<T&>().null());
7765
7766template<typename T>
7767using boolean_function_t = decltype(std::declval<T&>().boolean(std::declval<bool>()));
7768
7769template<typename T, typename Integer>
7770using number_integer_function_t = decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
7771
7772template<typename T, typename Unsigned>
7773using number_unsigned_function_t = decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
7774
7775template<typename T, typename Float, typename String>
7777 decltype(std::declval<T&>().number_float(std::declval<Float>(), std::declval<const String&>()));
7778
7779template<typename T, typename String>
7780using string_function_t = decltype(std::declval<T&>().string(std::declval<String&>()));
7781
7782template<typename T, typename Binary>
7783using binary_function_t = decltype(std::declval<T&>().binary(std::declval<Binary&>()));
7784
7785template<typename T>
7786using start_object_function_t = decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
7787
7788template<typename T, typename String>
7789using key_function_t = decltype(std::declval<T&>().key(std::declval<String&>()));
7790
7791template<typename T>
7792using end_object_function_t = decltype(std::declval<T&>().end_object());
7793
7794template<typename T>
7795using start_array_function_t = decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
7796
7797template<typename T>
7798using end_array_function_t = decltype(std::declval<T&>().end_array());
7799
7800template<typename T, typename Exception>
7801using parse_error_function_t = decltype(std::declval<T&>().parse_error(std::declval<std::size_t>(),
7802 std::declval<const std::string&>(),
7803 std::declval<const Exception&>()));
7804
7805template<typename SAX, typename BasicJsonType>
7807{
7808 private:
7809 static_assert(is_basic_json<BasicJsonType>::value, "BasicJsonType must be of type basic_json<...>");
7810
7811 using number_integer_t = typename BasicJsonType::number_integer_t;
7812 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7813 using number_float_t = typename BasicJsonType::number_float_t;
7814 using string_t = typename BasicJsonType::string_t;
7815 using binary_t = typename BasicJsonType::binary_t;
7816 using exception_t = typename BasicJsonType::exception;
7817
7818 public:
7819 static constexpr bool value =
7832};
7833
7834template<typename SAX, typename BasicJsonType>
7836{
7837 private:
7838 static_assert(is_basic_json<BasicJsonType>::value, "BasicJsonType must be of type basic_json<...>");
7839
7840 using number_integer_t = typename BasicJsonType::number_integer_t;
7841 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7842 using number_float_t = typename BasicJsonType::number_float_t;
7843 using string_t = typename BasicJsonType::string_t;
7844 using binary_t = typename BasicJsonType::binary_t;
7845 using exception_t = typename BasicJsonType::exception;
7846
7847 public:
7848 static_assert(is_detected_exact<bool, null_function_t, SAX>::value, "Missing/invalid function: bool null()");
7850 "Missing/invalid function: bool boolean(bool)");
7852 "Missing/invalid function: bool boolean(bool)");
7854 "Missing/invalid function: bool number_integer(number_integer_t)");
7856 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
7858 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
7860 "Missing/invalid function: bool string(string_t&)");
7862 "Missing/invalid function: bool binary(binary_t&)");
7864 "Missing/invalid function: bool start_object(std::size_t)");
7866 "Missing/invalid function: bool key(string_t&)");
7868 "Missing/invalid function: bool end_object()");
7870 "Missing/invalid function: bool start_array(std::size_t)");
7872 "Missing/invalid function: bool end_array()");
7874 "Missing/invalid function: bool parse_error(std::size_t, const "
7875 "std::string&, const exception&)");
7876};
7877} // namespace detail
7878} // namespace nlohmann
7879
7880// #include <nlohmann/detail/meta/type_traits.hpp>
7881
7882// #include <nlohmann/detail/value_t.hpp>
7883
7884namespace nlohmann
7885{
7886namespace detail
7887{
7888
7889/// how to treat CBOR tags
7891{
7892 error, ///< throw a parse_error exception in case of a tag
7893 ignore, ///< ignore tags
7894 store ///< store tags as binary type
7895};
7896
7897/*!
7898@brief determine system byte order
7899
7900@return true if and only if system's byte order is little endian
7901
7902@note from https://stackoverflow.com/a/1001328/266378
7903*/
7904static inline bool little_endianness(int num = 1) noexcept
7905{
7906 return *reinterpret_cast<char*>(&num) == 1;
7907}
7908
7909///////////////////
7910// binary reader //
7911///////////////////
7912
7913/*!
7914@brief deserialization of CBOR, MessagePack, and UBJSON values
7915*/
7916template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
7918{
7919 using number_integer_t = typename BasicJsonType::number_integer_t;
7920 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7921 using number_float_t = typename BasicJsonType::number_float_t;
7922 using string_t = typename BasicJsonType::string_t;
7923 using binary_t = typename BasicJsonType::binary_t;
7924 using json_sax_t = SAX;
7925 using char_type = typename InputAdapterType::char_type;
7926 using char_int_type = typename std::char_traits<char_type>::int_type;
7927
7928 public:
7929 /*!
7930 @brief create a binary reader
7931
7932 @param[in] adapter input adapter to read from
7933 */
7934 explicit binary_reader(InputAdapterType&& adapter) noexcept
7935 : ia(std::move(adapter))
7936 {
7938 }
7939
7940 // make class move-only
7942 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7945 default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7946 ~binary_reader() = default;
7947
7948 /*!
7949 @param[in] format the binary format to parse
7950 @param[in] sax_ a SAX event processor
7951 @param[in] strict whether to expect the input to be consumed completed
7952 @param[in] tag_handler how to treat CBOR tags
7953
7954 @return whether parsing was successful
7955 */
7957 bool sax_parse(const input_format_t format,
7958 json_sax_t* sax_,
7959 const bool strict = true,
7960 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
7961 {
7962 sax = sax_;
7963 bool result = false;
7964
7965 switch (format) {
7968 break;
7969
7971 result = parse_cbor_internal(true, tag_handler);
7972 break;
7973
7976 break;
7977
7980 break;
7981
7982 case input_format_t::json: // LCOV_EXCL_LINE
7983 default: // LCOV_EXCL_LINE
7984 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
7985 }
7986
7987 // strict mode: next byte must be EOF
7988 if (result && strict) {
7989 if (format == input_format_t::ubjson) {
7991 } else {
7992 get();
7993 }
7994
7995 if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof())) {
7996 return sax->parse_error(
7999 110, chars_read,
8000 exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"),
8001 BasicJsonType()));
8002 }
8003 }
8004
8005 return result;
8006 }
8007
8008 private:
8009 //////////
8010 // BSON //
8011 //////////
8012
8013 /*!
8014 @brief Reads in a BSON-object and passes it to the SAX-parser.
8015 @return whether a valid BSON-value was passed to the SAX parser
8016 */
8018 {
8019 std::int32_t document_size{};
8021
8022 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) {
8023 return false;
8024 }
8025
8026 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/ false))) {
8027 return false;
8028 }
8029
8030 return sax->end_object();
8031 }
8032
8033 /*!
8034 @brief Parses a C-style string from the BSON input.
8035 @param[in,out] result A reference to the string variable where the read
8036 string is to be stored.
8037 @return `true` if the \x00-byte indicating the end of the string was
8038 encountered before the EOF; false` indicates an unexpected EOF.
8039 */
8040 bool get_bson_cstr(string_t& result)
8041 {
8042 auto out = std::back_inserter(result);
8043 while (true) {
8044 get();
8046 return false;
8047 }
8048 if (current == 0x00) {
8049 return true;
8050 }
8051 *out++ = static_cast<typename string_t::value_type>(current);
8052 }
8053 }
8054
8055 /*!
8056 @brief Parses a zero-terminated string of length @a len from the BSON
8057 input.
8058 @param[in] len The length (including the zero-byte at the end) of the
8059 string to be read.
8060 @param[in,out] result A reference to the string variable where the read
8061 string is to be stored.
8062 @tparam NumberType The type of the length @a len
8063 @pre len >= 1
8064 @return `true` if the string was successfully parsed
8065 */
8066 template<typename NumberType>
8067 bool get_bson_string(const NumberType len, string_t& result)
8068 {
8069 if (JSON_HEDLEY_UNLIKELY(len < 1)) {
8070 auto last_token = get_token_string();
8071 return sax->parse_error(
8072 chars_read, last_token,
8075 "string length must be at least 1, is " + std::to_string(len),
8076 "string"),
8077 BasicJsonType()));
8078 }
8079
8080 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result)
8081 && get() != std::char_traits<char_type>::eof();
8082 }
8083
8084 /*!
8085 @brief Parses a byte array input of length @a len from the BSON input.
8086 @param[in] len The length of the byte array to be read.
8087 @param[in,out] result A reference to the binary variable where the read
8088 array is to be stored.
8089 @tparam NumberType The type of the length @a len
8090 @pre len >= 0
8091 @return `true` if the byte array was successfully parsed
8092 */
8093 template<typename NumberType>
8094 bool get_bson_binary(const NumberType len, binary_t& result)
8095 {
8096 if (JSON_HEDLEY_UNLIKELY(len < 0)) {
8097 auto last_token = get_token_string();
8098 return sax->parse_error(
8099 chars_read, last_token,
8102 "byte array length cannot be negative, is " + std::to_string(len),
8103 "binary"),
8104 BasicJsonType()));
8105 }
8106
8107 // All BSON binary values have a subtype
8108 std::uint8_t subtype{};
8110 result.set_subtype(subtype);
8111
8113 }
8114
8115 /*!
8116 @brief Read a BSON document element of the given @a element_type.
8117 @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
8118 @param[in] element_type_parse_position The position in the input stream,
8119 where the `element_type` was read.
8120 @warning Not all BSON element types are supported yet. An unsupported
8121 @a element_type will give rise to a parse_error.114:
8122 Unsupported BSON record type 0x...
8123 @return whether a valid BSON-object/array was passed to the SAX parser
8124 */
8125 bool parse_bson_element_internal(const char_int_type element_type, const std::size_t element_type_parse_position)
8126 {
8127 switch (element_type) {
8128 case 0x01: // double
8129 {
8130 double number{};
8132 && sax->number_float(static_cast<number_float_t>(number), "");
8133 }
8134
8135 case 0x02: // string
8136 {
8137 std::int32_t len{};
8140 && sax->string(value);
8141 }
8142
8143 case 0x03: // object
8144 {
8145 return parse_bson_internal();
8146 }
8147
8148 case 0x04: // array
8149 {
8150 return parse_bson_array();
8151 }
8152
8153 case 0x05: // binary
8154 {
8155 std::int32_t len{};
8158 && sax->binary(value);
8159 }
8160
8161 case 0x08: // boolean
8162 {
8163 return sax->boolean(get() != 0);
8164 }
8165
8166 case 0x0A: // null
8167 {
8168 return sax->null();
8169 }
8170
8171 case 0x10: // int32
8172 {
8173 std::int32_t value{};
8175 }
8176
8177 case 0x12: // int64
8178 {
8179 std::int64_t value{};
8181 }
8182
8183 default: // anything else not supported (yet)
8184 {
8185 std::array<char, 3> cr{{}};
8186 static_cast<void>(
8187 (std::snprintf)(cr.data(), cr.size(), "%.2hhX",
8188 static_cast<unsigned char>(
8189 element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8190 return sax->parse_error(element_type_parse_position, std::string(cr.data()),
8191 parse_error::create(114, element_type_parse_position,
8192 "Unsupported BSON record type 0x" + std::string(cr.data()),
8193 BasicJsonType()));
8194 }
8195 }
8196 }
8197
8198 /*!
8199 @brief Read a BSON element list (as specified in the BSON-spec)
8200
8201 The same binary layout is used for objects and arrays, hence it must be
8202 indicated with the argument @a is_array which one is expected
8203 (true --> array, false --> object).
8204
8205 @param[in] is_array Determines if the element list being read is to be
8206 treated as an object (@a is_array == false), or as an
8207 array (@a is_array == true).
8208 @return whether a valid BSON-object/array was passed to the SAX parser
8209 */
8210 bool parse_bson_element_list(const bool is_array)
8211 {
8212 string_t key;
8213
8214 while (auto element_type = get()) {
8216 return false;
8217 }
8218
8219 const std::size_t element_type_parse_position = chars_read;
8220 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) {
8221 return false;
8222 }
8223
8224 if (!is_array && !sax->key(key)) {
8225 return false;
8226 }
8227
8228 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) {
8229 return false;
8230 }
8231
8232 // get_bson_cstr only appends
8233 key.clear();
8234 }
8235
8236 return true;
8237 }
8238
8239 /*!
8240 @brief Reads an array from the BSON input and passes it to the SAX-parser.
8241 @return whether a valid BSON-array was passed to the SAX parser
8242 */
8244 {
8245 std::int32_t document_size{};
8247
8248 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) {
8249 return false;
8250 }
8251
8252 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/ true))) {
8253 return false;
8254 }
8255
8256 return sax->end_array();
8257 }
8258
8259 //////////
8260 // CBOR //
8261 //////////
8262
8263 /*!
8264 @param[in] get_char whether a new character should be retrieved from the
8265 input (true) or whether the last read character should
8266 be considered instead (false)
8267 @param[in] tag_handler how CBOR tags should be treated
8268
8269 @return whether a valid CBOR value was passed to the SAX parser
8270 */
8271 bool parse_cbor_internal(const bool get_char, const cbor_tag_handler_t tag_handler)
8272 {
8273 switch (get_char ? get() : current) {
8274 // EOF
8275 case std::char_traits<char_type>::eof():
8276 return unexpect_eof(input_format_t::cbor, "value");
8277
8278 // Integer 0x00..0x17 (0..23)
8279 case 0x00:
8280 case 0x01:
8281 case 0x02:
8282 case 0x03:
8283 case 0x04:
8284 case 0x05:
8285 case 0x06:
8286 case 0x07:
8287 case 0x08:
8288 case 0x09:
8289 case 0x0A:
8290 case 0x0B:
8291 case 0x0C:
8292 case 0x0D:
8293 case 0x0E:
8294 case 0x0F:
8295 case 0x10:
8296 case 0x11:
8297 case 0x12:
8298 case 0x13:
8299 case 0x14:
8300 case 0x15:
8301 case 0x16:
8302 case 0x17:
8303 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
8304
8305 case 0x18: // Unsigned integer (one-byte uint8_t follows)
8306 {
8307 std::uint8_t number{};
8308 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8309 }
8310
8311 case 0x19: // Unsigned integer (two-byte uint16_t follows)
8312 {
8313 std::uint16_t number{};
8314 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8315 }
8316
8317 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
8318 {
8319 std::uint32_t number{};
8320 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8321 }
8322
8323 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
8324 {
8325 std::uint64_t number{};
8326 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8327 }
8328
8329 // Negative integer -1-0x00..-1-0x17 (-1..-24)
8330 case 0x20:
8331 case 0x21:
8332 case 0x22:
8333 case 0x23:
8334 case 0x24:
8335 case 0x25:
8336 case 0x26:
8337 case 0x27:
8338 case 0x28:
8339 case 0x29:
8340 case 0x2A:
8341 case 0x2B:
8342 case 0x2C:
8343 case 0x2D:
8344 case 0x2E:
8345 case 0x2F:
8346 case 0x30:
8347 case 0x31:
8348 case 0x32:
8349 case 0x33:
8350 case 0x34:
8351 case 0x35:
8352 case 0x36:
8353 case 0x37:
8354 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
8355
8356 case 0x38: // Negative integer (one-byte uint8_t follows)
8357 {
8358 std::uint8_t number{};
8359 return get_number(input_format_t::cbor, number)
8360 && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8361 }
8362
8363 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
8364 {
8365 std::uint16_t number{};
8366 return get_number(input_format_t::cbor, number)
8367 && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8368 }
8369
8370 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
8371 {
8372 std::uint32_t number{};
8373 return get_number(input_format_t::cbor, number)
8374 && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8375 }
8376
8377 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
8378 {
8379 std::uint64_t number{};
8380 return get_number(input_format_t::cbor, number)
8381 && sax->number_integer(static_cast<number_integer_t>(-1)
8382 - static_cast<number_integer_t>(number));
8383 }
8384
8385 // Binary data (0x00..0x17 bytes follow)
8386 case 0x40:
8387 case 0x41:
8388 case 0x42:
8389 case 0x43:
8390 case 0x44:
8391 case 0x45:
8392 case 0x46:
8393 case 0x47:
8394 case 0x48:
8395 case 0x49:
8396 case 0x4A:
8397 case 0x4B:
8398 case 0x4C:
8399 case 0x4D:
8400 case 0x4E:
8401 case 0x4F:
8402 case 0x50:
8403 case 0x51:
8404 case 0x52:
8405 case 0x53:
8406 case 0x54:
8407 case 0x55:
8408 case 0x56:
8409 case 0x57:
8410 case 0x58: // Binary data (one-byte uint8_t for n follows)
8411 case 0x59: // Binary data (two-byte uint16_t for n follow)
8412 case 0x5A: // Binary data (four-byte uint32_t for n follow)
8413 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
8414 case 0x5F: // Binary data (indefinite length)
8415 {
8416 binary_t b;
8417 return get_cbor_binary(b) && sax->binary(b);
8418 }
8419
8420 // UTF-8 string (0x00..0x17 bytes follow)
8421 case 0x60:
8422 case 0x61:
8423 case 0x62:
8424 case 0x63:
8425 case 0x64:
8426 case 0x65:
8427 case 0x66:
8428 case 0x67:
8429 case 0x68:
8430 case 0x69:
8431 case 0x6A:
8432 case 0x6B:
8433 case 0x6C:
8434 case 0x6D:
8435 case 0x6E:
8436 case 0x6F:
8437 case 0x70:
8438 case 0x71:
8439 case 0x72:
8440 case 0x73:
8441 case 0x74:
8442 case 0x75:
8443 case 0x76:
8444 case 0x77:
8445 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
8446 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
8447 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
8448 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
8449 case 0x7F: // UTF-8 string (indefinite length)
8450 {
8451 string_t s;
8452 return get_cbor_string(s) && sax->string(s);
8453 }
8454
8455 // array (0x00..0x17 data items follow)
8456 case 0x80:
8457 case 0x81:
8458 case 0x82:
8459 case 0x83:
8460 case 0x84:
8461 case 0x85:
8462 case 0x86:
8463 case 0x87:
8464 case 0x88:
8465 case 0x89:
8466 case 0x8A:
8467 case 0x8B:
8468 case 0x8C:
8469 case 0x8D:
8470 case 0x8E:
8471 case 0x8F:
8472 case 0x90:
8473 case 0x91:
8474 case 0x92:
8475 case 0x93:
8476 case 0x94:
8477 case 0x95:
8478 case 0x96:
8479 case 0x97:
8480 return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu),
8481 tag_handler);
8482
8483 case 0x98: // array (one-byte uint8_t for n follows)
8484 {
8485 std::uint8_t len{};
8486 return get_number(input_format_t::cbor, len)
8487 && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8488 }
8489
8490 case 0x99: // array (two-byte uint16_t for n follow)
8491 {
8492 std::uint16_t len{};
8493 return get_number(input_format_t::cbor, len)
8494 && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8495 }
8496
8497 case 0x9A: // array (four-byte uint32_t for n follow)
8498 {
8499 std::uint32_t len{};
8500 return get_number(input_format_t::cbor, len)
8501 && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8502 }
8503
8504 case 0x9B: // array (eight-byte uint64_t for n follow)
8505 {
8506 std::uint64_t len{};
8507 return get_number(input_format_t::cbor, len)
8509 }
8510
8511 case 0x9F: // array (indefinite length)
8512 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
8513
8514 // map (0x00..0x17 pairs of data items follow)
8515 case 0xA0:
8516 case 0xA1:
8517 case 0xA2:
8518 case 0xA3:
8519 case 0xA4:
8520 case 0xA5:
8521 case 0xA6:
8522 case 0xA7:
8523 case 0xA8:
8524 case 0xA9:
8525 case 0xAA:
8526 case 0xAB:
8527 case 0xAC:
8528 case 0xAD:
8529 case 0xAE:
8530 case 0xAF:
8531 case 0xB0:
8532 case 0xB1:
8533 case 0xB2:
8534 case 0xB3:
8535 case 0xB4:
8536 case 0xB5:
8537 case 0xB6:
8538 case 0xB7:
8539 return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu),
8540 tag_handler);
8541
8542 case 0xB8: // map (one-byte uint8_t for n follows)
8543 {
8544 std::uint8_t len{};
8545 return get_number(input_format_t::cbor, len)
8546 && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8547 }
8548
8549 case 0xB9: // map (two-byte uint16_t for n follow)
8550 {
8551 std::uint16_t len{};
8552 return get_number(input_format_t::cbor, len)
8553 && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8554 }
8555
8556 case 0xBA: // map (four-byte uint32_t for n follow)
8557 {
8558 std::uint32_t len{};
8559 return get_number(input_format_t::cbor, len)
8560 && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8561 }
8562
8563 case 0xBB: // map (eight-byte uint64_t for n follow)
8564 {
8565 std::uint64_t len{};
8566 return get_number(input_format_t::cbor, len)
8568 }
8569
8570 case 0xBF: // map (indefinite length)
8571 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
8572
8573 case 0xC6: // tagged item
8574 case 0xC7:
8575 case 0xC8:
8576 case 0xC9:
8577 case 0xCA:
8578 case 0xCB:
8579 case 0xCC:
8580 case 0xCD:
8581 case 0xCE:
8582 case 0xCF:
8583 case 0xD0:
8584 case 0xD1:
8585 case 0xD2:
8586 case 0xD3:
8587 case 0xD4:
8588 case 0xD8: // tagged item (1 bytes follow)
8589 case 0xD9: // tagged item (2 bytes follow)
8590 case 0xDA: // tagged item (4 bytes follow)
8591 case 0xDB: // tagged item (8 bytes follow)
8592 {
8593 switch (tag_handler) {
8595 auto last_token = get_token_string();
8596 return sax->parse_error(
8597 chars_read, last_token,
8599 112, chars_read,
8600 exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"),
8601 BasicJsonType()));
8602 }
8603
8605 // ignore binary subtype
8606 switch (current) {
8607 case 0xD8: {
8608 std::uint8_t subtype_to_ignore{};
8609 get_number(input_format_t::cbor, subtype_to_ignore);
8610 break;
8611 }
8612 case 0xD9: {
8613 std::uint16_t subtype_to_ignore{};
8614 get_number(input_format_t::cbor, subtype_to_ignore);
8615 break;
8616 }
8617 case 0xDA: {
8618 std::uint32_t subtype_to_ignore{};
8619 get_number(input_format_t::cbor, subtype_to_ignore);
8620 break;
8621 }
8622 case 0xDB: {
8623 std::uint64_t subtype_to_ignore{};
8624 get_number(input_format_t::cbor, subtype_to_ignore);
8625 break;
8626 }
8627 default:
8628 break;
8629 }
8630 return parse_cbor_internal(true, tag_handler);
8631 }
8632
8634 binary_t b;
8635 // use binary subtype and store in binary container
8636 switch (current) {
8637 case 0xD8: {
8638 std::uint8_t subtype{};
8640 b.set_subtype(
8642 break;
8643 }
8644 case 0xD9: {
8645 std::uint16_t subtype{};
8647 b.set_subtype(
8649 break;
8650 }
8651 case 0xDA: {
8652 std::uint32_t subtype{};
8654 b.set_subtype(
8656 break;
8657 }
8658 case 0xDB: {
8659 std::uint64_t subtype{};
8661 b.set_subtype(
8663 break;
8664 }
8665 default:
8666 return parse_cbor_internal(true, tag_handler);
8667 }
8668 get();
8669 return get_cbor_binary(b) && sax->binary(b);
8670 }
8671
8672 default: // LCOV_EXCL_LINE
8674 false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8675 return false; // LCOV_EXCL_LINE
8676 }
8677 }
8678
8679 case 0xF4: // false
8680 return sax->boolean(false);
8681
8682 case 0xF5: // true
8683 return sax->boolean(true);
8684
8685 case 0xF6: // null
8686 return sax->null();
8687
8688 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
8689 {
8690 const auto byte1_raw = get();
8692 return false;
8693 }
8694 const auto byte2_raw = get();
8696 return false;
8697 }
8698
8699 const auto byte1 = static_cast<unsigned char>(byte1_raw);
8700 const auto byte2 = static_cast<unsigned char>(byte2_raw);
8701
8702 // code from RFC 7049, Appendix D, Figure 3:
8703 // As half-precision floating-point numbers were only added
8704 // to IEEE 754 in 2008, today's programming platforms often
8705 // still only have limited support for them. It is very
8706 // easy to include at least decoding support for them even
8707 // without such support. An example of a small decoder for
8708 // half-precision floating-point numbers in the C language
8709 // is shown in Fig. 3.
8710 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
8711 const double val = [&half] {
8712 const int exp = (half >> 10u) & 0x1Fu;
8713 const unsigned int mant = half & 0x3FFu;
8714 JSON_ASSERT(0 <= exp && exp <= 32);
8715 JSON_ASSERT(mant <= 1024);
8716 switch (exp) {
8717 case 0:
8718 return std::ldexp(mant, -24);
8719 case 31:
8720 return (mant == 0) ? std::numeric_limits<double>::infinity()
8721 : std::numeric_limits<double>::quiet_NaN();
8722 default:
8723 return std::ldexp(mant + 1024, exp - 25);
8724 }
8725 }();
8726 return sax->number_float(
8727 (half & 0x8000u) != 0 ? static_cast<number_float_t>(-val) : static_cast<number_float_t>(val), "");
8728 }
8729
8730 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
8731 {
8732 float number{};
8733 return get_number(input_format_t::cbor, number)
8734 && sax->number_float(static_cast<number_float_t>(number), "");
8735 }
8736
8737 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
8738 {
8739 double number{};
8740 return get_number(input_format_t::cbor, number)
8741 && sax->number_float(static_cast<number_float_t>(number), "");
8742 }
8743
8744 default: // anything else (0xFF is handled inside the other types)
8745 {
8746 auto last_token = get_token_string();
8747 return sax->parse_error(chars_read, last_token,
8750 "invalid byte: 0x" + last_token, "value"),
8751 BasicJsonType()));
8752 }
8753 }
8754 }
8755
8756 /*!
8757 @brief reads a CBOR string
8758
8759 This function first reads starting bytes to determine the expected
8760 string length and then copies this number of bytes into a string.
8761 Additionally, CBOR's strings with indefinite lengths are supported.
8762
8763 @param[out] result created string
8764
8765 @return whether string creation completed
8766 */
8768 {
8770 return false;
8771 }
8772
8773 switch (current) {
8774 // UTF-8 string (0x00..0x17 bytes follow)
8775 case 0x60:
8776 case 0x61:
8777 case 0x62:
8778 case 0x63:
8779 case 0x64:
8780 case 0x65:
8781 case 0x66:
8782 case 0x67:
8783 case 0x68:
8784 case 0x69:
8785 case 0x6A:
8786 case 0x6B:
8787 case 0x6C:
8788 case 0x6D:
8789 case 0x6E:
8790 case 0x6F:
8791 case 0x70:
8792 case 0x71:
8793 case 0x72:
8794 case 0x73:
8795 case 0x74:
8796 case 0x75:
8797 case 0x76:
8798 case 0x77: {
8799 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
8800 }
8801
8802 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
8803 {
8804 std::uint8_t len{};
8806 }
8807
8808 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
8809 {
8810 std::uint16_t len{};
8812 }
8813
8814 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
8815 {
8816 std::uint32_t len{};
8818 }
8819
8820 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
8821 {
8822 std::uint64_t len{};
8824 }
8825
8826 case 0x7F: // UTF-8 string (indefinite length)
8827 {
8828 while (get() != 0xFF) {
8829 string_t chunk;
8830 if (!get_cbor_string(chunk)) {
8831 return false;
8832 }
8833 result.append(chunk);
8834 }
8835 return true;
8836 }
8837
8838 default: {
8839 auto last_token = get_token_string();
8840 return sax->parse_error(
8841 chars_read, last_token,
8843 113, chars_read,
8846 "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x"
8847 + last_token,
8848 "string"),
8849 BasicJsonType()));
8850 }
8851 }
8852 }
8853
8854 /*!
8855 @brief reads a CBOR byte array
8856
8857 This function first reads starting bytes to determine the expected
8858 byte array length and then copies this number of bytes into the byte array.
8859 Additionally, CBOR's byte arrays with indefinite lengths are supported.
8860
8861 @param[out] result created byte array
8862
8863 @return whether byte array creation completed
8864 */
8866 {
8868 return false;
8869 }
8870
8871 switch (current) {
8872 // Binary data (0x00..0x17 bytes follow)
8873 case 0x40:
8874 case 0x41:
8875 case 0x42:
8876 case 0x43:
8877 case 0x44:
8878 case 0x45:
8879 case 0x46:
8880 case 0x47:
8881 case 0x48:
8882 case 0x49:
8883 case 0x4A:
8884 case 0x4B:
8885 case 0x4C:
8886 case 0x4D:
8887 case 0x4E:
8888 case 0x4F:
8889 case 0x50:
8890 case 0x51:
8891 case 0x52:
8892 case 0x53:
8893 case 0x54:
8894 case 0x55:
8895 case 0x56:
8896 case 0x57: {
8897 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
8898 }
8899
8900 case 0x58: // Binary data (one-byte uint8_t for n follows)
8901 {
8902 std::uint8_t len{};
8904 }
8905
8906 case 0x59: // Binary data (two-byte uint16_t for n follow)
8907 {
8908 std::uint16_t len{};
8910 }
8911
8912 case 0x5A: // Binary data (four-byte uint32_t for n follow)
8913 {
8914 std::uint32_t len{};
8916 }
8917
8918 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
8919 {
8920 std::uint64_t len{};
8922 }
8923
8924 case 0x5F: // Binary data (indefinite length)
8925 {
8926 while (get() != 0xFF) {
8927 binary_t chunk;
8928 if (!get_cbor_binary(chunk)) {
8929 return false;
8930 }
8931 result.insert(result.end(), chunk.begin(), chunk.end());
8932 }
8933 return true;
8934 }
8935
8936 default: {
8937 auto last_token = get_token_string();
8938 return sax->parse_error(
8939 chars_read, last_token,
8942 "expected length specification (0x40-0x5B) or indefinite "
8943 "binary array type (0x5F); last byte: 0x"
8944 + last_token,
8945 "binary"),
8946 BasicJsonType()));
8947 }
8948 }
8949 }
8950
8951 /*!
8952 @param[in] len the length of the array or static_cast<std::size_t>(-1) for an
8953 array of indefinite size
8954 @param[in] tag_handler how CBOR tags should be treated
8955 @return whether array creation completed
8956 */
8957 bool get_cbor_array(const std::size_t len, const cbor_tag_handler_t tag_handler)
8958 {
8959 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) {
8960 return false;
8961 }
8962
8963 if (len != static_cast<std::size_t>(-1)) {
8964 for (std::size_t i = 0; i < len; ++i) {
8965 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) {
8966 return false;
8967 }
8968 }
8969 } else {
8970 while (get() != 0xFF) {
8971 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) {
8972 return false;
8973 }
8974 }
8975 }
8976
8977 return sax->end_array();
8978 }
8979
8980 /*!
8981 @param[in] len the length of the object or static_cast<std::size_t>(-1) for an
8982 object of indefinite size
8983 @param[in] tag_handler how CBOR tags should be treated
8984 @return whether object creation completed
8985 */
8986 bool get_cbor_object(const std::size_t len, const cbor_tag_handler_t tag_handler)
8987 {
8988 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) {
8989 return false;
8990 }
8991
8992 if (len != 0) {
8993 string_t key;
8994 if (len != static_cast<std::size_t>(-1)) {
8995 for (std::size_t i = 0; i < len; ++i) {
8996 get();
8997 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) {
8998 return false;
8999 }
9000
9001 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) {
9002 return false;
9003 }
9004 key.clear();
9005 }
9006 } else {
9007 while (get() != 0xFF) {
9008 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) {
9009 return false;
9010 }
9011
9012 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) {
9013 return false;
9014 }
9015 key.clear();
9016 }
9017 }
9018 }
9019
9020 return sax->end_object();
9021 }
9022
9023 /////////////
9024 // MsgPack //
9025 /////////////
9026
9027 /*!
9028 @return whether a valid MessagePack value was passed to the SAX parser
9029 */
9031 {
9032 switch (get()) {
9033 // EOF
9034 case std::char_traits<char_type>::eof():
9035 return unexpect_eof(input_format_t::msgpack, "value");
9036
9037 // positive fixint
9038 case 0x00:
9039 case 0x01:
9040 case 0x02:
9041 case 0x03:
9042 case 0x04:
9043 case 0x05:
9044 case 0x06:
9045 case 0x07:
9046 case 0x08:
9047 case 0x09:
9048 case 0x0A:
9049 case 0x0B:
9050 case 0x0C:
9051 case 0x0D:
9052 case 0x0E:
9053 case 0x0F:
9054 case 0x10:
9055 case 0x11:
9056 case 0x12:
9057 case 0x13:
9058 case 0x14:
9059 case 0x15:
9060 case 0x16:
9061 case 0x17:
9062 case 0x18:
9063 case 0x19:
9064 case 0x1A:
9065 case 0x1B:
9066 case 0x1C:
9067 case 0x1D:
9068 case 0x1E:
9069 case 0x1F:
9070 case 0x20:
9071 case 0x21:
9072 case 0x22:
9073 case 0x23:
9074 case 0x24:
9075 case 0x25:
9076 case 0x26:
9077 case 0x27:
9078 case 0x28:
9079 case 0x29:
9080 case 0x2A:
9081 case 0x2B:
9082 case 0x2C:
9083 case 0x2D:
9084 case 0x2E:
9085 case 0x2F:
9086 case 0x30:
9087 case 0x31:
9088 case 0x32:
9089 case 0x33:
9090 case 0x34:
9091 case 0x35:
9092 case 0x36:
9093 case 0x37:
9094 case 0x38:
9095 case 0x39:
9096 case 0x3A:
9097 case 0x3B:
9098 case 0x3C:
9099 case 0x3D:
9100 case 0x3E:
9101 case 0x3F:
9102 case 0x40:
9103 case 0x41:
9104 case 0x42:
9105 case 0x43:
9106 case 0x44:
9107 case 0x45:
9108 case 0x46:
9109 case 0x47:
9110 case 0x48:
9111 case 0x49:
9112 case 0x4A:
9113 case 0x4B:
9114 case 0x4C:
9115 case 0x4D:
9116 case 0x4E:
9117 case 0x4F:
9118 case 0x50:
9119 case 0x51:
9120 case 0x52:
9121 case 0x53:
9122 case 0x54:
9123 case 0x55:
9124 case 0x56:
9125 case 0x57:
9126 case 0x58:
9127 case 0x59:
9128 case 0x5A:
9129 case 0x5B:
9130 case 0x5C:
9131 case 0x5D:
9132 case 0x5E:
9133 case 0x5F:
9134 case 0x60:
9135 case 0x61:
9136 case 0x62:
9137 case 0x63:
9138 case 0x64:
9139 case 0x65:
9140 case 0x66:
9141 case 0x67:
9142 case 0x68:
9143 case 0x69:
9144 case 0x6A:
9145 case 0x6B:
9146 case 0x6C:
9147 case 0x6D:
9148 case 0x6E:
9149 case 0x6F:
9150 case 0x70:
9151 case 0x71:
9152 case 0x72:
9153 case 0x73:
9154 case 0x74:
9155 case 0x75:
9156 case 0x76:
9157 case 0x77:
9158 case 0x78:
9159 case 0x79:
9160 case 0x7A:
9161 case 0x7B:
9162 case 0x7C:
9163 case 0x7D:
9164 case 0x7E:
9165 case 0x7F:
9166 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9167
9168 // fixmap
9169 case 0x80:
9170 case 0x81:
9171 case 0x82:
9172 case 0x83:
9173 case 0x84:
9174 case 0x85:
9175 case 0x86:
9176 case 0x87:
9177 case 0x88:
9178 case 0x89:
9179 case 0x8A:
9180 case 0x8B:
9181 case 0x8C:
9182 case 0x8D:
9183 case 0x8E:
9184 case 0x8F:
9185 return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
9186
9187 // fixarray
9188 case 0x90:
9189 case 0x91:
9190 case 0x92:
9191 case 0x93:
9192 case 0x94:
9193 case 0x95:
9194 case 0x96:
9195 case 0x97:
9196 case 0x98:
9197 case 0x99:
9198 case 0x9A:
9199 case 0x9B:
9200 case 0x9C:
9201 case 0x9D:
9202 case 0x9E:
9203 case 0x9F:
9204 return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
9205
9206 // fixstr
9207 case 0xA0:
9208 case 0xA1:
9209 case 0xA2:
9210 case 0xA3:
9211 case 0xA4:
9212 case 0xA5:
9213 case 0xA6:
9214 case 0xA7:
9215 case 0xA8:
9216 case 0xA9:
9217 case 0xAA:
9218 case 0xAB:
9219 case 0xAC:
9220 case 0xAD:
9221 case 0xAE:
9222 case 0xAF:
9223 case 0xB0:
9224 case 0xB1:
9225 case 0xB2:
9226 case 0xB3:
9227 case 0xB4:
9228 case 0xB5:
9229 case 0xB6:
9230 case 0xB7:
9231 case 0xB8:
9232 case 0xB9:
9233 case 0xBA:
9234 case 0xBB:
9235 case 0xBC:
9236 case 0xBD:
9237 case 0xBE:
9238 case 0xBF:
9239 case 0xD9: // str 8
9240 case 0xDA: // str 16
9241 case 0xDB: // str 32
9242 {
9243 string_t s;
9244 return get_msgpack_string(s) && sax->string(s);
9245 }
9246
9247 case 0xC0: // nil
9248 return sax->null();
9249
9250 case 0xC2: // false
9251 return sax->boolean(false);
9252
9253 case 0xC3: // true
9254 return sax->boolean(true);
9255
9256 case 0xC4: // bin 8
9257 case 0xC5: // bin 16
9258 case 0xC6: // bin 32
9259 case 0xC7: // ext 8
9260 case 0xC8: // ext 16
9261 case 0xC9: // ext 32
9262 case 0xD4: // fixext 1
9263 case 0xD5: // fixext 2
9264 case 0xD6: // fixext 4
9265 case 0xD7: // fixext 8
9266 case 0xD8: // fixext 16
9267 {
9268 binary_t b;
9269 return get_msgpack_binary(b) && sax->binary(b);
9270 }
9271
9272 case 0xCA: // float 32
9273 {
9274 float number{};
9275 return get_number(input_format_t::msgpack, number)
9276 && sax->number_float(static_cast<number_float_t>(number), "");
9277 }
9278
9279 case 0xCB: // float 64
9280 {
9281 double number{};
9282 return get_number(input_format_t::msgpack, number)
9283 && sax->number_float(static_cast<number_float_t>(number), "");
9284 }
9285
9286 case 0xCC: // uint 8
9287 {
9288 std::uint8_t number{};
9289 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9290 }
9291
9292 case 0xCD: // uint 16
9293 {
9294 std::uint16_t number{};
9295 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9296 }
9297
9298 case 0xCE: // uint 32
9299 {
9300 std::uint32_t number{};
9301 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9302 }
9303
9304 case 0xCF: // uint 64
9305 {
9306 std::uint64_t number{};
9307 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9308 }
9309
9310 case 0xD0: // int 8
9311 {
9312 std::int8_t number{};
9313 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9314 }
9315
9316 case 0xD1: // int 16
9317 {
9318 std::int16_t number{};
9319 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9320 }
9321
9322 case 0xD2: // int 32
9323 {
9324 std::int32_t number{};
9325 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9326 }
9327
9328 case 0xD3: // int 64
9329 {
9330 std::int64_t number{};
9331 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9332 }
9333
9334 case 0xDC: // array 16
9335 {
9336 std::uint16_t len{};
9337 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
9338 }
9339
9340 case 0xDD: // array 32
9341 {
9342 std::uint32_t len{};
9343 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
9344 }
9345
9346 case 0xDE: // map 16
9347 {
9348 std::uint16_t len{};
9349 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
9350 }
9351
9352 case 0xDF: // map 32
9353 {
9354 std::uint32_t len{};
9355 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
9356 }
9357
9358 // negative fixint
9359 case 0xE0:
9360 case 0xE1:
9361 case 0xE2:
9362 case 0xE3:
9363 case 0xE4:
9364 case 0xE5:
9365 case 0xE6:
9366 case 0xE7:
9367 case 0xE8:
9368 case 0xE9:
9369 case 0xEA:
9370 case 0xEB:
9371 case 0xEC:
9372 case 0xED:
9373 case 0xEE:
9374 case 0xEF:
9375 case 0xF0:
9376 case 0xF1:
9377 case 0xF2:
9378 case 0xF3:
9379 case 0xF4:
9380 case 0xF5:
9381 case 0xF6:
9382 case 0xF7:
9383 case 0xF8:
9384 case 0xF9:
9385 case 0xFA:
9386 case 0xFB:
9387 case 0xFC:
9388 case 0xFD:
9389 case 0xFE:
9390 case 0xFF:
9391 return sax->number_integer(static_cast<std::int8_t>(current));
9392
9393 default: // anything else
9394 {
9395 auto last_token = get_token_string();
9396 return sax->parse_error(chars_read, last_token,
9399 "invalid byte: 0x" + last_token, "value"),
9400 BasicJsonType()));
9401 }
9402 }
9403 }
9404
9405 /*!
9406 @brief reads a MessagePack string
9407
9408 This function first reads starting bytes to determine the expected
9409 string length and then copies this number of bytes into a string.
9410
9411 @param[out] result created string
9412
9413 @return whether string creation completed
9414 */
9416 {
9418 return false;
9419 }
9420
9421 switch (current) {
9422 // fixstr
9423 case 0xA0:
9424 case 0xA1:
9425 case 0xA2:
9426 case 0xA3:
9427 case 0xA4:
9428 case 0xA5:
9429 case 0xA6:
9430 case 0xA7:
9431 case 0xA8:
9432 case 0xA9:
9433 case 0xAA:
9434 case 0xAB:
9435 case 0xAC:
9436 case 0xAD:
9437 case 0xAE:
9438 case 0xAF:
9439 case 0xB0:
9440 case 0xB1:
9441 case 0xB2:
9442 case 0xB3:
9443 case 0xB4:
9444 case 0xB5:
9445 case 0xB6:
9446 case 0xB7:
9447 case 0xB8:
9448 case 0xB9:
9449 case 0xBA:
9450 case 0xBB:
9451 case 0xBC:
9452 case 0xBD:
9453 case 0xBE:
9454 case 0xBF: {
9455 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
9456 }
9457
9458 case 0xD9: // str 8
9459 {
9460 std::uint8_t len{};
9462 }
9463
9464 case 0xDA: // str 16
9465 {
9466 std::uint16_t len{};
9468 }
9469
9470 case 0xDB: // str 32
9471 {
9472 std::uint32_t len{};
9474 }
9475
9476 default: {
9477 auto last_token = get_token_string();
9478 return sax->parse_error(
9479 chars_read, last_token,
9481 113, chars_read,
9483 "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x"
9484 + last_token,
9485 "string"),
9486 BasicJsonType()));
9487 }
9488 }
9489 }
9490
9491 /*!
9492 @brief reads a MessagePack byte array
9493
9494 This function first reads starting bytes to determine the expected
9495 byte array length and then copies this number of bytes into a byte array.
9496
9497 @param[out] result created byte array
9498
9499 @return whether byte array creation completed
9500 */
9502 {
9503 // helper function to set the subtype
9504 auto assign_and_return_true = [&result](std::int8_t subtype) {
9505 result.set_subtype(static_cast<std::uint8_t>(subtype));
9506 return true;
9507 };
9508
9509 switch (current) {
9510 case 0xC4: // bin 8
9511 {
9512 std::uint8_t len{};
9514 }
9515
9516 case 0xC5: // bin 16
9517 {
9518 std::uint16_t len{};
9520 }
9521
9522 case 0xC6: // bin 32
9523 {
9524 std::uint32_t len{};
9526 }
9527
9528 case 0xC7: // ext 8
9529 {
9530 std::uint8_t len{};
9531 std::int8_t subtype{};
9533 && get_binary(input_format_t::msgpack, len, result) && assign_and_return_true(subtype);
9534 }
9535
9536 case 0xC8: // ext 16
9537 {
9538 std::uint16_t len{};
9539 std::int8_t subtype{};
9541 && get_binary(input_format_t::msgpack, len, result) && assign_and_return_true(subtype);
9542 }
9543
9544 case 0xC9: // ext 32
9545 {
9546 std::uint32_t len{};
9547 std::int8_t subtype{};
9549 && get_binary(input_format_t::msgpack, len, result) && assign_and_return_true(subtype);
9550 }
9551
9552 case 0xD4: // fixext 1
9553 {
9554 std::int8_t subtype{};
9556 && assign_and_return_true(subtype);
9557 }
9558
9559 case 0xD5: // fixext 2
9560 {
9561 std::int8_t subtype{};
9563 && assign_and_return_true(subtype);
9564 }
9565
9566 case 0xD6: // fixext 4
9567 {
9568 std::int8_t subtype{};
9570 && assign_and_return_true(subtype);
9571 }
9572
9573 case 0xD7: // fixext 8
9574 {
9575 std::int8_t subtype{};
9577 && assign_and_return_true(subtype);
9578 }
9579
9580 case 0xD8: // fixext 16
9581 {
9582 std::int8_t subtype{};
9584 && assign_and_return_true(subtype);
9585 }
9586
9587 default: // LCOV_EXCL_LINE
9588 return false; // LCOV_EXCL_LINE
9589 }
9590 }
9591
9592 /*!
9593 @param[in] len the length of the array
9594 @return whether array creation completed
9595 */
9596 bool get_msgpack_array(const std::size_t len)
9597 {
9598 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) {
9599 return false;
9600 }
9601
9602 for (std::size_t i = 0; i < len; ++i) {
9604 return false;
9605 }
9606 }
9607
9608 return sax->end_array();
9609 }
9610
9611 /*!
9612 @param[in] len the length of the object
9613 @return whether object creation completed
9614 */
9615 bool get_msgpack_object(const std::size_t len)
9616 {
9617 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) {
9618 return false;
9619 }
9620
9621 string_t key;
9622 for (std::size_t i = 0; i < len; ++i) {
9623 get();
9625 return false;
9626 }
9627
9629 return false;
9630 }
9631 key.clear();
9632 }
9633
9634 return sax->end_object();
9635 }
9636
9637 ////////////
9638 // UBJSON //
9639 ////////////
9640
9641 /*!
9642 @param[in] get_char whether a new character should be retrieved from the
9643 input (true, default) or whether the last read
9644 character should be considered instead
9645
9646 @return whether a valid UBJSON value was passed to the SAX parser
9647 */
9648 bool parse_ubjson_internal(const bool get_char = true)
9649 {
9650 return get_ubjson_value(get_char ? get_ignore_noop() : current);
9651 }
9652
9653 /*!
9654 @brief reads a UBJSON string
9655
9656 This function is either called after reading the 'S' byte explicitly
9657 indicating a string, or in case of an object key where the 'S' byte can be
9658 left out.
9659
9660 @param[out] result created string
9661 @param[in] get_char whether a new character should be retrieved from the
9662 input (true, default) or whether the last read
9663 character should be considered instead
9664
9665 @return whether string creation completed
9666 */
9667 bool get_ubjson_string(string_t& result, const bool get_char = true)
9668 {
9669 if (get_char) {
9670 get(); // TODO(niels): may we ignore N here?
9671 }
9672
9674 return false;
9675 }
9676
9677 switch (current) {
9678 case 'U': {
9679 std::uint8_t len{};
9681 }
9682
9683 case 'i': {
9684 std::int8_t len{};
9686 }
9687
9688 case 'I': {
9689 std::int16_t len{};
9691 }
9692
9693 case 'l': {
9694 std::int32_t len{};
9696 }
9697
9698 case 'L': {
9699 std::int64_t len{};
9701 }
9702
9703 default:
9704 auto last_token = get_token_string();
9705 return sax->parse_error(
9706 chars_read, last_token,
9708 113, chars_read,
9711 "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"),
9712 BasicJsonType()));
9713 }
9714 }
9715
9716 /*!
9717 @param[out] result determined size
9718 @return whether size determination completed
9719 */
9721 {
9722 switch (get_ignore_noop()) {
9723 case 'U': {
9724 std::uint8_t number{};
9726 return false;
9727 }
9728 result = static_cast<std::size_t>(number);
9729 return true;
9730 }
9731
9732 case 'i': {
9733 std::int8_t number{};
9735 return false;
9736 }
9737 result = static_cast<std::size_t>(
9738 number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
9739 return true;
9740 }
9741
9742 case 'I': {
9743 std::int16_t number{};
9745 return false;
9746 }
9747 result = static_cast<std::size_t>(number);
9748 return true;
9749 }
9750
9751 case 'l': {
9752 std::int32_t number{};
9754 return false;
9755 }
9756 result = static_cast<std::size_t>(number);
9757 return true;
9758 }
9759
9760 case 'L': {
9761 std::int64_t number{};
9763 return false;
9764 }
9765 result = static_cast<std::size_t>(number);
9766 return true;
9767 }
9768
9769 default: {
9770 auto last_token = get_token_string();
9771 return sax->parse_error(
9772 chars_read, last_token,
9774 113, chars_read,
9776 "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x"
9777 + last_token,
9778 "size"),
9779 BasicJsonType()));
9780 }
9781 }
9782 }
9783
9784 /*!
9785 @brief determine the type and size for a container
9786
9787 In the optimized UBJSON format, a type and a size can be provided to allow
9788 for a more compact representation.
9789
9790 @param[out] result pair of the size and the type
9791
9792 @return whether pair creation completed
9793 */
9794 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result)
9795 {
9796 result.first = string_t::npos; // size
9797 result.second = 0; // type
9798
9800
9801 if (current == '$') {
9802 result.second = get(); // must not ignore 'N', because 'N' maybe the type
9804 return false;
9805 }
9806
9808 if (JSON_HEDLEY_UNLIKELY(current != '#')) {
9810 return false;
9811 }
9812 auto last_token = get_token_string();
9813 return sax->parse_error(
9814 chars_read, last_token,
9816 112, chars_read,
9818 "expected '#' after type information; last byte: 0x" + last_token, "size"),
9819 BasicJsonType()));
9820 }
9821
9822 return get_ubjson_size_value(result.first);
9823 }
9824
9825 if (current == '#') {
9826 return get_ubjson_size_value(result.first);
9827 }
9828
9829 return true;
9830 }
9831
9832 /*!
9833 @param prefix the previously read or set type prefix
9834 @return whether value creation completed
9835 */
9837 {
9838 switch (prefix) {
9839 case std::char_traits<char_type>::eof(): // EOF
9840 return unexpect_eof(input_format_t::ubjson, "value");
9841
9842 case 'T': // true
9843 return sax->boolean(true);
9844 case 'F': // false
9845 return sax->boolean(false);
9846
9847 case 'Z': // null
9848 return sax->null();
9849
9850 case 'U': {
9851 std::uint8_t number{};
9852 return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number);
9853 }
9854
9855 case 'i': {
9856 std::int8_t number{};
9857 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
9858 }
9859
9860 case 'I': {
9861 std::int16_t number{};
9862 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
9863 }
9864
9865 case 'l': {
9866 std::int32_t number{};
9867 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
9868 }
9869
9870 case 'L': {
9871 std::int64_t number{};
9872 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
9873 }
9874
9875 case 'd': {
9876 float number{};
9877 return get_number(input_format_t::ubjson, number)
9878 && sax->number_float(static_cast<number_float_t>(number), "");
9879 }
9880
9881 case 'D': {
9882 double number{};
9883 return get_number(input_format_t::ubjson, number)
9884 && sax->number_float(static_cast<number_float_t>(number), "");
9885 }
9886
9887 case 'H': {
9889 }
9890
9891 case 'C': // char
9892 {
9893 get();
9895 return false;
9896 }
9897 if (JSON_HEDLEY_UNLIKELY(current > 127)) {
9898 auto last_token = get_token_string();
9899 return sax->parse_error(
9900 chars_read, last_token,
9902 113, chars_read,
9904 "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token,
9905 "char"),
9906 BasicJsonType()));
9907 }
9908 string_t s(1, static_cast<typename string_t::value_type>(current));
9909 return sax->string(s);
9910 }
9911
9912 case 'S': // string
9913 {
9914 string_t s;
9915 return get_ubjson_string(s) && sax->string(s);
9916 }
9917
9918 case '[': // array
9919 return get_ubjson_array();
9920
9921 case '{': // object
9922 return get_ubjson_object();
9923
9924 default: // anything else
9925 {
9926 auto last_token = get_token_string();
9927 return sax->parse_error(chars_read, last_token,
9930 "invalid byte: 0x" + last_token, "value"),
9931 BasicJsonType()));
9932 }
9933 }
9934 }
9935
9936 /*!
9937 @return whether array creation completed
9938 */
9940 {
9941 std::pair<std::size_t, char_int_type> size_and_type;
9942 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) {
9943 return false;
9944 }
9945
9946 if (size_and_type.first != string_t::npos) {
9947 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) {
9948 return false;
9949 }
9950
9951 if (size_and_type.second != 0) {
9952 if (size_and_type.second != 'N') {
9953 for (std::size_t i = 0; i < size_and_type.first; ++i) {
9954 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) {
9955 return false;
9956 }
9957 }
9958 }
9959 } else {
9960 for (std::size_t i = 0; i < size_and_type.first; ++i) {
9962 return false;
9963 }
9964 }
9965 }
9966 } else {
9967 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) {
9968 return false;
9969 }
9970
9971 while (current != ']') {
9973 return false;
9974 }
9976 }
9977 }
9978
9979 return sax->end_array();
9980 }
9981
9982 /*!
9983 @return whether object creation completed
9984 */
9986 {
9987 std::pair<std::size_t, char_int_type> size_and_type;
9988 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) {
9989 return false;
9990 }
9991
9992 string_t key;
9993 if (size_and_type.first != string_t::npos) {
9994 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) {
9995 return false;
9996 }
9997
9998 if (size_and_type.second != 0) {
9999 for (std::size_t i = 0; i < size_and_type.first; ++i) {
10001 return false;
10002 }
10003 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) {
10004 return false;
10005 }
10006 key.clear();
10007 }
10008 } else {
10009 for (std::size_t i = 0; i < size_and_type.first; ++i) {
10011 return false;
10012 }
10014 return false;
10015 }
10016 key.clear();
10017 }
10018 }
10019 } else {
10020 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) {
10021 return false;
10022 }
10023
10024 while (current != '}') {
10025 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) {
10026 return false;
10027 }
10029 return false;
10030 }
10032 key.clear();
10033 }
10034 }
10035
10036 return sax->end_object();
10037 }
10038
10039 // Note, no reader for UBJSON binary types is implemented because they do
10040 // not exist
10041
10043 {
10044 // get size of following number string
10045 std::size_t size{};
10046 auto res = get_ubjson_size_value(size);
10047 if (JSON_HEDLEY_UNLIKELY(!res)) {
10048 return res;
10049 }
10050
10051 // get number string
10052 std::vector<char> number_vector;
10053 for (std::size_t i = 0; i < size; ++i) {
10054 get();
10056 return false;
10057 }
10058 number_vector.push_back(static_cast<char>(current));
10059 }
10060
10061 // parse number string
10062 using ia_type = decltype(detail::input_adapter(number_vector));
10063 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
10064 const auto result_number = number_lexer.scan();
10065 const auto number_string = number_lexer.get_token_string();
10066 const auto result_remainder = number_lexer.scan();
10067
10068 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
10069
10070 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) {
10071 return sax->parse_error(
10072 chars_read, number_string,
10075 "invalid number text: " + number_lexer.get_token_string(),
10076 "high-precision number"),
10077 BasicJsonType()));
10078 }
10079
10080 switch (result_number) {
10081 case token_type::value_integer:
10082 return sax->number_integer(number_lexer.get_number_integer());
10083 case token_type::value_unsigned:
10084 return sax->number_unsigned(number_lexer.get_number_unsigned());
10085 case token_type::value_float:
10086 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
10087 case token_type::uninitialized:
10088 case token_type::literal_true:
10089 case token_type::literal_false:
10090 case token_type::literal_null:
10091 case token_type::value_string:
10092 case token_type::begin_array:
10093 case token_type::begin_object:
10094 case token_type::end_array:
10095 case token_type::end_object:
10096 case token_type::name_separator:
10097 case token_type::value_separator:
10098 case token_type::parse_error:
10099 case token_type::end_of_input:
10100 case token_type::literal_or_value:
10101 default:
10102 return sax->parse_error(
10103 chars_read, number_string,
10106 "invalid number text: " + number_lexer.get_token_string(),
10107 "high-precision number"),
10108 BasicJsonType()));
10109 }
10110 }
10111
10112 ///////////////////////
10113 // Utility functions //
10114 ///////////////////////
10115
10116 /*!
10117 @brief get next character from the input
10118
10119 This function provides the interface to the used input adapter. It does
10120 not throw in case the input reached EOF, but returns a -'ve valued
10121 `std::char_traits<char_type>::eof()` in that case.
10122
10123 @return character read from the input
10124 */
10126 {
10127 ++chars_read;
10128 return current = ia.get_character();
10129 }
10130
10131 /*!
10132 @return character read from the input after ignoring all 'N' entries
10133 */
10135 {
10136 do {
10137 get();
10138 } while (current == 'N');
10139
10140 return current;
10141 }
10142
10143 /*
10144 @brief read a number from the input
10145
10146 @tparam NumberType the type of the number
10147 @param[in] format the current format (for diagnostics)
10148 @param[out] result number of type @a NumberType
10149
10150 @return whether conversion completed
10151
10152 @note This function needs to respect the system's endianness, because
10153 bytes in CBOR, MessagePack, and UBJSON are stored in network order
10154 (big endian) and therefore need reordering on little endian systems.
10155 */
10156 template<typename NumberType, bool InputIsLittleEndian = false>
10157 bool get_number(const input_format_t format, NumberType& result)
10158 {
10159 // step 1: read input into array with system's byte order
10160 std::array<std::uint8_t, sizeof(NumberType)> vec{};
10161 for (std::size_t i = 0; i < sizeof(NumberType); ++i) {
10162 get();
10163 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) {
10164 return false;
10165 }
10166
10167 // reverse byte order prior to conversion if necessary
10168 if (is_little_endian != InputIsLittleEndian) {
10169 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
10170 } else {
10171 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
10172 }
10173 }
10174
10175 // step 2: convert array into number of type T and return
10176 std::memcpy(&result, vec.data(), sizeof(NumberType));
10177 return true;
10178 }
10179
10180 /*!
10181 @brief create a string by reading characters from the input
10182
10183 @tparam NumberType the type of the number
10184 @param[in] format the current format (for diagnostics)
10185 @param[in] len number of characters to read
10186 @param[out] result string created by reading @a len bytes
10187
10188 @return whether string creation completed
10189
10190 @note We can not reserve @a len bytes for the result, because @a len
10191 may be too large. Usually, @ref unexpect_eof() detects the end of
10192 the input before we run out of string memory.
10193 */
10194 template<typename NumberType>
10195 bool get_string(const input_format_t format, const NumberType len, string_t& result)
10196 {
10197 bool success = true;
10198 for (NumberType i = 0; i < len; i++) {
10199 get();
10200 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) {
10201 success = false;
10202 break;
10203 }
10204 result.push_back(static_cast<typename string_t::value_type>(current));
10205 }
10206 return success;
10207 }
10208
10209 /*!
10210 @brief create a byte array by reading bytes from the input
10211
10212 @tparam NumberType the type of the number
10213 @param[in] format the current format (for diagnostics)
10214 @param[in] len number of bytes to read
10215 @param[out] result byte array created by reading @a len bytes
10216
10217 @return whether byte array creation completed
10218
10219 @note We can not reserve @a len bytes for the result, because @a len
10220 may be too large. Usually, @ref unexpect_eof() detects the end of
10221 the input before we run out of memory.
10222 */
10223 template<typename NumberType>
10224 bool get_binary(const input_format_t format, const NumberType len, binary_t& result)
10225 {
10226 bool success = true;
10227 for (NumberType i = 0; i < len; i++) {
10228 get();
10229 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) {
10230 success = false;
10231 break;
10232 }
10233 result.push_back(static_cast<std::uint8_t>(current));
10234 }
10235 return success;
10236 }
10237
10238 /*!
10239 @param[in] format the current format (for diagnostics)
10240 @param[in] context further context information (for diagnostics)
10241 @return whether the last read character is not EOF
10242 */
10244 bool unexpect_eof(const input_format_t format, const char* context) const
10245 {
10246 if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof())) {
10247 return sax->parse_error(chars_read, "<end of file>",
10249 exception_message(format, "unexpected end of input", context),
10250 BasicJsonType()));
10251 }
10252 return true;
10253 }
10254
10255 /*!
10256 @return a string representation of the last read byte
10257 */
10258 std::string get_token_string() const
10259 {
10260 std::array<char, 3> cr{{}};
10261 static_cast<void>((std::snprintf)(
10262 cr.data(), cr.size(), "%.2hhX",
10263 static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
10264 return std::string{cr.data()};
10265 }
10266
10267 /*!
10268 @param[in] format the current format
10269 @param[in] detail a detailed error message
10270 @param[in] context further context information
10271 @return a message string to use in the parse_error exceptions
10272 */
10273 std::string exception_message(const input_format_t format,
10274 const std::string& detail,
10275 const std::string& context) const
10276 {
10277 std::string error_msg = "syntax error while parsing ";
10278
10279 switch (format) {
10281 error_msg += "CBOR";
10282 break;
10283
10285 error_msg += "MessagePack";
10286 break;
10287
10289 error_msg += "UBJSON";
10290 break;
10291
10293 error_msg += "BSON";
10294 break;
10295
10296 case input_format_t::json: // LCOV_EXCL_LINE
10297 default: // LCOV_EXCL_LINE
10298 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10299 }
10300
10301 return error_msg + " " + context + ": " + detail;
10302 }
10303
10304 private:
10305 /// input adapter
10306 InputAdapterType ia;
10307
10308 /// the current character
10309 char_int_type current = std::char_traits<char_type>::eof();
10310
10311 /// the number of characters read
10312 std::size_t chars_read = 0;
10313
10314 /// whether we can assume little endianness
10316
10317 /// the SAX parser
10318 json_sax_t* sax = nullptr;
10319};
10320} // namespace detail
10321} // namespace nlohmann
10322
10323// #include <nlohmann/detail/input/input_adapters.hpp>
10324
10325// #include <nlohmann/detail/input/lexer.hpp>
10326
10327// #include <nlohmann/detail/input/parser.hpp>
10328
10329#include <cmath> // isfinite
10330#include <cstdint> // uint8_t
10331#include <functional> // function
10332#include <string> // string
10333#include <utility> // move
10334#include <vector> // vector
10335
10336// #include <nlohmann/detail/exceptions.hpp>
10337
10338// #include <nlohmann/detail/input/input_adapters.hpp>
10339
10340// #include <nlohmann/detail/input/json_sax.hpp>
10341
10342// #include <nlohmann/detail/input/lexer.hpp>
10343
10344// #include <nlohmann/detail/macro_scope.hpp>
10345
10346// #include <nlohmann/detail/meta/is_sax.hpp>
10347
10348// #include <nlohmann/detail/value_t.hpp>
10349
10350namespace nlohmann
10351{
10352namespace detail
10353{
10354////////////
10355// parser //
10356////////////
10357
10358enum class parse_event_t : std::uint8_t
10359{
10360 /// the parser read `{` and started to process a JSON object
10361 object_start,
10362 /// the parser read `}` and finished processing a JSON object
10363 object_end,
10364 /// the parser read `[` and started to process a JSON array
10365 array_start,
10366 /// the parser read `]` and finished processing a JSON array
10368 /// the parser read a key of a value in an object
10370 /// the parser finished reading a JSON value
10372};
10373
10374template<typename BasicJsonType>
10375using parser_callback_t = std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
10376
10377/*!
10378@brief syntax analysis
10379
10380This class implements a recursive descent parser.
10381*/
10382template<typename BasicJsonType, typename InputAdapterType>
10384{
10385 using number_integer_t = typename BasicJsonType::number_integer_t;
10386 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
10387 using number_float_t = typename BasicJsonType::number_float_t;
10388 using string_t = typename BasicJsonType::string_t;
10391
10392 public:
10393 /// a parser reading from an input adapter
10394 explicit parser(InputAdapterType&& adapter,
10395 const parser_callback_t<BasicJsonType> cb = nullptr,
10396 const bool allow_exceptions_ = true,
10397 const bool skip_comments = false)
10398 : callback(cb)
10399 , m_lexer(std::move(adapter), skip_comments)
10400 , allow_exceptions(allow_exceptions_)
10401 {
10402 // read first token
10403 get_token();
10404 }
10405
10406 /*!
10407 @brief public parser interface
10408
10409 @param[in] strict whether to expect the last token to be EOF
10410 @param[in,out] result parsed JSON value
10411
10412 @throw parse_error.101 in case of an unexpected token
10413 @throw parse_error.102 if to_unicode fails or surrogate error
10414 @throw parse_error.103 if to_unicode fails
10415 */
10417 {
10418 if (callback) {
10420 sax_parse_internal(&sdp);
10421
10422 // in strict mode, input must be completely read
10423 if (strict && (get_token() != token_type::end_of_input)) {
10424 sdp.parse_error(m_lexer.get_position(), m_lexer.get_token_string(),
10425 parse_error::create(101, m_lexer.get_position(),
10426 exception_message(token_type::end_of_input, "value"),
10427 BasicJsonType()));
10428 }
10429
10430 // in case of an error, return discarded value
10431 if (sdp.is_errored()) {
10433 return;
10434 }
10435
10436 // set top-level value to null if it was discarded by the callback
10437 // function
10438 if (result.is_discarded()) {
10439 result = nullptr;
10440 }
10441 } else {
10443 sax_parse_internal(&sdp);
10444
10445 // in strict mode, input must be completely read
10446 if (strict && (get_token() != token_type::end_of_input)) {
10447 sdp.parse_error(m_lexer.get_position(), m_lexer.get_token_string(),
10448 parse_error::create(101, m_lexer.get_position(),
10449 exception_message(token_type::end_of_input, "value"),
10450 BasicJsonType()));
10451 }
10452
10453 // in case of an error, return discarded value
10454 if (sdp.is_errored()) {
10456 return;
10457 }
10458 }
10459
10460 result.assert_invariant();
10461 }
10462
10463 /*!
10464 @brief public accept interface
10465
10466 @param[in] strict whether to expect the last token to be EOF
10467 @return whether the input is a proper JSON text
10468 */
10469 bool accept(const bool strict = true)
10470 {
10472 return sax_parse(&sax_acceptor, strict);
10473 }
10474
10475 template<typename SAX>
10477 bool sax_parse(SAX* sax, const bool strict = true)
10478 {
10480 const bool result = sax_parse_internal(sax);
10481
10482 // strict mode: next byte must be EOF
10483 if (result && strict && (get_token() != token_type::end_of_input)) {
10484 return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(),
10485 parse_error::create(101, m_lexer.get_position(),
10486 exception_message(token_type::end_of_input, "value"),
10487 BasicJsonType()));
10488 }
10489
10490 return result;
10491 }
10492
10493 private:
10494 template<typename SAX>
10496 bool sax_parse_internal(SAX* sax)
10497 {
10498 // stack to remember the hierarchy of structured values we are parsing
10499 // true = array; false = object
10500 std::vector<bool> states;
10501 // value to avoid a goto (see comment where set to true)
10502 bool skip_to_state_evaluation = false;
10503
10504 while (true) {
10505 if (!skip_to_state_evaluation) {
10506 // invariant: get_token() was called before each iteration
10507 switch (last_token) {
10508 case token_type::begin_object: {
10509 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) {
10510 return false;
10511 }
10512
10513 // closing } -> we are done
10514 if (get_token() == token_type::end_object) {
10515 if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) {
10516 return false;
10517 }
10518 break;
10519 }
10520
10521 // parse key
10522 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) {
10523 return sax->parse_error(
10524 m_lexer.get_position(), m_lexer.get_token_string(),
10525 parse_error::create(101, m_lexer.get_position(),
10526 exception_message(token_type::value_string, "object key"),
10527 BasicJsonType()));
10528 }
10529 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) {
10530 return false;
10531 }
10532
10533 // parse separator (:)
10534 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) {
10535 return sax->parse_error(
10536 m_lexer.get_position(), m_lexer.get_token_string(),
10537 parse_error::create(101, m_lexer.get_position(),
10538 exception_message(token_type::name_separator, "object separator"),
10539 BasicJsonType()));
10540 }
10541
10542 // remember we are now inside an object
10543 states.push_back(false);
10544
10545 // parse values
10546 get_token();
10547 continue;
10548 }
10549
10550 case token_type::begin_array: {
10551 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) {
10552 return false;
10553 }
10554
10555 // closing ] -> we are done
10556 if (get_token() == token_type::end_array) {
10557 if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) {
10558 return false;
10559 }
10560 break;
10561 }
10562
10563 // remember we are now inside an array
10564 states.push_back(true);
10565
10566 // parse values (no need to call get_token)
10567 continue;
10568 }
10569
10570 case token_type::value_float: {
10571 const auto res = m_lexer.get_number_float();
10572
10573 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) {
10574 return sax->parse_error(
10575 m_lexer.get_position(), m_lexer.get_token_string(),
10577 "number overflow parsing '" + m_lexer.get_token_string() + "'",
10578 BasicJsonType()));
10579 }
10580
10581 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) {
10582 return false;
10583 }
10584
10585 break;
10586 }
10587
10588 case token_type::literal_false: {
10589 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) {
10590 return false;
10591 }
10592 break;
10593 }
10594
10595 case token_type::literal_null: {
10596 if (JSON_HEDLEY_UNLIKELY(!sax->null())) {
10597 return false;
10598 }
10599 break;
10600 }
10601
10602 case token_type::literal_true: {
10603 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) {
10604 return false;
10605 }
10606 break;
10607 }
10608
10609 case token_type::value_integer: {
10610 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) {
10611 return false;
10612 }
10613 break;
10614 }
10615
10616 case token_type::value_string: {
10617 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) {
10618 return false;
10619 }
10620 break;
10621 }
10622
10623 case token_type::value_unsigned: {
10624 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) {
10625 return false;
10626 }
10627 break;
10628 }
10629
10630 case token_type::parse_error: {
10631 // using "uninitialized" to avoid "expected" message
10632 return sax->parse_error(
10633 m_lexer.get_position(), m_lexer.get_token_string(),
10634 parse_error::create(101, m_lexer.get_position(),
10635 exception_message(token_type::uninitialized, "value"),
10636 BasicJsonType()));
10637 }
10638
10639 case token_type::uninitialized:
10640 case token_type::end_array:
10641 case token_type::end_object:
10642 case token_type::name_separator:
10643 case token_type::value_separator:
10644 case token_type::end_of_input:
10645 case token_type::literal_or_value:
10646 default: // the last token was unexpected
10647 {
10648 return sax->parse_error(
10649 m_lexer.get_position(), m_lexer.get_token_string(),
10650 parse_error::create(101, m_lexer.get_position(),
10651 exception_message(token_type::literal_or_value, "value"),
10652 BasicJsonType()));
10653 }
10654 }
10655 } else {
10656 skip_to_state_evaluation = false;
10657 }
10658
10659 // we reached this line after we successfully parsed a value
10660 if (states.empty()) {
10661 // empty stack: we reached the end of the hierarchy: done
10662 return true;
10663 }
10664
10665 if (states.back()) // array
10666 {
10667 // comma -> next value
10668 if (get_token() == token_type::value_separator) {
10669 // parse a new value
10670 get_token();
10671 continue;
10672 }
10673
10674 // closing ]
10675 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) {
10676 if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) {
10677 return false;
10678 }
10679
10680 // We are done with this array. Before we can parse a
10681 // new value, we need to evaluate the new state first.
10682 // By setting skip_to_state_evaluation to false, we
10683 // are effectively jumping to the beginning of this if.
10684 JSON_ASSERT(!states.empty());
10685 states.pop_back();
10686 skip_to_state_evaluation = true;
10687 continue;
10688 }
10689
10690 return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(),
10691 parse_error::create(101, m_lexer.get_position(),
10692 exception_message(token_type::end_array, "array"),
10693 BasicJsonType()));
10694 }
10695
10696 // states.back() is false -> object
10697
10698 // comma -> next value
10699 if (get_token() == token_type::value_separator) {
10700 // parse key
10701 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) {
10702 return sax->parse_error(
10703 m_lexer.get_position(), m_lexer.get_token_string(),
10704 parse_error::create(101, m_lexer.get_position(),
10705 exception_message(token_type::value_string, "object key"),
10706 BasicJsonType()));
10707 }
10708
10709 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) {
10710 return false;
10711 }
10712
10713 // parse separator (:)
10714 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) {
10715 return sax->parse_error(
10716 m_lexer.get_position(), m_lexer.get_token_string(),
10717 parse_error::create(101, m_lexer.get_position(),
10718 exception_message(token_type::name_separator, "object separator"),
10719 BasicJsonType()));
10720 }
10721
10722 // parse values
10723 get_token();
10724 continue;
10725 }
10726
10727 // closing }
10728 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) {
10729 if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) {
10730 return false;
10731 }
10732
10733 // We are done with this object. Before we can parse a
10734 // new value, we need to evaluate the new state first.
10735 // By setting skip_to_state_evaluation to false, we
10736 // are effectively jumping to the beginning of this if.
10737 JSON_ASSERT(!states.empty());
10738 states.pop_back();
10739 skip_to_state_evaluation = true;
10740 continue;
10741 }
10742
10743 return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(),
10744 parse_error::create(101, m_lexer.get_position(),
10745 exception_message(token_type::end_object, "object"),
10746 BasicJsonType()));
10747 }
10748 }
10749
10750 /// get next token from lexer
10752
10753 std::string exception_message(const token_type expected, const std::string& context)
10754 {
10755 std::string error_msg = "syntax error ";
10756
10757 if (!context.empty()) {
10758 error_msg += "while parsing " + context + " ";
10759 }
10760
10761 error_msg += "- ";
10762
10763 if (last_token == token_type::parse_error) {
10764 error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" + m_lexer.get_token_string() + "'";
10765 } else {
10766 error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
10767 }
10768
10769 if (expected != token_type::uninitialized) {
10770 error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
10771 }
10772
10773 return error_msg;
10774 }
10775
10776 private:
10777 /// callback function
10779 /// the type of the last read token
10780 token_type last_token = token_type::uninitialized;
10781 /// the lexer
10783 /// whether to throw exceptions in case of errors
10784 const bool allow_exceptions = true;
10785};
10786
10787} // namespace detail
10788} // namespace nlohmann
10789
10790// #include <nlohmann/detail/iterators/internal_iterator.hpp>
10791
10792// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
10793
10794#include <cstddef> // ptrdiff_t
10795#include <limits> // numeric_limits
10796
10797// #include <nlohmann/detail/macro_scope.hpp>
10798
10799namespace nlohmann
10800{
10801namespace detail
10802{
10803/*
10804@brief an iterator for primitive JSON types
10805
10806This class models an iterator for primitive JSON types (boolean, number,
10807string). It's only purpose is to allow the iterator/const_iterator classes
10808to "iterate" over primitive values. Internally, the iterator is modeled by
10809a `difference_type` variable. Value begin_value (`0`) models the begin,
10810end_value (`1`) models past the end.
10811*/
10813{
10814 private:
10815 using difference_type = std::ptrdiff_t;
10816 static constexpr difference_type begin_value = 0;
10817 static constexpr difference_type end_value = begin_value + 1;
10818
10820 :
10821 /// iterator as signed integer type
10822 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
10823
10824 public:
10825 constexpr difference_type get_value() const noexcept { return m_it; }
10826
10827 /// set iterator to a defined beginning
10828 void set_begin() noexcept { m_it = begin_value; }
10829
10830 /// set iterator to a defined past the end
10831 void set_end() noexcept { m_it = end_value; }
10832
10833 /// return whether the iterator can be dereferenced
10834 constexpr bool is_begin() const noexcept { return m_it == begin_value; }
10835
10836 /// return whether the iterator is at end
10837 constexpr bool is_end() const noexcept { return m_it == end_value; }
10838
10839 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
10840 {
10841 return lhs.m_it == rhs.m_it;
10842 }
10843
10844 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
10845 {
10846 return lhs.m_it < rhs.m_it;
10847 }
10848
10850 {
10851 auto result = *this;
10852 result += n;
10853 return result;
10854 }
10855
10857 {
10858 return lhs.m_it - rhs.m_it;
10859 }
10860
10862 {
10863 ++m_it;
10864 return *this;
10865 }
10866
10867 primitive_iterator_t const operator++(int) noexcept // NOLINT(readability-const-return-type)
10868 {
10869 auto result = *this;
10870 ++m_it;
10871 return result;
10872 }
10873
10875 {
10876 --m_it;
10877 return *this;
10878 }
10879
10880 primitive_iterator_t const operator--(int) noexcept // NOLINT(readability-const-return-type)
10881 {
10882 auto result = *this;
10883 --m_it;
10884 return result;
10885 }
10886
10888 {
10889 m_it += n;
10890 return *this;
10891 }
10892
10894 {
10895 m_it -= n;
10896 return *this;
10897 }
10898};
10899} // namespace detail
10900} // namespace nlohmann
10901
10902namespace nlohmann
10903{
10904namespace detail
10905{
10906/*!
10907@brief an iterator value
10908
10909@note This structure could easily be a union, but MSVC currently does not allow
10910unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
10911*/
10912template<typename BasicJsonType>
10914{
10915 /// iterator for JSON objects
10916 typename BasicJsonType::object_t::iterator object_iterator{};
10917 /// iterator for JSON arrays
10918 typename BasicJsonType::array_t::iterator array_iterator{};
10919 /// generic iterator for all other types
10921};
10922} // namespace detail
10923} // namespace nlohmann
10924
10925// #include <nlohmann/detail/iterators/iter_impl.hpp>
10926
10927#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
10928#include <type_traits> // conditional, is_const, remove_const
10929
10930// #include <nlohmann/detail/exceptions.hpp>
10931
10932// #include <nlohmann/detail/iterators/internal_iterator.hpp>
10933
10934// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
10935
10936// #include <nlohmann/detail/macro_scope.hpp>
10937
10938// #include <nlohmann/detail/meta/cpp_future.hpp>
10939
10940// #include <nlohmann/detail/meta/type_traits.hpp>
10941
10942// #include <nlohmann/detail/value_t.hpp>
10943
10944namespace nlohmann
10945{
10946namespace detail
10947{
10948// forward declare, to be able to friend it later on
10949template<typename IteratorType>
10950class iteration_proxy;
10951template<typename IteratorType>
10953
10954/*!
10955@brief a template for a bidirectional iterator for the @ref basic_json class
10956This class implements a both iterators (iterator and const_iterator) for the
10957@ref basic_json class.
10958@note An iterator is called *initialized* when a pointer to a JSON value has
10959 been set (e.g., by a constructor or a copy assignment). If the iterator is
10960 default-constructed, it is *uninitialized* and most methods are undefined.
10961 **The library uses assertions to detect calls on uninitialized iterators.**
10962@requirement The class satisfies the following concept requirements:
10963-
10964[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
10965 The iterator that can be moved can be moved in both directions (i.e.
10966 incremented and decremented).
10967@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
10968 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
10969*/
10970template<typename BasicJsonType>
10971class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
10972{
10973 /// the iterator with BasicJsonType of different const-ness
10975 typename std::remove_const<BasicJsonType>::type,
10976 const BasicJsonType>::type>;
10977 /// allow basic_json to access private members
10982
10983 using object_t = typename BasicJsonType::object_t;
10984 using array_t = typename BasicJsonType::array_t;
10985 // make sure BasicJsonType is basic_json or const basic_json
10987 "iter_impl only accepts (const) basic_json");
10988
10989 public:
10990 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
10991 /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
10992 /// A user-defined iterator should provide publicly accessible typedefs named
10993 /// iterator_category, value_type, difference_type, pointer, and reference.
10994 /// Note that value_type is required to be non-const, even for constant iterators.
10995 using iterator_category = std::bidirectional_iterator_tag;
10996
10997 /// the type of the values when the iterator is dereferenced
10998 using value_type = typename BasicJsonType::value_type;
10999 /// a type to represent differences between iterators
11000 using difference_type = typename BasicJsonType::difference_type;
11001 /// defines a pointer to the type iterated over (value_type)
11002 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
11003 typename BasicJsonType::const_pointer,
11004 typename BasicJsonType::pointer>::type;
11005 /// defines a reference to the type iterated over (value_type)
11006 using reference = typename std::conditional<std::is_const<BasicJsonType>::value,
11007 typename BasicJsonType::const_reference,
11008 typename BasicJsonType::reference>::type;
11009
11010 iter_impl() = default;
11011 ~iter_impl() = default;
11012 iter_impl(iter_impl&&) noexcept = default;
11013 iter_impl& operator=(iter_impl&&) noexcept = default;
11014
11015 /*!
11016 @brief constructor for a given JSON instance
11017 @param[in] object pointer to a JSON object for this iterator
11018 @pre object != nullptr
11019 @post The iterator is initialized; i.e. `m_object != nullptr`.
11020 */
11021 explicit iter_impl(pointer object) noexcept
11022 : m_object(object)
11023 {
11024 JSON_ASSERT(m_object != nullptr);
11025
11026 switch (m_object->m_type) {
11027 case value_t::object: {
11028 m_it.object_iterator = typename object_t::iterator();
11029 break;
11030 }
11031
11032 case value_t::array: {
11033 m_it.array_iterator = typename array_t::iterator();
11034 break;
11035 }
11036
11037 case value_t::null:
11038 case value_t::string:
11039 case value_t::boolean:
11043 case value_t::binary:
11044 case value_t::discarded:
11045 default: {
11046 m_it.primitive_iterator = primitive_iterator_t();
11047 break;
11048 }
11049 }
11050 }
11051
11052 /*!
11053 @note The conventional copy constructor and copy assignment are implicitly
11054 defined. Combined with the following converting constructor and
11055 assignment, they support: (1) copy from iterator to iterator, (2)
11056 copy from const iterator to const iterator, and (3) conversion from
11057 iterator to const iterator. However conversion from const iterator
11058 to iterator is not defined.
11059 */
11060
11061 /*!
11062 @brief const copy constructor
11063 @param[in] other const iterator to copy from
11064 @note This copy constructor had to be defined explicitly to circumvent a bug
11065 occurring on msvc v19.0 compiler (VS 2015) debug build. For more
11066 information refer to: https://github.com/nlohmann/json/issues/1608
11067 */
11069 : m_object(other.m_object)
11070 , m_it(other.m_it)
11071 {}
11072
11073 /*!
11074 @brief converting assignment
11075 @param[in] other const iterator to copy from
11076 @return const/non-const iterator
11077 @note It is not checked whether @a other is initialized.
11078 */
11080 {
11081 if (&other != this) {
11082 m_object = other.m_object;
11083 m_it = other.m_it;
11084 }
11085 return *this;
11086 }
11087
11088 /*!
11089 @brief converting constructor
11090 @param[in] other non-const iterator to copy from
11091 @note It is not checked whether @a other is initialized.
11092 */
11093 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
11094 : m_object(other.m_object)
11095 , m_it(other.m_it)
11096 {}
11097
11098 /*!
11099 @brief converting assignment
11100 @param[in] other non-const iterator to copy from
11101 @return const/non-const iterator
11102 @note It is not checked whether @a other is initialized.
11103 */
11105 const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
11106 {
11107 m_object = other.m_object;
11108 m_it = other.m_it;
11109 return *this;
11110 }
11111
11113 :
11114 /*!
11115 @brief set the iterator to the first value
11116 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11117 */
11118 void
11119 set_begin() noexcept
11120 {
11121 JSON_ASSERT(m_object != nullptr);
11122
11123 switch (m_object->m_type) {
11124 case value_t::object: {
11125 m_it.object_iterator = m_object->m_value.object->begin();
11126 break;
11127 }
11128
11129 case value_t::array: {
11130 m_it.array_iterator = m_object->m_value.array->begin();
11131 break;
11132 }
11133
11134 case value_t::null: {
11135 // set to end so begin()==end() is true: null is empty
11136 m_it.primitive_iterator.set_end();
11137 break;
11138 }
11139
11140 case value_t::string:
11141 case value_t::boolean:
11145 case value_t::binary:
11146 case value_t::discarded:
11147 default: {
11148 m_it.primitive_iterator.set_begin();
11149 break;
11150 }
11151 }
11152 }
11153
11154 /*!
11155 @brief set the iterator past the last value
11156 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11157 */
11158 void set_end() noexcept
11159 {
11160 JSON_ASSERT(m_object != nullptr);
11161
11162 switch (m_object->m_type) {
11163 case value_t::object: {
11164 m_it.object_iterator = m_object->m_value.object->end();
11165 break;
11166 }
11167
11168 case value_t::array: {
11169 m_it.array_iterator = m_object->m_value.array->end();
11170 break;
11171 }
11172
11173 case value_t::null:
11174 case value_t::string:
11175 case value_t::boolean:
11179 case value_t::binary:
11180 case value_t::discarded:
11181 default: {
11182 m_it.primitive_iterator.set_end();
11183 break;
11184 }
11185 }
11186 }
11187
11188 public:
11189 /*!
11190 @brief return a reference to the value pointed to by the iterator
11191 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11192 */
11193 reference operator*() const
11194 {
11195 JSON_ASSERT(m_object != nullptr);
11196
11197 switch (m_object->m_type) {
11198 case value_t::object: {
11199 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
11200 return m_it.object_iterator->second;
11201 }
11202
11203 case value_t::array: {
11204 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
11205 return *m_it.array_iterator;
11206 }
11207
11208 case value_t::null:
11209 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11210
11211 case value_t::string:
11212 case value_t::boolean:
11216 case value_t::binary:
11217 case value_t::discarded:
11218 default: {
11219 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) {
11220 return *m_object;
11221 }
11222
11223 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11224 }
11225 }
11226 }
11227
11228 /*!
11229 @brief dereference the iterator
11230 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11231 */
11232 pointer operator->() const
11233 {
11234 JSON_ASSERT(m_object != nullptr);
11235
11236 switch (m_object->m_type) {
11237 case value_t::object: {
11238 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
11239 return &(m_it.object_iterator->second);
11240 }
11241
11242 case value_t::array: {
11243 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
11244 return &*m_it.array_iterator;
11245 }
11246
11247 case value_t::null:
11248 case value_t::string:
11249 case value_t::boolean:
11253 case value_t::binary:
11254 case value_t::discarded:
11255 default: {
11256 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) {
11257 return m_object;
11258 }
11259
11260 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11261 }
11262 }
11263 }
11264
11265 /*!
11266 @brief post-increment (it++)
11267 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11268 */
11269 iter_impl const operator++(int) // NOLINT(readability-const-return-type)
11270 {
11271 auto result = *this;
11272 ++(*this);
11273 return result;
11274 }
11275
11276 /*!
11277 @brief pre-increment (++it)
11278 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11279 */
11281 {
11282 JSON_ASSERT(m_object != nullptr);
11283
11284 switch (m_object->m_type) {
11285 case value_t::object: {
11286 std::advance(m_it.object_iterator, 1);
11287 break;
11288 }
11289
11290 case value_t::array: {
11291 std::advance(m_it.array_iterator, 1);
11292 break;
11293 }
11294
11295 case value_t::null:
11296 case value_t::string:
11297 case value_t::boolean:
11301 case value_t::binary:
11302 case value_t::discarded:
11303 default: {
11304 ++m_it.primitive_iterator;
11305 break;
11306 }
11307 }
11308
11309 return *this;
11310 }
11311
11312 /*!
11313 @brief post-decrement (it--)
11314 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11315 */
11316 iter_impl const operator--(int) // NOLINT(readability-const-return-type)
11317 {
11318 auto result = *this;
11319 --(*this);
11320 return result;
11321 }
11322
11323 /*!
11324 @brief pre-decrement (--it)
11325 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11326 */
11328 {
11329 JSON_ASSERT(m_object != nullptr);
11330
11331 switch (m_object->m_type) {
11332 case value_t::object: {
11333 std::advance(m_it.object_iterator, -1);
11334 break;
11335 }
11336
11337 case value_t::array: {
11338 std::advance(m_it.array_iterator, -1);
11339 break;
11340 }
11341
11342 case value_t::null:
11343 case value_t::string:
11344 case value_t::boolean:
11348 case value_t::binary:
11349 case value_t::discarded:
11350 default: {
11351 --m_it.primitive_iterator;
11352 break;
11353 }
11354 }
11355
11356 return *this;
11357 }
11358
11359 /*!
11360 @brief comparison: equal
11361 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11362 */
11363 template<typename IterImpl,
11364 detail::enable_if_t<(std::is_same<IterImpl, iter_impl>::value
11365 || std::is_same<IterImpl, other_iter_impl>::value),
11366 std::nullptr_t> = nullptr>
11367 bool operator==(const IterImpl& other) const
11368 {
11369 // if objects are not the same, the comparison is undefined
11370 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) {
11371 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
11372 }
11373
11374 JSON_ASSERT(m_object != nullptr);
11375
11376 switch (m_object->m_type) {
11377 case value_t::object:
11378 return (m_it.object_iterator == other.m_it.object_iterator);
11379
11380 case value_t::array:
11381 return (m_it.array_iterator == other.m_it.array_iterator);
11382
11383 case value_t::null:
11384 case value_t::string:
11385 case value_t::boolean:
11389 case value_t::binary:
11390 case value_t::discarded:
11391 default:
11392 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
11393 }
11394 }
11395
11396 /*!
11397 @brief comparison: not equal
11398 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11399 */
11400 template<typename IterImpl,
11401 detail::enable_if_t<(std::is_same<IterImpl, iter_impl>::value
11402 || std::is_same<IterImpl, other_iter_impl>::value),
11403 std::nullptr_t> = nullptr>
11404 bool operator!=(const IterImpl& other) const
11405 {
11406 return !operator==(other);
11407 }
11408
11409 /*!
11410 @brief comparison: smaller
11411 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11412 */
11413 bool operator<(const iter_impl& other) const
11414 {
11415 // if objects are not the same, the comparison is undefined
11416 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) {
11417 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
11418 }
11419
11420 JSON_ASSERT(m_object != nullptr);
11421
11422 switch (m_object->m_type) {
11423 case value_t::object:
11424 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object));
11425
11426 case value_t::array:
11427 return (m_it.array_iterator < other.m_it.array_iterator);
11428
11429 case value_t::null:
11430 case value_t::string:
11431 case value_t::boolean:
11435 case value_t::binary:
11436 case value_t::discarded:
11437 default:
11438 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
11439 }
11440 }
11441
11442 /*!
11443 @brief comparison: less than or equal
11444 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11445 */
11446 bool operator<=(const iter_impl& other) const { return !other.operator<(*this); }
11447
11448 /*!
11449 @brief comparison: greater than
11450 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11451 */
11452 bool operator>(const iter_impl& other) const { return !operator<=(other); }
11453
11454 /*!
11455 @brief comparison: greater than or equal
11456 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11457 */
11458 bool operator>=(const iter_impl& other) const { return !operator<(other); }
11459
11460 /*!
11461 @brief add to iterator
11462 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11463 */
11465 {
11466 JSON_ASSERT(m_object != nullptr);
11467
11468 switch (m_object->m_type) {
11469 case value_t::object:
11470 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
11471
11472 case value_t::array: {
11473 std::advance(m_it.array_iterator, i);
11474 break;
11475 }
11476
11477 case value_t::null:
11478 case value_t::string:
11479 case value_t::boolean:
11483 case value_t::binary:
11484 case value_t::discarded:
11485 default: {
11486 m_it.primitive_iterator += i;
11487 break;
11488 }
11489 }
11490
11491 return *this;
11492 }
11493
11494 /*!
11495 @brief subtract from iterator
11496 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11497 */
11499
11500 /*!
11501 @brief add to iterator
11502 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11503 */
11505 {
11506 auto result = *this;
11507 result += i;
11508 return result;
11509 }
11510
11511 /*!
11512 @brief addition of distance and iterator
11513 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11514 */
11516 {
11517 auto result = it;
11518 result += i;
11519 return result;
11520 }
11521
11522 /*!
11523 @brief subtract from iterator
11524 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11525 */
11527 {
11528 auto result = *this;
11529 result -= i;
11530 return result;
11531 }
11532
11533 /*!
11534 @brief return difference
11535 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11536 */
11538 {
11539 JSON_ASSERT(m_object != nullptr);
11540
11541 switch (m_object->m_type) {
11542 case value_t::object:
11543 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
11544
11545 case value_t::array:
11546 return m_it.array_iterator - other.m_it.array_iterator;
11547
11548 case value_t::null:
11549 case value_t::string:
11550 case value_t::boolean:
11554 case value_t::binary:
11555 case value_t::discarded:
11556 default:
11557 return m_it.primitive_iterator - other.m_it.primitive_iterator;
11558 }
11559 }
11560
11561 /*!
11562 @brief access to successor
11563 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11564 */
11566 {
11567 JSON_ASSERT(m_object != nullptr);
11568
11569 switch (m_object->m_type) {
11570 case value_t::object:
11571 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object));
11572
11573 case value_t::array:
11574 return *std::next(m_it.array_iterator, n);
11575
11576 case value_t::null:
11577 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11578
11579 case value_t::string:
11580 case value_t::boolean:
11584 case value_t::binary:
11585 case value_t::discarded:
11586 default: {
11587 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) {
11588 return *m_object;
11589 }
11590
11591 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11592 }
11593 }
11594 }
11595
11596 /*!
11597 @brief return the key of an object iterator
11598 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11599 */
11600 const typename object_t::key_type& key() const
11601 {
11602 JSON_ASSERT(m_object != nullptr);
11603
11604 if (JSON_HEDLEY_LIKELY(m_object->is_object())) {
11605 return m_it.object_iterator->first;
11606 }
11607
11608 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object));
11609 }
11610
11611 /*!
11612 @brief return the value of an iterator
11613 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11614 */
11615 reference value() const { return operator*(); }
11616
11618 :
11619 /// associated JSON instance
11620 pointer m_object = nullptr;
11621 /// the actual iterator of the associated instance
11623};
11624} // namespace detail
11625} // namespace nlohmann
11626
11627// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
11628
11629// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
11630
11631#include <cstddef> // ptrdiff_t
11632#include <iterator> // reverse_iterator
11633#include <utility> // declval
11634
11635namespace nlohmann
11636{
11637namespace detail
11638{
11639//////////////////////
11640// reverse_iterator //
11641//////////////////////
11642
11643/*!
11644@brief a template for a reverse iterator class
11645
11646@tparam Base the base iterator type to reverse. Valid types are @ref
11647iterator (to create @ref reverse_iterator) and @ref const_iterator (to
11648create @ref const_reverse_iterator).
11649
11650@requirement The class satisfies the following concept requirements:
11651-
11652[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
11653 The iterator that can be moved can be moved in both directions (i.e.
11654 incremented and decremented).
11655- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
11656 It is possible to write to the pointed-to element (only if @a Base is
11657 @ref iterator).
11658
11659@since version 1.0.0
11660*/
11661template<typename Base>
11662class json_reverse_iterator : public std::reverse_iterator<Base>
11663{
11664 public:
11665 using difference_type = std::ptrdiff_t;
11666 /// shortcut to the reverse iterator adapter
11667 using base_iterator = std::reverse_iterator<Base>;
11668 /// the reference type for the pointed-to element
11669 using reference = typename Base::reference;
11670
11671 /// create reverse iterator from iterator
11672 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
11673 : base_iterator(it)
11674 {}
11675
11676 /// create reverse iterator from base class
11677 explicit json_reverse_iterator(const base_iterator& it) noexcept
11678 : base_iterator(it)
11679 {}
11680
11681 /// post-increment (it++)
11682 json_reverse_iterator const operator++(int) // NOLINT(readability-const-return-type)
11683 {
11684 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
11685 }
11686
11687 /// pre-increment (++it)
11688 json_reverse_iterator& operator++() { return static_cast<json_reverse_iterator&>(base_iterator::operator++()); }
11689
11690 /// post-decrement (it--)
11691 json_reverse_iterator const operator--(int) // NOLINT(readability-const-return-type)
11692 {
11693 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
11694 }
11695
11696 /// pre-decrement (--it)
11697 json_reverse_iterator& operator--() { return static_cast<json_reverse_iterator&>(base_iterator::operator--()); }
11698
11699 /// add to iterator
11701 {
11702 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
11703 }
11704
11705 /// add to iterator
11707 {
11708 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
11709 }
11710
11711 /// subtract from iterator
11713 {
11714 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
11715 }
11716
11717 /// return difference
11719 {
11720 return base_iterator(*this) - base_iterator(other);
11721 }
11722
11723 /// access to successor
11724 reference operator[](difference_type n) const { return *(this->operator+(n)); }
11725
11726 /// return the key of an object iterator
11727 auto key() const -> decltype(std::declval<Base>().key())
11728 {
11729 auto it = --this->base();
11730 return it.key();
11731 }
11732
11733 /// return the value of an iterator
11735 {
11736 auto it = --this->base();
11737 return it.operator*();
11738 }
11739};
11740} // namespace detail
11741} // namespace nlohmann
11742
11743// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
11744
11745// #include <nlohmann/detail/json_pointer.hpp>
11746
11747#include <algorithm> // all_of
11748#include <cctype> // isdigit
11749#include <limits> // max
11750#include <numeric> // accumulate
11751#include <string> // string
11752#include <utility> // move
11753#include <vector> // vector
11754
11755// #include <nlohmann/detail/exceptions.hpp>
11756
11757// #include <nlohmann/detail/macro_scope.hpp>
11758
11759// #include <nlohmann/detail/string_escape.hpp>
11760
11761// #include <nlohmann/detail/value_t.hpp>
11762
11763namespace nlohmann
11764{
11765
11766/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
11767/// @sa https://json.nlohmann.me/api/json_pointer/
11768template<typename BasicJsonType>
11769class json_pointer
11770{
11771 // allow basic_json to access private members
11773 friend class basic_json;
11774
11775 public:
11776 /// @brief create JSON pointer
11777 /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
11778 explicit json_pointer(const std::string& s = "")
11780 {}
11781
11782 /// @brief return a string representation of the JSON pointer
11783 /// @sa https://json.nlohmann.me/api/json_pointer/to_string/
11784 std::string to_string() const
11785 {
11786 return std::accumulate(reference_tokens.begin(), reference_tokens.end(), std::string{},
11787 [](const std::string& a, const std::string& b) { return a + "/" + detail::escape(b); });
11788 }
11789
11790 /// @brief return a string representation of the JSON pointer
11791 /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
11792 operator std::string() const { return to_string(); }
11793
11794 /// @brief append another JSON pointer at the end of this JSON pointer
11795 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
11797 {
11798 reference_tokens.insert(reference_tokens.end(), ptr.reference_tokens.begin(), ptr.reference_tokens.end());
11799 return *this;
11800 }
11801
11802 /// @brief append an unescaped reference token at the end of this JSON pointer
11803 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
11804 json_pointer& operator/=(std::string token)
11805 {
11806 push_back(std::move(token));
11807 return *this;
11808 }
11809
11810 /// @brief append an array index at the end of this JSON pointer
11811 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
11812 json_pointer& operator/=(std::size_t array_idx) { return *this /= std::to_string(array_idx); }
11813
11814 /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
11815 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
11816 friend json_pointer operator/(const json_pointer& lhs, const json_pointer& rhs) { return json_pointer(lhs) /= rhs; }
11817
11818 /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
11819 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
11820 friend json_pointer operator/(const json_pointer& lhs,
11821 std::string token) // NOLINT(performance-unnecessary-value-param)
11822 {
11823 return json_pointer(lhs) /= std::move(token);
11824 }
11825
11826 /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
11827 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
11828 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
11829 {
11830 return json_pointer(lhs) /= array_idx;
11831 }
11832
11833 /// @brief returns the parent of this JSON pointer
11834 /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
11835 json_pointer parent_pointer() const
11836 {
11837 if (empty()) {
11838 return *this;
11839 }
11840
11842 res.pop_back();
11843 return res;
11844 }
11845
11846 /// @brief remove last reference token
11847 /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
11848 void pop_back()
11849 {
11850 if (JSON_HEDLEY_UNLIKELY(empty())) {
11851 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
11852 }
11853
11854 reference_tokens.pop_back();
11855 }
11856
11857 /// @brief return last reference token
11858 /// @sa https://json.nlohmann.me/api/json_pointer/back/
11859 const std::string& back() const
11860 {
11861 if (JSON_HEDLEY_UNLIKELY(empty())) {
11862 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
11863 }
11864
11865 return reference_tokens.back();
11866 }
11867
11868 /// @brief append an unescaped token at the end of the reference pointer
11869 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
11870 void push_back(const std::string& token) { reference_tokens.push_back(token); }
11871
11872 /// @brief append an unescaped token at the end of the reference pointer
11873 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
11874 void push_back(std::string&& token) { reference_tokens.push_back(std::move(token)); }
11875
11876 /// @brief return whether pointer points to the root document
11877 /// @sa https://json.nlohmann.me/api/json_pointer/empty/
11878 bool empty() const noexcept { return reference_tokens.empty(); }
11879
11880 private:
11881 /*!
11882 @param[in] s reference token to be converted into an array index
11883
11884 @return integer representation of @a s
11885
11886 @throw parse_error.106 if an array index begins with '0'
11887 @throw parse_error.109 if an array index begins not with a digit
11888 @throw out_of_range.404 if string @a s could not be converted to an integer
11889 @throw out_of_range.410 if an array index exceeds size_type
11890 */
11891 static typename BasicJsonType::size_type array_index(const std::string& s)
11892 {
11893 using size_type = typename BasicJsonType::size_type;
11894
11895 // error condition (cf. RFC 6901, Sect. 4)
11896 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) {
11897 JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'",
11898 BasicJsonType()));
11899 }
11900
11901 // error condition (cf. RFC 6901, Sect. 4)
11902 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) {
11903 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType()));
11904 }
11905
11906 std::size_t processed_chars = 0;
11907 unsigned long long res = 0; // NOLINT(runtime/int)
11908 JSON_TRY
11909 {
11910 res = std::stoull(s, &processed_chars);
11911 }
11912 JSON_CATCH(std::out_of_range&)
11913 {
11914 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
11915 }
11916
11917 // check if the string was completely read
11918 if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size())) {
11919 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
11920 }
11921
11922 // only triggered on special platforms (like 32bit), see also
11923 // https://github.com/nlohmann/json/pull/2203
11924 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
11925 {
11926 JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type",
11927 BasicJsonType())); // LCOV_EXCL_LINE
11928 }
11929
11930 return static_cast<size_type>(res);
11931 }
11932
11934 {
11935 if (JSON_HEDLEY_UNLIKELY(empty())) {
11936 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
11937 }
11938
11940 result.reference_tokens = {reference_tokens[0]};
11941 return result;
11942 }
11943
11944 private:
11945 /*!
11946 @brief create and return a reference to the pointed to value
11947
11948 @complexity Linear in the number of reference tokens.
11949
11950 @throw parse_error.109 if array index is not a number
11951 @throw type_error.313 if value cannot be unflattened
11952 */
11954 {
11955 auto* result = &j;
11956
11957 // in case no reference tokens exist, return a reference to the JSON value
11958 // j which will be overwritten by a primitive value
11959 for (const auto& reference_token : reference_tokens) {
11960 switch (result->type()) {
11961 case detail::value_t::null: {
11962 if (reference_token == "0") {
11963 // start a new array if reference token is 0
11964 result = &result->operator[](0);
11965 } else {
11966 // start a new object otherwise
11967 result = &result->operator[](reference_token);
11968 }
11969 break;
11970 }
11971
11973 // create an entry in the object
11974 result = &result->operator[](reference_token);
11975 break;
11976 }
11977
11979 // create an entry in the array
11980 result = &result->operator[](array_index(reference_token));
11981 break;
11982 }
11983
11984 /*
11985 The following code is only reached if there exists a reference
11986 token _and_ the current value is primitive. In this case, we have
11987 an error situation, because primitive values may only occur as
11988 single value; that is, with an empty list of reference tokens.
11989 */
11997 default:
11998 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j));
11999 }
12000 }
12001
12002 return *result;
12003 }
12004
12005 /*!
12006 @brief return a reference to the pointed to value
12007
12008 @note This version does not throw if a value is not present, but tries to
12009 create nested values instead. For instance, calling this function
12010 with pointer `"/this/that"` on a null value is equivalent to calling
12011 `operator[]("this").operator[]("that")` on that value, effectively
12012 changing the null value to an object.
12013
12014 @param[in] ptr a JSON value
12015
12016 @return reference to the JSON value pointed to by the JSON pointer
12017
12018 @complexity Linear in the length of the JSON pointer.
12019
12020 @throw parse_error.106 if an array index begins with '0'
12021 @throw parse_error.109 if an array index was not a number
12022 @throw out_of_range.404 if the JSON pointer can not be resolved
12023 */
12025 {
12026 for (const auto& reference_token : reference_tokens) {
12027 // convert null values to arrays or objects before continuing
12028 if (ptr->is_null()) {
12029 // check if reference token is a number
12030 const bool nums = std::all_of(reference_token.begin(), reference_token.end(),
12031 [](const unsigned char x) { return std::isdigit(x); });
12032
12033 // change value to array for numbers or "-" or to object otherwise
12034 *ptr = (nums || reference_token == "-") ? detail::value_t::array : detail::value_t::object;
12035 }
12036
12037 switch (ptr->type()) {
12039 // use unchecked object access
12040 ptr = &ptr->operator[](reference_token);
12041 break;
12042 }
12043
12045 if (reference_token == "-") {
12046 // explicitly treat "-" as index beyond the end
12047 ptr = &ptr->operator[](ptr->m_value.array->size());
12048 } else {
12049 // convert array index to number; unchecked access
12050 ptr = &ptr->operator[](array_index(reference_token));
12051 }
12052 break;
12053 }
12054
12063 default:
12064 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'",
12065 *ptr));
12066 }
12067 }
12068
12069 return *ptr;
12070 }
12071
12072 /*!
12073 @throw parse_error.106 if an array index begins with '0'
12074 @throw parse_error.109 if an array index was not a number
12075 @throw out_of_range.402 if the array index '-' is used
12076 @throw out_of_range.404 if the JSON pointer can not be resolved
12077 */
12079 {
12080 for (const auto& reference_token : reference_tokens) {
12081 switch (ptr->type()) {
12083 // note: at performs range check
12084 ptr = &ptr->at(reference_token);
12085 break;
12086 }
12087
12089 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) {
12090 // "-" always fails the range check
12092 402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range",
12093 *ptr));
12094 }
12095
12096 // note: at performs range check
12097 ptr = &ptr->at(array_index(reference_token));
12098 break;
12099 }
12100
12109 default:
12110 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'",
12111 *ptr));
12112 }
12113 }
12114
12115 return *ptr;
12116 }
12117
12118 /*!
12119 @brief return a const reference to the pointed to value
12120
12121 @param[in] ptr a JSON value
12122
12123 @return const reference to the JSON value pointed to by the JSON
12124 pointer
12125
12126 @throw parse_error.106 if an array index begins with '0'
12127 @throw parse_error.109 if an array index was not a number
12128 @throw out_of_range.402 if the array index '-' is used
12129 @throw out_of_range.404 if the JSON pointer can not be resolved
12130 */
12132 {
12133 for (const auto& reference_token : reference_tokens) {
12134 switch (ptr->type()) {
12136 // use unchecked object access
12137 ptr = &ptr->operator[](reference_token);
12138 break;
12139 }
12140
12142 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) {
12143 // "-" cannot be used for const access
12145 402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range",
12146 *ptr));
12147 }
12148
12149 // use unchecked array access
12150 ptr = &ptr->operator[](array_index(reference_token));
12151 break;
12152 }
12153
12162 default:
12163 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'",
12164 *ptr));
12165 }
12166 }
12167
12168 return *ptr;
12169 }
12170
12171 /*!
12172 @throw parse_error.106 if an array index begins with '0'
12173 @throw parse_error.109 if an array index was not a number
12174 @throw out_of_range.402 if the array index '-' is used
12175 @throw out_of_range.404 if the JSON pointer can not be resolved
12176 */
12177 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
12178 {
12179 for (const auto& reference_token : reference_tokens) {
12180 switch (ptr->type()) {
12182 // note: at performs range check
12183 ptr = &ptr->at(reference_token);
12184 break;
12185 }
12186
12188 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) {
12189 // "-" always fails the range check
12191 402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range",
12192 *ptr));
12193 }
12194
12195 // note: at performs range check
12196 ptr = &ptr->at(array_index(reference_token));
12197 break;
12198 }
12199
12208 default:
12209 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'",
12210 *ptr));
12211 }
12212 }
12213
12214 return *ptr;
12215 }
12216
12217 /*!
12218 @throw parse_error.106 if an array index begins with '0'
12219 @throw parse_error.109 if an array index was not a number
12220 */
12221 bool contains(const BasicJsonType* ptr) const
12222 {
12223 for (const auto& reference_token : reference_tokens) {
12224 switch (ptr->type()) {
12226 if (!ptr->contains(reference_token)) {
12227 // we did not find the key in the object
12228 return false;
12229 }
12230
12231 ptr = &ptr->operator[](reference_token);
12232 break;
12233 }
12234
12236 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) {
12237 // "-" always fails the range check
12238 return false;
12239 }
12240 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1
12241 && !("0" <= reference_token && reference_token <= "9")))
12242 {
12243 // invalid char
12244 return false;
12245 }
12246 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) {
12247 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) {
12248 // first char should be between '1' and '9'
12249 return false;
12250 }
12251 for (std::size_t i = 1; i < reference_token.size(); i++) {
12252 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) {
12253 // other char should be between '0' and '9'
12254 return false;
12255 }
12256 }
12257 }
12258
12259 const auto idx = array_index(reference_token);
12260 if (idx >= ptr->size()) {
12261 // index out of range
12262 return false;
12263 }
12264
12265 ptr = &ptr->operator[](idx);
12266 break;
12267 }
12268
12277 default: {
12278 // we do not expect primitive values if there is still a
12279 // reference token to process
12280 return false;
12281 }
12282 }
12283 }
12284
12285 // no reference token left means we found a primitive value
12286 return true;
12287 }
12288
12289 /*!
12290 @brief split the string input to reference tokens
12291
12292 @note This function is only called by the json_pointer constructor.
12293 All exceptions below are documented there.
12294
12295 @throw parse_error.107 if the pointer is not empty or begins with '/'
12296 @throw parse_error.108 if character '~' is not followed by '0' or '1'
12297 */
12298 static std::vector<std::string> split(const std::string& reference_string)
12299 {
12300 std::vector<std::string> result;
12301
12302 // special case: empty reference string -> no reference tokens
12303 if (reference_string.empty()) {
12304 return result;
12305 }
12306
12307 // check if nonempty reference string begins with slash
12308 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) {
12310 107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'",
12311 BasicJsonType()));
12312 }
12313
12314 // extract the reference tokens:
12315 // - slash: position of the last read slash (or end of string)
12316 // - start: position after the previous slash
12317 for (
12318 // search for the first slash after the first character
12319 std::size_t slash = reference_string.find_first_of('/', 1),
12320 // set the beginning of the first reference token
12321 start = 1;
12322 // we can stop if start == 0 (if slash == std::string::npos)
12323 start != 0;
12324 // set the beginning of the next reference token
12325 // (will eventually be 0 if slash == std::string::npos)
12326 start = (slash == std::string::npos) ? 0 : slash + 1,
12327 // find next slash
12328 slash = reference_string.find_first_of('/', start))
12329 {
12330 // use the text between the beginning of the reference token
12331 // (start) and the last slash (slash).
12332 auto reference_token = reference_string.substr(start, slash - start);
12333
12334 // check reference tokens are properly escaped
12335 for (std::size_t pos = reference_token.find_first_of('~'); pos != std::string::npos;
12336 pos = reference_token.find_first_of('~', pos + 1))
12337 {
12338 JSON_ASSERT(reference_token[pos] == '~');
12339
12340 // ~ must be followed by 0 or 1
12341 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1
12342 || (reference_token[pos + 1] != '0' && reference_token[pos + 1] != '1')))
12343 {
12345 108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType()));
12346 }
12347 }
12348
12349 // finally, store the reference token
12350 detail::unescape(reference_token);
12351 result.push_back(reference_token);
12352 }
12353
12354 return result;
12355 }
12356
12357 private:
12358 /*!
12359 @param[in] reference_string the reference string to the current value
12360 @param[in] value the value to consider
12361 @param[in,out] result the result object to insert values to
12362
12363 @note Empty objects or arrays are flattened to `null`.
12364 */
12365 static void flatten(const std::string& reference_string, const BasicJsonType& value, BasicJsonType& result)
12366 {
12367 switch (value.type()) {
12369 if (value.m_value.array->empty()) {
12370 // flatten empty array as null
12371 result[reference_string] = nullptr;
12372 } else {
12373 // iterate array and use index as reference string
12374 for (std::size_t i = 0; i < value.m_value.array->size(); ++i) {
12375 flatten(reference_string + "/" + std::to_string(i), value.m_value.array->operator[](i), result);
12376 }
12377 }
12378 break;
12379 }
12380
12382 if (value.m_value.object->empty()) {
12383 // flatten empty object as null
12384 result[reference_string] = nullptr;
12385 } else {
12386 // iterate object and use keys as reference string
12387 for (const auto& element : *value.m_value.object) {
12388 flatten(reference_string + "/" + detail::escape(element.first), element.second, result);
12389 }
12390 }
12391 break;
12392 }
12393
12402 default: {
12403 // add primitive value with its reference string
12404 result[reference_string] = value;
12405 break;
12406 }
12407 }
12408 }
12409
12410 /*!
12411 @param[in] value flattened JSON
12412
12413 @return unflattened JSON
12414
12415 @throw parse_error.109 if array index is not a number
12416 @throw type_error.314 if value is not an object
12417 @throw type_error.315 if object values are not primitive
12418 @throw type_error.313 if value cannot be unflattened
12419 */
12421 {
12422 if (JSON_HEDLEY_UNLIKELY(!value.is_object())) {
12423 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value));
12424 }
12425
12427
12428 // iterate the JSON object values
12429 for (const auto& element : *value.m_value.object) {
12430 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) {
12431 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second));
12432 }
12433
12434 // assign value to reference pointed to by JSON pointer; Note that if
12435 // the JSON pointer is "" (i.e., points to the whole value), function
12436 // get_and_create returns a reference to result itself. An assignment
12437 // will then create a primitive value.
12438 json_pointer(element.first).get_and_create(result) = element.second;
12439 }
12440
12441 return result;
12442 }
12443
12444 /*!
12445 @brief compares two JSON pointers for equality
12446
12447 @param[in] lhs JSON pointer to compare
12448 @param[in] rhs JSON pointer to compare
12449 @return whether @a lhs is equal to @a rhs
12450
12451 @complexity Linear in the length of the JSON pointer
12452
12453 @exceptionsafety No-throw guarantee: this function never throws exceptions.
12454 */
12455 friend bool operator==(json_pointer const& lhs, json_pointer const& rhs) noexcept
12456 {
12457 return lhs.reference_tokens == rhs.reference_tokens;
12458 }
12459
12460 /*!
12461 @brief compares two JSON pointers for inequality
12462
12463 @param[in] lhs JSON pointer to compare
12464 @param[in] rhs JSON pointer to compare
12465 @return whether @a lhs is not equal @a rhs
12466
12467 @complexity Linear in the length of the JSON pointer
12468
12469 @exceptionsafety No-throw guarantee: this function never throws exceptions.
12470 */
12471 friend bool operator!=(json_pointer const& lhs, json_pointer const& rhs) noexcept { return !(lhs == rhs); }
12472
12473 /// the reference tokens
12474 std::vector<std::string> reference_tokens;
12475};
12476} // namespace nlohmann
12477
12478// #include <nlohmann/detail/json_ref.hpp>
12479
12480#include <initializer_list>
12481#include <utility>
12482
12483// #include <nlohmann/detail/meta/type_traits.hpp>
12484
12485namespace nlohmann
12486{
12487namespace detail
12488{
12489template<typename BasicJsonType>
12491{
12492 public:
12494
12496 : owned_value(std::move(value))
12497 {}
12498
12500 : value_ref(&value)
12501 {}
12502
12503 json_ref(std::initializer_list<json_ref> init)
12504 : owned_value(init)
12505 {}
12506
12507 template<class... Args, enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0>
12508 json_ref(Args&&... args)
12509 : owned_value(std::forward<Args>(args)...)
12510 {}
12511
12512 // class should be movable only
12513 json_ref(json_ref&&) noexcept = default;
12514 json_ref(const json_ref&) = delete;
12515 json_ref& operator=(const json_ref&) = delete;
12516 json_ref& operator=(json_ref&&) = delete;
12517 ~json_ref() = default;
12518
12520 {
12521 if (value_ref == nullptr) {
12522 return std::move(owned_value);
12523 }
12524 return *value_ref;
12525 }
12526
12527 value_type const& operator*() const { return value_ref ? *value_ref : owned_value; }
12528
12529 value_type const* operator->() const { return &**this; }
12530
12531 private:
12532 mutable value_type owned_value = nullptr;
12533 value_type const* value_ref = nullptr;
12534};
12535} // namespace detail
12536} // namespace nlohmann
12537
12538// #include <nlohmann/detail/macro_scope.hpp>
12539
12540// #include <nlohmann/detail/string_escape.hpp>
12541
12542// #include <nlohmann/detail/meta/cpp_future.hpp>
12543
12544// #include <nlohmann/detail/meta/type_traits.hpp>
12545
12546// #include <nlohmann/detail/output/binary_writer.hpp>
12547
12548#include <algorithm> // reverse
12549#include <array> // array
12550#include <cmath> // isnan, isinf
12551#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
12552#include <cstring> // memcpy
12553#include <limits> // numeric_limits
12554#include <string> // string
12555#include <utility> // move
12556
12557// #include <nlohmann/detail/input/binary_reader.hpp>
12558
12559// #include <nlohmann/detail/macro_scope.hpp>
12560
12561// #include <nlohmann/detail/output/output_adapters.hpp>
12562
12563#include <algorithm> // copy
12564#include <cstddef> // size_t
12565#include <iterator> // back_inserter
12566#include <memory> // shared_ptr, make_shared
12567#include <string> // basic_string
12568#include <vector> // vector
12569
12570#ifndef JSON_NO_IO
12571#include <ios> // streamsize
12572#include <ostream> // basic_ostream
12573#endif // JSON_NO_IO
12574
12575// #include <nlohmann/detail/macro_scope.hpp>
12576
12577namespace nlohmann
12578{
12579namespace detail
12580{
12581/// abstract output adapter interface
12582template<typename CharType>
12584{
12585 virtual void write_character(CharType c) = 0;
12586 virtual void write_characters(const CharType* s, std::size_t length) = 0;
12587 virtual ~output_adapter_protocol() = default;
12588
12593 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
12594};
12595
12596/// a type to simplify interfaces
12597template<typename CharType>
12598using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
12599
12600/// output adapter for byte vectors
12601template<typename CharType, typename AllocatorType = std::allocator<CharType>>
12603{
12604 public:
12605 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
12606 : v(vec)
12607 {}
12608
12609 void write_character(CharType c) override { v.push_back(c); }
12610
12612 void write_characters(const CharType* s, std::size_t length) override
12613 {
12614 std::copy(s, s + length, std::back_inserter(v));
12615 }
12616
12617 private:
12618 std::vector<CharType, AllocatorType>& v;
12619};
12620
12621#ifndef JSON_NO_IO
12622/// output adapter for output streams
12623template<typename CharType>
12625{
12626 public:
12627 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
12628 : stream(s)
12629 {}
12630
12631 void write_character(CharType c) override { stream.put(c); }
12632
12634 void write_characters(const CharType* s, std::size_t length) override
12635 {
12636 stream.write(s, static_cast<std::streamsize>(length));
12637 }
12638
12639 private:
12640 std::basic_ostream<CharType>& stream;
12641};
12642#endif // JSON_NO_IO
12643
12644/// output adapter for basic_string
12645template<typename CharType, typename StringType = std::basic_string<CharType>>
12647{
12648 public:
12649 explicit output_string_adapter(StringType& s) noexcept
12650 : str(s)
12651 {}
12652
12653 void write_character(CharType c) override { str.push_back(c); }
12654
12656 void write_characters(const CharType* s, std::size_t length) override { str.append(s, length); }
12657
12658 private:
12660};
12661
12662template<typename CharType, typename StringType = std::basic_string<CharType>>
12664{
12665 public:
12666 template<typename AllocatorType = std::allocator<CharType>>
12667 output_adapter(std::vector<CharType, AllocatorType>& vec)
12668 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec))
12669 {}
12670
12671#ifndef JSON_NO_IO
12672 output_adapter(std::basic_ostream<CharType>& s)
12673 : oa(std::make_shared<output_stream_adapter<CharType>>(s))
12674 {}
12675#endif // JSON_NO_IO
12676
12678 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s))
12679 {}
12680
12681 operator output_adapter_t<CharType>() { return oa; }
12682
12683 private:
12685};
12686} // namespace detail
12687} // namespace nlohmann
12688
12689namespace nlohmann
12690{
12691namespace detail
12692{
12693///////////////////
12694// binary writer //
12695///////////////////
12696
12697/*!
12698@brief serialization to CBOR and MessagePack values
12699*/
12700template<typename BasicJsonType, typename CharType>
12702{
12703 using string_t = typename BasicJsonType::string_t;
12704 using binary_t = typename BasicJsonType::binary_t;
12705 using number_float_t = typename BasicJsonType::number_float_t;
12706
12707 public:
12708 /*!
12709 @brief create a binary writer
12710
12711 @param[in] adapter output adapter to write to
12712 */
12714 : oa(std::move(adapter))
12715 {
12716 JSON_ASSERT(oa);
12717 }
12718
12719 /*!
12720 @param[in] j JSON value to serialize
12721 @pre j.type() == value_t::object
12722 */
12724 {
12725 switch (j.type()) {
12726 case value_t::object: {
12727 write_bson_object(*j.m_value.object);
12728 break;
12729 }
12730
12731 case value_t::null:
12732 case value_t::array:
12733 case value_t::string:
12734 case value_t::boolean:
12738 case value_t::binary:
12739 case value_t::discarded:
12740 default: {
12742 317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()),
12743 j));
12744 }
12745 }
12746 }
12747
12748 /*!
12749 @param[in] j JSON value to serialize
12750 */
12752 {
12753 switch (j.type()) {
12754 case value_t::null: {
12755 oa->write_character(to_char_type(0xF6));
12756 break;
12757 }
12758
12759 case value_t::boolean: {
12760 oa->write_character(j.m_value.boolean ? to_char_type(0xF5) : to_char_type(0xF4));
12761 break;
12762 }
12763
12765 if (j.m_value.number_integer >= 0) {
12766 // CBOR does not differentiate between positive signed
12767 // integers and unsigned integers. Therefore, we used the
12768 // code from the value_t::number_unsigned case here.
12769 if (j.m_value.number_integer <= 0x17) {
12770 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
12771 } else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)()) {
12772 oa->write_character(to_char_type(0x18));
12773 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
12774 } else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()) {
12775 oa->write_character(to_char_type(0x19));
12776 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
12777 } else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()) {
12778 oa->write_character(to_char_type(0x1A));
12779 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
12780 } else {
12781 oa->write_character(to_char_type(0x1B));
12782 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
12783 }
12784 } else {
12785 // The conversions below encode the sign in the first
12786 // byte, and the value is converted to a positive number.
12787 const auto positive_number = -1 - j.m_value.number_integer;
12788 if (j.m_value.number_integer >= -24) {
12789 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
12790 } else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)()) {
12791 oa->write_character(to_char_type(0x38));
12792 write_number(static_cast<std::uint8_t>(positive_number));
12793 } else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)()) {
12794 oa->write_character(to_char_type(0x39));
12795 write_number(static_cast<std::uint16_t>(positive_number));
12796 } else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)()) {
12797 oa->write_character(to_char_type(0x3A));
12798 write_number(static_cast<std::uint32_t>(positive_number));
12799 } else {
12800 oa->write_character(to_char_type(0x3B));
12801 write_number(static_cast<std::uint64_t>(positive_number));
12802 }
12803 }
12804 break;
12805 }
12806
12808 if (j.m_value.number_unsigned <= 0x17) {
12809 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
12810 } else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) {
12811 oa->write_character(to_char_type(0x18));
12812 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
12813 } else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) {
12814 oa->write_character(to_char_type(0x19));
12815 write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
12816 } else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) {
12817 oa->write_character(to_char_type(0x1A));
12818 write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
12819 } else {
12820 oa->write_character(to_char_type(0x1B));
12821 write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
12822 }
12823 break;
12824 }
12825
12826 case value_t::number_float: {
12827 if (std::isnan(j.m_value.number_float)) {
12828 // NaN is 0xf97e00 in CBOR
12829 oa->write_character(to_char_type(0xF9));
12830 oa->write_character(to_char_type(0x7E));
12831 oa->write_character(to_char_type(0x00));
12832 } else if (std::isinf(j.m_value.number_float)) {
12833 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
12834 oa->write_character(to_char_type(0xf9));
12835 oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
12836 oa->write_character(to_char_type(0x00));
12837 } else {
12838 write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
12839 }
12840 break;
12841 }
12842
12843 case value_t::string: {
12844 // step 1: write control byte and the string length
12845 const auto N = j.m_value.string->size();
12846 if (N <= 0x17) {
12847 write_number(static_cast<std::uint8_t>(0x60 + N));
12848 } else if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
12849 oa->write_character(to_char_type(0x78));
12850 write_number(static_cast<std::uint8_t>(N));
12851 } else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
12852 oa->write_character(to_char_type(0x79));
12853 write_number(static_cast<std::uint16_t>(N));
12854 } else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
12855 oa->write_character(to_char_type(0x7A));
12856 write_number(static_cast<std::uint32_t>(N));
12857 }
12858 // LCOV_EXCL_START
12859 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
12860 {
12861 oa->write_character(to_char_type(0x7B));
12862 write_number(static_cast<std::uint64_t>(N));
12863 }
12864 // LCOV_EXCL_STOP
12865
12866 // step 2: write the string
12867 oa->write_characters(reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
12868 j.m_value.string->size());
12869 break;
12870 }
12871
12872 case value_t::array: {
12873 // step 1: write control byte and the array size
12874 const auto N = j.m_value.array->size();
12875 if (N <= 0x17) {
12876 write_number(static_cast<std::uint8_t>(0x80 + N));
12877 } else if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
12878 oa->write_character(to_char_type(0x98));
12879 write_number(static_cast<std::uint8_t>(N));
12880 } else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
12881 oa->write_character(to_char_type(0x99));
12882 write_number(static_cast<std::uint16_t>(N));
12883 } else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
12884 oa->write_character(to_char_type(0x9A));
12885 write_number(static_cast<std::uint32_t>(N));
12886 }
12887 // LCOV_EXCL_START
12888 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
12889 {
12890 oa->write_character(to_char_type(0x9B));
12891 write_number(static_cast<std::uint64_t>(N));
12892 }
12893 // LCOV_EXCL_STOP
12894
12895 // step 2: write each element
12896 for (const auto& el : *j.m_value.array) {
12897 write_cbor(el);
12898 }
12899 break;
12900 }
12901
12902 case value_t::binary: {
12903 if (j.m_value.binary->has_subtype()) {
12904 if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)()) {
12905 write_number(static_cast<std::uint8_t>(0xd8));
12906 write_number(static_cast<std::uint8_t>(j.m_value.binary->subtype()));
12907 } else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)()) {
12908 write_number(static_cast<std::uint8_t>(0xd9));
12909 write_number(static_cast<std::uint16_t>(j.m_value.binary->subtype()));
12910 } else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)()) {
12911 write_number(static_cast<std::uint8_t>(0xda));
12912 write_number(static_cast<std::uint32_t>(j.m_value.binary->subtype()));
12913 } else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)()) {
12914 write_number(static_cast<std::uint8_t>(0xdb));
12915 write_number(static_cast<std::uint64_t>(j.m_value.binary->subtype()));
12916 }
12917 }
12918
12919 // step 1: write control byte and the binary array size
12920 const auto N = j.m_value.binary->size();
12921 if (N <= 0x17) {
12922 write_number(static_cast<std::uint8_t>(0x40 + N));
12923 } else if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
12924 oa->write_character(to_char_type(0x58));
12925 write_number(static_cast<std::uint8_t>(N));
12926 } else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
12927 oa->write_character(to_char_type(0x59));
12928 write_number(static_cast<std::uint16_t>(N));
12929 } else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
12930 oa->write_character(to_char_type(0x5A));
12931 write_number(static_cast<std::uint32_t>(N));
12932 }
12933 // LCOV_EXCL_START
12934 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
12935 {
12936 oa->write_character(to_char_type(0x5B));
12937 write_number(static_cast<std::uint64_t>(N));
12938 }
12939 // LCOV_EXCL_STOP
12940
12941 // step 2: write each element
12942 oa->write_characters(reinterpret_cast<const CharType*>(j.m_value.binary->data()), N);
12943
12944 break;
12945 }
12946
12947 case value_t::object: {
12948 // step 1: write control byte and the object size
12949 const auto N = j.m_value.object->size();
12950 if (N <= 0x17) {
12951 write_number(static_cast<std::uint8_t>(0xA0 + N));
12952 } else if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
12953 oa->write_character(to_char_type(0xB8));
12954 write_number(static_cast<std::uint8_t>(N));
12955 } else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
12956 oa->write_character(to_char_type(0xB9));
12957 write_number(static_cast<std::uint16_t>(N));
12958 } else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
12959 oa->write_character(to_char_type(0xBA));
12960 write_number(static_cast<std::uint32_t>(N));
12961 }
12962 // LCOV_EXCL_START
12963 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
12964 {
12965 oa->write_character(to_char_type(0xBB));
12966 write_number(static_cast<std::uint64_t>(N));
12967 }
12968 // LCOV_EXCL_STOP
12969
12970 // step 2: write each element
12971 for (const auto& el : *j.m_value.object) {
12972 write_cbor(el.first);
12973 write_cbor(el.second);
12974 }
12975 break;
12976 }
12977
12978 case value_t::discarded:
12979 default:
12980 break;
12981 }
12982 }
12983
12984 /*!
12985 @param[in] j JSON value to serialize
12986 */
12988 {
12989 switch (j.type()) {
12990 case value_t::null: // nil
12991 {
12992 oa->write_character(to_char_type(0xC0));
12993 break;
12994 }
12995
12996 case value_t::boolean: // true and false
12997 {
12998 oa->write_character(j.m_value.boolean ? to_char_type(0xC3) : to_char_type(0xC2));
12999 break;
13000 }
13001
13003 if (j.m_value.number_integer >= 0) {
13004 // MessagePack does not differentiate between positive
13005 // signed integers and unsigned integers. Therefore, we used
13006 // the code from the value_t::number_unsigned case here.
13007 if (j.m_value.number_unsigned < 128) {
13008 // positive fixnum
13009 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13010 } else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) {
13011 // uint 8
13012 oa->write_character(to_char_type(0xCC));
13013 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13014 } else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) {
13015 // uint 16
13016 oa->write_character(to_char_type(0xCD));
13017 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13018 } else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) {
13019 // uint 32
13020 oa->write_character(to_char_type(0xCE));
13021 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13022 } else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) {
13023 // uint 64
13024 oa->write_character(to_char_type(0xCF));
13025 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13026 }
13027 } else {
13028 if (j.m_value.number_integer >= -32) {
13029 // negative fixnum
13030 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
13031 } else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)()
13032 && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
13033 {
13034 // int 8
13035 oa->write_character(to_char_type(0xD0));
13036 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
13037 } else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)()
13038 && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
13039 {
13040 // int 16
13041 oa->write_character(to_char_type(0xD1));
13042 write_number(static_cast<std::int16_t>(j.m_value.number_integer));
13043 } else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)()
13044 && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
13045 {
13046 // int 32
13047 oa->write_character(to_char_type(0xD2));
13048 write_number(static_cast<std::int32_t>(j.m_value.number_integer));
13049 } else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)()
13050 && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
13051 {
13052 // int 64
13053 oa->write_character(to_char_type(0xD3));
13054 write_number(static_cast<std::int64_t>(j.m_value.number_integer));
13055 }
13056 }
13057 break;
13058 }
13059
13061 if (j.m_value.number_unsigned < 128) {
13062 // positive fixnum
13063 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13064 } else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) {
13065 // uint 8
13066 oa->write_character(to_char_type(0xCC));
13067 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13068 } else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) {
13069 // uint 16
13070 oa->write_character(to_char_type(0xCD));
13071 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13072 } else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) {
13073 // uint 32
13074 oa->write_character(to_char_type(0xCE));
13075 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13076 } else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) {
13077 // uint 64
13078 oa->write_character(to_char_type(0xCF));
13079 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13080 }
13081 break;
13082 }
13083
13084 case value_t::number_float: {
13086 break;
13087 }
13088
13089 case value_t::string: {
13090 // step 1: write control byte and the string length
13091 const auto N = j.m_value.string->size();
13092 if (N <= 31) {
13093 // fixstr
13094 write_number(static_cast<std::uint8_t>(0xA0 | N));
13095 } else if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
13096 // str 8
13097 oa->write_character(to_char_type(0xD9));
13098 write_number(static_cast<std::uint8_t>(N));
13099 } else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
13100 // str 16
13101 oa->write_character(to_char_type(0xDA));
13102 write_number(static_cast<std::uint16_t>(N));
13103 } else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
13104 // str 32
13105 oa->write_character(to_char_type(0xDB));
13106 write_number(static_cast<std::uint32_t>(N));
13107 }
13108
13109 // step 2: write the string
13110 oa->write_characters(reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
13111 j.m_value.string->size());
13112 break;
13113 }
13114
13115 case value_t::array: {
13116 // step 1: write control byte and the array size
13117 const auto N = j.m_value.array->size();
13118 if (N <= 15) {
13119 // fixarray
13120 write_number(static_cast<std::uint8_t>(0x90 | N));
13121 } else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
13122 // array 16
13123 oa->write_character(to_char_type(0xDC));
13124 write_number(static_cast<std::uint16_t>(N));
13125 } else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
13126 // array 32
13127 oa->write_character(to_char_type(0xDD));
13128 write_number(static_cast<std::uint32_t>(N));
13129 }
13130
13131 // step 2: write each element
13132 for (const auto& el : *j.m_value.array) {
13133 write_msgpack(el);
13134 }
13135 break;
13136 }
13137
13138 case value_t::binary: {
13139 // step 0: determine if the binary type has a set subtype to
13140 // determine whether or not to use the ext or fixext types
13141 const bool use_ext = j.m_value.binary->has_subtype();
13142
13143 // step 1: write control byte and the byte string length
13144 const auto N = j.m_value.binary->size();
13145 if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
13146 std::uint8_t output_type{};
13147 bool fixed = true;
13148 if (use_ext) {
13149 switch (N) {
13150 case 1:
13151 output_type = 0xD4; // fixext 1
13152 break;
13153 case 2:
13154 output_type = 0xD5; // fixext 2
13155 break;
13156 case 4:
13157 output_type = 0xD6; // fixext 4
13158 break;
13159 case 8:
13160 output_type = 0xD7; // fixext 8
13161 break;
13162 case 16:
13163 output_type = 0xD8; // fixext 16
13164 break;
13165 default:
13166 output_type = 0xC7; // ext 8
13167 fixed = false;
13168 break;
13169 }
13170
13171 } else {
13172 output_type = 0xC4; // bin 8
13173 fixed = false;
13174 }
13175
13176 oa->write_character(to_char_type(output_type));
13177 if (!fixed) {
13178 write_number(static_cast<std::uint8_t>(N));
13179 }
13180 } else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
13181 std::uint8_t output_type = use_ext ? 0xC8 // ext 16
13182 : 0xC5; // bin 16
13183
13184 oa->write_character(to_char_type(output_type));
13185 write_number(static_cast<std::uint16_t>(N));
13186 } else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
13187 std::uint8_t output_type = use_ext ? 0xC9 // ext 32
13188 : 0xC6; // bin 32
13189
13190 oa->write_character(to_char_type(output_type));
13191 write_number(static_cast<std::uint32_t>(N));
13192 }
13193
13194 // step 1.5: if this is an ext type, write the subtype
13195 if (use_ext) {
13196 write_number(static_cast<std::int8_t>(j.m_value.binary->subtype()));
13197 }
13198
13199 // step 2: write the byte string
13200 oa->write_characters(reinterpret_cast<const CharType*>(j.m_value.binary->data()), N);
13201
13202 break;
13203 }
13204
13205 case value_t::object: {
13206 // step 1: write control byte and the object size
13207 const auto N = j.m_value.object->size();
13208 if (N <= 15) {
13209 // fixmap
13210 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
13211 } else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
13212 // map 16
13213 oa->write_character(to_char_type(0xDE));
13214 write_number(static_cast<std::uint16_t>(N));
13215 } else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
13216 // map 32
13217 oa->write_character(to_char_type(0xDF));
13218 write_number(static_cast<std::uint32_t>(N));
13219 }
13220
13221 // step 2: write each element
13222 for (const auto& el : *j.m_value.object) {
13223 write_msgpack(el.first);
13224 write_msgpack(el.second);
13225 }
13226 break;
13227 }
13228
13229 case value_t::discarded:
13230 default:
13231 break;
13232 }
13233 }
13234
13235 /*!
13236 @param[in] j JSON value to serialize
13237 @param[in] use_count whether to use '#' prefixes (optimized format)
13238 @param[in] use_type whether to use '$' prefixes (optimized format)
13239 @param[in] add_prefix whether prefixes need to be used for this value
13240 */
13241 void write_ubjson(const BasicJsonType& j, const bool use_count, const bool use_type, const bool add_prefix = true)
13242 {
13243 switch (j.type()) {
13244 case value_t::null: {
13245 if (add_prefix) {
13246 oa->write_character(to_char_type('Z'));
13247 }
13248 break;
13249 }
13250
13251 case value_t::boolean: {
13252 if (add_prefix) {
13253 oa->write_character(j.m_value.boolean ? to_char_type('T') : to_char_type('F'));
13254 }
13255 break;
13256 }
13257
13259 write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
13260 break;
13261 }
13262
13264 write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
13265 break;
13266 }
13267
13268 case value_t::number_float: {
13269 write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
13270 break;
13271 }
13272
13273 case value_t::string: {
13274 if (add_prefix) {
13275 oa->write_character(to_char_type('S'));
13276 }
13277 write_number_with_ubjson_prefix(j.m_value.string->size(), true);
13278 oa->write_characters(reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
13279 j.m_value.string->size());
13280 break;
13281 }
13282
13283 case value_t::array: {
13284 if (add_prefix) {
13285 oa->write_character(to_char_type('['));
13286 }
13287
13288 bool prefix_required = true;
13289 if (use_type && !j.m_value.array->empty()) {
13290 JSON_ASSERT(use_count);
13291 const CharType first_prefix = ubjson_prefix(j.front());
13292 const bool same_prefix =
13293 std::all_of(j.begin() + 1, j.end(), [this, first_prefix](const BasicJsonType& v) {
13294 return ubjson_prefix(v) == first_prefix;
13295 });
13296
13297 if (same_prefix) {
13298 prefix_required = false;
13299 oa->write_character(to_char_type('$'));
13300 oa->write_character(first_prefix);
13301 }
13302 }
13303
13304 if (use_count) {
13305 oa->write_character(to_char_type('#'));
13306 write_number_with_ubjson_prefix(j.m_value.array->size(), true);
13307 }
13308
13309 for (const auto& el : *j.m_value.array) {
13310 write_ubjson(el, use_count, use_type, prefix_required);
13311 }
13312
13313 if (!use_count) {
13314 oa->write_character(to_char_type(']'));
13315 }
13316
13317 break;
13318 }
13319
13320 case value_t::binary: {
13321 if (add_prefix) {
13322 oa->write_character(to_char_type('['));
13323 }
13324
13325 if (use_type && !j.m_value.binary->empty()) {
13326 JSON_ASSERT(use_count);
13327 oa->write_character(to_char_type('$'));
13328 oa->write_character('U');
13329 }
13330
13331 if (use_count) {
13332 oa->write_character(to_char_type('#'));
13333 write_number_with_ubjson_prefix(j.m_value.binary->size(), true);
13334 }
13335
13336 if (use_type) {
13337 oa->write_characters(reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13338 j.m_value.binary->size());
13339 } else {
13340 for (size_t i = 0; i < j.m_value.binary->size(); ++i) {
13341 oa->write_character(to_char_type('U'));
13342 oa->write_character(j.m_value.binary->data()[i]);
13343 }
13344 }
13345
13346 if (!use_count) {
13347 oa->write_character(to_char_type(']'));
13348 }
13349
13350 break;
13351 }
13352
13353 case value_t::object: {
13354 if (add_prefix) {
13355 oa->write_character(to_char_type('{'));
13356 }
13357
13358 bool prefix_required = true;
13359 if (use_type && !j.m_value.object->empty()) {
13360 JSON_ASSERT(use_count);
13361 const CharType first_prefix = ubjson_prefix(j.front());
13362 const bool same_prefix =
13363 std::all_of(j.begin(), j.end(), [this, first_prefix](const BasicJsonType& v) {
13364 return ubjson_prefix(v) == first_prefix;
13365 });
13366
13367 if (same_prefix) {
13368 prefix_required = false;
13369 oa->write_character(to_char_type('$'));
13370 oa->write_character(first_prefix);
13371 }
13372 }
13373
13374 if (use_count) {
13375 oa->write_character(to_char_type('#'));
13376 write_number_with_ubjson_prefix(j.m_value.object->size(), true);
13377 }
13378
13379 for (const auto& el : *j.m_value.object) {
13380 write_number_with_ubjson_prefix(el.first.size(), true);
13381 oa->write_characters(reinterpret_cast<const CharType*>(el.first.c_str()), el.first.size());
13382 write_ubjson(el.second, use_count, use_type, prefix_required);
13383 }
13384
13385 if (!use_count) {
13386 oa->write_character(to_char_type('}'));
13387 }
13388
13389 break;
13390 }
13391
13392 case value_t::discarded:
13393 default:
13394 break;
13395 }
13396 }
13397
13398 private:
13399 //////////
13400 // BSON //
13401 //////////
13402
13403 /*!
13404 @return The size of a BSON document entry header, including the id marker
13405 and the entry name size (and its null-terminator).
13406 */
13407 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
13408 {
13409 const auto it = name.find(static_cast<typename string_t::value_type>(0));
13410 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) {
13412 409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j));
13413 static_cast<void>(j);
13414 }
13415
13416 return /*id*/ 1ul + name.size() + /*zero-terminator*/ 1u;
13417 }
13418
13419 /*!
13420 @brief Writes the given @a element_type and @a name to the output adapter
13421 */
13422 void write_bson_entry_header(const string_t& name, const std::uint8_t element_type)
13423 {
13424 oa->write_character(to_char_type(element_type)); // boolean
13425 oa->write_characters(reinterpret_cast<const CharType*>(name.c_str()), name.size() + 1u);
13426 }
13427
13428 /*!
13429 @brief Writes a BSON element with key @a name and boolean value @a value
13430 */
13431 void write_bson_boolean(const string_t& name, const bool value)
13432 {
13433 write_bson_entry_header(name, 0x08);
13434 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
13435 }
13436
13437 /*!
13438 @brief Writes a BSON element with key @a name and double value @a value
13439 */
13440 void write_bson_double(const string_t& name, const double value)
13441 {
13442 write_bson_entry_header(name, 0x01);
13444 }
13445
13446 /*!
13447 @return The size of the BSON-encoded string in @a value
13448 */
13449 static std::size_t calc_bson_string_size(const string_t& value)
13450 {
13451 return sizeof(std::int32_t) + value.size() + 1ul;
13452 }
13453
13454 /*!
13455 @brief Writes a BSON element with key @a name and string value @a value
13456 */
13457 void write_bson_string(const string_t& name, const string_t& value)
13458 {
13459 write_bson_entry_header(name, 0x02);
13460
13461 write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
13462 oa->write_characters(reinterpret_cast<const CharType*>(value.c_str()), value.size() + 1);
13463 }
13464
13465 /*!
13466 @brief Writes a BSON element with key @a name and null value
13467 */
13468 void write_bson_null(const string_t& name) { write_bson_entry_header(name, 0x0A); }
13469
13470 /*!
13471 @return The size of the BSON-encoded integer @a value
13472 */
13473 static std::size_t calc_bson_integer_size(const std::int64_t value)
13474 {
13475 return (std::numeric_limits<std::int32_t>::min)() <= value
13476 && value <= (std::numeric_limits<std::int32_t>::max)()
13477 ? sizeof(std::int32_t)
13478 : sizeof(std::int64_t);
13479 }
13480
13481 /*!
13482 @brief Writes a BSON element with key @a name and integer @a value
13483 */
13484 void write_bson_integer(const string_t& name, const std::int64_t value)
13485 {
13486 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
13487 {
13488 write_bson_entry_header(name, 0x10); // int32
13489 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
13490 } else {
13491 write_bson_entry_header(name, 0x12); // int64
13492 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
13493 }
13494 }
13495
13496 /*!
13497 @return The size of the BSON-encoded unsigned integer in @a j
13498 */
13499 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
13500 {
13501 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) ? sizeof(std::int32_t)
13502 : sizeof(std::int64_t);
13503 }
13504
13505 /*!
13506 @brief Writes a BSON element with key @a name and unsigned @a value
13507 */
13508 void write_bson_unsigned(const string_t& name, const BasicJsonType& j)
13509 {
13510 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) {
13511 write_bson_entry_header(name, 0x10 /* int32 */);
13512 write_number<std::int32_t, true>(static_cast<std::int32_t>(j.m_value.number_unsigned));
13513 } else if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
13514 {
13515 write_bson_entry_header(name, 0x12 /* int64 */);
13516 write_number<std::int64_t, true>(static_cast<std::int64_t>(j.m_value.number_unsigned));
13517 } else {
13519 "integer number " + std::to_string(j.m_value.number_unsigned)
13520 + " cannot be represented by BSON as it does not fit int64",
13521 j));
13522 }
13523 }
13524
13525 /*!
13526 @brief Writes a BSON element with key @a name and object @a value
13527 */
13528 void write_bson_object_entry(const string_t& name, const typename BasicJsonType::object_t& value)
13529 {
13530 write_bson_entry_header(name, 0x03); // object
13532 }
13533
13534 /*!
13535 @return The size of the BSON-encoded array @a value
13536 */
13537 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
13538 {
13539 std::size_t array_index = 0ul;
13540
13541 const std::size_t embedded_document_size =
13542 std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0),
13543 [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type& el) {
13544 return result + calc_bson_element_size(std::to_string(array_index++), el);
13545 });
13546
13547 return sizeof(std::int32_t) + embedded_document_size + 1ul;
13548 }
13549
13550 /*!
13551 @return The size of the BSON-encoded binary array @a value
13552 */
13553 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
13554 {
13555 return sizeof(std::int32_t) + value.size() + 1ul;
13556 }
13557
13558 /*!
13559 @brief Writes a BSON element with key @a name and array @a value
13560 */
13561 void write_bson_array(const string_t& name, const typename BasicJsonType::array_t& value)
13562 {
13563 write_bson_entry_header(name, 0x04); // array
13564 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
13565
13566 std::size_t array_index = 0ul;
13567
13568 for (const auto& el : value) {
13569 write_bson_element(std::to_string(array_index++), el);
13570 }
13571
13572 oa->write_character(to_char_type(0x00));
13573 }
13574
13575 /*!
13576 @brief Writes a BSON element with key @a name and binary value @a value
13577 */
13578 void write_bson_binary(const string_t& name, const binary_t& value)
13579 {
13580 write_bson_entry_header(name, 0x05);
13581
13582 write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
13583 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype())
13584 : static_cast<std::uint8_t>(0x00));
13585
13586 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
13587 }
13588
13589 /*!
13590 @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
13591 @return The calculated size for the BSON document entry for @a j with the given @a name.
13592 */
13593 static std::size_t calc_bson_element_size(const string_t& name, const BasicJsonType& j)
13594 {
13595 const auto header_size = calc_bson_entry_header_size(name, j);
13596 switch (j.type()) {
13597 case value_t::object:
13598 return header_size + calc_bson_object_size(*j.m_value.object);
13599
13600 case value_t::array:
13601 return header_size + calc_bson_array_size(*j.m_value.array);
13602
13603 case value_t::binary:
13604 return header_size + calc_bson_binary_size(*j.m_value.binary);
13605
13606 case value_t::boolean:
13607 return header_size + 1ul;
13608
13610 return header_size + 8ul;
13611
13613 return header_size + calc_bson_integer_size(j.m_value.number_integer);
13614
13616 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
13617
13618 case value_t::string:
13619 return header_size + calc_bson_string_size(*j.m_value.string);
13620
13621 case value_t::null:
13622 return header_size + 0ul;
13623
13624 // LCOV_EXCL_START
13625 case value_t::discarded:
13626 default:
13627 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
13628 return 0ul;
13629 // LCOV_EXCL_STOP
13630 }
13631 }
13632
13633 /*!
13634 @brief Serializes the JSON value @a j to BSON and associates it with the
13635 key @a name.
13636 @param name The name to associate with the JSON entity @a j within the
13637 current BSON document
13638 */
13639 void write_bson_element(const string_t& name, const BasicJsonType& j)
13640 {
13641 switch (j.type()) {
13642 case value_t::object:
13643 return write_bson_object_entry(name, *j.m_value.object);
13644
13645 case value_t::array:
13646 return write_bson_array(name, *j.m_value.array);
13647
13648 case value_t::binary:
13649 return write_bson_binary(name, *j.m_value.binary);
13650
13651 case value_t::boolean:
13652 return write_bson_boolean(name, j.m_value.boolean);
13653
13655 return write_bson_double(name, j.m_value.number_float);
13656
13658 return write_bson_integer(name, j.m_value.number_integer);
13659
13661 return write_bson_unsigned(name, j);
13662
13663 case value_t::string:
13664 return write_bson_string(name, *j.m_value.string);
13665
13666 case value_t::null:
13667 return write_bson_null(name);
13668
13669 // LCOV_EXCL_START
13670 case value_t::discarded:
13671 default:
13672 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
13673 return;
13674 // LCOV_EXCL_STOP
13675 }
13676 }
13677
13678 /*!
13679 @brief Calculates the size of the BSON serialization of the given
13680 JSON-object @a j.
13681 @param[in] value JSON value to serialize
13682 @pre value.type() == value_t::object
13683 */
13684 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
13685 {
13686 std::size_t document_size =
13687 std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
13688 [](size_t result, const typename BasicJsonType::object_t::value_type& el) {
13689 return result += calc_bson_element_size(el.first, el.second);
13690 });
13691
13692 return sizeof(std::int32_t) + document_size + 1ul;
13693 }
13694
13695 /*!
13696 @param[in] value JSON value to serialize
13697 @pre value.type() == value_t::object
13698 */
13699 void write_bson_object(const typename BasicJsonType::object_t& value)
13700 {
13702
13703 for (const auto& el : value) {
13704 write_bson_element(el.first, el.second);
13705 }
13706
13707 oa->write_character(to_char_type(0x00));
13708 }
13709
13710 //////////
13711 // CBOR //
13712 //////////
13713
13714 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
13715 {
13716 return to_char_type(0xFA); // Single-Precision Float
13717 }
13718
13719 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
13720 {
13721 return to_char_type(0xFB); // Double-Precision Float
13722 }
13723
13724 /////////////
13725 // MsgPack //
13726 /////////////
13727
13728 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
13729 {
13730 return to_char_type(0xCA); // float 32
13731 }
13732
13733 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
13734 {
13735 return to_char_type(0xCB); // float 64
13736 }
13737
13738 ////////////
13739 // UBJSON //
13740 ////////////
13741
13742 // UBJSON: write number (floating point)
13743 template<typename NumberType, typename std::enable_if<std::is_floating_point<NumberType>::value, int>::type = 0>
13744 void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix)
13745 {
13746 if (add_prefix) {
13747 oa->write_character(get_ubjson_float_prefix(n));
13748 }
13749 write_number(n);
13750 }
13751
13752 // UBJSON: write number (unsigned integer)
13753 template<typename NumberType, typename std::enable_if<std::is_unsigned<NumberType>::value, int>::type = 0>
13754 void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix)
13755 {
13756 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)())) {
13757 if (add_prefix) {
13758 oa->write_character(to_char_type('i')); // int8
13759 }
13760 write_number(static_cast<std::uint8_t>(n));
13761 } else if (n <= (std::numeric_limits<std::uint8_t>::max)()) {
13762 if (add_prefix) {
13763 oa->write_character(to_char_type('U')); // uint8
13764 }
13765 write_number(static_cast<std::uint8_t>(n));
13766 } else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)())) {
13767 if (add_prefix) {
13768 oa->write_character(to_char_type('I')); // int16
13769 }
13770 write_number(static_cast<std::int16_t>(n));
13771 } else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) {
13772 if (add_prefix) {
13773 oa->write_character(to_char_type('l')); // int32
13774 }
13775 write_number(static_cast<std::int32_t>(n));
13776 } else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) {
13777 if (add_prefix) {
13778 oa->write_character(to_char_type('L')); // int64
13779 }
13780 write_number(static_cast<std::int64_t>(n));
13781 } else {
13782 if (add_prefix) {
13783 oa->write_character(to_char_type('H')); // high-precision number
13784 }
13785
13786 const auto number = BasicJsonType(n).dump();
13787 write_number_with_ubjson_prefix(number.size(), true);
13788 for (std::size_t i = 0; i < number.size(); ++i) {
13789 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
13790 }
13791 }
13792 }
13793
13794 // UBJSON: write number (signed integer)
13795 template<typename NumberType,
13796 typename std::enable_if<std::is_signed<NumberType>::value && !std::is_floating_point<NumberType>::value,
13797 int>::type = 0>
13798 void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix)
13799 {
13800 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)()) {
13801 if (add_prefix) {
13802 oa->write_character(to_char_type('i')); // int8
13803 }
13804 write_number(static_cast<std::int8_t>(n));
13805 } else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n
13806 && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
13807 {
13808 if (add_prefix) {
13809 oa->write_character(to_char_type('U')); // uint8
13810 }
13811 write_number(static_cast<std::uint8_t>(n));
13812 } else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)()) {
13813 if (add_prefix) {
13814 oa->write_character(to_char_type('I')); // int16
13815 }
13816 write_number(static_cast<std::int16_t>(n));
13817 } else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)()) {
13818 if (add_prefix) {
13819 oa->write_character(to_char_type('l')); // int32
13820 }
13821 write_number(static_cast<std::int32_t>(n));
13822 } else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)()) {
13823 if (add_prefix) {
13824 oa->write_character(to_char_type('L')); // int64
13825 }
13826 write_number(static_cast<std::int64_t>(n));
13827 }
13828 // LCOV_EXCL_START
13829 else
13830 {
13831 if (add_prefix) {
13832 oa->write_character(to_char_type('H')); // high-precision number
13833 }
13834
13835 const auto number = BasicJsonType(n).dump();
13836 write_number_with_ubjson_prefix(number.size(), true);
13837 for (std::size_t i = 0; i < number.size(); ++i) {
13838 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
13839 }
13840 }
13841 // LCOV_EXCL_STOP
13842 }
13843
13844 /*!
13845 @brief determine the type prefix of container values
13846 */
13847 CharType ubjson_prefix(const BasicJsonType& j) const noexcept
13848 {
13849 switch (j.type()) {
13850 case value_t::null:
13851 return 'Z';
13852
13853 case value_t::boolean:
13854 return j.m_value.boolean ? 'T' : 'F';
13855
13857 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer
13858 && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
13859 {
13860 return 'i';
13861 }
13862 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer
13863 && j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
13864 {
13865 return 'U';
13866 }
13867 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer
13868 && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
13869 {
13870 return 'I';
13871 }
13872 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer
13873 && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
13874 {
13875 return 'l';
13876 }
13877 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_value.number_integer
13878 && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
13879 {
13880 return 'L';
13881 }
13882 // anything else is treated as high-precision number
13883 return 'H'; // LCOV_EXCL_LINE
13884 }
13885
13887 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
13888 {
13889 return 'i';
13890 }
13891 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
13892 {
13893 return 'U';
13894 }
13895 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
13896 {
13897 return 'I';
13898 }
13899 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
13900 {
13901 return 'l';
13902 }
13903 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
13904 {
13905 return 'L';
13906 }
13907 // anything else is treated as high-precision number
13908 return 'H'; // LCOV_EXCL_LINE
13909 }
13910
13912 return get_ubjson_float_prefix(j.m_value.number_float);
13913
13914 case value_t::string:
13915 return 'S';
13916
13917 case value_t::array: // fallthrough
13918 case value_t::binary:
13919 return '[';
13920
13921 case value_t::object:
13922 return '{';
13923
13924 case value_t::discarded:
13925 default: // discarded values
13926 return 'N';
13927 }
13928 }
13929
13930 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
13931 {
13932 return 'd'; // float 32
13933 }
13934
13935 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
13936 {
13937 return 'D'; // float 64
13938 }
13939
13940 ///////////////////////
13941 // Utility functions //
13942 ///////////////////////
13943
13944 /*
13945 @brief write a number to output input
13946 @param[in] n number of type @a NumberType
13947 @tparam NumberType the type of the number
13948 @tparam OutputIsLittleEndian Set to true if output data is
13949 required to be little endian
13950
13951 @note This function needs to respect the system's endianness, because bytes
13952 in CBOR, MessagePack, and UBJSON are stored in network order (big
13953 endian) and therefore need reordering on little endian systems.
13954 */
13955 template<typename NumberType, bool OutputIsLittleEndian = false>
13956 void write_number(const NumberType n)
13957 {
13958 // step 1: write number to array of length NumberType
13959 std::array<CharType, sizeof(NumberType)> vec{};
13960 std::memcpy(vec.data(), &n, sizeof(NumberType));
13961
13962 // step 2: write array to output (with possible reordering)
13963 if (is_little_endian != OutputIsLittleEndian) {
13964 // reverse byte order prior to conversion if necessary
13965 std::reverse(vec.begin(), vec.end());
13966 }
13967
13968 oa->write_characters(vec.data(), sizeof(NumberType));
13969 }
13970
13972 {
13973#ifdef __GNUC__
13974#pragma GCC diagnostic push
13975#pragma GCC diagnostic ignored "-Wfloat-equal"
13976#endif
13977 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest())
13978 && static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)())
13979 && static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
13980 {
13981 oa->write_character(format == detail::input_format_t::cbor
13982 ? get_cbor_float_prefix(static_cast<float>(n))
13983 : get_msgpack_float_prefix(static_cast<float>(n)));
13984 write_number(static_cast<float>(n));
13985 } else {
13986 oa->write_character(format == detail::input_format_t::cbor ? get_cbor_float_prefix(n)
13988 write_number(n);
13989 }
13990#ifdef __GNUC__
13991#pragma GCC diagnostic pop
13992#endif
13993 }
13994
13995 public:
13996 // The following to_char_type functions are implement the conversion
13997 // between uint8_t and CharType. In case CharType is not unsigned,
13998 // such a conversion is required to allow values greater than 128.
13999 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
14000 template<typename C = CharType, enable_if_t<std::is_signed<C>::value && std::is_signed<char>::value>* = nullptr>
14001 static constexpr CharType to_char_type(std::uint8_t x) noexcept
14002 {
14003 return *reinterpret_cast<char*>(&x);
14004 }
14005
14006 template<typename C = CharType, enable_if_t<std::is_signed<C>::value && std::is_unsigned<char>::value>* = nullptr>
14007 static CharType to_char_type(std::uint8_t x) noexcept
14008 {
14009 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
14010 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
14011 CharType result;
14012 std::memcpy(&result, &x, sizeof(x));
14013 return result;
14014 }
14015
14016 template<typename C = CharType, enable_if_t<std::is_unsigned<C>::value>* = nullptr>
14017 static constexpr CharType to_char_type(std::uint8_t x) noexcept
14018 {
14019 return x;
14020 }
14021
14022 template<typename InputCharType,
14023 typename C = CharType,
14024 enable_if_t<std::is_signed<C>::value && std::is_signed<char>::value
14025 && std::is_same<char, typename std::remove_cv<InputCharType>::type>::value>* = nullptr>
14026 static constexpr CharType to_char_type(InputCharType x) noexcept
14027 {
14028 return x;
14029 }
14030
14031 private:
14032 /// whether we can assume little endianness
14034
14035 /// the output
14037};
14038} // namespace detail
14039} // namespace nlohmann
14040
14041// #include <nlohmann/detail/output/output_adapters.hpp>
14042
14043// #include <nlohmann/detail/output/serializer.hpp>
14044
14045#include <algorithm> // reverse, remove, fill, find, none_of
14046#include <array> // array
14047#include <clocale> // localeconv, lconv
14048#include <cmath> // labs, isfinite, isnan, signbit
14049#include <cstddef> // size_t, ptrdiff_t
14050#include <cstdint> // uint8_t
14051#include <cstdio> // snprintf
14052#include <iomanip> // setfill, setw
14053#include <limits> // numeric_limits
14054#include <sstream> // stringstream
14055#include <string> // string, char_traits
14056#include <type_traits> // is_same
14057#include <utility> // move
14058
14059// #include <nlohmann/detail/conversions/to_chars.hpp>
14060
14061#include <array> // array
14062#include <cmath> // signbit, isfinite
14063#include <cstdint> // intN_t, uintN_t
14064#include <cstring> // memcpy, memmove
14065#include <limits> // numeric_limits
14066#include <type_traits> // conditional
14067
14068// #include <nlohmann/detail/macro_scope.hpp>
14069
14070namespace nlohmann
14071{
14072namespace detail
14073{
14074
14075/*!
14076@brief implements the Grisu2 algorithm for binary to decimal floating-point
14077conversion.
14078
14079This implementation is a slightly modified version of the reference
14080implementation which may be obtained from
14081http://florian.loitsch.com/publications (bench.tar.gz).
14082
14083The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
14084
14085For a detailed description of the algorithm see:
14086
14087[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
14088 Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
14089 Language Design and Implementation, PLDI 2010
14090[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
14091 Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
14092 Design and Implementation, PLDI 1996
14093*/
14094namespace dtoa_impl
14095{
14096
14097template<typename Target, typename Source>
14098Target reinterpret_bits(const Source source)
14099{
14100 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
14101
14102 Target target;
14103 std::memcpy(&target, &source, sizeof(Source));
14104 return target;
14105}
14106
14107struct diyfp // f * 2^e
14108{
14109 static constexpr int kPrecision = 64; // = q
14110
14111 std::uint64_t f = 0;
14112 int e = 0;
14113
14114 constexpr diyfp(std::uint64_t f_, int e_) noexcept
14115 : f(f_)
14116 , e(e_)
14117 {}
14118
14119 /*!
14120 @brief returns x - y
14121 @pre x.e == y.e and x.f >= y.f
14122 */
14123 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
14124 {
14125 JSON_ASSERT(x.e == y.e);
14126 JSON_ASSERT(x.f >= y.f);
14127
14128 return {x.f - y.f, x.e};
14129 }
14130
14131 /*!
14132 @brief returns x * y
14133 @note The result is rounded. (Only the upper q bits are returned.)
14134 */
14135 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
14136 {
14137 static_assert(kPrecision == 64, "internal error");
14138
14139 // Computes:
14140 // f = round((x.f * y.f) / 2^q)
14141 // e = x.e + y.e + q
14142
14143 // Emulate the 64-bit * 64-bit multiplication:
14144 //
14145 // p = u * v
14146 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
14147 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
14148 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
14149 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
14150 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
14151 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
14152 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
14153 //
14154 // (Since Q might be larger than 2^32 - 1)
14155 //
14156 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
14157 //
14158 // (Q_hi + H does not overflow a 64-bit int)
14159 //
14160 // = p_lo + 2^64 p_hi
14161
14162 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
14163 const std::uint64_t u_hi = x.f >> 32u;
14164 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
14165 const std::uint64_t v_hi = y.f >> 32u;
14166
14167 const std::uint64_t p0 = u_lo * v_lo;
14168 const std::uint64_t p1 = u_lo * v_hi;
14169 const std::uint64_t p2 = u_hi * v_lo;
14170 const std::uint64_t p3 = u_hi * v_hi;
14171
14172 const std::uint64_t p0_hi = p0 >> 32u;
14173 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
14174 const std::uint64_t p1_hi = p1 >> 32u;
14175 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
14176 const std::uint64_t p2_hi = p2 >> 32u;
14177
14178 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
14179
14180 // The full product might now be computed as
14181 //
14182 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
14183 // p_lo = p0_lo + (Q << 32)
14184 //
14185 // But in this particular case here, the full p_lo is not required.
14186 // Effectively we only need to add the highest bit in p_lo to p_hi (and
14187 // Q_hi + 1 does not overflow).
14188
14189 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
14190
14191 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
14192
14193 return {h, x.e + y.e + 64};
14194 }
14195
14196 /*!
14197 @brief normalize x such that the significand is >= 2^(q-1)
14198 @pre x.f != 0
14199 */
14200 static diyfp normalize(diyfp x) noexcept
14201 {
14202 JSON_ASSERT(x.f != 0);
14203
14204 while ((x.f >> 63u) == 0) {
14205 x.f <<= 1u;
14206 x.e--;
14207 }
14208
14209 return x;
14210 }
14211
14212 /*!
14213 @brief normalize x such that the result has the exponent E
14214 @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
14215 */
14216 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
14217 {
14218 const int delta = x.e - target_exponent;
14219
14220 JSON_ASSERT(delta >= 0);
14221 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
14222
14223 return {x.f << delta, target_exponent};
14224 }
14225};
14226
14233
14234/*!
14235Compute the (normalized) diyfp representing the input number 'value' and its
14236boundaries.
14237
14238@pre value must be finite and positive
14239*/
14240template<typename FloatType>
14242{
14243 JSON_ASSERT(std::isfinite(value));
14244 JSON_ASSERT(value > 0);
14245
14246 // Convert the IEEE representation into a diyfp.
14247 //
14248 // If v is denormal:
14249 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
14250 // If v is normalized:
14251 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
14252
14253 static_assert(std::numeric_limits<FloatType>::is_iec559,
14254 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
14255
14256 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
14257 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
14258 constexpr int kMinExp = 1 - kBias;
14259 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
14260
14261 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t>::type;
14262
14263 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
14264 const std::uint64_t E = bits >> (kPrecision - 1);
14265 const std::uint64_t F = bits & (kHiddenBit - 1);
14266
14267 const bool is_denormal = E == 0;
14268 const diyfp v = is_denormal ? diyfp(F, kMinExp) : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
14269
14270 // Compute the boundaries m- and m+ of the floating-point value
14271 // v = f * 2^e.
14272 //
14273 // Determine v- and v+, the floating-point predecessor and successor if v,
14274 // respectively.
14275 //
14276 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
14277 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
14278 //
14279 // v+ = v + 2^e
14280 //
14281 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
14282 // between m- and m+ round to v, regardless of how the input rounding
14283 // algorithm breaks ties.
14284 //
14285 // ---+-------------+-------------+-------------+-------------+--- (A)
14286 // v- m- v m+ v+
14287 //
14288 // -----------------+------+------+-------------+-------------+--- (B)
14289 // v- m- v m+ v+
14290
14291 const bool lower_boundary_is_closer = F == 0 && E > 1;
14292 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
14293 const diyfp m_minus = lower_boundary_is_closer ? diyfp(4 * v.f - 1, v.e - 2) // (B)
14294 : diyfp(2 * v.f - 1, v.e - 1); // (A)
14295
14296 // Determine the normalized w+ = m+.
14297 const diyfp w_plus = diyfp::normalize(m_plus);
14298
14299 // Determine w- = m- such that e_(w-) = e_(w+).
14300 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
14301
14302 return {diyfp::normalize(v), w_minus, w_plus};
14303}
14304
14305// Given normalized diyfp w, Grisu needs to find a (normalized) cached
14306// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
14307// within a certain range [alpha, gamma] (Definition 3.2 from [1])
14308//
14309// alpha <= e = e_c + e_w + q <= gamma
14310//
14311// or
14312//
14313// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
14314// <= f_c * f_w * 2^gamma
14315//
14316// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
14317//
14318// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
14319//
14320// or
14321//
14322// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
14323//
14324// The choice of (alpha,gamma) determines the size of the table and the form of
14325// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
14326// in practice:
14327//
14328// The idea is to cut the number c * w = f * 2^e into two parts, which can be
14329// processed independently: An integral part p1, and a fractional part p2:
14330//
14331// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
14332// = (f div 2^-e) + (f mod 2^-e) * 2^e
14333// = p1 + p2 * 2^e
14334//
14335// The conversion of p1 into decimal form requires a series of divisions and
14336// modulos by (a power of) 10. These operations are faster for 32-bit than for
14337// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
14338// achieved by choosing
14339//
14340// -e >= 32 or e <= -32 := gamma
14341//
14342// In order to convert the fractional part
14343//
14344// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
14345//
14346// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
14347// d[-i] are extracted in order:
14348//
14349// (10 * p2) div 2^-e = d[-1]
14350// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
14351//
14352// The multiplication by 10 must not overflow. It is sufficient to choose
14353//
14354// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
14355//
14356// Since p2 = f mod 2^-e < 2^-e,
14357//
14358// -e <= 60 or e >= -60 := alpha
14359
14360constexpr int kAlpha = -60;
14361constexpr int kGamma = -32;
14362
14363struct cached_power // c = f * 2^e ~= 10^k
14364{
14365 std::uint64_t f;
14366 int e;
14367 int k;
14368};
14369
14370/*!
14371For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
14372power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
14373satisfies (Definition 3.2 from [1])
14374
14375 alpha <= e_c + e + q <= gamma.
14376*/
14378{
14379 // Now
14380 //
14381 // alpha <= e_c + e + q <= gamma (1)
14382 // ==> f_c * 2^alpha <= c * 2^e * 2^q
14383 //
14384 // and since the c's are normalized, 2^(q-1) <= f_c,
14385 //
14386 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
14387 // ==> 2^(alpha - e - 1) <= c
14388 //
14389 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
14390 //
14391 // k = ceil( log_10( 2^(alpha - e - 1) ) )
14392 // = ceil( (alpha - e - 1) * log_10(2) )
14393 //
14394 // From the paper:
14395 // "In theory the result of the procedure could be wrong since c is rounded,
14396 // and the computation itself is approximated [...]. In practice, however,
14397 // this simple function is sufficient."
14398 //
14399 // For IEEE double precision floating-point numbers converted into
14400 // normalized diyfp's w = f * 2^e, with q = 64,
14401 //
14402 // e >= -1022 (min IEEE exponent)
14403 // -52 (p - 1)
14404 // -52 (p - 1, possibly normalize denormal IEEE numbers)
14405 // -11 (normalize the diyfp)
14406 // = -1137
14407 //
14408 // and
14409 //
14410 // e <= +1023 (max IEEE exponent)
14411 // -52 (p - 1)
14412 // -11 (normalize the diyfp)
14413 // = 960
14414 //
14415 // This binary exponent range [-1137,960] results in a decimal exponent
14416 // range [-307,324]. One does not need to store a cached power for each
14417 // k in this range. For each such k it suffices to find a cached power
14418 // such that the exponent of the product lies in [alpha,gamma].
14419 // This implies that the difference of the decimal exponents of adjacent
14420 // table entries must be less than or equal to
14421 //
14422 // floor( (gamma - alpha) * log_10(2) ) = 8.
14423 //
14424 // (A smaller distance gamma-alpha would require a larger table.)
14425
14426 // NB:
14427 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
14428
14429 constexpr int kCachedPowersMinDecExp = -300;
14430 constexpr int kCachedPowersDecStep = 8;
14431
14432 static constexpr std::array<cached_power, 79> kCachedPowers = {{
14433 {0xAB70FE17C79AC6CA, -1060, -300}, {0xFF77B1FCBEBCDC4F, -1034, -292}, {0xBE5691EF416BD60C, -1007, -284},
14434 {0x8DD01FAD907FFC3C, -980, -276}, {0xD3515C2831559A83, -954, -268}, {0x9D71AC8FADA6C9B5, -927, -260},
14435 {0xEA9C227723EE8BCB, -901, -252}, {0xAECC49914078536D, -874, -244}, {0x823C12795DB6CE57, -847, -236},
14436 {0xC21094364DFB5637, -821, -228}, {0x9096EA6F3848984F, -794, -220}, {0xD77485CB25823AC7, -768, -212},
14437 {0xA086CFCD97BF97F4, -741, -204}, {0xEF340A98172AACE5, -715, -196}, {0xB23867FB2A35B28E, -688, -188},
14438 {0x84C8D4DFD2C63F3B, -661, -180}, {0xC5DD44271AD3CDBA, -635, -172}, {0x936B9FCEBB25C996, -608, -164},
14439 {0xDBAC6C247D62A584, -582, -156}, {0xA3AB66580D5FDAF6, -555, -148}, {0xF3E2F893DEC3F126, -529, -140},
14440 {0xB5B5ADA8AAFF80B8, -502, -132}, {0x87625F056C7C4A8B, -475, -124}, {0xC9BCFF6034C13053, -449, -116},
14441 {0x964E858C91BA2655, -422, -108}, {0xDFF9772470297EBD, -396, -100}, {0xA6DFBD9FB8E5B88F, -369, -92},
14442 {0xF8A95FCF88747D94, -343, -84}, {0xB94470938FA89BCF, -316, -76}, {0x8A08F0F8BF0F156B, -289, -68},
14443 {0xCDB02555653131B6, -263, -60}, {0x993FE2C6D07B7FAC, -236, -52}, {0xE45C10C42A2B3B06, -210, -44},
14444 {0xAA242499697392D3, -183, -36}, {0xFD87B5F28300CA0E, -157, -28}, {0xBCE5086492111AEB, -130, -20},
14445 {0x8CBCCC096F5088CC, -103, -12}, {0xD1B71758E219652C, -77, -4}, {0x9C40000000000000, -50, 4},
14446 {0xE8D4A51000000000, -24, 12}, {0xAD78EBC5AC620000, 3, 20}, {0x813F3978F8940984, 30, 28},
14447 {0xC097CE7BC90715B3, 56, 36}, {0x8F7E32CE7BEA5C70, 83, 44}, {0xD5D238A4ABE98068, 109, 52},
14448 {0x9F4F2726179A2245, 136, 60}, {0xED63A231D4C4FB27, 162, 68}, {0xB0DE65388CC8ADA8, 189, 76},
14449 {0x83C7088E1AAB65DB, 216, 84}, {0xC45D1DF942711D9A, 242, 92}, {0x924D692CA61BE758, 269, 100},
14450 {0xDA01EE641A708DEA, 295, 108}, {0xA26DA3999AEF774A, 322, 116}, {0xF209787BB47D6B85, 348, 124},
14451 {0xB454E4A179DD1877, 375, 132}, {0x865B86925B9BC5C2, 402, 140}, {0xC83553C5C8965D3D, 428, 148},
14452 {0x952AB45CFA97A0B3, 455, 156}, {0xDE469FBD99A05FE3, 481, 164}, {0xA59BC234DB398C25, 508, 172},
14453 {0xF6C69A72A3989F5C, 534, 180}, {0xB7DCBF5354E9BECE, 561, 188}, {0x88FCF317F22241E2, 588, 196},
14454 {0xCC20CE9BD35C78A5, 614, 204}, {0x98165AF37B2153DF, 641, 212}, {0xE2A0B5DC971F303A, 667, 220},
14455 {0xA8D9D1535CE3B396, 694, 228}, {0xFB9B7CD9A4A7443C, 720, 236}, {0xBB764C4CA7A44410, 747, 244},
14456 {0x8BAB8EEFB6409C1A, 774, 252}, {0xD01FEF10A657842C, 800, 260}, {0x9B10A4E5E9913129, 827, 268},
14457 {0xE7109BFBA19C0C9D, 853, 276}, {0xAC2820D9623BF429, 880, 284}, {0x80444B5E7AA7CF85, 907, 292},
14458 {0xBF21E44003ACDD2D, 933, 300}, {0x8E679C2F5E44FF8F, 960, 308}, {0xD433179D9C8CB841, 986, 316},
14459 {0x9E19DB92B4E31BA9, 1013, 324},
14460 }};
14461
14462 // This computation gives exactly the same results for k as
14463 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
14464 // for |e| <= 1500, but doesn't require floating-point operations.
14465 // NB: log_10(2) ~= 78913 / 2^18
14466 JSON_ASSERT(e >= -1500);
14467 JSON_ASSERT(e <= 1500);
14468 const int f = kAlpha - e - 1;
14469 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
14470
14471 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
14472 JSON_ASSERT(index >= 0);
14473 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
14474
14475 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
14476 JSON_ASSERT(kAlpha <= cached.e + e + 64);
14477 JSON_ASSERT(kGamma >= cached.e + e + 64);
14478
14479 return cached;
14480}
14481
14482/*!
14483For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
14484For n == 0, returns 1 and sets pow10 := 1.
14485*/
14486inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
14487{
14488 // LCOV_EXCL_START
14489 if (n >= 1000000000) {
14490 pow10 = 1000000000;
14491 return 10;
14492 }
14493 // LCOV_EXCL_STOP
14494 if (n >= 100000000) {
14495 pow10 = 100000000;
14496 return 9;
14497 }
14498 if (n >= 10000000) {
14499 pow10 = 10000000;
14500 return 8;
14501 }
14502 if (n >= 1000000) {
14503 pow10 = 1000000;
14504 return 7;
14505 }
14506 if (n >= 100000) {
14507 pow10 = 100000;
14508 return 6;
14509 }
14510 if (n >= 10000) {
14511 pow10 = 10000;
14512 return 5;
14513 }
14514 if (n >= 1000) {
14515 pow10 = 1000;
14516 return 4;
14517 }
14518 if (n >= 100) {
14519 pow10 = 100;
14520 return 3;
14521 }
14522 if (n >= 10) {
14523 pow10 = 10;
14524 return 2;
14525 }
14526
14527 pow10 = 1;
14528 return 1;
14529}
14530
14531inline void grisu2_round(char* buf,
14532 int len,
14533 std::uint64_t dist,
14534 std::uint64_t delta,
14535 std::uint64_t rest,
14536 std::uint64_t ten_k)
14537{
14538 JSON_ASSERT(len >= 1);
14539 JSON_ASSERT(dist <= delta);
14540 JSON_ASSERT(rest <= delta);
14541 JSON_ASSERT(ten_k > 0);
14542
14543 // <--------------------------- delta ---->
14544 // <---- dist --------->
14545 // --------------[------------------+-------------------]--------------
14546 // M- w M+
14547 //
14548 // ten_k
14549 // <------>
14550 // <---- rest ---->
14551 // --------------[------------------+----+--------------]--------------
14552 // w V
14553 // = buf * 10^k
14554 //
14555 // ten_k represents a unit-in-the-last-place in the decimal representation
14556 // stored in buf.
14557 // Decrement buf by ten_k while this takes buf closer to w.
14558
14559 // The tests are written in this order to avoid overflow in unsigned
14560 // integer arithmetic.
14561
14562 while (rest < dist && delta - rest >= ten_k && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) {
14563 JSON_ASSERT(buf[len - 1] != '0');
14564 buf[len - 1]--;
14565 rest += ten_k;
14566 }
14567}
14568
14569/*!
14570Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
14571M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
14572*/
14573inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
14574{
14575 static_assert(kAlpha >= -60, "internal error");
14576 static_assert(kGamma <= -32, "internal error");
14577
14578 // Generates the digits (and the exponent) of a decimal floating-point
14579 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
14580 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
14581 //
14582 // <--------------------------- delta ---->
14583 // <---- dist --------->
14584 // --------------[------------------+-------------------]--------------
14585 // M- w M+
14586 //
14587 // Grisu2 generates the digits of M+ from left to right and stops as soon as
14588 // V is in [M-,M+].
14589
14590 JSON_ASSERT(M_plus.e >= kAlpha);
14591 JSON_ASSERT(M_plus.e <= kGamma);
14592
14593 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
14594 std::uint64_t dist = diyfp::sub(M_plus, w).f; // (significand of (M+ - w ), implicit exponent is e)
14595
14596 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
14597 //
14598 // M+ = f * 2^e
14599 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
14600 // = ((p1 ) * 2^-e + (p2 )) * 2^e
14601 // = p1 + p2 * 2^e
14602
14603 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
14604
14605 auto p1 = static_cast<std::uint32_t>(M_plus.f
14606 >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
14607 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
14608
14609 // 1)
14610 //
14611 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
14612
14613 JSON_ASSERT(p1 > 0);
14614
14615 std::uint32_t pow10{};
14616 const int k = find_largest_pow10(p1, pow10);
14617
14618 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
14619 //
14620 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
14621 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
14622 //
14623 // M+ = p1 + p2 * 2^e
14624 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
14625 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
14626 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
14627 //
14628 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
14629 //
14630 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
14631 //
14632 // but stop as soon as
14633 //
14634 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
14635
14636 int n = k;
14637 while (n > 0) {
14638 // Invariants:
14639 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
14640 // pow10 = 10^(n-1) <= p1 < 10^n
14641 //
14642 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
14643 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
14644 //
14645 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
14646 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
14647 //
14648 JSON_ASSERT(d <= 9);
14649 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
14650 //
14651 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
14652 //
14653 p1 = r;
14654 n--;
14655 //
14656 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
14657 // pow10 = 10^n
14658 //
14659
14660 // Now check if enough digits have been generated.
14661 // Compute
14662 //
14663 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
14664 //
14665 // Note:
14666 // Since rest and delta share the same exponent e, it suffices to
14667 // compare the significands.
14668 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
14669 if (rest <= delta) {
14670 // V = buffer * 10^n, with M- <= V <= M+.
14671
14672 decimal_exponent += n;
14673
14674 // We may now just stop. But instead look if the buffer could be
14675 // decremented to bring V closer to w.
14676 //
14677 // pow10 = 10^n is now 1 ulp in the decimal representation V.
14678 // The rounding procedure works with diyfp's with an implicit
14679 // exponent of e.
14680 //
14681 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
14682 //
14683 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
14684 grisu2_round(buffer, length, dist, delta, rest, ten_n);
14685
14686 return;
14687 }
14688
14689 pow10 /= 10;
14690 //
14691 // pow10 = 10^(n-1) <= p1 < 10^n
14692 // Invariants restored.
14693 }
14694
14695 // 2)
14696 //
14697 // The digits of the integral part have been generated:
14698 //
14699 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
14700 // = buffer + p2 * 2^e
14701 //
14702 // Now generate the digits of the fractional part p2 * 2^e.
14703 //
14704 // Note:
14705 // No decimal point is generated: the exponent is adjusted instead.
14706 //
14707 // p2 actually represents the fraction
14708 //
14709 // p2 * 2^e
14710 // = p2 / 2^-e
14711 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
14712 //
14713 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
14714 //
14715 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
14716 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
14717 //
14718 // using
14719 //
14720 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
14721 // = ( d) * 2^-e + ( r)
14722 //
14723 // or
14724 // 10^m * p2 * 2^e = d + r * 2^e
14725 //
14726 // i.e.
14727 //
14728 // M+ = buffer + p2 * 2^e
14729 // = buffer + 10^-m * (d + r * 2^e)
14730 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
14731 //
14732 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
14733
14734 JSON_ASSERT(p2 > delta);
14735
14736 int m = 0;
14737 for (;;) {
14738 // Invariant:
14739 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
14740 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
14741 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
14742 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
14743 //
14744 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
14745 p2 *= 10;
14746 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
14747 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
14748 //
14749 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
14750 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
14751 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
14752 //
14753 JSON_ASSERT(d <= 9);
14754 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
14755 //
14756 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
14757 //
14758 p2 = r;
14759 m++;
14760 //
14761 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
14762 // Invariant restored.
14763
14764 // Check if enough digits have been generated.
14765 //
14766 // 10^-m * p2 * 2^e <= delta * 2^e
14767 // p2 * 2^e <= 10^m * delta * 2^e
14768 // p2 <= 10^m * delta
14769 delta *= 10;
14770 dist *= 10;
14771 if (p2 <= delta) {
14772 break;
14773 }
14774 }
14775
14776 // V = buffer * 10^-m, with M- <= V <= M+.
14777
14778 decimal_exponent -= m;
14779
14780 // 1 ulp in the decimal representation is now 10^-m.
14781 // Since delta and dist are now scaled by 10^m, we need to do the
14782 // same with ulp in order to keep the units in sync.
14783 //
14784 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
14785 //
14786 const std::uint64_t ten_m = one.f;
14787 grisu2_round(buffer, length, dist, delta, p2, ten_m);
14788
14789 // By construction this algorithm generates the shortest possible decimal
14790 // number (Loitsch, Theorem 6.2) which rounds back to w.
14791 // For an input number of precision p, at least
14792 //
14793 // N = 1 + ceil(p * log_10(2))
14794 //
14795 // decimal digits are sufficient to identify all binary floating-point
14796 // numbers (Matula, "In-and-Out conversions").
14797 // This implies that the algorithm does not produce more than N decimal
14798 // digits.
14799 //
14800 // N = 17 for p = 53 (IEEE double precision)
14801 // N = 9 for p = 24 (IEEE single precision)
14802}
14803
14804/*!
14805v = buf * 10^decimal_exponent
14806len is the length of the buffer (number of decimal digits)
14807The buffer must be large enough, i.e. >= max_digits10.
14808*/
14810inline void grisu2(char* buf, int& len, int& decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
14811{
14812 JSON_ASSERT(m_plus.e == m_minus.e);
14813 JSON_ASSERT(m_plus.e == v.e);
14814
14815 // --------(-----------------------+-----------------------)-------- (A)
14816 // m- v m+
14817 //
14818 // --------------------(-----------+-----------------------)-------- (B)
14819 // m- v m+
14820 //
14821 // First scale v (and m- and m+) such that the exponent is in the range
14822 // [alpha, gamma].
14823
14824 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
14825
14826 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
14827
14828 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
14829 const diyfp w = diyfp::mul(v, c_minus_k);
14830 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
14831 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
14832
14833 // ----(---+---)---------------(---+---)---------------(---+---)----
14834 // w- w w+
14835 // = c*m- = c*v = c*m+
14836 //
14837 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
14838 // w+ are now off by a small amount.
14839 // In fact:
14840 //
14841 // w - v * 10^k < 1 ulp
14842 //
14843 // To account for this inaccuracy, add resp. subtract 1 ulp.
14844 //
14845 // --------+---[---------------(---+---)---------------]---+--------
14846 // w- M- w M+ w+
14847 //
14848 // Now any number in [M-, M+] (bounds included) will round to w when input,
14849 // regardless of how the input rounding algorithm breaks ties.
14850 //
14851 // And digit_gen generates the shortest possible such number in [M-, M+].
14852 // Note that this does not mean that Grisu2 always generates the shortest
14853 // possible number in the interval (m-, m+).
14854 const diyfp M_minus(w_minus.f + 1, w_minus.e);
14855 const diyfp M_plus(w_plus.f - 1, w_plus.e);
14856
14857 decimal_exponent = -cached.k; // = -(-k) = k
14858
14859 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
14860}
14861
14862/*!
14863v = buf * 10^decimal_exponent
14864len is the length of the buffer (number of decimal digits)
14865The buffer must be large enough, i.e. >= max_digits10.
14866*/
14867template<typename FloatType>
14869void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
14870{
14871 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
14872 "internal error: not enough precision");
14873
14874 JSON_ASSERT(std::isfinite(value));
14875 JSON_ASSERT(value > 0);
14876
14877 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
14878 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
14879 // decimal representations are not exactly "short".
14880 //
14881 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
14882 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
14883 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
14884 // does.
14885 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
14886 // representation using the corresponding std::from_chars function recovers value exactly". That
14887 // indicates that single precision floating-point numbers should be recovered using
14888 // 'std::strtof'.
14889 //
14890 // NB: If the neighbors are computed for single-precision numbers, there is a single float
14891 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
14892 // value is off by 1 ulp.
14893#if 0
14894 const boundaries w = compute_boundaries(static_cast<double>(value));
14895#else
14897#endif
14898
14899 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
14900}
14901
14902/*!
14903@brief appends a decimal representation of e to buf
14904@return a pointer to the element following the exponent.
14905@pre -1000 < e < 1000
14906*/
14909inline char* append_exponent(char* buf, int e)
14910{
14911 JSON_ASSERT(e > -1000);
14912 JSON_ASSERT(e < 1000);
14913
14914 if (e < 0) {
14915 e = -e;
14916 *buf++ = '-';
14917 } else {
14918 *buf++ = '+';
14919 }
14920
14921 auto k = static_cast<std::uint32_t>(e);
14922 if (k < 10) {
14923 // Always print at least two digits in the exponent.
14924 // This is for compatibility with printf("%g").
14925 *buf++ = '0';
14926 *buf++ = static_cast<char>('0' + k);
14927 } else if (k < 100) {
14928 *buf++ = static_cast<char>('0' + k / 10);
14929 k %= 10;
14930 *buf++ = static_cast<char>('0' + k);
14931 } else {
14932 *buf++ = static_cast<char>('0' + k / 100);
14933 k %= 100;
14934 *buf++ = static_cast<char>('0' + k / 10);
14935 k %= 10;
14936 *buf++ = static_cast<char>('0' + k);
14937 }
14938
14939 return buf;
14940}
14941
14942/*!
14943@brief prettify v = buf * 10^decimal_exponent
14944
14945If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
14946notation. Otherwise it will be printed in exponential notation.
14947
14948@pre min_exp < 0
14949@pre max_exp > 0
14950*/
14953inline char* format_buffer(char* buf, int len, int decimal_exponent, int min_exp, int max_exp)
14954{
14955 JSON_ASSERT(min_exp < 0);
14956 JSON_ASSERT(max_exp > 0);
14957
14958 const int k = len;
14959 const int n = len + decimal_exponent;
14960
14961 // v = buf * 10^(n-k)
14962 // k is the length of the buffer (number of decimal digits)
14963 // n is the position of the decimal point relative to the start of the buffer.
14964
14965 if (k <= n && n <= max_exp) {
14966 // digits[000]
14967 // len <= max_exp + 2
14968
14969 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
14970 // Make it look like a floating-point number (#362, #378)
14971 buf[n + 0] = '.';
14972 buf[n + 1] = '0';
14973 return buf + (static_cast<size_t>(n) + 2);
14974 }
14975
14976 if (0 < n && n <= max_exp) {
14977 // dig.its
14978 // len <= max_digits10 + 1
14979
14980 JSON_ASSERT(k > n);
14981
14982 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
14983 buf[n] = '.';
14984 return buf + (static_cast<size_t>(k) + 1U);
14985 }
14986
14987 if (min_exp < n && n <= 0) {
14988 // 0.[000]digits
14989 // len <= 2 + (-min_exp - 1) + max_digits10
14990
14991 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
14992 buf[0] = '0';
14993 buf[1] = '.';
14994 std::memset(buf + 2, '0', static_cast<size_t>(-n));
14995 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
14996 }
14997
14998 if (k == 1) {
14999 // dE+123
15000 // len <= 1 + 5
15001
15002 buf += 1;
15003 } else {
15004 // d.igitsE+123
15005 // len <= max_digits10 + 1 + 5
15006
15007 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
15008 buf[1] = '.';
15009 buf += 1 + static_cast<size_t>(k);
15010 }
15011
15012 *buf++ = 'e';
15013 return append_exponent(buf, n - 1);
15014}
15015
15016} // namespace dtoa_impl
15017
15018/*!
15019@brief generates a decimal representation of the floating-point number value in [first, last).
15020
15021The format of the resulting decimal representation is similar to printf's %g
15022format. Returns an iterator pointing past-the-end of the decimal representation.
15023
15024@note The input number must be finite, i.e. NaN's and Inf's are not supported.
15025@note The buffer must be large enough.
15026@note The result is NOT null-terminated.
15027*/
15028template<typename FloatType>
15030JSON_HEDLEY_RETURNS_NON_NULL char* to_chars(char* first, const char* last, FloatType value)
15031{
15032 static_cast<void>(last); // maybe unused - fix warning
15033 JSON_ASSERT(std::isfinite(value));
15034
15035 // Use signbit(value) instead of (value < 0) since signbit works for -0.
15036 if (std::signbit(value)) {
15037 value = -value;
15038 *first++ = '-';
15039 }
15040
15041#ifdef __GNUC__
15042#pragma GCC diagnostic push
15043#pragma GCC diagnostic ignored "-Wfloat-equal"
15044#endif
15045 if (value == 0) // +-0
15046 {
15047 *first++ = '0';
15048 // Make it look like a floating-point number (#362, #378)
15049 *first++ = '.';
15050 *first++ = '0';
15051 return first;
15052 }
15053#ifdef __GNUC__
15054#pragma GCC diagnostic pop
15055#endif
15056
15057 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
15058
15059 // Compute v = buffer * 10^decimal_exponent.
15060 // The decimal digits are stored in the buffer, which needs to be interpreted
15061 // as an unsigned decimal integer.
15062 // len is the length of the buffer, i.e. the number of decimal digits.
15063 int len = 0;
15064 int decimal_exponent = 0;
15065 dtoa_impl::grisu2(first, len, decimal_exponent, value);
15066
15067 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
15068
15069 // Format the buffer like printf("%.*g", prec, value)
15070 constexpr int kMinExp = -4;
15071 // Use digits10 here to increase compatibility with version 2.
15072 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
15073
15074 JSON_ASSERT(last - first >= kMaxExp + 2);
15075 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
15076 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
15077
15078 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
15079}
15080
15081} // namespace detail
15082} // namespace nlohmann
15083
15084// #include <nlohmann/detail/exceptions.hpp>
15085
15086// #include <nlohmann/detail/macro_scope.hpp>
15087
15088// #include <nlohmann/detail/meta/cpp_future.hpp>
15089
15090// #include <nlohmann/detail/output/binary_writer.hpp>
15091
15092// #include <nlohmann/detail/output/output_adapters.hpp>
15093
15094// #include <nlohmann/detail/value_t.hpp>
15095
15096namespace nlohmann
15097{
15098namespace detail
15099{
15100///////////////////
15101// serialization //
15102///////////////////
15103
15104/// how to treat decoding errors
15106{
15107 strict, ///< throw a type_error exception in case of invalid UTF-8
15108 replace, ///< replace invalid UTF-8 sequences with U+FFFD
15109 ignore ///< ignore invalid UTF-8 sequences
15110};
15111
15112template<typename BasicJsonType>
15114{
15115 using string_t = typename BasicJsonType::string_t;
15116 using number_float_t = typename BasicJsonType::number_float_t;
15117 using number_integer_t = typename BasicJsonType::number_integer_t;
15118 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
15119 using binary_char_t = typename BasicJsonType::binary_t::value_type;
15120 static constexpr std::uint8_t UTF8_ACCEPT = 0;
15121 static constexpr std::uint8_t UTF8_REJECT = 1;
15122
15123 public:
15124 /*!
15125 @param[in] s output stream to serialize to
15126 @param[in] ichar indentation character to use
15127 @param[in] error_handler_ how to react on decoding errors
15128 */
15130 : o(std::move(s))
15131 , loc(std::localeconv())
15132 , thousands_sep(loc->thousands_sep == nullptr ? '\0'
15133 : std::char_traits<char>::to_char_type(*(loc->thousands_sep)))
15134 , decimal_point(loc->decimal_point == nullptr ? '\0'
15135 : std::char_traits<char>::to_char_type(*(loc->decimal_point)))
15136 , indent_char(ichar)
15138 , error_handler(error_handler_)
15139 {}
15140
15141 // delete because of pointer members
15142 serializer(const serializer&) = delete;
15146 ~serializer() = default;
15147
15148 /*!
15149 @brief internal implementation of the serialization function
15150
15151 This function is called by the public member function dump and organizes
15152 the serialization internally. The indentation level is propagated as
15153 additional parameter. In case of arrays and objects, the function is
15154 called recursively.
15155
15156 - strings and object keys are escaped using `escape_string()`
15157 - integer numbers are converted implicitly via `operator<<`
15158 - floating-point numbers are converted to a string using `"%g"` format
15159 - binary values are serialized as objects containing the subtype and the
15160 byte array
15161
15162 @param[in] val value to serialize
15163 @param[in] pretty_print whether the output shall be pretty-printed
15164 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
15165 in the output are escaped with `\uXXXX` sequences, and the result consists
15166 of ASCII characters only.
15167 @param[in] indent_step the indent level
15168 @param[in] current_indent the current indent level (only used internally)
15169 */
15170 void dump(const BasicJsonType& val,
15171 const bool pretty_print,
15172 const bool ensure_ascii,
15173 const unsigned int indent_step,
15174 const unsigned int current_indent = 0)
15175 {
15176 switch (val.m_type) {
15177 case value_t::object: {
15178 if (val.m_value.object->empty()) {
15179 o->write_characters("{}", 2);
15180 return;
15181 }
15182
15183 if (pretty_print) {
15184 o->write_characters("{\n", 2);
15185
15186 // variable to hold indentation for recursive calls
15187 const auto new_indent = current_indent + indent_step;
15188 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) {
15189 indent_string.resize(indent_string.size() * 2, ' ');
15190 }
15191
15192 // first n-1 elements
15193 auto i = val.m_value.object->cbegin();
15194 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) {
15195 o->write_characters(indent_string.c_str(), new_indent);
15196 o->write_character('\"');
15197 dump_escaped(i->first, ensure_ascii);
15198 o->write_characters("\": ", 3);
15199 dump(i->second, true, ensure_ascii, indent_step, new_indent);
15200 o->write_characters(",\n", 2);
15201 }
15202
15203 // last element
15204 JSON_ASSERT(i != val.m_value.object->cend());
15205 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
15206 o->write_characters(indent_string.c_str(), new_indent);
15207 o->write_character('\"');
15208 dump_escaped(i->first, ensure_ascii);
15209 o->write_characters("\": ", 3);
15210 dump(i->second, true, ensure_ascii, indent_step, new_indent);
15211
15212 o->write_character('\n');
15213 o->write_characters(indent_string.c_str(), current_indent);
15214 o->write_character('}');
15215 } else {
15216 o->write_character('{');
15217
15218 // first n-1 elements
15219 auto i = val.m_value.object->cbegin();
15220 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) {
15221 o->write_character('\"');
15222 dump_escaped(i->first, ensure_ascii);
15223 o->write_characters("\":", 2);
15224 dump(i->second, false, ensure_ascii, indent_step, current_indent);
15225 o->write_character(',');
15226 }
15227
15228 // last element
15229 JSON_ASSERT(i != val.m_value.object->cend());
15230 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
15231 o->write_character('\"');
15232 dump_escaped(i->first, ensure_ascii);
15233 o->write_characters("\":", 2);
15234 dump(i->second, false, ensure_ascii, indent_step, current_indent);
15235
15236 o->write_character('}');
15237 }
15238
15239 return;
15240 }
15241
15242 case value_t::array: {
15243 if (val.m_value.array->empty()) {
15244 o->write_characters("[]", 2);
15245 return;
15246 }
15247
15248 if (pretty_print) {
15249 o->write_characters("[\n", 2);
15250
15251 // variable to hold indentation for recursive calls
15252 const auto new_indent = current_indent + indent_step;
15253 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) {
15254 indent_string.resize(indent_string.size() * 2, ' ');
15255 }
15256
15257 // first n-1 elements
15258 for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i) {
15259 o->write_characters(indent_string.c_str(), new_indent);
15260 dump(*i, true, ensure_ascii, indent_step, new_indent);
15261 o->write_characters(",\n", 2);
15262 }
15263
15264 // last element
15265 JSON_ASSERT(!val.m_value.array->empty());
15266 o->write_characters(indent_string.c_str(), new_indent);
15267 dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
15268
15269 o->write_character('\n');
15270 o->write_characters(indent_string.c_str(), current_indent);
15271 o->write_character(']');
15272 } else {
15273 o->write_character('[');
15274
15275 // first n-1 elements
15276 for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i) {
15277 dump(*i, false, ensure_ascii, indent_step, current_indent);
15278 o->write_character(',');
15279 }
15280
15281 // last element
15282 JSON_ASSERT(!val.m_value.array->empty());
15283 dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
15284
15285 o->write_character(']');
15286 }
15287
15288 return;
15289 }
15290
15291 case value_t::string: {
15292 o->write_character('\"');
15293 dump_escaped(*val.m_value.string, ensure_ascii);
15294 o->write_character('\"');
15295 return;
15296 }
15297
15298 case value_t::binary: {
15299 if (pretty_print) {
15300 o->write_characters("{\n", 2);
15301
15302 // variable to hold indentation for recursive calls
15303 const auto new_indent = current_indent + indent_step;
15304 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) {
15305 indent_string.resize(indent_string.size() * 2, ' ');
15306 }
15307
15308 o->write_characters(indent_string.c_str(), new_indent);
15309
15310 o->write_characters("\"bytes\": [", 10);
15311
15312 if (!val.m_value.binary->empty()) {
15313 for (auto i = val.m_value.binary->cbegin(); i != val.m_value.binary->cend() - 1; ++i) {
15314 dump_integer(*i);
15315 o->write_characters(", ", 2);
15316 }
15317 dump_integer(val.m_value.binary->back());
15318 }
15319
15320 o->write_characters("],\n", 3);
15321 o->write_characters(indent_string.c_str(), new_indent);
15322
15323 o->write_characters("\"subtype\": ", 11);
15324 if (val.m_value.binary->has_subtype()) {
15325 dump_integer(val.m_value.binary->subtype());
15326 } else {
15327 o->write_characters("null", 4);
15328 }
15329 o->write_character('\n');
15330 o->write_characters(indent_string.c_str(), current_indent);
15331 o->write_character('}');
15332 } else {
15333 o->write_characters("{\"bytes\":[", 10);
15334
15335 if (!val.m_value.binary->empty()) {
15336 for (auto i = val.m_value.binary->cbegin(); i != val.m_value.binary->cend() - 1; ++i) {
15337 dump_integer(*i);
15338 o->write_character(',');
15339 }
15340 dump_integer(val.m_value.binary->back());
15341 }
15342
15343 o->write_characters("],\"subtype\":", 12);
15344 if (val.m_value.binary->has_subtype()) {
15345 dump_integer(val.m_value.binary->subtype());
15346 o->write_character('}');
15347 } else {
15348 o->write_characters("null}", 5);
15349 }
15350 }
15351 return;
15352 }
15353
15354 case value_t::boolean: {
15355 if (val.m_value.boolean) {
15356 o->write_characters("true", 4);
15357 } else {
15358 o->write_characters("false", 5);
15359 }
15360 return;
15361 }
15362
15364 dump_integer(val.m_value.number_integer);
15365 return;
15366 }
15367
15369 dump_integer(val.m_value.number_unsigned);
15370 return;
15371 }
15372
15373 case value_t::number_float: {
15374 dump_float(val.m_value.number_float);
15375 return;
15376 }
15377
15378 case value_t::discarded: {
15379 o->write_characters("<discarded>", 11);
15380 return;
15381 }
15382
15383 case value_t::null: {
15384 o->write_characters("null", 4);
15385 return;
15386 }
15387
15388 default: // LCOV_EXCL_LINE
15389 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
15390 }
15391 }
15392
15394 :
15395 /*!
15396 @brief dump escaped string
15397
15398 Escape a string by replacing certain special characters by a sequence of an
15399 escape character (backslash) and another character and other control
15400 characters by a sequence of "\u" followed by a four-digit hex
15401 representation. The escaped string is written to output stream @a o.
15402
15403 @param[in] s the string to escape
15404 @param[in] ensure_ascii whether to escape non-ASCII characters with
15405 \uXXXX sequences
15406
15407 @complexity Linear in the length of string @a s.
15408 */
15409 void
15410 dump_escaped(const string_t& s, const bool ensure_ascii)
15411 {
15412 std::uint32_t codepoint{};
15413 std::uint8_t state = UTF8_ACCEPT;
15414 std::size_t bytes = 0; // number of bytes written to string_buffer
15415
15416 // number of bytes written at the point of the last valid byte
15418 std::size_t undumped_chars = 0;
15419
15420 for (std::size_t i = 0; i < s.size(); ++i) {
15421 const auto byte = static_cast<std::uint8_t>(s[i]);
15422
15423 switch (decode(state, codepoint, byte)) {
15424 case UTF8_ACCEPT: // decode found a new code point
15425 {
15426 switch (codepoint) {
15427 case 0x08: // backspace
15428 {
15429 string_buffer[bytes++] = '\\';
15430 string_buffer[bytes++] = 'b';
15431 break;
15432 }
15433
15434 case 0x09: // horizontal tab
15435 {
15436 string_buffer[bytes++] = '\\';
15437 string_buffer[bytes++] = 't';
15438 break;
15439 }
15440
15441 case 0x0A: // newline
15442 {
15443 string_buffer[bytes++] = '\\';
15444 string_buffer[bytes++] = 'n';
15445 break;
15446 }
15447
15448 case 0x0C: // formfeed
15449 {
15450 string_buffer[bytes++] = '\\';
15451 string_buffer[bytes++] = 'f';
15452 break;
15453 }
15454
15455 case 0x0D: // carriage return
15456 {
15457 string_buffer[bytes++] = '\\';
15458 string_buffer[bytes++] = 'r';
15459 break;
15460 }
15461
15462 case 0x22: // quotation mark
15463 {
15464 string_buffer[bytes++] = '\\';
15465 string_buffer[bytes++] = '\"';
15466 break;
15467 }
15468
15469 case 0x5C: // reverse solidus
15470 {
15471 string_buffer[bytes++] = '\\';
15472 string_buffer[bytes++] = '\\';
15473 break;
15474 }
15475
15476 default: {
15477 // escape control characters (0x00..0x1F) or, if
15478 // ensure_ascii parameter is used, non-ASCII characters
15479 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) {
15480 if (codepoint <= 0xFFFF) {
15481 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
15482 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
15483 static_cast<std::uint16_t>(codepoint)));
15484 bytes += 6;
15485 } else {
15486 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
15487 static_cast<void>(
15488 (std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
15489 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
15490 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
15491 bytes += 12;
15492 }
15493 } else {
15494 // copy byte to buffer (all previous bytes
15495 // been copied have in default case above)
15496 string_buffer[bytes++] = s[i];
15497 }
15498 break;
15499 }
15500 }
15501
15502 // write buffer and reset index; there must be 13 bytes
15503 // left, as this is the maximal number of bytes to be
15504 // written ("\uxxxx\uxxxx\0") for one code point
15505 if (string_buffer.size() - bytes < 13) {
15506 o->write_characters(string_buffer.data(), bytes);
15507 bytes = 0;
15508 }
15509
15510 // remember the byte position of this accept
15512 undumped_chars = 0;
15513 break;
15514 }
15515
15516 case UTF8_REJECT: // decode found invalid UTF-8 byte
15517 {
15518 switch (error_handler) {
15520 std::stringstream ss;
15521 ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (byte | 0);
15523 316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + ss.str(),
15524 BasicJsonType()));
15525 }
15526
15529 // in case we saw this character the first time, we
15530 // would like to read it again, because the byte
15531 // may be OK for itself, but just not OK for the
15532 // previous sequence
15533 if (undumped_chars > 0) {
15534 --i;
15535 }
15536
15537 // reset length buffer to the last accepted index;
15538 // thus removing/ignoring the invalid characters
15540
15542 // add a replacement character
15543 if (ensure_ascii) {
15544 string_buffer[bytes++] = '\\';
15545 string_buffer[bytes++] = 'u';
15546 string_buffer[bytes++] = 'f';
15547 string_buffer[bytes++] = 'f';
15548 string_buffer[bytes++] = 'f';
15549 string_buffer[bytes++] = 'd';
15550 } else {
15551 string_buffer[bytes++] =
15553 string_buffer[bytes++] =
15555 string_buffer[bytes++] =
15557 }
15558
15559 // write buffer and reset index; there must be 13 bytes
15560 // left, as this is the maximal number of bytes to be
15561 // written ("\uxxxx\uxxxx\0") for one code point
15562 if (string_buffer.size() - bytes < 13) {
15563 o->write_characters(string_buffer.data(), bytes);
15564 bytes = 0;
15565 }
15566
15568 }
15569
15570 undumped_chars = 0;
15571
15572 // continue processing the string
15574 break;
15575 }
15576
15577 default: // LCOV_EXCL_LINE
15579 false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
15580 }
15581 break;
15582 }
15583
15584 default: // decode found yet incomplete multi-byte code point
15585 {
15586 if (!ensure_ascii) {
15587 // code point will not be escaped - copy byte to buffer
15588 string_buffer[bytes++] = s[i];
15589 }
15591 break;
15592 }
15593 }
15594 }
15595
15596 // we finished processing the string
15598 // write buffer
15599 if (bytes > 0) {
15600 o->write_characters(string_buffer.data(), bytes);
15601 }
15602 } else {
15603 // we finish reading, but do not accept: string was incomplete
15604 switch (error_handler) {
15606 std::stringstream ss;
15607 ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex
15608 << (static_cast<std::uint8_t>(s.back()) | 0);
15609 JSON_THROW(
15610 type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + ss.str(), BasicJsonType()));
15611 }
15612
15614 // write all accepted bytes
15615 o->write_characters(string_buffer.data(), bytes_after_last_accept);
15616 break;
15617 }
15618
15620 // write all accepted bytes
15621 o->write_characters(string_buffer.data(), bytes_after_last_accept);
15622 // add a replacement character
15623 if (ensure_ascii) {
15624 o->write_characters("\\ufffd", 6);
15625 } else {
15626 o->write_characters("\xEF\xBF\xBD", 3);
15627 }
15628 break;
15629 }
15630
15631 default: // LCOV_EXCL_LINE
15632 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
15633 }
15634 }
15635 }
15636
15637 private:
15638 /*!
15639 @brief count digits
15640
15641 Count the number of decimal (base 10) digits for an input unsigned integer.
15642
15643 @param[in] x unsigned integer number to count its digits
15644 @return number of decimal digits
15645 */
15646 inline unsigned int count_digits(number_unsigned_t x) noexcept
15647 {
15648 unsigned int n_digits = 1;
15649 for (;;) {
15650 if (x < 10) {
15651 return n_digits;
15652 }
15653 if (x < 100) {
15654 return n_digits + 1;
15655 }
15656 if (x < 1000) {
15657 return n_digits + 2;
15658 }
15659 if (x < 10000) {
15660 return n_digits + 3;
15661 }
15662 x = x / 10000u;
15663 n_digits += 4;
15664 }
15665 }
15666
15667 // templates to avoid warnings about useless casts
15668 template<typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
15669 bool is_negative_number(NumberType x)
15670 {
15671 return x < 0;
15672 }
15673
15674 template<typename NumberType, enable_if_t<std::is_unsigned<NumberType>::value, int> = 0>
15675 bool is_negative_number(NumberType /*unused*/)
15676 {
15677 return false;
15678 }
15679
15680 /*!
15681 @brief dump an integer
15682
15683 Dump a given integer to output stream @a o. Works internally with
15684 @a number_buffer.
15685
15686 @param[in] x integer number (signed or unsigned) to dump
15687 @tparam NumberType either @a number_integer_t or @a number_unsigned_t
15688 */
15689 template<
15690 typename NumberType,
15691 detail::enable_if_t<std::is_integral<NumberType>::value || std::is_same<NumberType, number_unsigned_t>::value
15692 || std::is_same<NumberType, number_integer_t>::value
15693 || std::is_same<NumberType, binary_char_t>::value,
15694 int> = 0>
15695 void dump_integer(NumberType x)
15696 {
15697 static constexpr std::array<std::array<char, 2>, 100> digits_to_99{{
15698 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}},
15699 {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}}, {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}},
15700 {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}}, {{'2', '0'}},
15701 {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}},
15702 {{'2', '8'}}, {{'2', '9'}}, {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}},
15703 {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}}, {{'4', '0'}}, {{'4', '1'}},
15704 {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}},
15705 {{'4', '9'}}, {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}},
15706 {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}}, {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}},
15707 {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
15708 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}},
15709 {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}}, {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}},
15710 {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}}, {{'9', '0'}},
15711 {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}},
15712 {{'9', '8'}}, {{'9', '9'}},
15713 }};
15714
15715 // special case for "0"
15716 if (x == 0) {
15717 o->write_character('0');
15718 return;
15719 }
15720
15721 // use a pointer to fill the buffer
15722 auto buffer_ptr =
15723 number_buffer
15724 .begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
15725
15726 number_unsigned_t abs_value;
15727
15728 unsigned int n_chars{};
15729
15730 if (is_negative_number(x)) {
15731 *buffer_ptr = '-';
15732 abs_value = remove_sign(static_cast<number_integer_t>(x));
15733
15734 // account one more byte for the minus sign
15735 n_chars = 1 + count_digits(abs_value);
15736 } else {
15737 abs_value = static_cast<number_unsigned_t>(x);
15738 n_chars = count_digits(abs_value);
15739 }
15740
15741 // spare 1 byte for '\0'
15742 JSON_ASSERT(n_chars < number_buffer.size() - 1);
15743
15744 // jump to the end to generate the string from backward,
15745 // so we later avoid reversing the result
15746 buffer_ptr += n_chars;
15747
15748 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
15749 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
15750 while (abs_value >= 100) {
15751 const auto digits_index = static_cast<unsigned>((abs_value % 100));
15752 abs_value /= 100;
15753 *(--buffer_ptr) = digits_to_99[digits_index][1];
15754 *(--buffer_ptr) = digits_to_99[digits_index][0];
15755 }
15756
15757 if (abs_value >= 10) {
15758 const auto digits_index = static_cast<unsigned>(abs_value);
15759 *(--buffer_ptr) = digits_to_99[digits_index][1];
15760 *(--buffer_ptr) = digits_to_99[digits_index][0];
15761 } else {
15762 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
15763 }
15764
15765 o->write_characters(number_buffer.data(), n_chars);
15766 }
15767
15768 /*!
15769 @brief dump a floating-point number
15770
15771 Dump a given floating-point number to output stream @a o. Works internally
15772 with @a number_buffer.
15773
15774 @param[in] x floating-point number to dump
15775 */
15776 void dump_float(number_float_t x)
15777 {
15778 // NaN / inf
15779 if (!std::isfinite(x)) {
15780 o->write_characters("null", 4);
15781 return;
15782 }
15783
15784 // If number_float_t is an IEEE-754 single or double precision number,
15785 // use the Grisu2 algorithm to produce short numbers which are
15786 // guaranteed to round-trip, using strtof and strtod, resp.
15787 //
15788 // NB: The test below works if <long double> == <double>.
15789 static constexpr bool is_ieee_single_or_double =
15790 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24
15791 && std::numeric_limits<number_float_t>::max_exponent == 128)
15792 || (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53
15793 && std::numeric_limits<number_float_t>::max_exponent == 1024);
15794
15795 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
15796 }
15797
15798 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
15799 {
15800 auto* begin = number_buffer.data();
15801 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
15802
15803 o->write_characters(begin, static_cast<size_t>(end - begin));
15804 }
15805
15806 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
15807 {
15808 // get number of digits for a float -> text -> float round-trip
15809 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
15810
15811 // the actual conversion
15812 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
15813 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
15814
15815 // negative value indicates an error
15816 JSON_ASSERT(len > 0);
15817 // check if buffer was large enough
15818 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
15819
15820 // erase thousands separator
15821 if (thousands_sep != '\0') {
15822 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see
15823 // https://github.com/nlohmann/json/issues/3081
15824 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
15825 std::fill(end, number_buffer.end(), '\0');
15826 JSON_ASSERT((end - number_buffer.begin()) <= len);
15827 len = (end - number_buffer.begin());
15828 }
15829
15830 // convert decimal point to '.'
15831 if (decimal_point != '\0' && decimal_point != '.') {
15832 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see
15833 // https://github.com/nlohmann/json/issues/3081
15834 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
15835 if (dec_pos != number_buffer.end()) {
15836 *dec_pos = '.';
15837 }
15838 }
15839
15840 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
15841
15842 // determine if we need to append ".0"
15843 const bool value_is_int_like = std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
15844 [](char c) { return c == '.' || c == 'e'; });
15845
15846 if (value_is_int_like) {
15847 o->write_characters(".0", 2);
15848 }
15849 }
15850
15851 /*!
15852 @brief check whether a string is UTF-8 encoded
15853
15854 The function checks each byte of a string whether it is UTF-8 encoded. The
15855 result of the check is stored in the @a state parameter. The function must
15856 be called initially with state 0 (accept). State 1 means the string must
15857 be rejected, because the current byte is not allowed. If the string is
15858 completely processed, but the state is non-zero, the string ended
15859 prematurely; that is, the last byte indicated more bytes should have
15860 followed.
15861
15862 @param[in,out] state the state of the decoding
15863 @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
15864 @param[in] byte next byte to decode
15865 @return new state
15866
15867 @note The function has been edited: a std::array is used.
15868
15869 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
15870 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
15871 */
15872 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
15873 {
15874 static const std::array<std::uint8_t, 400> utf8d = {{
15875 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
15876 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
15877 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
15878 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
15879 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
15880 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
15881 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
15882 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
15883 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
15884 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
15885 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
15886 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
15887 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
15888 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
15889 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
15890 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
15891 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
15892 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
15893 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
15894 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1,
15895 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
15896 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1,
15897 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
15898 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1,
15899 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
15900 }};
15901
15902 JSON_ASSERT(byte < utf8d.size());
15903 const std::uint8_t type = utf8d[byte];
15904
15905 codep = (state != UTF8_ACCEPT) ? (byte & 0x3fu) | (codep << 6u) : (0xFFu >> type) & (byte);
15906
15907 std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
15908 JSON_ASSERT(index < 400);
15909 state = utf8d[index];
15910 return state;
15911 }
15912
15913 /*
15914 * Overload to make the compiler happy while it is instantiating
15915 * dump_integer for number_unsigned_t.
15916 * Must never be called.
15917 */
15919 {
15920 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
15921 return x; // LCOV_EXCL_LINE
15922 }
15923
15924 /*
15925 * Helper function for dump_integer
15926 *
15927 * This function takes a negative signed integer and returns its absolute
15928 * value as unsigned integer. The plus/minus shuffling is necessary as we can
15929 * not directly remove the sign of an arbitrary signed integer as the
15930 * absolute values of INT_MIN and INT_MAX are usually not the same. See
15931 * #1708 for details.
15932 */
15933 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
15934 {
15935 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
15936 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
15937 }
15938
15939 private:
15940 /// the output of the serializer
15941 output_adapter_t<char> o = nullptr;
15942
15943 /// a (hopefully) large enough character buffer
15944 std::array<char, 64> number_buffer{{}};
15945
15946 /// the locale
15947 const std::lconv* loc = nullptr;
15948 /// the locale's thousand separator character
15949 const char thousands_sep = '\0';
15950 /// the locale's decimal point character
15951 const char decimal_point = '\0';
15952
15953 /// string buffer
15954 std::array<char, 512> string_buffer{{}};
15955
15956 /// the indentation character
15957 const char indent_char;
15958 /// the indentation string
15960
15961 /// error_handler how to react on decoding errors
15963};
15964} // namespace detail
15965} // namespace nlohmann
15966
15967// #include <nlohmann/detail/value_t.hpp>
15968
15969// #include <nlohmann/json_fwd.hpp>
15970
15971// #include <nlohmann/ordered_map.hpp>
15972
15973#include <functional> // less
15974#include <initializer_list> // initializer_list
15975#include <iterator> // input_iterator_tag, iterator_traits
15976#include <memory> // allocator
15977#include <stdexcept> // for out_of_range
15978#include <type_traits> // enable_if, is_convertible
15979#include <utility> // pair
15980#include <vector> // vector
15981
15982// #include <nlohmann/detail/macro_scope.hpp>
15983
15984namespace nlohmann
15985{
15986
15987/// ordered_map: a minimal map-like container that preserves insertion order
15988/// for use within nlohmann::basic_json<ordered_map>
15989template<class Key,
15990 class T,
15991 class IgnoredLess = std::less<Key>,
15992 class Allocator = std::allocator<std::pair<const Key, T>>>
15993struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
15994{
15995 using key_type = Key;
15996 using mapped_type = T;
15997 using Container = std::vector<std::pair<const Key, T>, Allocator>;
15998 using iterator = typename Container::iterator;
15999 using const_iterator = typename Container::const_iterator;
16000 using size_type = typename Container::size_type;
16001 using value_type = typename Container::value_type;
16002
16003 // Explicit constructors instead of `using Container::Container`
16004 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
16006 : Container{alloc}
16007 {}
16008 template<class It>
16009 ordered_map(It first, It last, const Allocator& alloc = Allocator())
16010 : Container{first, last, alloc}
16011 {}
16012 ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator())
16013 : Container{init, alloc}
16014 {}
16015
16016 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
16017 {
16018 for (auto it = this->begin(); it != this->end(); ++it) {
16019 if (it->first == key) {
16020 return {it, false};
16021 }
16022 }
16023 Container::emplace_back(key, t);
16024 return {--this->end(), true};
16025 }
16026
16027 T& operator[](const Key& key) { return emplace(key, T{}).first->second; }
16028
16029 const T& operator[](const Key& key) const { return at(key); }
16030
16031 T& at(const Key& key)
16032 {
16033 for (auto it = this->begin(); it != this->end(); ++it) {
16034 if (it->first == key) {
16035 return it->second;
16036 }
16037 }
16038
16039 JSON_THROW(std::out_of_range("key not found"));
16040 }
16041
16042 const T& at(const Key& key) const
16043 {
16044 for (auto it = this->begin(); it != this->end(); ++it) {
16045 if (it->first == key) {
16046 return it->second;
16047 }
16048 }
16049
16050 JSON_THROW(std::out_of_range("key not found"));
16051 }
16052
16053 size_type erase(const Key& key)
16054 {
16055 for (auto it = this->begin(); it != this->end(); ++it) {
16056 if (it->first == key) {
16057 // Since we cannot move const Keys, re-construct them in place
16058 for (auto next = it; ++next != this->end(); ++it) {
16059 it->~value_type(); // Destroy but keep allocation
16060 new (&*it) value_type{std::move(*next)};
16061 }
16062 Container::pop_back();
16063 return 1;
16064 }
16065 }
16066 return 0;
16067 }
16068
16069 iterator erase(iterator pos) { return erase(pos, std::next(pos)); }
16070
16072 {
16073 const auto elements_affected = std::distance(first, last);
16074 const auto offset = std::distance(Container::begin(), first);
16075
16076 // This is the start situation. We need to delete elements_affected
16077 // elements (3 in this example: e, f, g), and need to return an
16078 // iterator past the last deleted element (h in this example).
16079 // Note that offset is the distance from the start of the vector
16080 // to first. We will need this later.
16081
16082 // [ a, b, c, d, e, f, g, h, i, j ]
16083 // ^ ^
16084 // first last
16085
16086 // Since we cannot move const Keys, we re-construct them in place.
16087 // We start at first and re-construct (viz. copy) the elements from
16088 // the back of the vector. Example for first iteration:
16089
16090 // ,--------.
16091 // v | destroy e and re-construct with h
16092 // [ a, b, c, d, e, f, g, h, i, j ]
16093 // ^ ^
16094 // it it + elements_affected
16095
16096 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it) {
16097 it->~value_type(); // destroy but keep allocation
16098 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
16099 }
16100
16101 // [ a, b, c, d, h, i, j, h, i, j ]
16102 // ^ ^
16103 // first last
16104
16105 // remove the unneeded elements at the end of the vector
16106 Container::resize(this->size() - static_cast<size_type>(elements_affected));
16107
16108 // [ a, b, c, d, h, i, j ]
16109 // ^ ^
16110 // first last
16111
16112 // first is now pointing past the last deleted element, but we cannot
16113 // use this iterator, because it may have been invalidated by the
16114 // resize call. Instead, we can return begin() + offset.
16115 return Container::begin() + offset;
16116 }
16117
16118 size_type count(const Key& key) const
16119 {
16120 for (auto it = this->begin(); it != this->end(); ++it) {
16121 if (it->first == key) {
16122 return 1;
16123 }
16124 }
16125 return 0;
16126 }
16127
16128 iterator find(const Key& key)
16129 {
16130 for (auto it = this->begin(); it != this->end(); ++it) {
16131 if (it->first == key) {
16132 return it;
16133 }
16134 }
16135 return Container::end();
16136 }
16137
16138 const_iterator find(const Key& key) const
16139 {
16140 for (auto it = this->begin(); it != this->end(); ++it) {
16141 if (it->first == key) {
16142 return it;
16143 }
16144 }
16145 return Container::end();
16146 }
16147
16148 std::pair<iterator, bool> insert(value_type&& value) { return emplace(value.first, std::move(value.second)); }
16149
16150 std::pair<iterator, bool> insert(const value_type& value)
16151 {
16152 for (auto it = this->begin(); it != this->end(); ++it) {
16153 if (it->first == value.first) {
16154 return {it, false};
16155 }
16156 }
16157 Container::push_back(value);
16158 return {--this->end(), true};
16159 }
16160
16161 template<typename InputIt>
16163 typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
16164 std::input_iterator_tag>::value>::type;
16165
16166 template<typename InputIt, typename = require_input_iter<InputIt>>
16167 void insert(InputIt first, InputIt last)
16168 {
16169 for (auto it = first; it != last; ++it) {
16170 insert(*it);
16171 }
16172 }
16173};
16174
16175} // namespace nlohmann
16176
16177#if defined(JSON_HAS_CPP_17)
16178#include <string_view>
16179#endif
16180
16181/*!
16182@brief namespace for Niels Lohmann
16183@see https://github.com/nlohmann
16184@since version 1.0.0
16185*/
16186namespace nlohmann
16187{
16188
16189/*!
16190@brief a class to store JSON values
16191
16192@internal
16193@invariant The member variables @a m_value and @a m_type have the following
16194relationship:
16195- If `m_type == value_t::object`, then `m_value.object != nullptr`.
16196- If `m_type == value_t::array`, then `m_value.array != nullptr`.
16197- If `m_type == value_t::string`, then `m_value.string != nullptr`.
16198The invariants are checked by member function assert_invariant().
16199
16200@note ObjectType trick from https://stackoverflow.com/a/9860911
16201@endinternal
16202
16203@since version 1.0.0
16204
16205@nosubgrouping
16206*/
16208class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
16209{
16210 private:
16211 template<detail::value_t>
16213 friend ::nlohmann::json_pointer<basic_json>;
16214
16215 template<typename BasicJsonType, typename InputType>
16216 friend class ::nlohmann::detail::parser;
16217 friend ::nlohmann::detail::serializer<basic_json>;
16218 template<typename BasicJsonType>
16219 friend class ::nlohmann::detail::iter_impl;
16220 template<typename BasicJsonType, typename CharType>
16221 friend class ::nlohmann::detail::binary_writer;
16222 template<typename BasicJsonType, typename InputType, typename SAX>
16223 friend class ::nlohmann::detail::binary_reader;
16224 template<typename BasicJsonType>
16225 friend class ::nlohmann::detail::json_sax_dom_parser;
16226 template<typename BasicJsonType>
16227 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
16228 friend class ::nlohmann::detail::exception;
16229
16230 /// workaround type for MSVC
16232
16234 :
16235 // convenience aliases for types residing in namespace detail;
16237
16238 template<typename InputAdapterType>
16239 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
16240 InputAdapterType adapter,
16242 const bool allow_exceptions = true,
16243 const bool ignore_comments = false)
16244 {
16245 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter), std::move(cb),
16246 allow_exceptions, ignore_comments);
16247 }
16248
16249 private:
16251 template<typename BasicJsonType>
16253 template<typename BasicJsonType>
16255 template<typename Iterator>
16257 template<typename Base>
16259
16260 template<typename CharType>
16262
16263 template<typename InputType>
16265 template<typename CharType>
16267
16269
16270 public:
16272 /// JSON Pointer, see @ref nlohmann::json_pointer
16274 template<typename T, typename SFINAE>
16275 using json_serializer = JSONSerializer<T, SFINAE>;
16276 /// how to treat decoding errors
16278 /// how to treat CBOR tags
16280 /// helper type for initializer lists of basic_json values
16281 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
16282
16284 /// SAX interface type, see @ref nlohmann::json_sax
16286
16287 ////////////////
16288 // exceptions //
16289 ////////////////
16290
16291 /// @name exceptions
16292 /// Classes to implement user-defined exceptions.
16293 /// @{
16294
16301
16302 /// @}
16303
16304 /////////////////////
16305 // container types //
16306 /////////////////////
16307
16308 /// @name container types
16309 /// The canonic container types to use @ref basic_json like any other STL
16310 /// container.
16311 /// @{
16312
16313 /// the type of elements in a basic_json container
16314 using value_type = basic_json;
16315
16316 /// the type of an element reference
16318 /// the type of an element const reference
16320
16321 /// a type to represent differences between iterators
16322 using difference_type = std::ptrdiff_t;
16323 /// a type to represent container sizes
16324 using size_type = std::size_t;
16325
16326 /// the allocator type
16328
16329 /// the type of an element pointer
16330 using pointer = typename std::allocator_traits<allocator_type>::pointer;
16331 /// the type of an element const pointer
16332 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
16333
16334 /// an iterator for a basic_json container
16336 /// a const iterator for a basic_json container
16338 /// a reverse iterator for a basic_json container
16340 /// a const reverse iterator for a basic_json container
16342
16343 /// @}
16344
16345 /// @brief returns the allocator associated with the container
16346 /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
16347 static allocator_type get_allocator() { return allocator_type(); }
16348
16349 /// @brief returns version information on the library
16350 /// @sa https://json.nlohmann.me/api/basic_json/meta/
16352 static basic_json meta()
16353 {
16355
16356 result["copyright"] = "(C) 2013-2022 Niels Lohmann";
16357 result["name"] = "JSON for Modern C++";
16358 result["url"] = "https://github.com/nlohmann/json";
16359 result["version"]["string"] = std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "."
16360 + std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "."
16361 + std::to_string(NLOHMANN_JSON_VERSION_PATCH);
16362 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
16363 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
16364 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
16365
16366#ifdef _WIN32
16367 result["platform"] = "win32";
16368#elif defined __linux__
16369 result["platform"] = "linux";
16370#elif defined __APPLE__
16371 result["platform"] = "apple";
16372#elif defined __unix__
16373 result["platform"] = "unix";
16374#else
16375 result["platform"] = "unknown";
16376#endif
16377
16378#if defined(__ICC) || defined(__INTEL_COMPILER)
16379 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
16380#elif defined(__clang__)
16381 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
16382#elif defined(__GNUC__) || defined(__GNUG__)
16383 result["compiler"] = {{"family", "gcc"},
16384 {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "."
16385 + std::to_string(__GNUC_PATCHLEVEL__)}};
16386#elif defined(__HP_cc) || defined(__HP_aCC)
16387 result["compiler"] = "hp"
16388#elif defined(__IBMCPP__)
16389 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
16390#elif defined(_MSC_VER)
16391 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
16392#elif defined(__PGI)
16393 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
16394#elif defined(__SUNPRO_CC)
16395 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
16396#else
16397 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
16398#endif
16399
16400#ifdef __cplusplus
16401 result["compiler"]["c++"] = std::to_string(__cplusplus);
16402#else
16403 result["compiler"]["c++"] = "unknown";
16404#endif
16405 return result;
16406 }
16407
16408 ///////////////////////////
16409 // JSON value data types //
16410 ///////////////////////////
16411
16412 /// @name JSON value data types
16413 /// The data types to store a JSON value. These types are derived from
16414 /// the template arguments passed to class @ref basic_json.
16415 /// @{
16416
16417 /// @brief object key comparator type
16418 /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
16419#if defined(JSON_HAS_CPP_14)
16420 // Use transparent comparator if possible, combined with perfect forwarding
16421 // on find() and count() calls prevents unnecessary string construction.
16422 using object_comparator_t = std::less<>;
16423#else
16424 using object_comparator_t = std::less<StringType>;
16425#endif
16426
16427 /// @brief a type for an object
16428 /// @sa https://json.nlohmann.me/api/basic_json/object_t/
16429 using object_t =
16430 ObjectType<StringType, basic_json, object_comparator_t, AllocatorType<std::pair<const StringType, basic_json>>>;
16431
16432 /// @brief a type for an array
16433 /// @sa https://json.nlohmann.me/api/basic_json/array_t/
16434 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
16435
16436 /// @brief a type for a string
16437 /// @sa https://json.nlohmann.me/api/basic_json/string_t/
16438 using string_t = StringType;
16439
16440 /// @brief a type for a boolean
16441 /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
16442 using boolean_t = BooleanType;
16443
16444 /// @brief a type for a number (integer)
16445 /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
16446 using number_integer_t = NumberIntegerType;
16447
16448 /// @brief a type for a number (unsigned)
16449 /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
16450 using number_unsigned_t = NumberUnsignedType;
16451
16452 /// @brief a type for a number (floating-point)
16453 /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
16454 using number_float_t = NumberFloatType;
16455
16456 /// @brief a type for a packed binary type
16457 /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
16459
16460 /// @}
16461
16462 private:
16463 /// helper for exception-safe object creation
16464 template<typename T, typename... Args>
16465 JSON_HEDLEY_RETURNS_NON_NULL static T* create(Args&&... args)
16466 {
16467 AllocatorType<T> alloc;
16468 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
16469
16470 auto deleter = [&](T* obj) { AllocatorTraits::deallocate(alloc, obj, 1); };
16471 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
16472 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
16473 JSON_ASSERT(obj != nullptr);
16474 return obj.release();
16475 }
16476
16477 ////////////////////////
16478 // JSON value storage //
16479 ////////////////////////
16480
16482 :
16483 /*!
16484 @brief a JSON value
16485
16486 The actual storage for a JSON value of the @ref basic_json class. This
16487 union combines the different storage types for the JSON value types
16488 defined in @ref value_t.
16489
16490 JSON type | value_t type | used type
16491 --------- | --------------- | ------------------------
16492 object | object | pointer to @ref object_t
16493 array | array | pointer to @ref array_t
16494 string | string | pointer to @ref string_t
16495 boolean | boolean | @ref boolean_t
16496 number | number_integer | @ref number_integer_t
16497 number | number_unsigned | @ref number_unsigned_t
16498 number | number_float | @ref number_float_t
16499 binary | binary | pointer to @ref binary_t
16500 null | null | *no value is stored*
16501
16502 @note Variable-length types (objects, arrays, and strings) are stored as
16503 pointers. The size of the union should not exceed 64 bits if the default
16504 value types are used.
16505
16506 @since version 1.0.0
16507 */
16508 union json_value {
16509 /// object (stored with pointer to save storage)
16510 object_t* object;
16511 /// array (stored with pointer to save storage)
16512 array_t* array;
16513 /// string (stored with pointer to save storage)
16514 string_t* string;
16515 /// binary (stored with pointer to save storage)
16516 binary_t* binary;
16517 /// boolean
16518 boolean_t boolean;
16519 /// number (integer)
16520 number_integer_t number_integer;
16521 /// number (unsigned integer)
16522 number_unsigned_t number_unsigned;
16523 /// number (floating-point)
16524 number_float_t number_float;
16525
16526 /// default constructor (for null values)
16527 json_value() = default;
16528 /// constructor for booleans
16529 json_value(boolean_t v) noexcept
16530 : boolean(v)
16531 {}
16532 /// constructor for numbers (integer)
16533 json_value(number_integer_t v) noexcept
16534 : number_integer(v)
16535 {}
16536 /// constructor for numbers (unsigned)
16537 json_value(number_unsigned_t v) noexcept
16538 : number_unsigned(v)
16539 {}
16540 /// constructor for numbers (floating-point)
16541 json_value(number_float_t v) noexcept
16542 : number_float(v)
16543 {}
16544 /// constructor for empty values of a given type
16546 {
16547 switch (t) {
16548 case value_t::object: {
16549 object = create<object_t>();
16550 break;
16551 }
16552
16553 case value_t::array: {
16555 break;
16556 }
16557
16558 case value_t::string: {
16559 string = create<string_t>("");
16560 break;
16561 }
16562
16563 case value_t::binary: {
16565 break;
16566 }
16567
16568 case value_t::boolean: {
16569 boolean = static_cast<boolean_t>(false);
16570 break;
16571 }
16572
16573 case value_t::number_integer: {
16574 number_integer = static_cast<number_integer_t>(0);
16575 break;
16576 }
16577
16578 case value_t::number_unsigned: {
16579 number_unsigned = static_cast<number_unsigned_t>(0);
16580 break;
16581 }
16582
16583 case value_t::number_float: {
16584 number_float = static_cast<number_float_t>(0.0);
16585 break;
16586 }
16587
16588 case value_t::null: {
16589 object = nullptr; // silence warning, see #821
16590 break;
16591 }
16592
16593 case value_t::discarded:
16594 default: {
16595 object = nullptr; // silence warning, see #821
16596 if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) {
16597 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5",
16598 basic_json())); // LCOV_EXCL_LINE
16599 }
16600 break;
16601 }
16602 }
16603 }
16604
16605 /// constructor for strings
16606 json_value(const string_t& value)
16607 : string(create<string_t>(value))
16608 {}
16609
16610 /// constructor for rvalue strings
16611 json_value(string_t&& value)
16612 : string(create<string_t>(std::move(value)))
16613 {}
16614
16615 /// constructor for objects
16616 json_value(const object_t& value)
16617 : object(create<object_t>(value))
16618 {}
16619
16620 /// constructor for rvalue objects
16621 json_value(object_t&& value)
16622 : object(create<object_t>(std::move(value)))
16623 {}
16624
16625 /// constructor for arrays
16626 json_value(const array_t& value)
16627 : array(create<array_t>(value))
16628 {}
16629
16630 /// constructor for rvalue arrays
16631 json_value(array_t&& value)
16632 : array(create<array_t>(std::move(value)))
16633 {}
16634
16635 /// constructor for binary arrays
16636 json_value(const typename binary_t::container_type& value)
16637 : binary(create<binary_t>(value))
16638 {}
16639
16640 /// constructor for rvalue binary arrays
16641 json_value(typename binary_t::container_type&& value)
16642 : binary(create<binary_t>(std::move(value)))
16643 {}
16644
16645 /// constructor for binary arrays (internal type)
16646 json_value(const binary_t& value)
16647 : binary(create<binary_t>(value))
16648 {}
16649
16650 /// constructor for rvalue binary arrays (internal type)
16651 json_value(binary_t&& value)
16652 : binary(create<binary_t>(std::move(value)))
16653 {}
16654
16656 {
16657 if (t == value_t::array || t == value_t::object) {
16658 // flatten the current json_value to a heap-allocated stack
16659 std::vector<basic_json> stack;
16660
16661 // move the top-level items to stack
16662 if (t == value_t::array) {
16663 stack.reserve(array->size());
16664 std::move(array->begin(), array->end(), std::back_inserter(stack));
16665 } else {
16666 stack.reserve(object->size());
16667 for (auto&& it : *object) {
16668 stack.push_back(std::move(it.second));
16669 }
16670 }
16671
16672 while (!stack.empty()) {
16673 // move the last item to local variable to be processed
16674 basic_json current_item(std::move(stack.back()));
16675 stack.pop_back();
16676
16677 // if current_item is array/object, move
16678 // its children to the stack to be processed later
16679 if (current_item.is_array()) {
16680 std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(),
16681 std::back_inserter(stack));
16682
16683 current_item.m_value.array->clear();
16684 } else if (current_item.is_object()) {
16685 for (auto&& it : *current_item.m_value.object) {
16686 stack.push_back(std::move(it.second));
16687 }
16688
16689 current_item.m_value.object->clear();
16690 }
16691
16692 // it's now safe that current_item get destructed
16693 // since it doesn't have any children
16694 }
16695 }
16696
16697 switch (t) {
16698 case value_t::object: {
16699 AllocatorType<object_t> alloc;
16700 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
16701 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
16702 break;
16703 }
16704
16705 case value_t::array: {
16706 AllocatorType<array_t> alloc;
16707 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
16708 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
16709 break;
16710 }
16711
16712 case value_t::string: {
16713 AllocatorType<string_t> alloc;
16714 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
16715 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
16716 break;
16717 }
16718
16719 case value_t::binary: {
16720 AllocatorType<binary_t> alloc;
16721 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
16722 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
16723 break;
16724 }
16725
16726 case value_t::null:
16727 case value_t::boolean:
16728 case value_t::number_integer:
16729 case value_t::number_unsigned:
16730 case value_t::number_float:
16731 case value_t::discarded:
16732 default: {
16733 break;
16734 }
16735 }
16736 }
16737 };
16738
16739 private:
16740 /*!
16741 @brief checks the class invariants
16742
16743 This function asserts the class invariants. It needs to be called at the
16744 end of every constructor to make sure that created objects respect the
16745 invariant. Furthermore, it has to be called each time the type of a JSON
16746 value is changed, because the invariant expresses a relationship between
16747 @a m_type and @a m_value.
16748
16749 Furthermore, the parent relation is checked for arrays and objects: If
16750 @a check_parents true and the value is an array or object, then the
16751 container's elements must have the current value as parent.
16752
16753 @param[in] check_parents whether the parent relation should be checked.
16754 The value is true by default and should only be set to false
16755 during destruction of objects when the invariant does not
16756 need to hold.
16757 */
16758 void assert_invariant(bool check_parents = true) const noexcept
16759 {
16760 JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
16761 JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
16762 JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
16763 JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
16764
16765#if JSON_DIAGNOSTICS
16766 JSON_TRY
16767 {
16768 // cppcheck-suppress assertWithSideEffect
16769 JSON_ASSERT(!check_parents || !is_structured()
16770 || std::all_of(begin(), end(), [this](const basic_json& j) { return j.m_parent == this; }));
16771 }
16772 JSON_CATCH(...) {} // LCOV_EXCL_LINE
16773#endif
16774 static_cast<void>(check_parents);
16775 }
16776
16778 {
16779#if JSON_DIAGNOSTICS
16780 switch (m_type) {
16781 case value_t::array: {
16782 for (auto& element : *m_value.array) {
16783 element.m_parent = this;
16784 }
16785 break;
16786 }
16787
16788 case value_t::object: {
16789 for (auto& element : *m_value.object) {
16790 element.second.m_parent = this;
16791 }
16792 break;
16793 }
16794
16795 case value_t::null:
16796 case value_t::string:
16797 case value_t::boolean:
16798 case value_t::number_integer:
16799 case value_t::number_unsigned:
16800 case value_t::number_float:
16801 case value_t::binary:
16802 case value_t::discarded:
16803 default:
16804 break;
16805 }
16806#endif
16807 }
16808
16810 {
16811#if JSON_DIAGNOSTICS
16812 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i) {
16813 (it + i)->m_parent = this;
16814 }
16815#else
16816 static_cast<void>(count_set_parents);
16817#endif
16818 return it;
16819 }
16820
16821 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
16822 {
16823#if JSON_DIAGNOSTICS
16824 if (old_capacity != static_cast<std::size_t>(-1)) {
16825 // see https://github.com/nlohmann/json/issues/2838
16826 JSON_ASSERT(type() == value_t::array);
16827 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) {
16828 // capacity has changed: update all parents
16829 set_parents();
16830 return j;
16831 }
16832 }
16833
16834 // ordered_json uses a vector internally, so pointers could have
16835 // been invalidated; see https://github.com/nlohmann/json/issues/2962
16836#ifdef JSON_HEDLEY_MSVC_VERSION
16837#pragma warning(push)
16838#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
16839#endif
16841 set_parents();
16842 return j;
16843 }
16844#ifdef JSON_HEDLEY_MSVC_VERSION
16845#pragma warning(pop)
16846#endif
16847
16848 j.m_parent = this;
16849#else
16850 static_cast<void>(j);
16851 static_cast<void>(old_capacity);
16852#endif
16853 return j;
16854 }
16855
16856 public:
16857 //////////////////////////
16858 // JSON parser callback //
16859 //////////////////////////
16860
16861 /// @brief parser event types
16862 /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
16863 using parse_event_t = detail::parse_event_t;
16864
16865 /// @brief per-element parser callback type
16866 /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
16867 using parser_callback_t = detail::parser_callback_t<basic_json>;
16868
16869 //////////////////
16870 // constructors //
16871 //////////////////
16872
16873 /// @name constructors and destructors
16874 /// Constructors of class @ref basic_json, copy/move constructor, copy
16875 /// assignment, static functions creating objects, and the destructor.
16876 /// @{
16877
16878 /// @brief create an empty value with a given type
16879 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
16880 basic_json(const value_t v)
16881 : m_type(v)
16882 , m_value(v)
16883 {
16885 }
16886
16887 /// @brief create a null object
16888 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
16889 basic_json(std::nullptr_t = nullptr) noexcept
16890 : basic_json(value_t::null)
16891 {
16893 }
16894
16895 /// @brief create a JSON value from compatible types
16896 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
16897 template<typename CompatibleType,
16899 detail::enable_if_t<!detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value,
16900 int> = 0>
16901 basic_json(CompatibleType&& val) noexcept(
16902 noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
16903 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(), std::forward<CompatibleType>(val))))
16904 {
16905 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
16906 set_parents();
16908 }
16909
16910 /// @brief create a JSON value from an existing one
16911 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
16912 template<typename BasicJsonType,
16913 detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value
16914 && !std::is_same<basic_json, BasicJsonType>::value,
16915 int> = 0>
16916 basic_json(const BasicJsonType& val)
16917 {
16918 using other_boolean_t = typename BasicJsonType::boolean_t;
16919 using other_number_float_t = typename BasicJsonType::number_float_t;
16920 using other_number_integer_t = typename BasicJsonType::number_integer_t;
16921 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
16922 using other_string_t = typename BasicJsonType::string_t;
16923 using other_object_t = typename BasicJsonType::object_t;
16924 using other_array_t = typename BasicJsonType::array_t;
16925 using other_binary_t = typename BasicJsonType::binary_t;
16926
16927 switch (val.type()) {
16928 case value_t::boolean:
16929 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
16930 break;
16931 case value_t::number_float:
16932 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
16933 break;
16934 case value_t::number_integer:
16935 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
16936 break;
16937 case value_t::number_unsigned:
16938 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
16939 break;
16940 case value_t::string:
16941 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
16942 break;
16943 case value_t::object:
16944 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
16945 break;
16946 case value_t::array:
16947 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
16948 break;
16949 case value_t::binary:
16950 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
16951 break;
16952 case value_t::null:
16953 *this = nullptr;
16954 break;
16955 case value_t::discarded:
16956 m_type = value_t::discarded;
16957 break;
16958 default: // LCOV_EXCL_LINE
16959 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16960 }
16961 set_parents();
16963 }
16964
16965 /// @brief create a container (array or object) from an initializer list
16966 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
16967 basic_json(initializer_list_t init, bool type_deduction = true, value_t manual_type = value_t::array)
16968 {
16969 // check if each element is an array with two elements whose first
16970 // element is a string
16971 bool is_an_object = std::all_of(init.begin(), init.end(), [](const detail::json_ref<basic_json>& element_ref) {
16972 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
16973 });
16974
16975 // adjust type if type deduction is not wanted
16976 if (!type_deduction) {
16977 // if array is wanted, do not create an object though possible
16978 if (manual_type == value_t::array) {
16979 is_an_object = false;
16980 }
16981
16982 // if object is wanted but impossible, throw an exception
16983 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) {
16984 JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json()));
16985 }
16986 }
16987
16988 if (is_an_object) {
16989 // the initializer list is a list of pairs -> create object
16990 m_type = value_t::object;
16991 m_value = value_t::object;
16992
16993 for (auto& element_ref : init) {
16994 auto element = element_ref.moved_or_copied();
16995 m_value.object->emplace(std::move(*((*element.m_value.array)[0].m_value.string)),
16996 std::move((*element.m_value.array)[1]));
16997 }
16998 } else {
16999 // the initializer list describes an array -> create array
17000 m_type = value_t::array;
17001 m_value.array = create<array_t>(init.begin(), init.end());
17002 }
17003
17004 set_parents();
17006 }
17007
17008 /// @brief explicitly create a binary array (without subtype)
17009 /// @sa https://json.nlohmann.me/api/basic_json/binary/
17011 static basic_json binary(const typename binary_t::container_type& init)
17012 {
17013 auto res = basic_json();
17014 res.m_type = value_t::binary;
17015 res.m_value = init;
17016 return res;
17017 }
17018
17019 /// @brief explicitly create a binary array (with subtype)
17020 /// @sa https://json.nlohmann.me/api/basic_json/binary/
17022 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
17023 {
17024 auto res = basic_json();
17025 res.m_type = value_t::binary;
17026 res.m_value = binary_t(init, subtype);
17027 return res;
17028 }
17029
17030 /// @brief explicitly create a binary array
17031 /// @sa https://json.nlohmann.me/api/basic_json/binary/
17033 static basic_json binary(typename binary_t::container_type&& init)
17034 {
17035 auto res = basic_json();
17036 res.m_type = value_t::binary;
17037 res.m_value = std::move(init);
17038 return res;
17039 }
17040
17041 /// @brief explicitly create a binary array (with subtype)
17042 /// @sa https://json.nlohmann.me/api/basic_json/binary/
17044 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
17045 {
17046 auto res = basic_json();
17047 res.m_type = value_t::binary;
17048 res.m_value = binary_t(std::move(init), subtype);
17049 return res;
17050 }
17051
17052 /// @brief explicitly create an array from an initializer list
17053 /// @sa https://json.nlohmann.me/api/basic_json/array/
17055 static basic_json array(initializer_list_t init = {}) { return basic_json(init, false, value_t::array); }
17056
17057 /// @brief explicitly create an object from an initializer list
17058 /// @sa https://json.nlohmann.me/api/basic_json/object/
17060 static basic_json object(initializer_list_t init = {}) { return basic_json(init, false, value_t::object); }
17061
17062 /// @brief construct an array with count copies of given value
17063 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
17064 basic_json(size_type cnt, const basic_json& val)
17065 : m_type(value_t::array)
17066 {
17067 m_value.array = create<array_t>(cnt, val);
17068 set_parents();
17070 }
17071
17072 /// @brief construct a JSON container given an iterator range
17073 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
17074 template<class InputIT,
17075 typename std::enable_if<std::is_same<InputIT, typename basic_json_t::iterator>::value
17076 || std::is_same<InputIT, typename basic_json_t::const_iterator>::value,
17077 int>::type = 0>
17078 basic_json(InputIT first, InputIT last)
17079 {
17080 JSON_ASSERT(first.m_object != nullptr);
17081 JSON_ASSERT(last.m_object != nullptr);
17082
17083 // make sure iterator fits the current value
17084 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) {
17085 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json()));
17086 }
17087
17088 // copy type from first iterator
17089 m_type = first.m_object->m_type;
17090
17091 // check if iterator range is complete for primitive values
17092 switch (m_type) {
17093 case value_t::boolean:
17094 case value_t::number_float:
17095 case value_t::number_integer:
17096 case value_t::number_unsigned:
17097 case value_t::string: {
17098 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
17099 || !last.m_it.primitive_iterator.is_end()))
17100 {
17101 JSON_THROW(invalid_iterator::create(204, "iterators out of range", *first.m_object));
17102 }
17103 break;
17104 }
17105
17106 case value_t::null:
17107 case value_t::object:
17108 case value_t::array:
17109 case value_t::binary:
17110 case value_t::discarded:
17111 default:
17112 break;
17113 }
17114
17115 switch (m_type) {
17116 case value_t::number_integer: {
17117 m_value.number_integer = first.m_object->m_value.number_integer;
17118 break;
17119 }
17120
17121 case value_t::number_unsigned: {
17122 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
17123 break;
17124 }
17125
17126 case value_t::number_float: {
17127 m_value.number_float = first.m_object->m_value.number_float;
17128 break;
17129 }
17130
17131 case value_t::boolean: {
17132 m_value.boolean = first.m_object->m_value.boolean;
17133 break;
17134 }
17135
17136 case value_t::string: {
17137 m_value = *first.m_object->m_value.string;
17138 break;
17139 }
17140
17141 case value_t::object: {
17142 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
17143 break;
17144 }
17145
17146 case value_t::array: {
17147 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
17148 break;
17149 }
17150
17151 case value_t::binary: {
17152 m_value = *first.m_object->m_value.binary;
17153 break;
17154 }
17155
17156 case value_t::null:
17157 case value_t::discarded:
17158 default:
17160 206, "cannot construct with iterators from " + std::string(first.m_object->type_name()),
17161 *first.m_object));
17162 }
17163
17164 set_parents();
17166 }
17167
17168 ///////////////////////////////////////
17169 // other constructors and destructor //
17170 ///////////////////////////////////////
17171
17172 template<typename JsonRef,
17174 std::is_same<typename JsonRef::value_type, basic_json>>::value,
17175 int> = 0>
17176 basic_json(const JsonRef& ref)
17177 : basic_json(ref.moved_or_copied())
17178 {}
17179
17180 /// @brief copy constructor
17181 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
17182 basic_json(const basic_json& other)
17183 : m_type(other.m_type)
17184 {
17185 // check of passed value is valid
17186 other.assert_invariant();
17187
17188 switch (m_type) {
17189 case value_t::object: {
17190 m_value = *other.m_value.object;
17191 break;
17192 }
17193
17194 case value_t::array: {
17195 m_value = *other.m_value.array;
17196 break;
17197 }
17198
17199 case value_t::string: {
17200 m_value = *other.m_value.string;
17201 break;
17202 }
17203
17204 case value_t::boolean: {
17205 m_value = other.m_value.boolean;
17206 break;
17207 }
17208
17209 case value_t::number_integer: {
17210 m_value = other.m_value.number_integer;
17211 break;
17212 }
17213
17214 case value_t::number_unsigned: {
17215 m_value = other.m_value.number_unsigned;
17216 break;
17217 }
17218
17219 case value_t::number_float: {
17220 m_value = other.m_value.number_float;
17221 break;
17222 }
17223
17224 case value_t::binary: {
17225 m_value = *other.m_value.binary;
17226 break;
17227 }
17228
17229 case value_t::null:
17230 case value_t::discarded:
17231 default:
17232 break;
17233 }
17234
17235 set_parents();
17237 }
17238
17239 /// @brief move constructor
17240 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
17242 : m_type(std::move(other.m_type))
17243 , m_value(std::move(other.m_value))
17244 {
17245 // check that passed value is valid
17246 other.assert_invariant(false);
17247
17248 // invalidate payload
17249 other.m_type = value_t::null;
17250 other.m_value = {};
17251
17252 set_parents();
17254 }
17255
17256 /// @brief copy assignment
17257 /// @sa https://json.nlohmann.me/api/basic_json/operator=/
17258 basic_json& operator=(basic_json other) noexcept(std::is_nothrow_move_constructible<value_t>::value
17259 && std::is_nothrow_move_assignable<value_t>::value
17260 && std::is_nothrow_move_constructible<json_value>::value
17261 && std::is_nothrow_move_assignable<json_value>::value)
17262 {
17263 // check that passed value is valid
17264 other.assert_invariant();
17265
17266 using std::swap;
17267 swap(m_type, other.m_type);
17268 swap(m_value, other.m_value);
17269
17270 set_parents();
17272 return *this;
17273 }
17274
17275 /// @brief destructor
17276 /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
17277 ~basic_json() noexcept
17278 {
17279 assert_invariant(false);
17280 m_value.destroy(m_type);
17281 }
17282
17283 /// @}
17284
17285 public:
17286 ///////////////////////
17287 // object inspection //
17288 ///////////////////////
17289
17290 /// @name object inspection
17291 /// Functions to inspect the type of a JSON value.
17292 /// @{
17293
17294 /// @brief serialization
17295 /// @sa https://json.nlohmann.me/api/basic_json/dump/
17296 string_t dump(const int indent = -1,
17297 const char indent_char = ' ',
17298 const bool ensure_ascii = false,
17299 const error_handler_t error_handler = error_handler_t::strict) const
17300 {
17301 string_t result;
17302 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
17303
17304 if (indent >= 0) {
17305 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
17306 } else {
17307 s.dump(*this, false, ensure_ascii, 0);
17308 }
17309
17310 return result;
17311 }
17312
17313 /// @brief return the type of the JSON value (explicit)
17314 /// @sa https://json.nlohmann.me/api/basic_json/type/
17315 constexpr value_t type() const noexcept { return m_type; }
17316
17317 /// @brief return whether type is primitive
17318 /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
17319 constexpr bool is_primitive() const noexcept
17320 {
17321 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
17322 }
17323
17324 /// @brief return whether type is structured
17325 /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
17326 constexpr bool is_structured() const noexcept { return is_array() || is_object(); }
17327
17328 /// @brief return whether value is null
17329 /// @sa https://json.nlohmann.me/api/basic_json/is_null/
17330 constexpr bool is_null() const noexcept { return m_type == value_t::null; }
17331
17332 /// @brief return whether value is a boolean
17333 /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
17334 constexpr bool is_boolean() const noexcept { return m_type == value_t::boolean; }
17335
17336 /// @brief return whether value is a number
17337 /// @sa https://json.nlohmann.me/api/basic_json/is_number/
17338 constexpr bool is_number() const noexcept { return is_number_integer() || is_number_float(); }
17339
17340 /// @brief return whether value is an integer number
17341 /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
17342 constexpr bool is_number_integer() const noexcept
17343 {
17344 return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
17345 }
17346
17347 /// @brief return whether value is an unsigned integer number
17348 /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
17349 constexpr bool is_number_unsigned() const noexcept { return m_type == value_t::number_unsigned; }
17350
17351 /// @brief return whether value is a floating-point number
17352 /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
17353 constexpr bool is_number_float() const noexcept { return m_type == value_t::number_float; }
17354
17355 /// @brief return whether value is an object
17356 /// @sa https://json.nlohmann.me/api/basic_json/is_object/
17357 constexpr bool is_object() const noexcept { return m_type == value_t::object; }
17358
17359 /// @brief return whether value is an array
17360 /// @sa https://json.nlohmann.me/api/basic_json/is_array/
17361 constexpr bool is_array() const noexcept { return m_type == value_t::array; }
17362
17363 /// @brief return whether value is a string
17364 /// @sa https://json.nlohmann.me/api/basic_json/is_string/
17365 constexpr bool is_string() const noexcept { return m_type == value_t::string; }
17366
17367 /// @brief return whether value is a binary array
17368 /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
17369 constexpr bool is_binary() const noexcept { return m_type == value_t::binary; }
17370
17371 /// @brief return whether value is discarded
17372 /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
17373 constexpr bool is_discarded() const noexcept { return m_type == value_t::discarded; }
17374
17375 /// @brief return the type of the JSON value (implicit)
17376 /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
17377 constexpr operator value_t() const noexcept { return m_type; }
17378
17379 /// @}
17380
17381 private:
17382 //////////////////
17383 // value access //
17384 //////////////////
17385
17386 /// get a boolean (explicit)
17387 boolean_t get_impl(boolean_t* /*unused*/) const
17388 {
17389 if (JSON_HEDLEY_LIKELY(is_boolean())) {
17390 return m_value.boolean;
17391 }
17392
17393 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this));
17394 }
17395
17396 /// get a pointer to the value (object)
17397 object_t* get_impl_ptr(object_t* /*unused*/) noexcept { return is_object() ? m_value.object : nullptr; }
17398
17399 /// get a pointer to the value (object)
17400 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
17401 {
17402 return is_object() ? m_value.object : nullptr;
17403 }
17404
17405 /// get a pointer to the value (array)
17406 array_t* get_impl_ptr(array_t* /*unused*/) noexcept { return is_array() ? m_value.array : nullptr; }
17407
17408 /// get a pointer to the value (array)
17409 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
17410 {
17411 return is_array() ? m_value.array : nullptr;
17412 }
17413
17414 /// get a pointer to the value (string)
17415 string_t* get_impl_ptr(string_t* /*unused*/) noexcept { return is_string() ? m_value.string : nullptr; }
17416
17417 /// get a pointer to the value (string)
17418 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
17419 {
17420 return is_string() ? m_value.string : nullptr;
17421 }
17422
17423 /// get a pointer to the value (boolean)
17424 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept { return is_boolean() ? &m_value.boolean : nullptr; }
17425
17426 /// get a pointer to the value (boolean)
17427 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
17428 {
17429 return is_boolean() ? &m_value.boolean : nullptr;
17430 }
17431
17432 /// get a pointer to the value (integer number)
17433 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
17434 {
17435 return is_number_integer() ? &m_value.number_integer : nullptr;
17436 }
17437
17438 /// get a pointer to the value (integer number)
17439 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
17440 {
17441 return is_number_integer() ? &m_value.number_integer : nullptr;
17442 }
17443
17444 /// get a pointer to the value (unsigned number)
17445 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
17446 {
17447 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
17448 }
17449
17450 /// get a pointer to the value (unsigned number)
17451 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
17452 {
17453 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
17454 }
17455
17456 /// get a pointer to the value (floating-point number)
17457 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
17458 {
17459 return is_number_float() ? &m_value.number_float : nullptr;
17460 }
17461
17462 /// get a pointer to the value (floating-point number)
17463 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
17464 {
17465 return is_number_float() ? &m_value.number_float : nullptr;
17466 }
17467
17468 /// get a pointer to the value (binary)
17469 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept { return is_binary() ? m_value.binary : nullptr; }
17470
17471 /// get a pointer to the value (binary)
17472 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
17473 {
17474 return is_binary() ? m_value.binary : nullptr;
17475 }
17476
17477 /*!
17478 @brief helper function to implement get_ref()
17479
17480 This function helps to implement get_ref() without code duplication for
17481 const and non-const overloads
17482
17483 @tparam ThisType will be deduced as `basic_json` or `const basic_json`
17484
17485 @throw type_error.303 if ReferenceType does not match underlying value
17486 type of the current JSON
17487 */
17488 template<typename ReferenceType, typename ThisType>
17489 static ReferenceType get_ref_impl(ThisType& obj)
17490 {
17491 // delegate the call to get_ptr<>()
17492 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
17493
17494 if (JSON_HEDLEY_LIKELY(ptr != nullptr)) {
17495 return *ptr;
17496 }
17497
17499 303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj));
17500 }
17501
17502 public:
17503 /// @name value access
17504 /// Direct access to the stored value of a JSON value.
17505 /// @{
17506
17507 /// @brief get a pointer value (implicit)
17508 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
17509 template<typename PointerType, typename std::enable_if<std::is_pointer<PointerType>::value, int>::type = 0>
17510 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
17511 {
17512 // delegate the call to get_impl_ptr<>()
17513 return get_impl_ptr(static_cast<PointerType>(nullptr));
17514 }
17515
17516 /// @brief get a pointer value (implicit)
17517 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
17518 template<typename PointerType,
17519 typename std::enable_if<std::is_pointer<PointerType>::value
17520 && std::is_const<typename std::remove_pointer<PointerType>::type>::value,
17521 int>::type = 0>
17522 constexpr auto get_ptr() const noexcept
17523 -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
17524 {
17525 // delegate the call to get_impl_ptr<>() const
17526 return get_impl_ptr(static_cast<PointerType>(nullptr));
17527 }
17528
17529 private:
17530 /*!
17531 @brief get a value (explicit)
17532
17533 Explicit type conversion between the JSON value and a compatible value
17534 which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
17535 and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
17536 The value is converted by calling the @ref json_serializer<ValueType>
17537 `from_json()` method.
17538
17539 The function is equivalent to executing
17540 @code {.cpp}
17541 ValueType ret;
17542 JSONSerializer<ValueType>::from_json(*this, ret);
17543 return ret;
17544 @endcode
17545
17546 This overloads is chosen if:
17547 - @a ValueType is not @ref basic_json,
17548 - @ref json_serializer<ValueType> has a `from_json()` method of the form
17549 `void from_json(const basic_json&, ValueType&)`, and
17550 - @ref json_serializer<ValueType> does not have a `from_json()` method of
17551 the form `ValueType from_json(const basic_json&)`
17552
17553 @tparam ValueType the returned value type
17554
17555 @return copy of the JSON value, converted to @a ValueType
17556
17557 @throw what @ref json_serializer<ValueType> `from_json()` method throws
17558
17559 @liveexample{The example below shows several conversions from JSON values
17560 to other types. There a few things to note: (1) Floating-point numbers can
17561 be converted to integers\, (2) A JSON array can be converted to a standard
17562 `std::vector<short>`\, (3) A JSON object can be converted to C++
17563 associative containers such as `std::unordered_map<std::string\,
17564 json>`.,get__ValueType_const}
17565
17566 @since version 2.1.0
17567 */
17568 template<typename ValueType,
17569 detail::enable_if_t<detail::is_default_constructible<ValueType>::value
17570 && detail::has_from_json<basic_json_t, ValueType>::value,
17571 int> = 0>
17572 ValueType get_impl(detail::priority_tag<0> /*unused*/) const
17573 noexcept(noexcept(JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(),
17574 std::declval<ValueType&>())))
17575 {
17576 auto ret = ValueType();
17577 JSONSerializer<ValueType>::from_json(*this, ret);
17578 return ret;
17579 }
17580
17581 /*!
17582 @brief get a value (explicit); special case
17583
17584 Explicit type conversion between the JSON value and a compatible value
17585 which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
17586 and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
17587 The value is converted by calling the @ref json_serializer<ValueType>
17588 `from_json()` method.
17589
17590 The function is equivalent to executing
17591 @code {.cpp}
17592 return JSONSerializer<ValueType>::from_json(*this);
17593 @endcode
17594
17595 This overloads is chosen if:
17596 - @a ValueType is not @ref basic_json and
17597 - @ref json_serializer<ValueType> has a `from_json()` method of the form
17598 `ValueType from_json(const basic_json&)`
17599
17600 @note If @ref json_serializer<ValueType> has both overloads of
17601 `from_json()`, this one is chosen.
17602
17603 @tparam ValueType the returned value type
17604
17605 @return copy of the JSON value, converted to @a ValueType
17606
17607 @throw what @ref json_serializer<ValueType> `from_json()` method throws
17608
17609 @since version 2.1.0
17610 */
17611 template<typename ValueType,
17612 detail::enable_if_t<detail::has_non_default_from_json<basic_json_t, ValueType>::value, int> = 0>
17613 ValueType get_impl(detail::priority_tag<1> /*unused*/) const
17614 noexcept(noexcept(JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
17615 {
17616 return JSONSerializer<ValueType>::from_json(*this);
17617 }
17618
17619 /*!
17620 @brief get special-case overload
17621
17622 This overloads converts the current @ref basic_json in a different
17623 @ref basic_json type
17624
17625 @tparam BasicJsonType == @ref basic_json
17626
17627 @return a copy of *this, converted into @a BasicJsonType
17628
17629 @complexity Depending on the implementation of the called `from_json()`
17630 method.
17631
17632 @since version 3.2.0
17633 */
17634 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
17635 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
17636 {
17637 return *this;
17638 }
17639
17640 /*!
17641 @brief get special-case overload
17642
17643 This overloads avoids a lot of template boilerplate, it can be seen as the
17644 identity method
17645
17646 @tparam BasicJsonType == @ref basic_json
17647
17648 @return a copy of *this
17649
17650 @complexity Constant.
17651
17652 @since version 2.1.0
17653 */
17654 template<typename BasicJsonType, detail::enable_if_t<std::is_same<BasicJsonType, basic_json_t>::value, int> = 0>
17655 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
17656 {
17657 return *this;
17658 }
17659
17660 /*!
17661 @brief get a pointer value (explicit)
17662 @copydoc get()
17663 */
17664 template<typename PointerType, detail::enable_if_t<std::is_pointer<PointerType>::value, int> = 0>
17665 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
17666 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
17667 {
17668 // delegate the call to get_ptr
17669 return get_ptr<PointerType>();
17670 }
17671
17672 public:
17673 /*!
17674 @brief get a (pointer) value (explicit)
17675
17676 Performs explicit type conversion between the JSON value and a compatible value if required.
17677
17678 - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
17679 No copies are made.
17680
17681 - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
17682 from the current @ref basic_json.
17683
17684 - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
17685 method.
17686
17687 @tparam ValueTypeCV the provided value type
17688 @tparam ValueType the returned value type
17689
17690 @return copy of the JSON value, converted to @tparam ValueType if necessary
17691
17692 @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
17693
17694 @since version 2.1.0
17695 */
17696 template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
17697#if defined(JSON_HAS_CPP_14)
17698 constexpr
17699#endif
17700 auto
17701 get() const
17702 noexcept(noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4>{})))
17703 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4>{}))
17704 {
17705 // we cannot static_assert on ValueTypeCV being non-const, because
17706 // there is support for get<const basic_json_t>(), which is why we
17707 // still need the uncvref
17708 static_assert(!std::is_reference<ValueTypeCV>::value,
17709 "get() cannot be used with reference types, you might want to use get_ref()");
17710 return get_impl<ValueType>(detail::priority_tag<4>{});
17711 }
17712
17713 /*!
17714 @brief get a pointer value (explicit)
17715
17716 Explicit pointer access to the internally stored JSON value. No copies are
17717 made.
17718
17719 @warning The pointer becomes invalid if the underlying JSON object
17720 changes.
17721
17722 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
17723 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
17724 @ref number_unsigned_t, or @ref number_float_t.
17725
17726 @return pointer to the internally stored JSON value if the requested
17727 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
17728
17729 @complexity Constant.
17730
17731 @liveexample{The example below shows how pointers to internal values of a
17732 JSON value can be requested. Note that no type conversions are made and a
17733 `nullptr` is returned if the value and the requested pointer type does not
17734 match.,get__PointerType}
17735
17736 @sa see @ref get_ptr() for explicit pointer-member access
17737
17738 @since version 1.0.0
17739 */
17740 template<typename PointerType, typename std::enable_if<std::is_pointer<PointerType>::value, int>::type = 0>
17741 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
17742 {
17743 // delegate the call to get_ptr
17744 return get_ptr<PointerType>();
17745 }
17746
17747 /// @brief get a value (explicit)
17748 /// @sa https://json.nlohmann.me/api/basic_json/get_to/
17749 template<typename ValueType,
17750 detail::enable_if_t<!detail::is_basic_json<ValueType>::value
17751 && detail::has_from_json<basic_json_t, ValueType>::value,
17752 int> = 0>
17753 ValueType& get_to(ValueType& v) const
17754 noexcept(noexcept(JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
17755 {
17756 JSONSerializer<ValueType>::from_json(*this, v);
17757 return v;
17758 }
17759
17760 // specialization to allow calling get_to with a basic_json value
17761 // see https://github.com/nlohmann/json/issues/2175
17762 template<typename ValueType, detail::enable_if_t<detail::is_basic_json<ValueType>::value, int> = 0>
17763 ValueType& get_to(ValueType& v) const
17764 {
17765 v = *this;
17766 return v;
17767 }
17768
17769 template<typename T,
17770 std::size_t N,
17771 typename Array =
17772 T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
17773 detail::enable_if_t<detail::has_from_json<basic_json_t, Array>::value, int> = 0>
17774 Array get_to(
17775 T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
17776 noexcept(noexcept(JSONSerializer<Array>::from_json(std::declval<const basic_json_t&>(), v)))
17777 {
17778 JSONSerializer<Array>::from_json(*this, v);
17779 return v;
17780 }
17781
17782 /// @brief get a reference value (implicit)
17783 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
17784 template<typename ReferenceType, typename std::enable_if<std::is_reference<ReferenceType>::value, int>::type = 0>
17785 ReferenceType get_ref()
17786 {
17787 // delegate call to get_ref_impl
17788 return get_ref_impl<ReferenceType>(*this);
17789 }
17790
17791 /// @brief get a reference value (implicit)
17792 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
17793 template<typename ReferenceType,
17794 typename std::enable_if<std::is_reference<ReferenceType>::value
17795 && std::is_const<typename std::remove_reference<ReferenceType>::type>::value,
17796 int>::type = 0>
17797 ReferenceType get_ref() const
17798 {
17799 // delegate call to get_ref_impl
17800 return get_ref_impl<ReferenceType>(*this);
17801 }
17802
17803 /*!
17804 @brief get a value (implicit)
17805
17806 Implicit type conversion between the JSON value and a compatible value.
17807 The call is realized by calling @ref get() const.
17808
17809 @tparam ValueType non-pointer type compatible to the JSON value, for
17810 instance `int` for JSON integer numbers, `bool` for JSON booleans, or
17811 `std::vector` types for JSON arrays. The character type of @ref string_t
17812 as well as an initializer list of this type is excluded to avoid
17813 ambiguities as these types implicitly convert to `std::string`.
17814
17815 @return copy of the JSON value, converted to type @a ValueType
17816
17817 @throw type_error.302 in case passed type @a ValueType is incompatible
17818 to the JSON value type (e.g., the JSON value is of type boolean, but a
17819 string is requested); see example below
17820
17821 @complexity Linear in the size of the JSON value.
17822
17823 @liveexample{The example below shows several conversions from JSON values
17824 to other types. There a few things to note: (1) Floating-point numbers can
17825 be converted to integers\, (2) A JSON array can be converted to a standard
17826 `std::vector<short>`\, (3) A JSON object can be converted to C++
17827 associative containers such as `std::unordered_map<std::string\,
17828 json>`.,operator__ValueType}
17829
17830 @since version 1.0.0
17831 */
17832 template<typename ValueType,
17833 typename std::enable_if<
17834 detail::conjunction<
17835 detail::negation<std::is_pointer<ValueType>>,
17836 detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
17837 detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
17838 detail::negation<detail::is_basic_json<ValueType>>,
17839 detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
17840
17841#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
17842 detail::negation<std::is_same<ValueType, std::string_view>>,
17843#endif
17844 detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>>::value,
17845 int>::type = 0>
17846 JSON_EXPLICIT operator ValueType() const
17847 {
17848 // delegate the call to get<>() const
17849 return get<ValueType>();
17850 }
17851
17852 /// @brief get a binary value
17853 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
17854 binary_t& get_binary()
17855 {
17856 if (!is_binary()) {
17857 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
17858 }
17859
17860 return *get_ptr<binary_t*>();
17861 }
17862
17863 /// @brief get a binary value
17864 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
17865 const binary_t& get_binary() const
17866 {
17867 if (!is_binary()) {
17868 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
17869 }
17870
17871 return *get_ptr<const binary_t*>();
17872 }
17873
17874 /// @}
17875
17876 ////////////////////
17877 // element access //
17878 ////////////////////
17879
17880 /// @name element access
17881 /// Access to the JSON value.
17882 /// @{
17883
17884 /// @brief access specified array element with bounds checking
17885 /// @sa https://json.nlohmann.me/api/basic_json/at/
17887 {
17888 // at only works for arrays
17889 if (JSON_HEDLEY_LIKELY(is_array())) {
17890 JSON_TRY
17891 {
17892 return set_parent(m_value.array->at(idx));
17893 }
17894 JSON_CATCH(std::out_of_range&)
17895 {
17896 // create better exception explanation
17897 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
17898 }
17899 } else {
17900 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
17901 }
17902 }
17903
17904 /// @brief access specified array element with bounds checking
17905 /// @sa https://json.nlohmann.me/api/basic_json/at/
17906 const_reference at(size_type idx) const
17907 {
17908 // at only works for arrays
17909 if (JSON_HEDLEY_LIKELY(is_array())) {
17910 JSON_TRY
17911 {
17912 return m_value.array->at(idx);
17913 }
17914 JSON_CATCH(std::out_of_range&)
17915 {
17916 // create better exception explanation
17917 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
17918 }
17919 } else {
17920 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
17921 }
17922 }
17923
17924 /// @brief access specified object element with bounds checking
17925 /// @sa https://json.nlohmann.me/api/basic_json/at/
17926 reference at(const typename object_t::key_type& key)
17927 {
17928 // at only works for objects
17929 if (JSON_HEDLEY_LIKELY(is_object())) {
17930 JSON_TRY
17931 {
17932 return set_parent(m_value.object->at(key));
17933 }
17934 JSON_CATCH(std::out_of_range&)
17935 {
17936 // create better exception explanation
17937 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
17938 }
17939 } else {
17940 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
17941 }
17942 }
17943
17944 /// @brief access specified object element with bounds checking
17945 /// @sa https://json.nlohmann.me/api/basic_json/at/
17946 const_reference at(const typename object_t::key_type& key) const
17947 {
17948 // at only works for objects
17949 if (JSON_HEDLEY_LIKELY(is_object())) {
17950 JSON_TRY
17951 {
17952 return m_value.object->at(key);
17953 }
17954 JSON_CATCH(std::out_of_range&)
17955 {
17956 // create better exception explanation
17957 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
17958 }
17959 } else {
17960 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
17961 }
17962 }
17963
17964 /// @brief access specified array element
17965 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
17967 {
17968 // implicitly convert null value to an empty array
17969 if (is_null()) {
17970 m_type = value_t::array;
17971 m_value.array = create<array_t>();
17973 }
17974
17975 // operator[] only works for arrays
17976 if (JSON_HEDLEY_LIKELY(is_array())) {
17977 // fill up array with null values if given idx is outside range
17978 if (idx >= m_value.array->size()) {
17979#if JSON_DIAGNOSTICS
17980 // remember array size & capacity before resizing
17981 const auto old_size = m_value.array->size();
17982 const auto old_capacity = m_value.array->capacity();
17983#endif
17984 m_value.array->resize(idx + 1);
17985
17986#if JSON_DIAGNOSTICS
17987 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) {
17988 // capacity has changed: update all parents
17989 set_parents();
17990 } else {
17991 // set parent for values added above
17992 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size),
17993 static_cast<typename iterator::difference_type>(idx + 1 - old_size));
17994 }
17995#endif
17997 }
17998
17999 return m_value.array->operator[](idx);
18000 }
18001
18003 305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
18004 }
18005
18006 /// @brief access specified array element
18007 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
18009 {
18010 // const operator[] only works for arrays
18011 if (JSON_HEDLEY_LIKELY(is_array())) {
18012 return m_value.array->operator[](idx);
18013 }
18014
18016 305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
18017 }
18018
18019 /// @brief access specified object element
18020 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
18021 reference operator[](const typename object_t::key_type& key)
18022 {
18023 // implicitly convert null value to an empty object
18024 if (is_null()) {
18025 m_type = value_t::object;
18026 m_value.object = create<object_t>();
18028 }
18029
18030 // operator[] only works for objects
18031 if (JSON_HEDLEY_LIKELY(is_object())) {
18032 return set_parent(m_value.object->operator[](key));
18033 }
18034
18036 305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
18037 }
18038
18039 /// @brief access specified object element
18040 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
18041 const_reference operator[](const typename object_t::key_type& key) const
18042 {
18043 // const operator[] only works for objects
18044 if (JSON_HEDLEY_LIKELY(is_object())) {
18045 JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
18046 return m_value.object->find(key)->second;
18047 }
18048
18050 305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
18051 }
18052
18053 /// @brief access specified object element
18054 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
18055 template<typename T>
18057 reference operator[](T* key)
18058 {
18059 // implicitly convert null to object
18060 if (is_null()) {
18061 m_type = value_t::object;
18062 m_value = value_t::object;
18064 }
18065
18066 // at only works for objects
18067 if (JSON_HEDLEY_LIKELY(is_object())) {
18068 return set_parent(m_value.object->operator[](key));
18069 }
18070
18072 305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
18073 }
18074
18075 /// @brief access specified object element
18076 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
18077 template<typename T>
18079 const_reference operator[](T* key) const
18080 {
18081 // at only works for objects
18082 if (JSON_HEDLEY_LIKELY(is_object())) {
18083 JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
18084 return m_value.object->find(key)->second;
18085 }
18086
18088 305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
18089 }
18090
18091 /// @brief access specified object element with default value
18092 /// @sa https://json.nlohmann.me/api/basic_json/value/
18093 /// using std::is_convertible in a std::enable_if will fail when using explicit conversions
18094 template<class ValueType,
18095 typename std::enable_if<detail::is_getable<basic_json_t, ValueType>::value
18096 && !std::is_same<value_t, ValueType>::value,
18097 int>::type = 0>
18098 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
18099 {
18100 // at only works for objects
18101 if (JSON_HEDLEY_LIKELY(is_object())) {
18102 // if key is found, return value and given default value otherwise
18103 const auto it = find(key);
18104 if (it != end()) {
18105 return it->template get<ValueType>();
18106 }
18107
18108 return default_value;
18109 }
18110
18111 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
18112 }
18113
18114 /// @brief access specified object element with default value
18115 /// @sa https://json.nlohmann.me/api/basic_json/value/
18116 /// overload for a default value of type const char*
18117 string_t value(const typename object_t::key_type& key, const char* default_value) const
18118 {
18119 return value(key, string_t(default_value));
18120 }
18121
18122 /// @brief access specified object element via JSON Pointer with default value
18123 /// @sa https://json.nlohmann.me/api/basic_json/value/
18124 template<class ValueType,
18125 typename std::enable_if<detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
18126 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
18127 {
18128 // at only works for objects
18129 if (JSON_HEDLEY_LIKELY(is_object())) {
18130 // if pointer resolves a value, return it or use default value
18131 JSON_TRY
18132 {
18133 return ptr.get_checked(this).template get<ValueType>();
18134 }
18136 {
18137 return default_value;
18138 }
18139 }
18140
18141 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
18142 }
18143
18144 /// @brief access specified object element via JSON Pointer with default value
18145 /// @sa https://json.nlohmann.me/api/basic_json/value/
18146 /// overload for a default value of type const char*
18148 string_t value(const json_pointer& ptr, const char* default_value) const
18149 {
18150 return value(ptr, string_t(default_value));
18151 }
18152
18153 /// @brief access the first element
18154 /// @sa https://json.nlohmann.me/api/basic_json/front/
18155 reference front() { return *begin(); }
18156
18157 /// @brief access the first element
18158 /// @sa https://json.nlohmann.me/api/basic_json/front/
18159 const_reference front() const { return *cbegin(); }
18160
18161 /// @brief access the last element
18162 /// @sa https://json.nlohmann.me/api/basic_json/back/
18163 reference back()
18164 {
18165 auto tmp = end();
18166 --tmp;
18167 return *tmp;
18168 }
18169
18170 /// @brief access the last element
18171 /// @sa https://json.nlohmann.me/api/basic_json/back/
18172 const_reference back() const
18173 {
18174 auto tmp = cend();
18175 --tmp;
18176 return *tmp;
18177 }
18178
18179 /// @brief remove element given an iterator
18180 /// @sa https://json.nlohmann.me/api/basic_json/erase/
18181 template<class IteratorType,
18182 typename std::enable_if<std::is_same<IteratorType, typename basic_json_t::iterator>::value
18183 || std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
18184 int>::type = 0>
18185 IteratorType erase(IteratorType pos)
18186 {
18187 // make sure iterator fits the current value
18188 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) {
18189 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
18190 }
18191
18192 IteratorType result = end();
18193
18194 switch (m_type) {
18195 case value_t::boolean:
18196 case value_t::number_float:
18197 case value_t::number_integer:
18198 case value_t::number_unsigned:
18199 case value_t::string:
18200 case value_t::binary: {
18201 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) {
18202 JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this));
18203 }
18204
18205 if (is_string()) {
18206 AllocatorType<string_t> alloc;
18207 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
18208 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
18209 m_value.string = nullptr;
18210 } else if (is_binary()) {
18211 AllocatorType<binary_t> alloc;
18212 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
18213 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
18214 m_value.binary = nullptr;
18215 }
18216
18217 m_type = value_t::null;
18219 break;
18220 }
18221
18222 case value_t::object: {
18223 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
18224 break;
18225 }
18226
18227 case value_t::array: {
18228 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
18229 break;
18230 }
18231
18232 case value_t::null:
18233 case value_t::discarded:
18234 default:
18235 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
18236 }
18237
18238 return result;
18239 }
18240
18241 /// @brief remove elements given an iterator range
18242 /// @sa https://json.nlohmann.me/api/basic_json/erase/
18243 template<class IteratorType,
18244 typename std::enable_if<std::is_same<IteratorType, typename basic_json_t::iterator>::value
18245 || std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
18246 int>::type = 0>
18247 IteratorType erase(IteratorType first, IteratorType last)
18248 {
18249 // make sure iterator fits the current value
18250 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) {
18251 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this));
18252 }
18253
18254 IteratorType result = end();
18255
18256 switch (m_type) {
18257 case value_t::boolean:
18258 case value_t::number_float:
18259 case value_t::number_integer:
18260 case value_t::number_unsigned:
18261 case value_t::string:
18262 case value_t::binary: {
18263 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
18264 || !last.m_it.primitive_iterator.is_end()))
18265 {
18266 JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this));
18267 }
18268
18269 if (is_string()) {
18270 AllocatorType<string_t> alloc;
18271 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
18272 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
18273 m_value.string = nullptr;
18274 } else if (is_binary()) {
18275 AllocatorType<binary_t> alloc;
18276 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
18277 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
18278 m_value.binary = nullptr;
18279 }
18280
18281 m_type = value_t::null;
18283 break;
18284 }
18285
18286 case value_t::object: {
18287 result.m_it.object_iterator =
18288 m_value.object->erase(first.m_it.object_iterator, last.m_it.object_iterator);
18289 break;
18290 }
18291
18292 case value_t::array: {
18293 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, last.m_it.array_iterator);
18294 break;
18295 }
18296
18297 case value_t::null:
18298 case value_t::discarded:
18299 default:
18300 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
18301 }
18302
18303 return result;
18304 }
18305
18306 /// @brief remove element from a JSON object given a key
18307 /// @sa https://json.nlohmann.me/api/basic_json/erase/
18308 size_type erase(const typename object_t::key_type& key)
18309 {
18310 // this erase only works for objects
18311 if (JSON_HEDLEY_LIKELY(is_object())) {
18312 return m_value.object->erase(key);
18313 }
18314
18315 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
18316 }
18317
18318 /// @brief remove element from a JSON array given an index
18319 /// @sa https://json.nlohmann.me/api/basic_json/erase/
18320 void erase(const size_type idx)
18321 {
18322 // this erase only works for arrays
18323 if (JSON_HEDLEY_LIKELY(is_array())) {
18324 if (JSON_HEDLEY_UNLIKELY(idx >= size())) {
18325 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
18326 }
18327
18328 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
18329 } else {
18330 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
18331 }
18332 }
18333
18334 /// @}
18335
18336 ////////////
18337 // lookup //
18338 ////////////
18339
18340 /// @name lookup
18341 /// @{
18342
18343 /// @brief find an element in a JSON object
18344 /// @sa https://json.nlohmann.me/api/basic_json/find/
18345 template<typename KeyT>
18346 iterator find(KeyT&& key)
18347 {
18348 auto result = end();
18349
18350 if (is_object()) {
18351 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
18352 }
18353
18354 return result;
18355 }
18356
18357 /// @brief find an element in a JSON object
18358 /// @sa https://json.nlohmann.me/api/basic_json/find/
18359 template<typename KeyT>
18360 const_iterator find(KeyT&& key) const
18361 {
18362 auto result = cend();
18363
18364 if (is_object()) {
18365 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
18366 }
18367
18368 return result;
18369 }
18370
18371 /// @brief returns the number of occurrences of a key in a JSON object
18372 /// @sa https://json.nlohmann.me/api/basic_json/count/
18373 template<typename KeyT>
18374 size_type count(KeyT&& key) const
18375 {
18376 // return 0 for all nonobject types
18377 return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
18378 }
18379
18380 /// @brief check the existence of an element in a JSON object
18381 /// @sa https://json.nlohmann.me/api/basic_json/contains/
18382 template<
18383 typename KeyT,
18384 typename std::enable_if<!std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int>::type = 0>
18385 bool contains(KeyT&& key) const
18386 {
18387 return is_object() && m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
18388 }
18389
18390 /// @brief check the existence of an element in a JSON object given a JSON pointer
18391 /// @sa https://json.nlohmann.me/api/basic_json/contains/
18392 bool contains(const json_pointer& ptr) const { return ptr.contains(this); }
18393
18394 /// @}
18395
18396 ///////////////
18397 // iterators //
18398 ///////////////
18399
18400 /// @name iterators
18401 /// @{
18402
18403 /// @brief returns an iterator to the first element
18404 /// @sa https://json.nlohmann.me/api/basic_json/begin/
18405 iterator begin() noexcept
18406 {
18407 iterator result(this);
18408 result.set_begin();
18409 return result;
18410 }
18411
18412 /// @brief returns an iterator to the first element
18413 /// @sa https://json.nlohmann.me/api/basic_json/begin/
18414 const_iterator begin() const noexcept { return cbegin(); }
18415
18416 /// @brief returns a const iterator to the first element
18417 /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
18418 const_iterator cbegin() const noexcept
18419 {
18420 const_iterator result(this);
18421 result.set_begin();
18422 return result;
18423 }
18424
18425 /// @brief returns an iterator to one past the last element
18426 /// @sa https://json.nlohmann.me/api/basic_json/end/
18427 iterator end() noexcept
18428 {
18429 iterator result(this);
18430 result.set_end();
18431 return result;
18432 }
18433
18434 /// @brief returns an iterator to one past the last element
18435 /// @sa https://json.nlohmann.me/api/basic_json/end/
18436 const_iterator end() const noexcept { return cend(); }
18437
18438 /// @brief returns an iterator to one past the last element
18439 /// @sa https://json.nlohmann.me/api/basic_json/cend/
18440 const_iterator cend() const noexcept
18441 {
18442 const_iterator result(this);
18443 result.set_end();
18444 return result;
18445 }
18446
18447 /// @brief returns an iterator to the reverse-beginning
18448 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
18449 reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
18450
18451 /// @brief returns an iterator to the reverse-beginning
18452 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
18453 const_reverse_iterator rbegin() const noexcept { return crbegin(); }
18454
18455 /// @brief returns an iterator to the reverse-end
18456 /// @sa https://json.nlohmann.me/api/basic_json/rend/
18457 reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
18458
18459 /// @brief returns an iterator to the reverse-end
18460 /// @sa https://json.nlohmann.me/api/basic_json/rend/
18461 const_reverse_iterator rend() const noexcept { return crend(); }
18462
18463 /// @brief returns a const reverse iterator to the last element
18464 /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
18465 const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
18466
18467 /// @brief returns a const reverse iterator to one before the first
18468 /// @sa https://json.nlohmann.me/api/basic_json/crend/
18469 const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }
18470
18471 public:
18472 /// @brief wrapper to access iterator member functions in range-based for
18473 /// @sa https://json.nlohmann.me/api/basic_json/items/
18474 /// @deprecated This function is deprecated since 3.1.0 and will be removed in
18475 /// version 4.0.0 of the library. Please use @ref items() instead;
18476 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
18477 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
18478 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept { return ref.items(); }
18479
18480 /// @brief wrapper to access iterator member functions in range-based for
18481 /// @sa https://json.nlohmann.me/api/basic_json/items/
18482 /// @deprecated This function is deprecated since 3.1.0 and will be removed in
18483 /// version 4.0.0 of the library. Please use @ref items() instead;
18484 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
18485 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
18486 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept { return ref.items(); }
18487
18488 /// @brief helper to access iterator member functions in range-based for
18489 /// @sa https://json.nlohmann.me/api/basic_json/items/
18490 iteration_proxy<iterator> items() noexcept { return iteration_proxy<iterator>(*this); }
18491
18492 /// @brief helper to access iterator member functions in range-based for
18493 /// @sa https://json.nlohmann.me/api/basic_json/items/
18494 iteration_proxy<const_iterator> items() const noexcept { return iteration_proxy<const_iterator>(*this); }
18495
18496 /// @}
18497
18498 //////////////
18499 // capacity //
18500 //////////////
18501
18502 /// @name capacity
18503 /// @{
18504
18505 /// @brief checks whether the container is empty.
18506 /// @sa https://json.nlohmann.me/api/basic_json/empty/
18507 bool empty() const noexcept
18508 {
18509 switch (m_type) {
18510 case value_t::null: {
18511 // null values are empty
18512 return true;
18513 }
18514
18515 case value_t::array: {
18516 // delegate call to array_t::empty()
18517 return m_value.array->empty();
18518 }
18519
18520 case value_t::object: {
18521 // delegate call to object_t::empty()
18522 return m_value.object->empty();
18523 }
18524
18525 case value_t::string:
18526 case value_t::boolean:
18527 case value_t::number_integer:
18528 case value_t::number_unsigned:
18529 case value_t::number_float:
18530 case value_t::binary:
18531 case value_t::discarded:
18532 default: {
18533 // all other types are nonempty
18534 return false;
18535 }
18536 }
18537 }
18538
18539 /// @brief returns the number of elements
18540 /// @sa https://json.nlohmann.me/api/basic_json/size/
18541 size_type size() const noexcept
18542 {
18543 switch (m_type) {
18544 case value_t::null: {
18545 // null values are empty
18546 return 0;
18547 }
18548
18549 case value_t::array: {
18550 // delegate call to array_t::size()
18551 return m_value.array->size();
18552 }
18553
18554 case value_t::object: {
18555 // delegate call to object_t::size()
18556 return m_value.object->size();
18557 }
18558
18559 case value_t::string:
18560 case value_t::boolean:
18561 case value_t::number_integer:
18562 case value_t::number_unsigned:
18563 case value_t::number_float:
18564 case value_t::binary:
18565 case value_t::discarded:
18566 default: {
18567 // all other types have size 1
18568 return 1;
18569 }
18570 }
18571 }
18572
18573 /// @brief returns the maximum possible number of elements
18574 /// @sa https://json.nlohmann.me/api/basic_json/max_size/
18575 size_type max_size() const noexcept
18576 {
18577 switch (m_type) {
18578 case value_t::array: {
18579 // delegate call to array_t::max_size()
18580 return m_value.array->max_size();
18581 }
18582
18583 case value_t::object: {
18584 // delegate call to object_t::max_size()
18585 return m_value.object->max_size();
18586 }
18587
18588 case value_t::null:
18589 case value_t::string:
18590 case value_t::boolean:
18591 case value_t::number_integer:
18592 case value_t::number_unsigned:
18593 case value_t::number_float:
18594 case value_t::binary:
18595 case value_t::discarded:
18596 default: {
18597 // all other types have max_size() == size()
18598 return size();
18599 }
18600 }
18601 }
18602
18603 /// @}
18604
18605 ///////////////
18606 // modifiers //
18607 ///////////////
18608
18609 /// @name modifiers
18610 /// @{
18611
18612 /// @brief clears the contents
18613 /// @sa https://json.nlohmann.me/api/basic_json/clear/
18614 void clear() noexcept
18615 {
18616 switch (m_type) {
18617 case value_t::number_integer: {
18618 m_value.number_integer = 0;
18619 break;
18620 }
18621
18622 case value_t::number_unsigned: {
18623 m_value.number_unsigned = 0;
18624 break;
18625 }
18626
18627 case value_t::number_float: {
18628 m_value.number_float = 0.0;
18629 break;
18630 }
18631
18632 case value_t::boolean: {
18633 m_value.boolean = false;
18634 break;
18635 }
18636
18637 case value_t::string: {
18638 m_value.string->clear();
18639 break;
18640 }
18641
18642 case value_t::binary: {
18643 m_value.binary->clear();
18644 break;
18645 }
18646
18647 case value_t::array: {
18648 m_value.array->clear();
18649 break;
18650 }
18651
18652 case value_t::object: {
18653 m_value.object->clear();
18654 break;
18655 }
18656
18657 case value_t::null:
18658 case value_t::discarded:
18659 default:
18660 break;
18661 }
18662 }
18663
18664 /// @brief add an object to an array
18665 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
18666 void push_back(basic_json&& val)
18667 {
18668 // push_back only works for null objects or arrays
18669 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) {
18670 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
18671 }
18672
18673 // transform null object into an array
18674 if (is_null()) {
18675 m_type = value_t::array;
18676 m_value = value_t::array;
18678 }
18679
18680 // add element to array (move semantics)
18681 const auto old_capacity = m_value.array->capacity();
18682 m_value.array->push_back(std::move(val));
18683 set_parent(m_value.array->back(), old_capacity);
18684 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
18685 }
18686
18687 /// @brief add an object to an array
18688 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
18690 {
18691 push_back(std::move(val));
18692 return *this;
18693 }
18694
18695 /// @brief add an object to an array
18696 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
18697 void push_back(const basic_json& val)
18698 {
18699 // push_back only works for null objects or arrays
18700 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) {
18701 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
18702 }
18703
18704 // transform null object into an array
18705 if (is_null()) {
18706 m_type = value_t::array;
18707 m_value = value_t::array;
18709 }
18710
18711 // add element to array
18712 const auto old_capacity = m_value.array->capacity();
18713 m_value.array->push_back(val);
18714 set_parent(m_value.array->back(), old_capacity);
18715 }
18716
18717 /// @brief add an object to an array
18718 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
18719 reference operator+=(const basic_json& val)
18720 {
18721 push_back(val);
18722 return *this;
18723 }
18724
18725 /// @brief add an object to an object
18726 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
18727 void push_back(const typename object_t::value_type& val)
18728 {
18729 // push_back only works for null objects or objects
18730 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) {
18731 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
18732 }
18733
18734 // transform null object into an object
18735 if (is_null()) {
18736 m_type = value_t::object;
18737 m_value = value_t::object;
18739 }
18740
18741 // add element to object
18742 auto res = m_value.object->insert(val);
18743 set_parent(res.first->second);
18744 }
18745
18746 /// @brief add an object to an object
18747 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
18748 reference operator+=(const typename object_t::value_type& val)
18749 {
18750 push_back(val);
18751 return *this;
18752 }
18753
18754 /// @brief add an object to an object
18755 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
18756 void push_back(initializer_list_t init)
18757 {
18758 if (is_object() && init.size() == 2 && (*init.begin())->is_string()) {
18759 basic_json&& key = init.begin()->moved_or_copied();
18760 push_back(typename object_t::value_type(std::move(key.get_ref<string_t&>()),
18761 (init.begin() + 1)->moved_or_copied()));
18762 } else {
18763 push_back(basic_json(init));
18764 }
18765 }
18766
18767 /// @brief add an object to an object
18768 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
18770 {
18771 push_back(init);
18772 return *this;
18773 }
18774
18775 /// @brief add an object to an array
18776 /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
18777 template<class... Args>
18778 reference emplace_back(Args&&... args)
18779 {
18780 // emplace_back only works for null objects or arrays
18781 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) {
18782 JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this));
18783 }
18784
18785 // transform null object into an array
18786 if (is_null()) {
18787 m_type = value_t::array;
18788 m_value = value_t::array;
18790 }
18791
18792 // add element to array (perfect forwarding)
18793 const auto old_capacity = m_value.array->capacity();
18794 m_value.array->emplace_back(std::forward<Args>(args)...);
18795 return set_parent(m_value.array->back(), old_capacity);
18796 }
18797
18798 /// @brief add an object to an object if key does not exist
18799 /// @sa https://json.nlohmann.me/api/basic_json/emplace/
18800 template<class... Args>
18801 std::pair<iterator, bool> emplace(Args&&... args)
18802 {
18803 // emplace only works for null objects or arrays
18804 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) {
18805 JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this));
18806 }
18807
18808 // transform null object into an object
18809 if (is_null()) {
18810 m_type = value_t::object;
18811 m_value = value_t::object;
18813 }
18814
18815 // add element to array (perfect forwarding)
18816 auto res = m_value.object->emplace(std::forward<Args>(args)...);
18817 set_parent(res.first->second);
18818
18819 // create result iterator and set iterator to the result of emplace
18820 auto it = begin();
18821 it.m_it.object_iterator = res.first;
18822
18823 // return pair of iterator and boolean
18824 return {it, res.second};
18825 }
18826
18827 /// Helper for insertion of an iterator
18828 /// @note: This uses std::distance to support GCC 4.8,
18829 /// see https://github.com/nlohmann/json/pull/1257
18830 template<typename... Args>
18831 iterator insert_iterator(const_iterator pos, Args&&... args)
18832 {
18833 iterator result(this);
18834 JSON_ASSERT(m_value.array != nullptr);
18835
18836 auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
18837 m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
18838 result.m_it.array_iterator = m_value.array->begin() + insert_pos;
18839
18840 // This could have been written as:
18841 // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
18842 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
18843
18844 set_parents();
18845 return result;
18846 }
18847
18848 /// @brief inserts element into array
18849 /// @sa https://json.nlohmann.me/api/basic_json/insert/
18850 iterator insert(const_iterator pos, const basic_json& val)
18851 {
18852 // insert only works for arrays
18853 if (JSON_HEDLEY_LIKELY(is_array())) {
18854 // check if iterator pos fits to this JSON value
18855 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) {
18856 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
18857 }
18858
18859 // insert to array and return iterator
18860 return insert_iterator(pos, val);
18861 }
18862
18863 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
18864 }
18865
18866 /// @brief inserts element into array
18867 /// @sa https://json.nlohmann.me/api/basic_json/insert/
18868 iterator insert(const_iterator pos, basic_json&& val) { return insert(pos, val); }
18869
18870 /// @brief inserts copies of element into array
18871 /// @sa https://json.nlohmann.me/api/basic_json/insert/
18872 iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
18873 {
18874 // insert only works for arrays
18875 if (JSON_HEDLEY_LIKELY(is_array())) {
18876 // check if iterator pos fits to this JSON value
18877 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) {
18878 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
18879 }
18880
18881 // insert to array and return iterator
18882 return insert_iterator(pos, cnt, val);
18883 }
18884
18885 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
18886 }
18887
18888 /// @brief inserts range of elements into array
18889 /// @sa https://json.nlohmann.me/api/basic_json/insert/
18891 {
18892 // insert only works for arrays
18893 if (JSON_HEDLEY_UNLIKELY(!is_array())) {
18894 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
18895 }
18896
18897 // check if iterator pos fits to this JSON value
18898 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) {
18899 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
18900 }
18901
18902 // check if range iterators belong to the same JSON object
18903 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) {
18904 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
18905 }
18906
18907 if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) {
18908 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this));
18909 }
18910
18911 // insert to array and return iterator
18912 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
18913 }
18914
18915 /// @brief inserts elements from initializer list into array
18916 /// @sa https://json.nlohmann.me/api/basic_json/insert/
18918 {
18919 // insert only works for arrays
18920 if (JSON_HEDLEY_UNLIKELY(!is_array())) {
18921 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
18922 }
18923
18924 // check if iterator pos fits to this JSON value
18925 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) {
18926 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
18927 }
18928
18929 // insert to array and return iterator
18930 return insert_iterator(pos, ilist.begin(), ilist.end());
18931 }
18932
18933 /// @brief inserts range of elements into object
18934 /// @sa https://json.nlohmann.me/api/basic_json/insert/
18935 void insert(const_iterator first, const_iterator last)
18936 {
18937 // insert only works for objects
18938 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
18939 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
18940 }
18941
18942 // check if range iterators belong to the same JSON object
18943 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) {
18944 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
18945 }
18946
18947 // passed iterators must belong to objects
18948 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) {
18949 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this));
18950 }
18951
18952 m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
18953 }
18954
18955 /// @brief updates a JSON object from another object, overwriting existing keys
18956 /// @sa https://json.nlohmann.me/api/basic_json/update/
18957 void update(const_reference j, bool merge_objects = false) { update(j.begin(), j.end(), merge_objects); }
18958
18959 /// @brief updates a JSON object from another object, overwriting existing keys
18960 /// @sa https://json.nlohmann.me/api/basic_json/update/
18961 void update(const_iterator first, const_iterator last, bool merge_objects = false)
18962 {
18963 // implicitly convert null value to an empty object
18964 if (is_null()) {
18965 m_type = value_t::object;
18966 m_value.object = create<object_t>();
18968 }
18969
18970 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
18971 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this));
18972 }
18973
18974 // check if range iterators belong to the same JSON object
18975 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) {
18976 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
18977 }
18978
18979 // passed iterators must belong to objects
18980 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) {
18981 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(first.m_object->type_name()),
18982 *first.m_object));
18983 }
18984
18985 for (auto it = first; it != last; ++it) {
18986 if (merge_objects && it.value().is_object()) {
18987 auto it2 = m_value.object->find(it.key());
18988 if (it2 != m_value.object->end()) {
18989 it2->second.update(it.value(), true);
18990 continue;
18991 }
18992 }
18993 m_value.object->operator[](it.key()) = it.value();
18994#if JSON_DIAGNOSTICS
18995 m_value.object->operator[](it.key()).m_parent = this;
18996#endif
18997 }
18998 }
18999
19000 /// @brief exchanges the values
19001 /// @sa https://json.nlohmann.me/api/basic_json/swap/
19002 void swap(reference other) noexcept(std::is_nothrow_move_constructible<value_t>::value
19003 && std::is_nothrow_move_assignable<value_t>::value
19004 && std::is_nothrow_move_constructible<json_value>::value
19005 && std::is_nothrow_move_assignable<json_value>::value)
19006 {
19007 std::swap(m_type, other.m_type);
19008 std::swap(m_value, other.m_value);
19009
19010 set_parents();
19011 other.set_parents();
19013 }
19014
19015 /// @brief exchanges the values
19016 /// @sa https://json.nlohmann.me/api/basic_json/swap/
19017 friend void swap(reference left, reference right) noexcept(std::is_nothrow_move_constructible<value_t>::value
19018 && std::is_nothrow_move_assignable<value_t>::value
19019 && std::is_nothrow_move_constructible<json_value>::value
19020 && std::is_nothrow_move_assignable<json_value>::value)
19021 {
19022 left.swap(right);
19023 }
19024
19025 /// @brief exchanges the values
19026 /// @sa https://json.nlohmann.me/api/basic_json/swap/
19027 void swap(array_t& other) // NOLINT(bugprone-exception-escape)
19028 {
19029 // swap only works for arrays
19030 if (JSON_HEDLEY_LIKELY(is_array())) {
19031 std::swap(*(m_value.array), other);
19032 } else {
19033 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
19034 }
19035 }
19036
19037 /// @brief exchanges the values
19038 /// @sa https://json.nlohmann.me/api/basic_json/swap/
19039 void swap(object_t& other) // NOLINT(bugprone-exception-escape)
19040 {
19041 // swap only works for objects
19042 if (JSON_HEDLEY_LIKELY(is_object())) {
19043 std::swap(*(m_value.object), other);
19044 } else {
19045 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
19046 }
19047 }
19048
19049 /// @brief exchanges the values
19050 /// @sa https://json.nlohmann.me/api/basic_json/swap/
19051 void swap(string_t& other) // NOLINT(bugprone-exception-escape)
19052 {
19053 // swap only works for strings
19054 if (JSON_HEDLEY_LIKELY(is_string())) {
19055 std::swap(*(m_value.string), other);
19056 } else {
19057 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
19058 }
19059 }
19060
19061 /// @brief exchanges the values
19062 /// @sa https://json.nlohmann.me/api/basic_json/swap/
19063 void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
19064 {
19065 // swap only works for strings
19066 if (JSON_HEDLEY_LIKELY(is_binary())) {
19067 std::swap(*(m_value.binary), other);
19068 } else {
19069 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
19070 }
19071 }
19072
19073 /// @brief exchanges the values
19074 /// @sa https://json.nlohmann.me/api/basic_json/swap/
19075 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
19076 {
19077 // swap only works for strings
19078 if (JSON_HEDLEY_LIKELY(is_binary())) {
19079 std::swap(*(m_value.binary), other);
19080 } else {
19081 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
19082 }
19083 }
19084
19085 /// @}
19086
19087 public:
19088 //////////////////////////////////////////
19089 // lexicographical comparison operators //
19090 //////////////////////////////////////////
19091
19092 /// @name lexicographical comparison operators
19093 /// @{
19094
19095 /// @brief comparison: equal
19096 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
19097 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
19098 {
19099#ifdef __GNUC__
19100#pragma GCC diagnostic push
19101#pragma GCC diagnostic ignored "-Wfloat-equal"
19102#endif
19103 const auto lhs_type = lhs.type();
19104 const auto rhs_type = rhs.type();
19105
19106 if (lhs_type == rhs_type) {
19107 switch (lhs_type) {
19108 case value_t::array:
19109 return *lhs.m_value.array == *rhs.m_value.array;
19110
19111 case value_t::object:
19112 return *lhs.m_value.object == *rhs.m_value.object;
19113
19114 case value_t::null:
19115 return true;
19116
19117 case value_t::string:
19118 return *lhs.m_value.string == *rhs.m_value.string;
19119
19120 case value_t::boolean:
19121 return lhs.m_value.boolean == rhs.m_value.boolean;
19122
19123 case value_t::number_integer:
19124 return lhs.m_value.number_integer == rhs.m_value.number_integer;
19125
19126 case value_t::number_unsigned:
19127 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
19128
19129 case value_t::number_float:
19130 return lhs.m_value.number_float == rhs.m_value.number_float;
19131
19132 case value_t::binary:
19133 return *lhs.m_value.binary == *rhs.m_value.binary;
19134
19135 case value_t::discarded:
19136 default:
19137 return false;
19138 }
19139 } else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) {
19140 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
19141 } else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) {
19142 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
19143 } else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) {
19144 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
19145 } else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) {
19146 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
19147 } else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) {
19148 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
19149 } else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) {
19150 return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
19151 }
19152
19153 return false;
19154#ifdef __GNUC__
19155#pragma GCC diagnostic pop
19156#endif
19157 }
19158
19159 /// @brief comparison: equal
19160 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
19161 template<typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
19162 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
19163 {
19164 return lhs == basic_json(rhs);
19165 }
19166
19167 /// @brief comparison: equal
19168 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
19169 template<typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
19170 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
19171 {
19172 return basic_json(lhs) == rhs;
19173 }
19174
19175 /// @brief comparison: not equal
19176 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
19177 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept { return !(lhs == rhs); }
19178
19179 /// @brief comparison: not equal
19180 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
19181 template<typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
19182 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
19183 {
19184 return lhs != basic_json(rhs);
19185 }
19186
19187 /// @brief comparison: not equal
19188 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
19189 template<typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
19190 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
19191 {
19192 return basic_json(lhs) != rhs;
19193 }
19194
19195 /// @brief comparison: less than
19196 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
19197 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
19198 {
19199 const auto lhs_type = lhs.type();
19200 const auto rhs_type = rhs.type();
19201
19202 if (lhs_type == rhs_type) {
19203 switch (lhs_type) {
19204 case value_t::array:
19205 // note parentheses are necessary, see
19206 // https://github.com/nlohmann/json/issues/1530
19207 return (*lhs.m_value.array) < (*rhs.m_value.array);
19208
19209 case value_t::object:
19210 return (*lhs.m_value.object) < (*rhs.m_value.object);
19211
19212 case value_t::null:
19213 return false;
19214
19215 case value_t::string:
19216 return (*lhs.m_value.string) < (*rhs.m_value.string);
19217
19218 case value_t::boolean:
19219 return (lhs.m_value.boolean) < (rhs.m_value.boolean);
19220
19221 case value_t::number_integer:
19222 return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
19223
19224 case value_t::number_unsigned:
19225 return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned);
19226
19227 case value_t::number_float:
19228 return (lhs.m_value.number_float) < (rhs.m_value.number_float);
19229
19230 case value_t::binary:
19231 return (*lhs.m_value.binary) < (*rhs.m_value.binary);
19232
19233 case value_t::discarded:
19234 default:
19235 return false;
19236 }
19237 } else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) {
19238 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
19239 } else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) {
19240 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
19241 } else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) {
19242 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
19243 } else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) {
19244 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
19245 } else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) {
19246 return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
19247 } else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) {
19248 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
19249 }
19250
19251 // We only reach this line if we cannot compare values. In that case,
19252 // we compare types. Note we have to call the operator explicitly,
19253 // because MSVC has problems otherwise.
19254 return operator<(lhs_type, rhs_type);
19255 }
19256
19257 /// @brief comparison: less than
19258 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
19259 template<typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
19260 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
19261 {
19262 return lhs < basic_json(rhs);
19263 }
19264
19265 /// @brief comparison: less than
19266 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
19267 template<typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
19268 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
19269 {
19270 return basic_json(lhs) < rhs;
19271 }
19272
19273 /// @brief comparison: less than or equal
19274 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
19275 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept { return !(rhs < lhs); }
19276
19277 /// @brief comparison: less than or equal
19278 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
19279 template<typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
19280 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
19281 {
19282 return lhs <= basic_json(rhs);
19283 }
19284
19285 /// @brief comparison: less than or equal
19286 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
19287 template<typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
19288 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
19289 {
19290 return basic_json(lhs) <= rhs;
19291 }
19292
19293 /// @brief comparison: greater than
19294 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
19295 friend bool operator>(const_reference lhs, const_reference rhs) noexcept { return !(lhs <= rhs); }
19296
19297 /// @brief comparison: greater than
19298 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
19299 template<typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
19300 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
19301 {
19302 return lhs > basic_json(rhs);
19303 }
19304
19305 /// @brief comparison: greater than
19306 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
19307 template<typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
19308 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
19309 {
19310 return basic_json(lhs) > rhs;
19311 }
19312
19313 /// @brief comparison: greater than or equal
19314 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
19315 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept { return !(lhs < rhs); }
19316
19317 /// @brief comparison: greater than or equal
19318 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
19319 template<typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
19320 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
19321 {
19322 return lhs >= basic_json(rhs);
19323 }
19324
19325 /// @brief comparison: greater than or equal
19326 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
19327 template<typename ScalarType, typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
19328 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
19329 {
19330 return basic_json(lhs) >= rhs;
19331 }
19332
19333 /// @}
19334
19335 ///////////////////
19336 // serialization //
19337 ///////////////////
19338
19339 /// @name serialization
19340 /// @{
19341#ifndef JSON_NO_IO
19342 /// @brief serialize to stream
19343 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
19344 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
19345 {
19346 // read width member and use it as indentation parameter if nonzero
19347 const bool pretty_print = o.width() > 0;
19348 const auto indentation = pretty_print ? o.width() : 0;
19349
19350 // reset width to 0 for subsequent calls to this stream
19351 o.width(0);
19352
19353 // do the actual serialization
19354 serializer s(detail::output_adapter<char>(o), o.fill());
19355 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
19356 return o;
19357 }
19358
19359 /// @brief serialize to stream
19360 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
19361 /// @deprecated This function is deprecated since 3.0.0 and will be removed in
19362 /// version 4.0.0 of the library. Please use
19363 /// operator<<(std::ostream&, const basic_json&) instead; that is,
19364 /// replace calls like `j >> o;` with `o << j;`.
19365 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
19366 friend std::ostream& operator>>(const basic_json& j, std::ostream& o) { return o << j; }
19367#endif // JSON_NO_IO
19368 /// @}
19369
19370 /////////////////////
19371 // deserialization //
19372 /////////////////////
19373
19374 /// @name deserialization
19375 /// @{
19376
19377 /// @brief deserialize from a compatible input
19378 /// @sa https://json.nlohmann.me/api/basic_json/parse/
19379 template<typename InputType>
19380 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json parse(InputType&& i,
19381 const parser_callback_t cb = nullptr,
19382 const bool allow_exceptions = true,
19383 const bool ignore_comments = false)
19384 {
19386 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments)
19387 .parse(true, result);
19388 return result;
19389 }
19390
19391 /// @brief deserialize from a pair of character iterators
19392 /// @sa https://json.nlohmann.me/api/basic_json/parse/
19393 template<typename IteratorType>
19394 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json parse(IteratorType first,
19395 IteratorType last,
19396 const parser_callback_t cb = nullptr,
19397 const bool allow_exceptions = true,
19398 const bool ignore_comments = false)
19399 {
19401 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments)
19402 .parse(true, result);
19403 return result;
19404 }
19405
19407 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
19408 static basic_json parse(detail::span_input_adapter&& i,
19409 const parser_callback_t cb = nullptr,
19410 const bool allow_exceptions = true,
19411 const bool ignore_comments = false)
19412 {
19414 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
19415 return result;
19416 }
19417
19418 /// @brief check if the input is valid JSON
19419 /// @sa https://json.nlohmann.me/api/basic_json/accept/
19420 template<typename InputType>
19421 static bool accept(InputType&& i, const bool ignore_comments = false)
19422 {
19423 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
19424 }
19425
19426 /// @brief check if the input is valid JSON
19427 /// @sa https://json.nlohmann.me/api/basic_json/accept/
19428 template<typename IteratorType>
19429 static bool accept(IteratorType first, IteratorType last, const bool ignore_comments = false)
19430 {
19431 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments)
19432 .accept(true);
19433 }
19434
19436 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
19437 static bool accept(detail::span_input_adapter&& i, const bool ignore_comments = false)
19438 {
19439 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
19440 }
19441
19442 /// @brief generate SAX events
19443 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
19444 template<typename InputType, typename SAX>
19446 static bool sax_parse(InputType&& i,
19447 SAX* sax,
19449 const bool strict = true,
19450 const bool ignore_comments = false)
19451 {
19452 auto ia = detail::input_adapter(std::forward<InputType>(i));
19453 return format == input_format_t::json
19454 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
19455 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
19456 }
19457
19458 /// @brief generate SAX events
19459 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
19460 template<class IteratorType, class SAX>
19462 static bool sax_parse(IteratorType first,
19463 IteratorType last,
19464 SAX* sax,
19466 const bool strict = true,
19467 const bool ignore_comments = false)
19468 {
19469 auto ia = detail::input_adapter(std::move(first), std::move(last));
19470 return format == input_format_t::json
19471 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
19472 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
19473 }
19474
19475 /// @brief generate SAX events
19476 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
19477 /// @deprecated This function is deprecated since 3.8.0 and will be removed in
19478 /// version 4.0.0 of the library. Please use
19479 /// sax_parse(ptr, ptr + len) instead.
19480 template<typename SAX>
19481 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
19482 JSON_HEDLEY_NON_NULL(2) static bool sax_parse(detail::span_input_adapter&& i,
19483 SAX* sax,
19485 const bool strict = true,
19486 const bool ignore_comments = false)
19487 {
19488 auto ia = i.get();
19489 return format == input_format_t::json
19490 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
19491 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
19492 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
19493 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
19494 }
19495#ifndef JSON_NO_IO
19496 /// @brief deserialize from stream
19497 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
19498 /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
19499 /// version 4.0.0 of the library. Please use
19500 /// operator>>(std::istream&, basic_json&) instead; that is,
19501 /// replace calls like `j << i;` with `i >> j;`.
19502 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
19503 friend std::istream& operator<<(basic_json& j, std::istream& i) { return operator>>(i, j); }
19504
19505 /// @brief deserialize from stream
19506 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
19507 friend std::istream& operator>>(std::istream& i, basic_json& j)
19508 {
19509 parser(detail::input_adapter(i)).parse(false, j);
19510 return i;
19511 }
19512#endif // JSON_NO_IO
19513 /// @}
19514
19515 ///////////////////////////
19516 // convenience functions //
19517 ///////////////////////////
19518
19519 /// @brief return the type as string
19520 /// @sa https://json.nlohmann.me/api/basic_json/type_name/
19522 const char* type_name() const noexcept
19523 {
19524 switch (m_type) {
19525 case value_t::null:
19526 return "null";
19527 case value_t::object:
19528 return "object";
19529 case value_t::array:
19530 return "array";
19531 case value_t::string:
19532 return "string";
19533 case value_t::boolean:
19534 return "boolean";
19535 case value_t::binary:
19536 return "binary";
19537 case value_t::discarded:
19538 return "discarded";
19539 case value_t::number_integer:
19540 case value_t::number_unsigned:
19541 case value_t::number_float:
19542 default:
19543 return "number";
19544 }
19545 }
19546
19548 :
19549 //////////////////////
19550 // member variables //
19551 //////////////////////
19552
19553 /// the type of the current element
19554 value_t m_type = value_t::null;
19555
19556 /// the value of the current element
19558
19559#if JSON_DIAGNOSTICS
19560 /// a pointer to a parent value (for debugging purposes)
19561 basic_json* m_parent = nullptr;
19562#endif
19563
19564 //////////////////////////////////////////
19565 // binary serialization/deserialization //
19566 //////////////////////////////////////////
19567
19568 /// @name binary serialization/deserialization support
19569 /// @{
19570
19571 public:
19572 /// @brief create a CBOR serialization of a given JSON value
19573 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
19574 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
19575 {
19576 std::vector<std::uint8_t> result;
19577 to_cbor(j, result);
19578 return result;
19579 }
19580
19581 /// @brief create a CBOR serialization of a given JSON value
19582 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
19583 static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
19584 {
19586 }
19587
19588 /// @brief create a CBOR serialization of a given JSON value
19589 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
19590 static void to_cbor(const basic_json& j, detail::output_adapter<char> o) { binary_writer<char>(o).write_cbor(j); }
19591
19592 /// @brief create a MessagePack serialization of a given JSON value
19593 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
19594 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
19595 {
19596 std::vector<std::uint8_t> result;
19597 to_msgpack(j, result);
19598 return result;
19599 }
19600
19601 /// @brief create a MessagePack serialization of a given JSON value
19602 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
19603 static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
19604 {
19606 }
19607
19608 /// @brief create a MessagePack serialization of a given JSON value
19609 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
19610 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
19611 {
19613 }
19614
19615 /// @brief create a UBJSON serialization of a given JSON value
19616 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
19617 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
19618 const bool use_size = false,
19619 const bool use_type = false)
19620 {
19621 std::vector<std::uint8_t> result;
19622 to_ubjson(j, result, use_size, use_type);
19623 return result;
19624 }
19625
19626 /// @brief create a UBJSON serialization of a given JSON value
19627 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
19628 static void to_ubjson(const basic_json& j,
19629 detail::output_adapter<std::uint8_t> o,
19630 const bool use_size = false,
19631 const bool use_type = false)
19632 {
19633 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
19634 }
19635
19636 /// @brief create a UBJSON serialization of a given JSON value
19637 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
19638 static void to_ubjson(const basic_json& j,
19639 detail::output_adapter<char> o,
19640 const bool use_size = false,
19641 const bool use_type = false)
19642 {
19643 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
19644 }
19645
19646 /// @brief create a BSON serialization of a given JSON value
19647 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
19648 static std::vector<std::uint8_t> to_bson(const basic_json& j)
19649 {
19650 std::vector<std::uint8_t> result;
19651 to_bson(j, result);
19652 return result;
19653 }
19654
19655 /// @brief create a BSON serialization of a given JSON value
19656 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
19657 static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
19658 {
19660 }
19661
19662 /// @brief create a BSON serialization of a given JSON value
19663 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
19664 static void to_bson(const basic_json& j, detail::output_adapter<char> o) { binary_writer<char>(o).write_bson(j); }
19665
19666 /// @brief create a JSON value from an input in CBOR format
19667 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
19668 template<typename InputType>
19670 InputType&& i,
19671 const bool strict = true,
19672 const bool allow_exceptions = true,
19673 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
19674 {
19676 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19677 auto ia = detail::input_adapter(std::forward<InputType>(i));
19678 const bool res =
19679 binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
19680 return res ? result : basic_json(value_t::discarded);
19681 }
19682
19683 /// @brief create a JSON value from an input in CBOR format
19684 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
19685 template<typename IteratorType>
19687 IteratorType first,
19688 IteratorType last,
19689 const bool strict = true,
19690 const bool allow_exceptions = true,
19691 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
19692 {
19694 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19695 auto ia = detail::input_adapter(std::move(first), std::move(last));
19696 const bool res =
19697 binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
19698 return res ? result : basic_json(value_t::discarded);
19699 }
19700
19701 template<typename T>
19702 JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) static basic_json
19703 from_cbor(const T* ptr,
19704 std::size_t len,
19705 const bool strict = true,
19706 const bool allow_exceptions = true,
19707 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
19708 {
19709 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
19710 }
19711
19713 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
19714 static basic_json from_cbor(detail::span_input_adapter&& i,
19715 const bool strict = true,
19716 const bool allow_exceptions = true,
19717 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
19718 {
19720 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19721 auto ia = i.get();
19722 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
19723 const bool res =
19724 binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
19725 return res ? result : basic_json(value_t::discarded);
19726 }
19727
19728 /// @brief create a JSON value from an input in MessagePack format
19729 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
19730 template<typename InputType>
19731 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json from_msgpack(InputType&& i,
19732 const bool strict = true,
19733 const bool allow_exceptions = true)
19734 {
19736 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19737 auto ia = detail::input_adapter(std::forward<InputType>(i));
19738 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
19739 return res ? result : basic_json(value_t::discarded);
19740 }
19741
19742 /// @brief create a JSON value from an input in MessagePack format
19743 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
19744 template<typename IteratorType>
19745 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json from_msgpack(IteratorType first,
19746 IteratorType last,
19747 const bool strict = true,
19748 const bool allow_exceptions = true)
19749 {
19751 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19752 auto ia = detail::input_adapter(std::move(first), std::move(last));
19753 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
19754 return res ? result : basic_json(value_t::discarded);
19755 }
19756
19757 template<typename T>
19758 JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) static basic_json
19759 from_msgpack(const T* ptr, std::size_t len, const bool strict = true, const bool allow_exceptions = true)
19760 {
19761 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
19762 }
19763
19765 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
19766 static basic_json from_msgpack(detail::span_input_adapter&& i,
19767 const bool strict = true,
19768 const bool allow_exceptions = true)
19769 {
19771 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19772 auto ia = i.get();
19773 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
19774 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
19775 return res ? result : basic_json(value_t::discarded);
19776 }
19777
19778 /// @brief create a JSON value from an input in UBJSON format
19779 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
19780 template<typename InputType>
19781 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json from_ubjson(InputType&& i,
19782 const bool strict = true,
19783 const bool allow_exceptions = true)
19784 {
19786 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19787 auto ia = detail::input_adapter(std::forward<InputType>(i));
19788 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
19789 return res ? result : basic_json(value_t::discarded);
19790 }
19791
19792 /// @brief create a JSON value from an input in UBJSON format
19793 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
19794 template<typename IteratorType>
19795 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json from_ubjson(IteratorType first,
19796 IteratorType last,
19797 const bool strict = true,
19798 const bool allow_exceptions = true)
19799 {
19801 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19802 auto ia = detail::input_adapter(std::move(first), std::move(last));
19803 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
19804 return res ? result : basic_json(value_t::discarded);
19805 }
19806
19807 template<typename T>
19808 JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) static basic_json
19809 from_ubjson(const T* ptr, std::size_t len, const bool strict = true, const bool allow_exceptions = true)
19810 {
19811 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
19812 }
19813
19815 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
19816 static basic_json from_ubjson(detail::span_input_adapter&& i,
19817 const bool strict = true,
19818 const bool allow_exceptions = true)
19819 {
19821 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19822 auto ia = i.get();
19823 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
19824 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
19825 return res ? result : basic_json(value_t::discarded);
19826 }
19827
19828 /// @brief create a JSON value from an input in BSON format
19829 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
19830 template<typename InputType>
19831 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json from_bson(InputType&& i,
19832 const bool strict = true,
19833 const bool allow_exceptions = true)
19834 {
19836 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19837 auto ia = detail::input_adapter(std::forward<InputType>(i));
19838 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
19839 return res ? result : basic_json(value_t::discarded);
19840 }
19841
19842 /// @brief create a JSON value from an input in BSON format
19843 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
19844 template<typename IteratorType>
19845 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json from_bson(IteratorType first,
19846 IteratorType last,
19847 const bool strict = true,
19848 const bool allow_exceptions = true)
19849 {
19851 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19852 auto ia = detail::input_adapter(std::move(first), std::move(last));
19853 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
19854 return res ? result : basic_json(value_t::discarded);
19855 }
19856
19857 template<typename T>
19858 JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) static basic_json
19859 from_bson(const T* ptr, std::size_t len, const bool strict = true, const bool allow_exceptions = true)
19860 {
19861 return from_bson(ptr, ptr + len, strict, allow_exceptions);
19862 }
19863
19865 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
19866 static basic_json from_bson(detail::span_input_adapter&& i,
19867 const bool strict = true,
19868 const bool allow_exceptions = true)
19869 {
19871 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19872 auto ia = i.get();
19873 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
19874 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
19875 return res ? result : basic_json(value_t::discarded);
19876 }
19877 /// @}
19878
19879 //////////////////////////
19880 // JSON Pointer support //
19881 //////////////////////////
19882
19883 /// @name JSON Pointer functions
19884 /// @{
19885
19886 /// @brief access specified element via JSON Pointer
19887 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19888 reference operator[](const json_pointer& ptr) { return ptr.get_unchecked(this); }
19889
19890 /// @brief access specified element via JSON Pointer
19891 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19892 const_reference operator[](const json_pointer& ptr) const { return ptr.get_unchecked(this); }
19893
19894 /// @brief access specified element via JSON Pointer
19895 /// @sa https://json.nlohmann.me/api/basic_json/at/
19896 reference at(const json_pointer& ptr) { return ptr.get_checked(this); }
19897
19898 /// @brief access specified element via JSON Pointer
19899 /// @sa https://json.nlohmann.me/api/basic_json/at/
19900 const_reference at(const json_pointer& ptr) const { return ptr.get_checked(this); }
19901
19902 /// @brief return flattened JSON value
19903 /// @sa https://json.nlohmann.me/api/basic_json/flatten/
19904 basic_json flatten() const
19905 {
19906 basic_json result(value_t::object);
19907 json_pointer::flatten("", *this, result);
19908 return result;
19909 }
19910
19911 /// @brief unflatten a previously flattened JSON value
19912 /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
19913 basic_json unflatten() const { return json_pointer::unflatten(*this); }
19914
19915 /// @}
19916
19917 //////////////////////////
19918 // JSON Patch functions //
19919 //////////////////////////
19920
19921 /// @name JSON Patch functions
19922 /// @{
19923
19924 /// @brief applies a JSON patch
19925 /// @sa https://json.nlohmann.me/api/basic_json/patch/
19926 basic_json patch(const basic_json& json_patch) const
19927 {
19928 // make a working copy to apply the patch to
19929 basic_json result = *this;
19930
19931 // the valid JSON Patch operations
19932 enum class patch_operations
19933 {
19934 add,
19935 remove,
19936 replace,
19937 move,
19938 copy,
19939 test,
19940 invalid
19941 };
19942
19943 const auto get_op = [](const std::string& op) {
19944 if (op == "add") {
19945 return patch_operations::add;
19946 }
19947 if (op == "remove") {
19948 return patch_operations::remove;
19949 }
19950 if (op == "replace") {
19951 return patch_operations::replace;
19952 }
19953 if (op == "move") {
19954 return patch_operations::move;
19955 }
19956 if (op == "copy") {
19957 return patch_operations::copy;
19958 }
19959 if (op == "test") {
19960 return patch_operations::test;
19961 }
19962
19963 return patch_operations::invalid;
19964 };
19965
19966 // wrapper for "add" operation; add value at ptr
19967 const auto operation_add = [&result](json_pointer& ptr, basic_json val) {
19968 // adding to the root of the target document means replacing it
19969 if (ptr.empty()) {
19970 result = val;
19971 return;
19972 }
19973
19974 // make sure the top element of the pointer exists
19975 json_pointer top_pointer = ptr.top();
19976 if (top_pointer != ptr) {
19977 result.at(top_pointer);
19978 }
19979
19980 // get reference to parent of JSON pointer ptr
19981 const auto last_path = ptr.back();
19982 ptr.pop_back();
19983 basic_json& parent = result[ptr];
19984
19985 switch (parent.m_type) {
19986 case value_t::null:
19987 case value_t::object: {
19988 // use operator[] to add value
19989 parent[last_path] = val;
19990 break;
19991 }
19992
19993 case value_t::array: {
19994 if (last_path == "-") {
19995 // special case: append to back
19996 parent.push_back(val);
19997 } else {
19998 const auto idx = json_pointer::array_index(last_path);
19999 if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) {
20000 // avoid undefined behavior
20002 401, "array index " + std::to_string(idx) + " is out of range", parent));
20003 }
20004
20005 // default case: insert add offset
20006 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
20007 }
20008 break;
20009 }
20010
20011 // if there exists a parent it cannot be primitive
20012 case value_t::string: // LCOV_EXCL_LINE
20013 case value_t::boolean: // LCOV_EXCL_LINE
20014 case value_t::number_integer: // LCOV_EXCL_LINE
20015 case value_t::number_unsigned: // LCOV_EXCL_LINE
20016 case value_t::number_float: // LCOV_EXCL_LINE
20017 case value_t::binary: // LCOV_EXCL_LINE
20018 case value_t::discarded: // LCOV_EXCL_LINE
20019 default: // LCOV_EXCL_LINE
20020 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
20021 }
20022 };
20023
20024 // wrapper for "remove" operation; remove value at ptr
20025 const auto operation_remove = [this, &result](json_pointer& ptr) {
20026 // get reference to parent of JSON pointer ptr
20027 const auto last_path = ptr.back();
20028 ptr.pop_back();
20029 basic_json& parent = result.at(ptr);
20030
20031 // remove child
20032 if (parent.is_object()) {
20033 // perform range check
20034 auto it = parent.find(last_path);
20035 if (JSON_HEDLEY_LIKELY(it != parent.end())) {
20036 parent.erase(it);
20037 } else {
20038 JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", *this));
20039 }
20040 } else if (parent.is_array()) {
20041 // note erase performs range check
20042 parent.erase(json_pointer::array_index(last_path));
20043 }
20044 };
20045
20046 // type check: top level value must be an array
20047 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) {
20048 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", json_patch));
20049 }
20050
20051 // iterate and apply the operations
20052 for (const auto& val : json_patch) {
20053 // wrapper to get a value for an operation
20054 const auto get_value = [&val](const std::string& op, const std::string& member,
20055 bool string_type) -> basic_json& {
20056 // find value
20057 auto it = val.m_value.object->find(member);
20058
20059 // context-sensitive error message
20060 const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
20061
20062 // check if desired value is present
20063 if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) {
20064 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
20065 JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", val));
20066 }
20067
20068 // check if result is of type string
20069 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) {
20070 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
20071 JSON_THROW(
20072 parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", val));
20073 }
20074
20075 // no error: return value
20076 return it->second;
20077 };
20078
20079 // type check: every element of the array must be an object
20080 if (JSON_HEDLEY_UNLIKELY(!val.is_object())) {
20081 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", val));
20082 }
20083
20084 // collect mandatory members
20085 const auto op = get_value("op", "op", true).template get<std::string>();
20086 const auto path = get_value(op, "path", true).template get<std::string>();
20087 json_pointer ptr(path);
20088
20089 switch (get_op(op)) {
20090 case patch_operations::add: {
20091 operation_add(ptr, get_value("add", "value", false));
20092 break;
20093 }
20094
20095 case patch_operations::remove: {
20096 operation_remove(ptr);
20097 break;
20098 }
20099
20100 case patch_operations::replace: {
20101 // the "path" location must exist - use at()
20102 result.at(ptr) = get_value("replace", "value", false);
20103 break;
20104 }
20105
20106 case patch_operations::move: {
20107 const auto from_path = get_value("move", "from", true).template get<std::string>();
20108 json_pointer from_ptr(from_path);
20109
20110 // the "from" location must exist - use at()
20111 basic_json v = result.at(from_ptr);
20112
20113 // The move operation is functionally identical to a
20114 // "remove" operation on the "from" location, followed
20115 // immediately by an "add" operation at the target
20116 // location with the value that was just removed.
20117 operation_remove(from_ptr);
20118 operation_add(ptr, v);
20119 break;
20120 }
20121
20122 case patch_operations::copy: {
20123 const auto from_path = get_value("copy", "from", true).template get<std::string>();
20124 const json_pointer from_ptr(from_path);
20125
20126 // the "from" location must exist - use at()
20127 basic_json v = result.at(from_ptr);
20128
20129 // The copy is functionally identical to an "add"
20130 // operation at the target location using the value
20131 // specified in the "from" member.
20132 operation_add(ptr, v);
20133 break;
20134 }
20135
20136 case patch_operations::test: {
20137 bool success = false;
20138 JSON_TRY
20139 {
20140 // check if "value" matches the one at "path"
20141 // the "path" location must exist - use at()
20142 success = (result.at(ptr) == get_value("test", "value", false));
20143 }
20145 {
20146 // ignore out of range errors: success remains false
20147 }
20148
20149 // throw an exception if test fails
20150 if (JSON_HEDLEY_UNLIKELY(!success)) {
20151 JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), val));
20152 }
20153
20154 break;
20155 }
20156
20157 case patch_operations::invalid:
20158 default: {
20159 // op must be "add", "remove", "replace", "move", "copy", or
20160 // "test"
20161 JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid", val));
20162 }
20163 }
20164 }
20165
20166 return result;
20167 }
20168
20169 /// @brief creates a diff as a JSON patch
20170 /// @sa https://json.nlohmann.me/api/basic_json/diff/
20172 static basic_json diff(const basic_json& source, const basic_json& target, const std::string& path = "")
20173 {
20174 // the patch
20175 basic_json result(value_t::array);
20176
20177 // if the values are the same, return empty patch
20178 if (source == target) {
20179 return result;
20180 }
20181
20182 if (source.type() != target.type()) {
20183 // different types: replace value
20184 result.push_back({{"op", "replace"}, {"path", path}, {"value", target}});
20185 return result;
20186 }
20187
20188 switch (source.type()) {
20189 case value_t::array: {
20190 // first pass: traverse common elements
20191 std::size_t i = 0;
20192 while (i < source.size() && i < target.size()) {
20193 // recursive call to compare array values at index i
20194 auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
20195 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
20196 ++i;
20197 }
20198
20199 // We now reached the end of at least one array
20200 // in a second pass, traverse the remaining elements
20201
20202 // remove my remaining elements
20203 const auto end_index = static_cast<difference_type>(result.size());
20204 while (i < source.size()) {
20205 // add operations in reverse order to avoid invalid
20206 // indices
20207 result.insert(result.begin() + end_index,
20208 object({{"op", "remove"}, {"path", path + "/" + std::to_string(i)}}));
20209 ++i;
20210 }
20211
20212 // add other remaining elements
20213 while (i < target.size()) {
20214 result.push_back({{"op", "add"}, {"path", path + "/-"}, {"value", target[i]}});
20215 ++i;
20216 }
20217
20218 break;
20219 }
20220
20221 case value_t::object: {
20222 // first pass: traverse this object's elements
20223 for (auto it = source.cbegin(); it != source.cend(); ++it) {
20224 // escape the key name to be used in a JSON patch
20225 const auto path_key = path + "/" + detail::escape(it.key());
20226
20227 if (target.find(it.key()) != target.end()) {
20228 // recursive call to compare object values at key it
20229 auto temp_diff = diff(it.value(), target[it.key()], path_key);
20230 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
20231 } else {
20232 // found a key that is not in o -> remove it
20233 result.push_back(object({{"op", "remove"}, {"path", path_key}}));
20234 }
20235 }
20236
20237 // second pass: traverse other object's elements
20238 for (auto it = target.cbegin(); it != target.cend(); ++it) {
20239 if (source.find(it.key()) == source.end()) {
20240 // found a key that is not in this -> add it
20241 const auto path_key = path + "/" + detail::escape(it.key());
20242 result.push_back({{"op", "add"}, {"path", path_key}, {"value", it.value()}});
20243 }
20244 }
20245
20246 break;
20247 }
20248
20249 case value_t::null:
20250 case value_t::string:
20251 case value_t::boolean:
20252 case value_t::number_integer:
20253 case value_t::number_unsigned:
20254 case value_t::number_float:
20255 case value_t::binary:
20256 case value_t::discarded:
20257 default: {
20258 // both primitive type: replace value
20259 result.push_back({{"op", "replace"}, {"path", path}, {"value", target}});
20260 break;
20261 }
20262 }
20263
20264 return result;
20265 }
20266
20267 /// @}
20268
20269 ////////////////////////////////
20270 // JSON Merge Patch functions //
20271 ////////////////////////////////
20272
20273 /// @name JSON Merge Patch functions
20274 /// @{
20275
20276 /// @brief applies a JSON Merge Patch
20277 /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
20278 void merge_patch(const basic_json& apply_patch)
20279 {
20280 if (apply_patch.is_object()) {
20281 if (!is_object()) {
20282 *this = object();
20283 }
20284 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) {
20285 if (it.value().is_null()) {
20286 erase(it.key());
20287 } else {
20288 operator[](it.key()).merge_patch(it.value());
20289 }
20290 }
20291 } else {
20292 *this = apply_patch;
20293 }
20294 }
20295
20296 /// @}
20297};
20298
20299/// @brief user-defined to_string function for JSON values
20300/// @sa https://json.nlohmann.me/api/basic_json/to_string/
20302std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
20303{
20304 return j.dump();
20305}
20306
20307} // namespace nlohmann
20308
20309///////////////////////
20310// nonmember support //
20311///////////////////////
20312
20313namespace std // NOLINT(cert-dcl58-cpp)
20314{
20315
20316/// @brief hash value for JSON objects
20317/// @sa https://json.nlohmann.me/api/basic_json/std_hash/
20320{
20321 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const { return nlohmann::detail::hash(j); }
20322};
20323
20324// specialization for std::less<value_t>
20325template<>
20326struct less<::nlohmann::detail::value_t> // do not remove the space after '<', see
20327 // https://github.com/nlohmann/json/pull/679
20328{
20329 /*!
20330 @brief compare two value_t enum values
20331 @since version 3.0.0
20332 */
20334 {
20335 return nlohmann::detail::operator<(lhs, rhs);
20336 }
20337};
20338
20339// C++20 prohibit function specialization in the std namespace.
20340#ifndef JSON_HAS_CPP_20
20341
20342/// @brief exchanges the values of two JSON objects
20343/// @sa https://json.nlohmann.me/api/basic_json/std_swap/
20345inline void swap(
20346 nlohmann::NLOHMANN_BASIC_JSON_TPL& j1,
20347 nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name)
20348 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value && // NOLINT(misc-redundant-expression)
20349 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
20350{
20351 j1.swap(j2);
20352}
20353
20354#endif
20355
20356} // namespace std
20357
20358/// @brief user-defined string literal for JSON values
20359/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
20361inline nlohmann::json operator"" _json(const char* s, std::size_t n)
20362{
20363 return nlohmann::json::parse(s, s + n);
20364}
20365
20366/// @brief user-defined string literal for JSON pointer
20367/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
20369inline nlohmann::json::json_pointer operator"" _json_pointer(const char* s, std::size_t n)
20370{
20371 return nlohmann::json::json_pointer(std::string(s, n));
20372}
20373
20374// #include <nlohmann/detail/macro_unscope.hpp>
20375
20376// restore clang diagnostic settings
20377#if defined(__clang__)
20378#pragma clang diagnostic pop
20379#endif
20380
20381// clean up
20382#undef JSON_ASSERT
20383#undef JSON_INTERNAL_CATCH
20384#undef JSON_CATCH
20385#undef JSON_THROW
20386#undef JSON_TRY
20387#undef JSON_PRIVATE_UNLESS_TESTED
20388#undef JSON_HAS_CPP_11
20389#undef JSON_HAS_CPP_14
20390#undef JSON_HAS_CPP_17
20391#undef JSON_HAS_CPP_20
20392#undef JSON_HAS_FILESYSTEM
20393#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
20394#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
20395#undef NLOHMANN_BASIC_JSON_TPL
20396#undef JSON_EXPLICIT
20397#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
20398
20399// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
20400
20401#undef JSON_HEDLEY_ALWAYS_INLINE
20402#undef JSON_HEDLEY_ARM_VERSION
20403#undef JSON_HEDLEY_ARM_VERSION_CHECK
20404#undef JSON_HEDLEY_ARRAY_PARAM
20405#undef JSON_HEDLEY_ASSUME
20406#undef JSON_HEDLEY_BEGIN_C_DECLS
20407#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
20408#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
20409#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
20410#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
20411#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
20412#undef JSON_HEDLEY_CLANG_HAS_FEATURE
20413#undef JSON_HEDLEY_CLANG_HAS_WARNING
20414#undef JSON_HEDLEY_COMPCERT_VERSION
20415#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
20416#undef JSON_HEDLEY_CONCAT
20417#undef JSON_HEDLEY_CONCAT3
20418#undef JSON_HEDLEY_CONCAT3_EX
20419#undef JSON_HEDLEY_CONCAT_EX
20420#undef JSON_HEDLEY_CONST
20421#undef JSON_HEDLEY_CONSTEXPR
20422#undef JSON_HEDLEY_CONST_CAST
20423#undef JSON_HEDLEY_CPP_CAST
20424#undef JSON_HEDLEY_CRAY_VERSION
20425#undef JSON_HEDLEY_CRAY_VERSION_CHECK
20426#undef JSON_HEDLEY_C_DECL
20427#undef JSON_HEDLEY_DEPRECATED
20428#undef JSON_HEDLEY_DEPRECATED_FOR
20429#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
20430#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
20431#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
20432#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
20433#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
20434#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
20435#undef JSON_HEDLEY_DIAGNOSTIC_POP
20436#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
20437#undef JSON_HEDLEY_DMC_VERSION
20438#undef JSON_HEDLEY_DMC_VERSION_CHECK
20439#undef JSON_HEDLEY_EMPTY_BASES
20440#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
20441#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
20442#undef JSON_HEDLEY_END_C_DECLS
20443#undef JSON_HEDLEY_FLAGS
20444#undef JSON_HEDLEY_FLAGS_CAST
20445#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
20446#undef JSON_HEDLEY_GCC_HAS_BUILTIN
20447#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
20448#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
20449#undef JSON_HEDLEY_GCC_HAS_EXTENSION
20450#undef JSON_HEDLEY_GCC_HAS_FEATURE
20451#undef JSON_HEDLEY_GCC_HAS_WARNING
20452#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
20453#undef JSON_HEDLEY_GCC_VERSION
20454#undef JSON_HEDLEY_GCC_VERSION_CHECK
20455#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
20456#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
20457#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
20458#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
20459#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
20460#undef JSON_HEDLEY_GNUC_HAS_FEATURE
20461#undef JSON_HEDLEY_GNUC_HAS_WARNING
20462#undef JSON_HEDLEY_GNUC_VERSION
20463#undef JSON_HEDLEY_GNUC_VERSION_CHECK
20464#undef JSON_HEDLEY_HAS_ATTRIBUTE
20465#undef JSON_HEDLEY_HAS_BUILTIN
20466#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
20467#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
20468#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
20469#undef JSON_HEDLEY_HAS_EXTENSION
20470#undef JSON_HEDLEY_HAS_FEATURE
20471#undef JSON_HEDLEY_HAS_WARNING
20472#undef JSON_HEDLEY_IAR_VERSION
20473#undef JSON_HEDLEY_IAR_VERSION_CHECK
20474#undef JSON_HEDLEY_IBM_VERSION
20475#undef JSON_HEDLEY_IBM_VERSION_CHECK
20476#undef JSON_HEDLEY_IMPORT
20477#undef JSON_HEDLEY_INLINE
20478#undef JSON_HEDLEY_INTEL_CL_VERSION
20479#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
20480#undef JSON_HEDLEY_INTEL_VERSION
20481#undef JSON_HEDLEY_INTEL_VERSION_CHECK
20482#undef JSON_HEDLEY_IS_CONSTANT
20483#undef JSON_HEDLEY_IS_CONSTEXPR_
20484#undef JSON_HEDLEY_LIKELY
20485#undef JSON_HEDLEY_MALLOC
20486#undef JSON_HEDLEY_MCST_LCC_VERSION
20487#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
20488#undef JSON_HEDLEY_MESSAGE
20489#undef JSON_HEDLEY_MSVC_VERSION
20490#undef JSON_HEDLEY_MSVC_VERSION_CHECK
20491#undef JSON_HEDLEY_NEVER_INLINE
20492#undef JSON_HEDLEY_NON_NULL
20493#undef JSON_HEDLEY_NO_ESCAPE
20494#undef JSON_HEDLEY_NO_RETURN
20495#undef JSON_HEDLEY_NO_THROW
20496#undef JSON_HEDLEY_NULL
20497#undef JSON_HEDLEY_PELLES_VERSION
20498#undef JSON_HEDLEY_PELLES_VERSION_CHECK
20499#undef JSON_HEDLEY_PGI_VERSION
20500#undef JSON_HEDLEY_PGI_VERSION_CHECK
20501#undef JSON_HEDLEY_PREDICT
20502#undef JSON_HEDLEY_PRINTF_FORMAT
20503#undef JSON_HEDLEY_PRIVATE
20504#undef JSON_HEDLEY_PUBLIC
20505#undef JSON_HEDLEY_PURE
20506#undef JSON_HEDLEY_REINTERPRET_CAST
20507#undef JSON_HEDLEY_REQUIRE
20508#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
20509#undef JSON_HEDLEY_REQUIRE_MSG
20510#undef JSON_HEDLEY_RESTRICT
20511#undef JSON_HEDLEY_RETURNS_NON_NULL
20512#undef JSON_HEDLEY_SENTINEL
20513#undef JSON_HEDLEY_STATIC_ASSERT
20514#undef JSON_HEDLEY_STATIC_CAST
20515#undef JSON_HEDLEY_STRINGIFY
20516#undef JSON_HEDLEY_STRINGIFY_EX
20517#undef JSON_HEDLEY_SUNPRO_VERSION
20518#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
20519#undef JSON_HEDLEY_TINYC_VERSION
20520#undef JSON_HEDLEY_TINYC_VERSION_CHECK
20521#undef JSON_HEDLEY_TI_ARMCL_VERSION
20522#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
20523#undef JSON_HEDLEY_TI_CL2000_VERSION
20524#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
20525#undef JSON_HEDLEY_TI_CL430_VERSION
20526#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
20527#undef JSON_HEDLEY_TI_CL6X_VERSION
20528#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
20529#undef JSON_HEDLEY_TI_CL7X_VERSION
20530#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
20531#undef JSON_HEDLEY_TI_CLPRU_VERSION
20532#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
20533#undef JSON_HEDLEY_TI_VERSION
20534#undef JSON_HEDLEY_TI_VERSION_CHECK
20535#undef JSON_HEDLEY_UNAVAILABLE
20536#undef JSON_HEDLEY_UNLIKELY
20537#undef JSON_HEDLEY_UNPREDICTABLE
20538#undef JSON_HEDLEY_UNREACHABLE
20539#undef JSON_HEDLEY_UNREACHABLE_RETURN
20540#undef JSON_HEDLEY_VERSION
20541#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
20542#undef JSON_HEDLEY_VERSION_DECODE_MINOR
20543#undef JSON_HEDLEY_VERSION_DECODE_REVISION
20544#undef JSON_HEDLEY_VERSION_ENCODE
20545#undef JSON_HEDLEY_WARNING
20546#undef JSON_HEDLEY_WARN_UNUSED_RESULT
20547#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
20548#undef JSON_HEDLEY_FALL_THROUGH
20549
20550#endif // INCLUDE_NLOHMANN_JSON_HPP_
vector< Double_t > dist(vector< Double_t > qp, Double_t mu)
Definition BmnMath.cxx:869
__m128 v
Definition P4_F32vec4.h:1
int i
Definition P4_F32vec4.h:22
__m128 m
Definition P4_F32vec4.h:27
TBuffer & operator>>(TBuffer &buf, Tmpl *&obj)
Bool_t operator<=(const TDatime &d1, const TDatime &d2)
Bool_t operator>(const TDatime &d1, const TDatime &d2)
Bool_t operator>=(const TDatime &d1, const TDatime &d2)
Bool_t operator<(const TDatime &d1, const TDatime &d2)
TRObject operator()(const T1 &t1) const
ROOT::R::TRInterface & operator<<(ROOT::R::TRInterface &r, TString code)
Binding & operator=(OUT(*fun)(U0 u0))
UInt_t Hash(const char *s)
std::string & operator+=(std::string &left, const TString &right)
TTime operator/(const TTime &t1, const TTime &t2)
a class to store JSON values
Definition json.hpp:16209
*constructor for rvalue objects json_value(object_t &&value)
Definition json.hpp:16621
{ *the type of elements in a basic_json container using value_type=basic_json value_type & reference
Definition json.hpp:16317
*brief a type for an array *sa AllocatorType< basic_json >
Definition json.hpp:16434
*constructor for rvalue binary arrays json_value(typename binary_t::container_type &&value)
Definition json.hpp:16641
* binary(stored with pointer to save storage) binary_t *binary
* array(stored with pointer to save storage) array_t *array
void assert_invariant(bool check_parents=true) const noexcept
checks the class invariants
Definition json.hpp:16758
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
Definition json.hpp:16332
typename std::allocator_traits< allocator_type >::pointer pointer
Definition json.hpp:16330
*constructor for rvalue strings json_value(string_t &&value)
Definition json.hpp:16611
iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
Definition json.hpp:16809
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
Definition json.hpp:16281
detail::cbor_tag_handler_t cbor_tag_handler_t
Definition json.hpp:16279
::nlohmann::detail::json_reverse_iterator< Base > json_reverse_iterator
Definition json.hpp:16258
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
Definition json.hpp:16339
reference set_parent(reference j, std::size_t old_capacity=static_cast< std::size_t >(-1))
Definition json.hpp:16821
::nlohmann::detail::binary_reader< basic_json, InputType > binary_reader
Definition json.hpp:16264
detail::invalid_iterator invalid_iterator
Definition json.hpp:16297
*constructor for rvalue arrays json_value(array_t &&value)
Definition json.hpp:16631
***name constructors and destructors *Constructors of class ref basic_json copy move constructor copy static functions creating and the destructor **the value of the current element json_value m_value
Definition json.hpp:19557
*constructor for binary arrays json_value(const typename binary_t::container_type &value)
Definition json.hpp:16636
::nlohmann::detail::iter_impl< BasicJsonType > iter_impl
Definition json.hpp:16254
*SAX interface type
Definition json.hpp:16284
void destroy(value_t t)
Definition json.hpp:16655
* string(stored with pointer to save storage) string_t *string
*constructor for strings json_value(const string_t &value)
Definition json.hpp:16606
*constructor for booleans json_value(boolean_t v) noexcept
Definition json.hpp:16529
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
Definition json.hpp:16341
::nlohmann::json_pointer< basic_json > json_pointer
Definition json.hpp:16273
::nlohmann::detail::binary_writer< basic_json, CharType > binary_writer
Definition json.hpp:16266
*constructor for objects json_value(const object_t &value)
Definition json.hpp:16616
friend class ::nlohmann::detail::exception
Definition json.hpp:16228
::nlohmann::detail::internal_iterator< BasicJsonType > internal_iterator
Definition json.hpp:16252
::nlohmann::detail::output_adapter_t< CharType > output_adapter_t
Definition json.hpp:16261
*constructor for empty values of a given type json_value(value_t t)
Definition json.hpp:16545
friend class ::nlohmann::detail::parser
Definition json.hpp:16216
***name JSON value data types *The data types to store a JSON value These types are derived from *the template arguments passed to class ref basic_json **brief a type for an object *sa object_comparator_t
Definition json.hpp:16430
std::allocator< basic_json > allocator_type
Definition json.hpp:16327
adl_serializer< T, SFINAE > json_serializer
Definition json.hpp:16275
{ using exception=detail::exception detail::parse_error parse_error
Definition json.hpp:16296
*helper for exception safe object creation static JSON_HEDLEY_RETURNS_NON_NULL T * create(Args &&... args)
Definition json.hpp:16465
static ::nlohmann::detail::parser< basic_json, InputAdapterType > parser(InputAdapterType adapter, detail::parser_callback_t< basic_json > cb=nullptr, const bool allow_exceptions=true, const bool ignore_comments=false)
Definition json.hpp:16239
::nlohmann::detail::primitive_iterator_t primitive_iterator_t
Definition json.hpp:16250
::nlohmann::detail::iteration_proxy< Iterator > iteration_proxy
Definition json.hpp:16256
***name JSON value data types *The data types to store a JSON value These types are derived from *the template arguments passed to class ref basic_json **brief a type for an object *sa basic_json
Definition json.hpp:16430
iter_impl< const basic_json > const_iterator
Definition json.hpp:16337
*constructor for arrays json_value(const array_t &value)
Definition json.hpp:16626
an internal type for a backed binary type
Definition json.hpp:4965
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition json.hpp:4986
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition json.hpp:4976
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:4981
bool operator!=(const byte_container_with_subtype &rhs) const
Definition json.hpp:5006
void clear_subtype() noexcept
clears the binary subtype
Definition json.hpp:5029
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition json.hpp:4971
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:4993
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition json.hpp:5025
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition json.hpp:5010
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition json.hpp:5018
bool operator==(const byte_container_with_subtype &rhs) const
Definition json.hpp:5000
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.hpp:7918
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:7920
**char_int_type get()
get next character from the input
Definition json.hpp:10125
bool get_msgpack_array(const std::size_t len)
Definition json.hpp:9596
**bool parse_cbor_internal(const bool get_char, const cbor_tag_handler_t tag_handler)
Definition json.hpp:8271
binary_reader & operator=(const binary_reader &)=delete
bool get_bson_string(const NumberType len, string_t &result)
Parses a C-style string from the BSON input.
Definition json.hpp:8067
bool parse_bson_element_internal(const char_int_type element_type, const std::size_t element_type_parse_position)
Read a BSON document element of the given element_type.
Definition json.hpp:8125
bool parse_bson_array()
Reads an array from the BSON input and passes it to the SAX-parser.
Definition json.hpp:8243
char_int_type get_ignore_noop()
Definition json.hpp:10134
binary_reader(InputAdapterType &&adapter) noexcept
create a binary reader
Definition json.hpp:7934
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:7919
bool get_cbor_array(const std::size_t len, const cbor_tag_handler_t tag_handler)
Definition json.hpp:8957
bool get_msgpack_binary(binary_t &result)
reads a MessagePack byte array
Definition json.hpp:9501
*whether we can assume little endianness const bool is_little_endian
Definition json.hpp:10315
bool get_cbor_object(const std::size_t len, const cbor_tag_handler_t tag_handler)
Definition json.hpp:8986
bool get_ubjson_string(string_t &result, const bool get_char=true)
reads a UBJSON string
Definition json.hpp:9667
bool parse_bson_element_list(const bool is_array)
Read a BSON element list (as specified in the BSON-spec).
Definition json.hpp:8210
bool get_string(const input_format_t format, const NumberType len, string_t &result)
create a string by reading characters from the input
Definition json.hpp:10195
bool get_cbor_string(string_t &result)
reads a CBOR string
Definition json.hpp:8767
bool get_binary(const input_format_t format, const NumberType len, binary_t &result)
create a byte array by reading bytes from the input
Definition json.hpp:10224
bool unexpect_eof(const input_format_t format, const char *context) const
Definition json.hpp:10244
*the number of characters read std::size_t chars_read
Definition json.hpp:10312
binary_reader & operator=(binary_reader &&)=default
bool get_ubjson_size_type(std::pair< std::size_t, char_int_type > &result)
determine the type and size for a container
Definition json.hpp:9794
std::string get_token_string() const
Definition json.hpp:10258
bool get_ubjson_value(const char_int_type prefix)
Definition json.hpp:9836
typename BasicJsonType::string_t string_t
Definition json.hpp:7922
*the json_sax_dom_parser< basic_json > parser json_sax_t * sax
Definition json.hpp:10318
bool get_msgpack_object(const std::size_t len)
Definition json.hpp:9615
bool get_bson_binary(const NumberType len, binary_t &result)
Parses a byte array input of length len from the BSON input.
Definition json.hpp:8094
std::string exception_message(const input_format_t format, const std::string &detail, const std::string &context) const
Definition json.hpp:10273
typename std::char_traits< char_type >::int_type char_int_type
Definition json.hpp:7926
**bool parse_ubjson_internal(const bool get_char=true)
Definition json.hpp:9648
binary_reader(const binary_reader &)=delete
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
Definition json.hpp:7957
bool get_ubjson_size_value(std::size_t &result)
Definition json.hpp:9720
typename InputAdapterType::char_type char_type
Definition json.hpp:7925
bool parse_bson_internal()
Reads in a BSON-object and passes it to the SAX-parser.
Definition json.hpp:8017
*the current character char_int_type current
Definition json.hpp:10309
bool get_number(const input_format_t format, NumberType &result)
Definition json.hpp:10157
bool get_cbor_binary(binary_t &result)
reads a CBOR byte array
Definition json.hpp:8865
binary_reader(binary_reader &&)=default
typename BasicJsonType::binary_t binary_t
Definition json.hpp:7923
bool get_msgpack_string(string_t &result)
reads a MessagePack string
Definition json.hpp:9415
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:7921
*input adapter InputAdapterType ia
Definition json.hpp:10306
serialization to CBOR and MessagePack values
Definition json.hpp:12702
void write_bson_array(const string_t &name, const typename BasicJsonType::array_t &value)
Writes a BSON element with key name and array value.
Definition json.hpp:13561
void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix)
Definition json.hpp:13754
void write_ubjson(const BasicJsonType &j, const bool use_count, const bool use_type, const bool add_prefix=true)
Definition json.hpp:13241
static constexpr CharType get_ubjson_float_prefix(double)
Definition json.hpp:13935
void write_bson_entry_header(const string_t &name, const std::uint8_t element_type)
Writes the given element_type and name to the output adapter.
Definition json.hpp:13422
static std::size_t calc_bson_element_size(const string_t &name, const basic_json &j)
Definition json.hpp:13593
void write_bson_double(const string_t &name, const double value)
Writes a BSON element with key name and double value value.
Definition json.hpp:13440
void write_bson_object(const typename basic_json::object_t &value)
Definition json.hpp:13699
typename BasicJsonType::string_t string_t
Definition json.hpp:12703
static constexpr CharType to_char_type(InputCharType x) noexcept
Definition json.hpp:14026
typename BasicJsonType::binary_t binary_t
Definition json.hpp:12704
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition json.hpp:12713
static constexpr CharType get_msgpack_float_prefix(double)
Definition json.hpp:13733
CharType ubjson_prefix(const basic_json &j) const noexcept
Definition json.hpp:13847
void write_bson_integer(const string_t &name, const std::int64_t value)
Writes a BSON element with key name and integer value.
Definition json.hpp:13484
**void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix)
Definition json.hpp:13744
static CharType to_char_type(std::uint8_t x) noexcept
Definition json.hpp:14007
void write_bson_string(const string_t &name, const string_t &value)
Writes a BSON element with key name and string value value.
Definition json.hpp:13457
void write_bson_object_entry(const string_t &name, const typename BasicJsonType::object_t &value)
Writes a BSON element with key name and object value.
Definition json.hpp:13528
static constexpr CharType get_ubjson_float_prefix(float)
Definition json.hpp:13930
void write_bson_element(const string_t &name, const basic_json &j)
Definition json.hpp:13639
**static std::size_t calc_bson_entry_header_size(const string_t &name, const BasicJsonType &j)
Definition json.hpp:13407
*whether we can assume little endianness const bool is_little_endian
Definition json.hpp:14033
void write_bson_binary(const string_t &name, const binary_t &value)
Writes a BSON element with key name and binary value value.
Definition json.hpp:13578
void write_bson_null(const string_t &name)
Writes a BSON element with key name and null value.
Definition json.hpp:13468
static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t &value)
Definition json.hpp:13553
void write_bson(const BasicJsonType &j)
Definition json.hpp:12723
void write_cbor(const BasicJsonType &j)
Definition json.hpp:12751
static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
Definition json.hpp:13499
static constexpr CharType to_char_type(std::uint8_t x) noexcept
Definition json.hpp:14001
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:12705
void write_bson_unsigned(const string_t &name, const BasicJsonType &j)
Writes a BSON element with key name and unsigned value.
Definition json.hpp:13508
**static constexpr CharType get_cbor_float_prefix(float)
Definition json.hpp:13714
static std::size_t calc_bson_object_size(const typename basic_json::object_t &value)
Definition json.hpp:13684
**static constexpr CharType get_msgpack_float_prefix(float)
Definition json.hpp:13728
void write_bson_boolean(const string_t &name, const bool value)
Writes a BSON element with key name and boolean value value.
Definition json.hpp:13431
*the output output_adapter_t< CharType > oa
Definition json.hpp:14036
void write_msgpack(const BasicJsonType &j)
Definition json.hpp:12987
void write_compact_float(const number_float_t n, detail::input_format_t format)
Definition json.hpp:13971
static std::size_t calc_bson_string_size(const string_t &value)
Definition json.hpp:13449
static std::size_t calc_bson_integer_size(const std::int64_t value)
Definition json.hpp:13473
static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t &value)
Definition json.hpp:13537
static constexpr CharType get_cbor_float_prefix(double)
Definition json.hpp:13719
general exception of the basic_json class
Definition json.hpp:2847
const int id
the id of the exception
Definition json.hpp:2853
static std::string diagnostics(const BasicJsonType &leaf_element)
Definition json.hpp:2868
static std::string name(const std::string &ename, int id_)
Definition json.hpp:2862
std::runtime_error m
an exception object as storage for error messages
Definition json.hpp:2923
const char * what() const noexcept override
returns the explanatory string
Definition json.hpp:2850
exception(int id_, const char *what_arg)
Definition json.hpp:2857
Input adapter for stdio file access.
Definition json.hpp:5221
std::FILE * m_file
the file pointer to read from
Definition json.hpp:5241
file_input_adapter(const file_input_adapter &)=delete
file_input_adapter(file_input_adapter &&) noexcept=default
std::char_traits< char >::int_type get_character() noexcept
Definition json.hpp:5237
file_input_adapter(std::FILE *f) noexcept
Definition json.hpp:5226
Input adapter for a (caching) istream.
Definition json.hpp:5254
input_stream_adapter(input_stream_adapter &&rhs) noexcept
Definition json.hpp:5277
input_stream_adapter & operator=(input_stream_adapter &)=delete
input_stream_adapter(const input_stream_adapter &)=delete
std::istream * is
the associated input stream
Definition json.hpp:5300
input_stream_adapter & operator=(input_stream_adapter &&)=delete
std::char_traits< char >::int_type get_character()
Definition json.hpp:5288
exception indicating errors with iterators
Definition json.hpp:2984
static invalid_iterator create(int id_, const std::string &what_arg, const BasicJsonType &context)
Definition json.hpp:2987
invalid_iterator(int id_, const char *what_arg)
Definition json.hpp:2995
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:11413
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.hpp:11526
iter_impl const operator--(int)
post-decrement (it–)
Definition json.hpp:11316
void set_end() noexcept
set the iterator past the last value
Definition json.hpp:11158
*the actual iterator of the associated instance internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
Definition json.hpp:11622
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:11327
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:11537
iter_impl< typename std::conditional< std::is_const< BasicJsonType >::value, typename std::remove_const< BasicJsonType >::type, const BasicJsonType >::type > other_iter_impl
Definition json.hpp:10974
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition json.hpp:11079
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:11193
iter_impl(iter_impl &&) noexcept=default
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:11458
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.hpp:11104
pointer operator->() const
dereference the iterator
Definition json.hpp:11232
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition json.hpp:11068
iter_impl const operator++(int)
post-increment (it++)
Definition json.hpp:11269
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.hpp:11093
iter_impl operator+(difference_type i) const
add to iterator
Definition json.hpp:11504
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.hpp:11515
const object_t::key_type & key() const
return the key of an object iterator
Definition json.hpp:11600
bool operator==(const IterImpl &other) const
comparison: equal
Definition json.hpp:11367
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:11452
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:11280
reference operator[](difference_type n) const
access to successor
Definition json.hpp:11565
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:11446
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:11464
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:11498
IteratorType anchor
the iterator
Definition json.hpp:4329
std::input_iterator_tag iterator_category
Definition json.hpp:4323
const string_type empty_str
an empty string (to return a reference for primitive values)
Definition json.hpp:4337
iteration_proxy_value(IteratorType it) noexcept
Definition json.hpp:4340
iteration_proxy_value value_type
Definition json.hpp:4320
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition json.hpp:4360
std::size_t array_index_last
last stringified array index
Definition json.hpp:4333
string_type array_index_str
a string representation of the array index
Definition json.hpp:4335
IteratorType::reference value() const
return value of the iterator
Definition json.hpp:4396
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.hpp:4348
std::size_t array_index
an index for arrays (used to create key names)
Definition json.hpp:4331
iteration_proxy_value & operator*()
dereference operator (needed for range-based for)
Definition json.hpp:4345
const string_type & key() const
return key of the iterator
Definition json.hpp:4363
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition json.hpp:4357
typename std::remove_cv< typename std::remove_reference< decltype(std::declval< IteratorType >().key())>::type >::type string_type
Definition json.hpp:4324
proxy class for the items() function
Definition json.hpp:4402
iteration_proxy_value< IteratorType > begin() noexcept
return iterator begin (needed for range-based for)
Definition json.hpp:4414
iteration_proxy_value< IteratorType > end() noexcept
return iterator end (needed for range-based for)
Definition json.hpp:4420
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.hpp:4409
typename std::iterator_traits< IteratorType >::value_type char_type
Definition json.hpp:5311
iterator_input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:5313
std::char_traits< char_type >::int_type get_character()
Definition json.hpp:5318
value_type const * value_ref
Definition json.hpp:12533
json_ref(json_ref &&) noexcept=default
value_type const & operator*() const
Definition json.hpp:12527
BasicJsonType value_type
Definition json.hpp:12493
json_ref(Args &&... args)
Definition json.hpp:12508
json_ref(const value_type &value)
Definition json.hpp:12499
value_type const * operator->() const
Definition json.hpp:12529
json_ref(std::initializer_list< json_ref > init)
Definition json.hpp:12503
json_ref(value_type &&value)
Definition json.hpp:12495
value_type moved_or_copied() const
Definition json.hpp:12519
*access to successor reference operator[](difference_type n) const
Definition json.hpp:11724
*return the value of an iterator reference value() const
Definition json.hpp:11734
typename Base::reference reference
Definition json.hpp:11669
std::reverse_iterator< Base > base_iterator
Definition json.hpp:11667
*create reverse iterator from base class explicit json_reverse_iterator(const base_iterator &it) noexcept
Definition json.hpp:11677
*return difference difference_type operator-(const json_reverse_iterator &other) const
Definition json.hpp:11718
*subtract from iterator json_reverse_iterator operator-(difference_type i) const
Definition json.hpp:11712
*add to iterator json_reverse_iterator & operator+=(difference_type i)
Definition json.hpp:11700
*create reverse iterator from iterator json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
Definition json.hpp:11672
*return the key of an object iterator auto key() const -> decltype(std::declval< Base >().key())
Definition json.hpp:11727
*add to iterator json_reverse_iterator operator+(difference_type i) const
Definition json.hpp:11706
bool start_object(std::size_t=static_cast< std::size_t >(-1))
Definition json.hpp:6284
typename BasicJsonType::string_t string_t
Definition json.hpp:6267
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:6264
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:6266
typename BasicJsonType::binary_t binary_t
Definition json.hpp:6268
bool start_array(std::size_t=static_cast< std::size_t >(-1))
Definition json.hpp:6290
bool parse_error(std::size_t, const std::string &, const detail::exception &)
Definition json.hpp:6294
bool number_integer(number_integer_t)
Definition json.hpp:6274
bool number_unsigned(number_unsigned_t)
Definition json.hpp:6276
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:6265
bool number_float(number_float_t, const string_t &)
Definition json.hpp:6278
typename BasicJsonType::string_t string_t
Definition json.hpp:5980
json_sax_dom_callback_parser & operator=(const json_sax_dom_callback_parser &)=delete
const bool allow_exceptions
whether to throw exceptions in case of errors
Definition json.hpp:6255
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:5978
BasicJsonType * object_element
helper to hold the reference for the next object element
Definition json.hpp:6249
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:5977
std::pair< bool, BasicJsonType * > handle_value(Value &&v, const bool skip_callback=false)
Definition json.hpp:6183
const parser_callback_t callback
callback function
Definition json.hpp:6253
typename BasicJsonType::parser_callback_t parser_callback_t
Definition json.hpp:5982
json_sax_dom_callback_parser(const json_sax_dom_callback_parser &)=delete
typename BasicJsonType::binary_t binary_t
Definition json.hpp:5981
bool number_integer(number_integer_t val)
Definition json.hpp:6014
BasicJsonType & root
the parsed JSON value
Definition json.hpp:6241
std::vector< BasicJsonType * > ref_stack
stack to model hierarchy of values
Definition json.hpp:6243
BasicJsonType discarded
a discarded value for the callback
Definition json.hpp:6257
std::vector< bool > key_keep_stack
stack to manage which object keys to keep
Definition json.hpp:6247
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:5979
typename BasicJsonType::parse_event_t parse_event_t
Definition json.hpp:5983
bool errored
whether a syntax error occurred
Definition json.hpp:6251
std::vector< bool > keep_stack
stack to manage which values to keep
Definition json.hpp:6245
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:6020
json_sax_dom_callback_parser & operator=(json_sax_dom_callback_parser &&)=default
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:6026
json_sax_dom_callback_parser(json_sax_dom_callback_parser &&)=default
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:6154
json_sax_dom_callback_parser(BasicJsonType &r, const parser_callback_t cb, const bool allow_exceptions_=true)
Definition json.hpp:5985
SAX implementation to create a JSON value from SAX events.
Definition json.hpp:5808
bool start_array(std::size_t len)
Definition json.hpp:5902
json_sax_dom_parser(const json_sax_dom_parser &)=delete
typename BasicJsonType::binary_t binary_t
Definition json.hpp:5814
json_sax_dom_parser & operator=(json_sax_dom_parser &&)=default
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:5853
bool errored
whether a syntax error occurred
Definition json.hpp:5968
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:5810
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:5921
JSON_HEDLEY_RETURNS_NON_NULL BasicJsonType * handle_value(Value &&v)
Definition json.hpp:5941
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:5811
bool start_object(std::size_t len)
Definition json.hpp:5877
BasicJsonType * object_element
helper to hold the reference for the next object element
Definition json.hpp:5966
std::vector< BasicJsonType * > ref_stack
stack to model hierarchy of values
Definition json.hpp:5964
const bool allow_exceptions
whether to throw exceptions in case of errors
Definition json.hpp:5970
constexpr bool is_errored() const
Definition json.hpp:5931
json_sax_dom_parser(json_sax_dom_parser &&)=default
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:5812
json_sax_dom_parser & operator=(const json_sax_dom_parser &)=delete
BasicJsonType & root
the parsed JSON value
Definition json.hpp:5962
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:5859
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true)
Definition json.hpp:5821
typename BasicJsonType::string_t string_t
Definition json.hpp:5813
bool number_integer(number_integer_t val)
Definition json.hpp:5847
JSON_HEDLEY_RETURNS_NON_NULL static JSON_HEDLEY_CONST const char * token_type_name(const token_type t) noexcept
return name of values of type token_type (only used for errors)
Definition json.hpp:6358
token_type
token types for the parser
Definition json.hpp:6335
@ value_float
an floating point number – use get_number_float() for actual value
Definition json.hpp:6343
@ begin_array
the character for array begin [
Definition json.hpp:6344
@ value_string
a string – use get_string() for actual value
Definition json.hpp:6340
@ end_array
the character for array end ]
Definition json.hpp:6346
@ uninitialized
indicating the scanner is uninitialized
Definition json.hpp:6336
@ parse_error
indicating a parse error
Definition json.hpp:6350
@ value_integer
a signed integer – use get_number_integer() for actual value
Definition json.hpp:6342
@ value_separator
the value separator ,
Definition json.hpp:6349
@ end_object
the character for object end }
Definition json.hpp:6347
@ begin_object
the character for object begin {
Definition json.hpp:6345
@ value_unsigned
an unsigned integer – use get_number_unsigned() for actual value
Definition json.hpp:6341
@ end_of_input
indicating the end of the input buffer
Definition json.hpp:6351
@ name_separator
the name separator :
Definition json.hpp:6348
@ literal_or_value
a literal or the begin of a value (only for diagnostics)
Definition json.hpp:6352
lexical analysis
Definition json.hpp:6407
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition json.hpp:7561
number_float_t value_float
Definition json.hpp:7739
const bool ignore_comments
whether comments should be ignored (true) or signaled as errors (false)
Definition json.hpp:7716
void add(char_int_type c)
add a character to token_buffer
Definition json.hpp:7544
void reset() noexcept
reset token_buffer; current character is beginning of token
Definition json.hpp:7473
token_type scan()
Definition json.hpp:7626
bool next_unget
whether the next get() call should just return current
Definition json.hpp:7722
char_int_type current
the current character
Definition json.hpp:7719
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:6410
typename std::char_traits< char_type >::int_type char_int_type
Definition json.hpp:6413
static JSON_HEDLEY_PURE char get_decimal_point() noexcept
return the locale-dependent decimal point
Definition json.hpp:6438
number_integer_t value_integer
Definition json.hpp:7737
InputAdapterType ia
input adapter
Definition json.hpp:7713
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:6408
lexer & operator=(lexer &&)=default
static void strtof(float &f, const char *str, char **endptr) noexcept
Definition json.hpp:7115
const char_int_type decimal_point_char
the decimal point
Definition json.hpp:7742
bool skip_bom()
skip the UTF-8 byte order mark
Definition json.hpp:7606
const char * error_message
a description of occurred lexer errors
Definition json.hpp:7734
lexer(InputAdapterType &&adapter, bool ignore_comments_=false) noexcept
Definition json.hpp:6418
position_t position
the start position of the current token
Definition json.hpp:7725
constexpr position_t get_position() const noexcept
return position of last read token
Definition json.hpp:7568
std::vector< char_type > token_string
raw input token string (for error messages)
Definition json.hpp:7728
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition json.hpp:7552
typename lexer_base< BasicJsonType >::token_type token_type
Definition json.hpp:6416
typename InputAdapterType::char_type char_type
Definition json.hpp:6412
char_int_type get()
Definition json.hpp:7490
token_type scan_number()
scan a number literal
Definition json.hpp:7163
lexer & operator=(lexer &)=delete
void unget()
unget current character (read it again on next get)
Definition json.hpp:7522
token_type scan_string()
scan a string literal
Definition json.hpp:6537
lexer(const lexer &)=delete
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition json.hpp:7555
string_t token_buffer
buffer for variable-length tokens (numbers, strings)
Definition json.hpp:7731
token_type scan_literal(const char_type *literal_text, const std::size_t length, token_type return_type)
Definition json.hpp:7456
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition json.hpp:7558
int get_codepoint()
get codepoint from 4 hex characters following \u
Definition json.hpp:6464
std::string get_token_string() const
return the last read token (for errors only).
Definition json.hpp:7573
number_unsigned_t value_unsigned
Definition json.hpp:7738
lexer(lexer &&)=default
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:6409
bool next_byte_in_range(std::initializer_list< char_int_type > ranges)
check if the next byte(s) are inside a given range
Definition json.hpp:6504
typename BasicJsonType::string_t string_t
Definition json.hpp:6411
bool scan_comment()
scan a comment
Definition json.hpp:7059
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition json.hpp:7596
exception indicating other library errors
Definition json.hpp:3041
static other_error create(int id_, const std::string &what_arg, const BasicJsonType &context)
Definition json.hpp:3044
other_error(int id_, const char *what_arg)
Definition json.hpp:3052
exception indicating access out of the defined range
Definition json.hpp:3022
static out_of_range create(int id_, const std::string &what_arg, const BasicJsonType &context)
Definition json.hpp:3025
out_of_range(int id_, const char *what_arg)
Definition json.hpp:3033
output_adapter_t< CharType > oa
Definition json.hpp:12684
output_adapter(std::basic_ostream< CharType > &s)
Definition json.hpp:12672
output_adapter(std::vector< CharType, AllocatorType > &vec)
Definition json.hpp:12667
void write_character(CharType c) override
Definition json.hpp:12631
std::basic_ostream< CharType > & stream
Definition json.hpp:12640
void write_characters(const CharType *s, std::size_t length) override
Definition json.hpp:12634
output_stream_adapter(std::basic_ostream< CharType > &s) noexcept
Definition json.hpp:12627
void write_character(CharType c) override
Definition json.hpp:12653
void write_characters(const CharType *s, std::size_t length) override
Definition json.hpp:12656
output_string_adapter(StringType &s) noexcept
Definition json.hpp:12649
void write_characters(const CharType *s, std::size_t length) override
Definition json.hpp:12612
output_vector_adapter(std::vector< CharType, AllocatorType > &vec) noexcept
Definition json.hpp:12605
void write_character(CharType c) override
Definition json.hpp:12609
std::vector< CharType, AllocatorType > & v
Definition json.hpp:12618
exception indicating a parse error
Definition json.hpp:2929
parse_error(int id_, std::size_t byte_, const char *what_arg)
Definition json.hpp:2969
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg, const BasicJsonType &context)
Definition json.hpp:2949
const std::size_t byte
byte index of the parse error
Definition json.hpp:2966
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, const BasicJsonType &context)
create a parse error exception
Definition json.hpp:2941
static std::string position_string(const position_t &pos)
Definition json.hpp:2974
bool sax_parse(SAX *sax, const bool strict=true)
Definition json.hpp:10477
bool accept(const bool strict=true)
public accept interface
Definition json.hpp:10469
typename BasicJsonType::string_t string_t
Definition json.hpp:10388
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:10386
typename lexer_t::token_type token_type
Definition json.hpp:10390
lexer< BasicJsonType, InputAdapterType > lexer_t
Definition json.hpp:10389
bool sax_parse_internal(SAX *sax)
Definition json.hpp:10496
*get next token from lexer token_type get_token()
Definition json.hpp:10751
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition json.hpp:10416
*a parser reading from an input adapter parser(InputAdapterType &&adapter, const parser_callback_t< BasicJsonType > cb=nullptr, const bool allow_exceptions_=true, const bool skip_comments=false)
Definition json.hpp:10394
*callback function const parser_callback_t< BasicJsonType > callback
Definition json.hpp:10778
std::string exception_message(const token_type expected, const std::string &context)
Definition json.hpp:10753
*the type of the last read token token_type last_token
Definition json.hpp:10780
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:10387
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:10385
*the lexer lexer_t m_lexer
Definition json.hpp:10782
*whether to throw exceptions in case of errors const bool allow_exceptions
Definition json.hpp:10784
primitive_iterator_t operator+(difference_type n) noexcept
Definition json.hpp:10849
primitive_iterator_t & operator++() noexcept
Definition json.hpp:10861
*return whether the iterator can be dereferenced constexpr bool is_begin() const noexcept
Definition json.hpp:10834
primitive_iterator_t & operator-=(difference_type n) noexcept
Definition json.hpp:10893
*set iterator to a defined beginning void set_begin() noexcept
Definition json.hpp:10828
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:10844
*set iterator to a defined past the end void set_end() noexcept
Definition json.hpp:10831
primitive_iterator_t const operator++(int) noexcept
Definition json.hpp:10867
static constexpr difference_type end_value
Definition json.hpp:10817
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:10839
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:10856
primitive_iterator_t & operator--() noexcept
Definition json.hpp:10874
constexpr difference_type get_value() const noexcept
Definition json.hpp:10825
primitive_iterator_t const operator--(int) noexcept
Definition json.hpp:10880
*return whether the iterator is at end constexpr bool is_end() const noexcept
Definition json.hpp:10837
primitive_iterator_t & operator+=(difference_type n) noexcept
Definition json.hpp:10887
static constexpr difference_type begin_value
Definition json.hpp:10816
*the indentation string string_t indent_string
Definition json.hpp:15959
*error_handler how to react on decoding errors const error_handler_t error_handler
Definition json.hpp:15962
*the locale s thousand separator character const char thousands_sep
Definition json.hpp:15949
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:15118
static constexpr std::uint8_t UTF8_ACCEPT
Definition json.hpp:15120
serializer(serializer &&)=delete
serializer & operator=(serializer &&)=delete
*string buffer std::array< char, 512 > string_buffer
Definition json.hpp:15954
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:15116
serializer & operator=(const serializer &)=delete
static constexpr std::uint8_t UTF8_REJECT
Definition json.hpp:15121
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
Definition json.hpp:15170
std::size_t bytes_after_last_accept
Definition json.hpp:15417
*a *(hopefully) large enough character buffer std the locale const std::lconv * loc
Definition json.hpp:15947
typename BasicJsonType::binary_t::value_type binary_char_t
Definition json.hpp:15119
JSON_PRIVATE_UNLESS_TESTED const bool ensure_ascii
Definition json.hpp:15411
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.hpp:15129
*the indentation character const char indent_char
Definition json.hpp:15957
typename BasicJsonType::string_t string_t
Definition json.hpp:15115
*the locale s decimal point character const char decimal_point
Definition json.hpp:15951
serializer(const serializer &)=delete
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:15117
contiguous_bytes_input_adapter && get()
Definition json.hpp:5645
span_input_adapter(CharT b, std::size_t l)
Definition json.hpp:5633
contiguous_bytes_input_adapter ia
Definition json.hpp:5651
span_input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:5641
exception indicating executing a member function with a wrong type
Definition json.hpp:3003
static type_error create(int id_, const std::string &what_arg, const BasicJsonType &context)
Definition json.hpp:3006
type_error(int id_, const char *what_arg)
Definition json.hpp:3014
std::char_traits< char >::int_type get_character() noexcept
Definition json.hpp:5463
wide_string_input_adapter(BaseInputAdapter base)
Definition json.hpp:5459
std::array< std::char_traits< char >::int_type, 4 > utf8_bytes
Definition json.hpp:5490
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
Definition json.hpp:3359
decltype(get< N >(std::declval<::nlohmann::detail::iteration_proxy_value< IteratorType > >())) type
Definition json.hpp:4461
@ BinaryType
@ StringType
void swap(RVec< T > &lhs, RVec< T > &rhs)
RVec< T0 > & operator/=(RVec< T0 > &v, const T1 &y)
RVec< PromoteType< T > > exp(const RVec< T > &v)
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION
Definition json.hpp:2298
#define JSON_HEDLEY_CONST
Definition json.hpp:1597
#define JSON_HEDLEY_DIAGNOSTIC_PUSH
Definition json.hpp:980
#define JSON_HEDLEY_WARN_UNUSED_RESULT
Definition json.hpp:1288
#define JSON_PRIVATE_UNLESS_TESTED
Definition json.hpp:2264
#define NLOHMANN_JSON_VERSION_PATCH
Definition json.hpp:44
*brief user defined string literal for JSON values *sa std::size_t n
Definition json.hpp:20362
#define JSON_HEDLEY_LIKELY(expr)
Definition json.hpp:1516
#define JSON_HEDLEY_NON_NULL(...)
Definition json.hpp:1420
#define JSON_INTERNAL_CATCH(exception)
Definition json.hpp:2231
#define JSON_HEDLEY_RETURNS_NON_NULL
Definition json.hpp:1770
#define JSON_CATCH(exception)
Definition json.hpp:2230
#define JSON_ASSERT(x)
Definition json.hpp:2257
#define JSON_THROW(exception)
Definition json.hpp:2228
#define NLOHMANN_JSON_VERSION_MAJOR
Definition json.hpp:42
#define NLOHMANN_BASIC_JSON_TPL
Definition json.hpp:2305
#define JSON_HEDLEY_UNLIKELY(expr)
Definition json.hpp:1517
#define JSON_TRY
Definition json.hpp:2229
#define NLOHMANN_JSON_VERSION_MINOR
Definition json.hpp:43
#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)
Definition json.hpp:2705
#define JSON_HEDLEY_DIAGNOSTIC_POP
Definition json.hpp:981
#define JSON_EXPLICIT
Definition json.hpp:2744
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
Definition json.hpp:1244
#define JSON_HEDLEY_PURE
Definition json.hpp:1573
double T(double x)
void update(const LAYERDATA &prevLayerData, LAYERDATA &currLayerData, double factorWeightDecay, EnumRegularization regularization)
void Compare(const TMatrixTBase< Element > &m1, const TMatrixTBase< Element > &m2)
implements the Grisu2 algorithm for binary to decimal floating-point conversion.
Definition json.hpp:14095
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
v = buf * 10^decimal_exponent len is the length of the buffer (number of decimal digits) The buffer m...
Definition json.hpp:14810
JSON_HEDLEY_RETURNS_NON_NULL char * format_buffer(char *buf, int len, int decimal_exponent, int min_exp, int max_exp)
prettify v = buf * 10^decimal_exponent
Definition json.hpp:14953
Target reinterpret_bits(const Source source)
Definition json.hpp:14098
boundaries compute_boundaries(FloatType value)
Compute the (normalized) diyfp representing the input number 'value' and its boundaries.
Definition json.hpp:14241
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
Definition json.hpp:14486
void grisu2_round(char *buf, int len, std::uint64_t dist, std::uint64_t delta, std::uint64_t rest, std::uint64_t ten_k)
Definition json.hpp:14531
JSON_HEDLEY_RETURNS_NON_NULL char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition json.hpp:14909
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
Definition json.hpp:14573
cached_power get_cached_power_for_binary_exponent(int e)
For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached power-of-ten c = f_c ...
Definition json.hpp:14377
detail namespace with internal helper functions
Definition json.hpp:96
typename detector< nonesuch, void, Op, Args... >::value_t is_detected
Definition json.hpp:2096
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.hpp:152
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
Definition json.hpp:2112
static void unescape(std::string &s)
string unescaping as described in RFC 6901 (Sect.
Definition json.hpp:2800
void to_json(BasicJsonType &j, T b) noexcept
Definition json.hpp:4726
make_integer_sequence< size_t, N > make_index_sequence
Definition json.hpp:3183
value_t
the JSON type enumeration
Definition json.hpp:126
@ number_integer
number value (signed integer)
Definition json.hpp:132
@ boolean
boolean value
Definition json.hpp:131
@ discarded
discarded by the parser callback function
Definition json.hpp:136
@ binary
binary array (ordered collection of bytes)
Definition json.hpp:135
@ object
object (unordered set of name/value pairs)
Definition json.hpp:128
@ string
string value
Definition json.hpp:130
@ number_float
number value (floating-point)
Definition json.hpp:134
@ number_unsigned
number value (unsigned integer)
Definition json.hpp:133
@ array
array (ordered collection of values)
Definition json.hpp:129
void from_json(const BasicJsonType &j, typename std::nullptr_t &n)
Definition json.hpp:3859
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
Definition json.hpp:2115
decltype(std::declval< T & >().string(std::declval< String & >())) string_function_t
Definition json.hpp:7780
decltype(std::declval< T & >().number_float(std::declval< Float >(), std::declval< const String & >())) number_float_function_t
Definition json.hpp:7776
value_type_t< iterator_traits< iterator_t< T > > > range_value_t
Definition json.hpp:3619
constexpr T static_const< T >::value
Definition json.hpp:3213
decltype(input_adapter(std::declval< const char * >(), std::declval< const char * >())) contiguous_bytes_input_adapter
Definition json.hpp:5598
void int_to_string(string_type &target, std::size_t value)
Definition json.hpp:4309
void from_json_array_impl(const BasicJsonType &j, typename BasicJsonType::array_t &arr, priority_tag< 3 >)
Definition json.hpp:3996
decltype(std::declval< T & >().parse_error(std::declval< std::size_t >(), std::declval< const std::string & >(), std::declval< const Exception & >())) parse_error_function_t
Definition json.hpp:7801
decltype(std::declval< T & >().key(std::declval< String & >())) key_function_t
Definition json.hpp:7789
JSON_HEDLEY_RETURNS_NON_NULL char * to_chars(char *first, const char *last, FloatType value)
generates a decimal representation of the floating-point number value in [first, last).
Definition json.hpp:15030
typename T::iterator_category iterator_category_t
Definition json.hpp:3451
typename T::difference_type difference_type_t
Definition json.hpp:3442
void to_json_tuple_impl(BasicJsonType &j, const Tuple &t, index_sequence< Idx... >)
Definition json.hpp:4868
cbor_tag_handler_t
how to treat CBOR tags
Definition json.hpp:7891
@ store
store tags as binary type
Definition json.hpp:7894
@ error
throw a parse_error exception in case of a tag
Definition json.hpp:7892
@ strict
throw a type_error exception in case of invalid UTF-8
Definition json.hpp:15107
@ ignore
ignore invalid UTF-8 sequences
Definition json.hpp:15109
@ replace
replace invalid UTF-8 sequences with U+FFFD
Definition json.hpp:15108
typename T::value_type value_type_t
Definition json.hpp:3439
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
Definition json.hpp:3076
iterator_input_adapter_factory< IteratorType >::adapter_type input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:5537
typename make_void< Ts... >::type void_t
Definition json.hpp:2062
make_index_sequence< sizeof...(Ts)> index_sequence_for
Definition json.hpp:3191
std::size_t combine(std::size_t seed, std::size_t h) noexcept
Definition json.hpp:5064
decltype(T::from_json(std::declval< Args >()...)) from_json_function
Definition json.hpp:3457
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition json.hpp:5082
static bool little_endianness(int num=1) noexcept
determine system byte order
Definition json.hpp:7904
decltype(std::declval< T & >().start_array(std::declval< std::size_t >())) start_array_function_t
Definition json.hpp:7795
typename T::pointer pointer_t
Definition json.hpp:3445
typename T::mapped_type mapped_type_t
Definition json.hpp:3433
decltype(std::declval< T & >().boolean(std::declval< bool >())) boolean_function_t
Definition json.hpp:7767
std::pair< A1, A2 > from_json_tuple_impl(BasicJsonType &&j, identity_tag< std::pair< A1, A2 > >, priority_tag< 0 >)
Definition json.hpp:4165
std::function< bool(int, parse_event_t, BasicJsonType &)> parser_callback_t
Definition json.hpp:10375
void get_arithmetic_value(const BasicJsonType &j, ArithmeticType &val)
Definition json.hpp:3873
typename T::reference reference_t
Definition json.hpp:3448
typename utility_internal::Gen< T, N >::type make_integer_sequence
Definition json.hpp:3175
decltype(std::declval< T >().template get< U >()) get_template_function
Definition json.hpp:3460
std::string escape(std::string s)
string escaping as described in RFC 6901 (Sect.
Definition json.hpp:2786
decltype(std::declval< T & >().number_unsigned(std::declval< Unsigned >())) number_unsigned_function_t
Definition json.hpp:7773
decltype(T::to_json(std::declval< Args >()...)) to_json_function
Definition json.hpp:3454
input_format_t
the supported input formats
Definition json.hpp:5203
decltype(std::declval< T & >().start_object(std::declval< std::size_t >())) start_object_function_t
Definition json.hpp:7786
std::tuple< Args... > from_json_tuple_impl_base(BasicJsonType &&j, index_sequence< Idx... >)
Definition json.hpp:4159
typename detector< nonesuch, void, Op, Args... >::type detected_t
Definition json.hpp:2103
std::array< T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType &&j, identity_tag< std::array< T, sizeof...(Idx)> >, index_sequence< Idx... >)
Definition json.hpp:4067
integer_sequence< size_t, Ints... > index_sequence
Definition json.hpp:3130
decltype(std::declval< T & >().end_object()) end_object_function_t
Definition json.hpp:7792
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition json.hpp:4426
void replace_substring(std::string &s, const std::string &f, const std::string &t)
replace all occurrences of a substring by another string
Definition json.hpp:2769
typename std::enable_if< B, T >::type enable_if_t
Definition json.hpp:3090
decltype(std::declval< T & >().end_array()) end_array_function_t
Definition json.hpp:7798
decltype(std::declval< T & >().null()) null_function_t
Definition json.hpp:7764
decltype(std::declval< T & >().binary(std::declval< Binary & >())) binary_function_t
Definition json.hpp:7783
typename T::key_type key_type_t
Definition json.hpp:3436
decltype(std::declval< T & >().number_integer(std::declval< Integer >())) number_integer_function_t
Definition json.hpp:7770
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
Definition json.hpp:12598
typename detected_or< Default, Op, Args... >::type detected_or_t
Definition json.hpp:2109
enable_if_t< is_range< R >::value, result_of_begin< decltype(std::declval< R & >())> > iterator_t
Definition json.hpp:3616
detector< Default, void, Op, Args... > detected_or
Definition json.hpp:2106
T conditional_static_cast(U value)
Definition json.hpp:3824
namespace for Niels Lohmann
Definition json.hpp:94
typename Container::size_type size_type
Definition json.hpp:16000
typename std::enable_if< std::is_convertible< typename std::iterator_traits< InputIt >::iterator_category, std::input_iterator_tag >::value >::type require_input_iter
Definition json.hpp:16162
*brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer *sa std::string token
Definition json.hpp:11822
bool contains(const BasicJsonType *ptr) const
Definition json.hpp:12221
T mapped_type
Definition json.hpp:15996
basic_json< nlohmann::ordered_map > ordered_json
specialization that maintains the insertion order of object keys
Definition json.hpp:3374
*brief create JSON pointer *sa reference_tokens const std::string & a
Definition json.hpp:11787
iterator find(const Key &key)
Definition json.hpp:16128
static BasicJsonType unflatten(const BasicJsonType &value)
Definition json.hpp:12420
*brief remove last reference token *sa JSON pointer has no parent
Definition json.hpp:11851
*brief create JSON pointer *sa reference_tokens end()
std::vector< std::pair< const Key, T >, Allocator > Container
Definition json.hpp:15997
static BasicJsonType::size_type array_index(const std::string &s)
Definition json.hpp:11891
json_pointer result
Definition json.hpp:11939
typename Container::value_type value_type
Definition json.hpp:16001
* ordered_map
Definition json.hpp:15989
typename Container::iterator iterator
Definition json.hpp:15998
size_type count(const Key &key) const
Definition json.hpp:16118
static void flatten(const std::string &reference_string, const BasicJsonType &value, BasicJsonType &result)
Definition json.hpp:12365
T & at(const Key &key)
Definition json.hpp:16031
*brief append another JSON pointer at the end of this JSON pointer *sa ptr reference_tokens begin()
*brief create JSON pointer *sa reference_tokens const std::string const std::string & b
Definition json.hpp:11787
*brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer *sa const json_pointer & rhs
Definition json.hpp:11816
BasicJsonType & get_checked(BasicJsonType *ptr) const
Definition json.hpp:12078
basic_json<> json
default specialization
Definition json.hpp:3365
res pop_back()
class class Allocator
Definition json.hpp:15992
result reference_tokens
Definition json.hpp:11940
friend bool operator!=(json_pointer const &lhs, json_pointer const &rhs) noexcept
compares two JSON pointers for inequality
Definition json.hpp:12471
typename Container::const_iterator const_iterator
Definition json.hpp:15999
size_type erase(const Key &key)
Definition json.hpp:16053
std::pair< iterator, bool > emplace(const key_type &key, T &&t)
Definition json.hpp:16016
BasicJsonType & get_and_create(BasicJsonType &j) const
create and return a reference to the pointed to value
Definition json.hpp:11953
*brief remove last reference token *sa JSON pointer has no BasicJsonType()))
return reference_tokens back()
*brief create a new JSON pointer by appending the array index token at the end of the JSON pointer *sa std::size_t array_idx
Definition json.hpp:11829
json_pointer res
Definition json.hpp:11841
static std::vector< std::string > split(const std::string &reference_string)
split the string input to reference tokens
Definition json.hpp:12298
friend bool operator==(json_pointer const &lhs, json_pointer const &rhs) noexcept
compares two JSON pointers for equality
Definition json.hpp:12455
std::pair< iterator, bool > insert(value_type &&value)
Definition json.hpp:16148
BasicJsonType & get_unchecked(BasicJsonType *ptr) const
return a reference to the pointed to value
Definition json.hpp:12024
T & operator[](const Key &key)
Definition json.hpp:16027
const char * Array
Definition json.hpp:4446
*brief exchanges the values of two JSON objects *sa nlohmann::NLOHMANN_BASIC_JSON_TPL &j2 noexcept(is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
Definition json.hpp:20347
const char * Value
default JSONSerializer template argument
Definition json.hpp:4918
static auto from_json(BasicJsonType &&j) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType >{}))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType >{}))
convert a JSON value to any value type
Definition json.hpp:4933
static auto from_json(BasicJsonType &&j, TargetType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), val), void())
convert a JSON value to any value type
Definition json.hpp:4922
static auto to_json(BasicJsonType &j, TargetType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< TargetType >(val)))) -> decltype(::nlohmann::to_json(j, std::forward< TargetType >(val)), void())
convert any value type to a JSON value
Definition json.hpp:4943
std::false_type value_t
Definition json.hpp:2084
static constexpr int kPrecision
Definition json.hpp:14109
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition json.hpp:14200
static diyfp normalize_to(const diyfp &x, const int target_exponent) noexcept
normalize x such that the result has the exponent E
Definition json.hpp:14216
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition json.hpp:14135
constexpr diyfp(std::uint64_t f_, int e_) noexcept
Definition json.hpp:14114
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition json.hpp:14123
static void construct(BasicJsonType &j, const CompatibleArrayType &arr)
Definition json.hpp:4639
static void construct(BasicJsonType &j, const std::valarray< T > &arr)
Definition json.hpp:4666
static void construct(BasicJsonType &j, const std::vector< bool > &arr)
Definition json.hpp:4652
static void construct(BasicJsonType &j, typename BasicJsonType::array_t &&arr)
Definition json.hpp:4627
static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr)
Definition json.hpp:4617
static void construct(BasicJsonType &j, const typename BasicJsonType::binary_t &b)
Definition json.hpp:4556
static void construct(BasicJsonType &j, typename BasicJsonType::binary_t &&b)
Definition json.hpp:4565
static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept
Definition json.hpp:4510
static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept
Definition json.hpp:4578
static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept
Definition json.hpp:4604
static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept
Definition json.hpp:4591
static void construct(BasicJsonType &j, typename BasicJsonType::object_t &&obj)
Definition json.hpp:4694
static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj)
Definition json.hpp:4684
static void construct(BasicJsonType &j, const CompatibleObjectType &obj)
Definition json.hpp:4706
static void construct(BasicJsonType &j, typename BasicJsonType::string_t &&s)
Definition json.hpp:4532
static void construct(BasicJsonType &j, const CompatibleStringType &str)
Definition json.hpp:4543
static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s)
Definition json.hpp:4523
auto operator()(const BasicJsonType &j, T &&val) const noexcept(noexcept(from_json(j, std::forward< T >(val)))) -> decltype(from_json(j, std::forward< T >(val)))
Definition json.hpp:4261
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3480
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3509
static constexpr std::size_t size() noexcept
Definition json.hpp:3121
*iterator for JSON objects BasicJsonType::object_t::iterator object_iterator
Definition json.hpp:10916
*iterator for JSON arrays BasicJsonType::array_t::iterator array_iterator
Definition json.hpp:10918
*generic iterator for all other types primitive_iterator_t primitive_iterator
Definition json.hpp:10920
static constexpr bool value
Definition json.hpp:3474
typename std::iterator_traits< T >::value_type value_type
Definition json.hpp:5514
static one test(decltype(&C::capacity))
detected_t< result_of_end, t_ref > sentinel
Definition json.hpp:3603
detected_t< result_of_begin, t_ref > iterator
Definition json.hpp:3602
static constexpr auto is_iterator_begin
Definition json.hpp:3608
typename std::add_lvalue_reference< T >::type t_ref
Definition json.hpp:3600
static constexpr bool value
Definition json.hpp:3611
typename BasicJsonType::string_t string_t
Definition json.hpp:7843
typename BasicJsonType::exception exception_t
Definition json.hpp:7845
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:7840
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:7842
typename BasicJsonType::binary_t binary_t
Definition json.hpp:7844
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:7841
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:7813
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:7812
typename BasicJsonType::exception exception_t
Definition json.hpp:7816
static constexpr bool value
Definition json.hpp:7819
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:7811
typename BasicJsonType::string_t string_t
Definition json.hpp:7814
typename BasicJsonType::binary_t binary_t
Definition json.hpp:7815
typename std::iterator_traits< iterator_type >::value_type char_type
Definition json.hpp:5502
static adapter_type create(IteratorType first, IteratorType last)
Definition json.hpp:5505
iterator_input_adapter< iterator_type > adapter_type
Definition json.hpp:5503
nonesuch(nonesuch const &)=delete
void operator=(nonesuch &&)=delete
nonesuch(nonesuch const &&)=delete
void operator=(nonesuch const &)=delete
virtual void write_characters(const CharType *s, std::size_t length)=0
virtual void write_character(CharType c)=0
output_adapter_protocol(output_adapter_protocol &&) noexcept=default
output_adapter_protocol(const output_adapter_protocol &)=default
struct to capture the start position of the current token
Definition json.hpp:2819
std::size_t lines_read
the number of lines read
Definition json.hpp:2825
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.hpp:2823
std::size_t chars_read_total
the total number of characters read
Definition json.hpp:2821
static constexpr T value
Definition json.hpp:3209
auto operator()(BasicJsonType &j, T &&val) const noexcept(noexcept(to_json(j, std::forward< T >(val)))) -> decltype(to_json(j, std::forward< T >(val)), void())
Definition json.hpp:4890
integer_sequence< T, Ints...,(Ints+SeqSize)..., 2 *SeqSize > type
Definition json.hpp:3148
typename Extend< typename Gen< T, N/2 >::type, N/2, N % 2 >::type type
Definition json.hpp:3156
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition json.hpp:5401
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition json.hpp:5346
SAX interface.
Definition json.hpp:5680
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
virtual bool string(string_t &val)=0
a string value was read
virtual bool null()=0
a null value was read
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:5681
typename BasicJsonType::binary_t binary_t
Definition json.hpp:5685
virtual bool end_array()=0
the end of an array was read
virtual bool key(string_t &val)=0
an object key was read
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:5682
virtual bool binary(binary_t &val)=0
a binary value was read
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:5683
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
json_sax(json_sax &&) noexcept=default
virtual bool boolean(bool val)=0
a boolean value was read
json_sax(const json_sax &)=default
virtual bool end_object()=0
the end of an object was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
typename BasicJsonType::string_t string_t
Definition json.hpp:5684
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
a minimal map-like container that preserves insertion order
Definition json.hpp:3370
bool operator()(nlohmann::detail::value_t lhs, nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.hpp:20333