3 __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 3.10.5
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 SPDX-License-Identifier: MIT
9 Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
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 \****************************************************************************/
39 #ifndef INCLUDE_NLOHMANN_JSON_HPP_
40 #define INCLUDE_NLOHMANN_JSON_HPP_
42 #define NLOHMANN_JSON_VERSION_MAJOR 3
43 #define NLOHMANN_JSON_VERSION_MINOR 10
44 #define NLOHMANN_JSON_VERSION_PATCH 5
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
51 #include <iosfwd> // istream, ostream
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
60 // #include <nlohmann/adl_serializer.hpp>
63 #include <type_traits>
66 // #include <nlohmann/detail/conversions/from_json.hpp>
69 #include <algorithm> // transform
70 #include <array> // array
71 #include <forward_list> // forward_list
72 #include <iterator> // inserter, front_inserter, end
74 #include <string> // string
75 #include <tuple> // tuple, make_tuple
76 #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
77 #include <unordered_map> // unordered_map
78 #include <utility> // pair, declval
79 #include <valarray> // valarray
81 // #include <nlohmann/detail/exceptions.hpp>
84 #include <exception> // exception
85 #include <stdexcept> // runtime_error
86 #include <string> // to_string
87 #include <vector> // vector
89 // #include <nlohmann/detail/value_t.hpp>
92 #include <array> // array
93 #include <cstddef> // size_t
94 #include <cstdint> // uint8_t
95 #include <string> // string
101 ///////////////////////////
102 // JSON type enumeration //
103 ///////////////////////////
106 @brief the JSON type enumeration
108 This enumeration collects the different JSON types. It is internally used to
109 distinguish the stored values, and the functions @ref basic_json::is_null(),
110 @ref basic_json::is_object(), @ref basic_json::is_array(),
111 @ref basic_json::is_string(), @ref basic_json::is_boolean(),
112 @ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
113 @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
114 @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
115 @ref basic_json::is_structured() rely on it.
117 @note There are three enumeration entries (number_integer, number_unsigned, and
118 number_float), because the library distinguishes these three types for numbers:
119 @ref basic_json::number_unsigned_t is used for unsigned integers,
120 @ref basic_json::number_integer_t is used for signed integers, and
121 @ref basic_json::number_float_t is used for floating-point numbers or to
122 approximate integers which do not fit in the limits of their respective type.
124 @sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
125 value with the default value for a given type
129 enum class value_t : std::uint8_t
131 null, ///< null value
132 object, ///< object (unordered set of name/value pairs)
133 array, ///< array (ordered collection of values)
134 string, ///< string value
135 boolean, ///< boolean value
136 number_integer, ///< number value (signed integer)
137 number_unsigned, ///< number value (unsigned integer)
138 number_float, ///< number value (floating-point)
139 binary, ///< binary array (ordered collection of bytes)
140 discarded ///< discarded by the parser callback function
144 @brief comparison operator for JSON types
146 Returns an ordering that is similar to Python:
147 - order: null < boolean < number < object < array < string < binary
148 - furthermore, each type is not smaller than itself
149 - discarded values are not comparable
150 - binary is represented as a b"" string in python and directly comparable to a
151 string; however, making a binary array directly comparable with a string would
152 be surprising behavior in a JSON file.
156 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
158 static constexpr std::array<std::uint8_t, 9> order = {{
159 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
160 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
165 const auto l_index = static_cast<std::size_t>(lhs);
166 const auto r_index = static_cast<std::size_t>(rhs);
167 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
169 } // namespace detail
170 } // namespace nlohmann
172 // #include <nlohmann/detail/string_escape.hpp>
176 // #include <nlohmann/detail/macro_scope.hpp>
179 #include <utility> // declval, pair
180 // #include <nlohmann/thirdparty/hedley/hedley.hpp>
183 /* Hedley - https://nemequ.github.io/hedley
184 * Created by Evan Nemerson <evan@nemerson.com>
186 * To the extent possible under law, the author(s) have dedicated all
187 * copyright and related and neighboring rights to this software to
188 * the public domain worldwide. This software is distributed without
191 * For details, see <http://creativecommons.org/publicdomain/zero/1.0/>.
192 * SPDX-License-Identifier: CC0-1.0
195 #if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
196 #if defined(JSON_HEDLEY_VERSION)
197 #undef JSON_HEDLEY_VERSION
199 #define JSON_HEDLEY_VERSION 15
201 #if defined(JSON_HEDLEY_STRINGIFY_EX)
202 #undef JSON_HEDLEY_STRINGIFY_EX
204 #define JSON_HEDLEY_STRINGIFY_EX(x) #x
206 #if defined(JSON_HEDLEY_STRINGIFY)
207 #undef JSON_HEDLEY_STRINGIFY
209 #define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
211 #if defined(JSON_HEDLEY_CONCAT_EX)
212 #undef JSON_HEDLEY_CONCAT_EX
214 #define JSON_HEDLEY_CONCAT_EX(a,b) a##b
216 #if defined(JSON_HEDLEY_CONCAT)
217 #undef JSON_HEDLEY_CONCAT
219 #define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
221 #if defined(JSON_HEDLEY_CONCAT3_EX)
222 #undef JSON_HEDLEY_CONCAT3_EX
224 #define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
226 #if defined(JSON_HEDLEY_CONCAT3)
227 #undef JSON_HEDLEY_CONCAT3
229 #define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
231 #if defined(JSON_HEDLEY_VERSION_ENCODE)
232 #undef JSON_HEDLEY_VERSION_ENCODE
234 #define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
236 #if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
237 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
239 #define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
241 #if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
242 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
244 #define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
246 #if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
247 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
249 #define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
251 #if defined(JSON_HEDLEY_GNUC_VERSION)
252 #undef JSON_HEDLEY_GNUC_VERSION
254 #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
255 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
256 #elif defined(__GNUC__)
257 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
260 #if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
261 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
263 #if defined(JSON_HEDLEY_GNUC_VERSION)
264 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
266 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
269 #if defined(JSON_HEDLEY_MSVC_VERSION)
270 #undef JSON_HEDLEY_MSVC_VERSION
272 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
273 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
274 #elif defined(_MSC_FULL_VER) && !defined(__ICL)
275 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
276 #elif defined(_MSC_VER) && !defined(__ICL)
277 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
280 #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
281 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
283 #if !defined(JSON_HEDLEY_MSVC_VERSION)
284 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
285 #elif defined(_MSC_VER) && (_MSC_VER >= 1400)
286 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
287 #elif defined(_MSC_VER) && (_MSC_VER >= 1200)
288 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
290 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
293 #if defined(JSON_HEDLEY_INTEL_VERSION)
294 #undef JSON_HEDLEY_INTEL_VERSION
296 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
297 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
298 #elif defined(__INTEL_COMPILER) && !defined(__ICL)
299 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
302 #if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
303 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
305 #if defined(JSON_HEDLEY_INTEL_VERSION)
306 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
308 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
311 #if defined(JSON_HEDLEY_INTEL_CL_VERSION)
312 #undef JSON_HEDLEY_INTEL_CL_VERSION
314 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
315 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
318 #if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
319 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
321 #if defined(JSON_HEDLEY_INTEL_CL_VERSION)
322 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
324 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
327 #if defined(JSON_HEDLEY_PGI_VERSION)
328 #undef JSON_HEDLEY_PGI_VERSION
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__)
334 #if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
335 #undef JSON_HEDLEY_PGI_VERSION_CHECK
337 #if defined(JSON_HEDLEY_PGI_VERSION)
338 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
340 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
343 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
344 #undef JSON_HEDLEY_SUNPRO_VERSION
346 #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
347 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
348 #elif defined(__SUNPRO_C)
349 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
350 #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
351 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
352 #elif defined(__SUNPRO_CC)
353 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
356 #if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
357 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
359 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
360 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
362 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
365 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
366 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
368 #if defined(__EMSCRIPTEN__)
369 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
372 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
373 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
375 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
376 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
378 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
381 #if defined(JSON_HEDLEY_ARM_VERSION)
382 #undef JSON_HEDLEY_ARM_VERSION
384 #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
385 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
386 #elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
387 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
390 #if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
391 #undef JSON_HEDLEY_ARM_VERSION_CHECK
393 #if defined(JSON_HEDLEY_ARM_VERSION)
394 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
396 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
399 #if defined(JSON_HEDLEY_IBM_VERSION)
400 #undef JSON_HEDLEY_IBM_VERSION
402 #if defined(__ibmxl__)
403 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
404 #elif defined(__xlC__) && defined(__xlC_ver__)
405 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
406 #elif defined(__xlC__)
407 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
410 #if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
411 #undef JSON_HEDLEY_IBM_VERSION_CHECK
413 #if defined(JSON_HEDLEY_IBM_VERSION)
414 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
416 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
419 #if defined(JSON_HEDLEY_TI_VERSION)
420 #undef JSON_HEDLEY_TI_VERSION
423 defined(__TI_COMPILER_VERSION__) && \
425 defined(__TMS470__) || defined(__TI_ARM__) || \
426 defined(__MSP430__) || \
427 defined(__TMS320C2000__) \
429 #if (__TI_COMPILER_VERSION__ >= 16000000)
430 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
434 #if defined(JSON_HEDLEY_TI_VERSION_CHECK)
435 #undef JSON_HEDLEY_TI_VERSION_CHECK
437 #if defined(JSON_HEDLEY_TI_VERSION)
438 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
440 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
443 #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
444 #undef JSON_HEDLEY_TI_CL2000_VERSION
446 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
447 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
450 #if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
451 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
453 #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
454 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
456 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
459 #if defined(JSON_HEDLEY_TI_CL430_VERSION)
460 #undef JSON_HEDLEY_TI_CL430_VERSION
462 #if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
463 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
466 #if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
467 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
469 #if defined(JSON_HEDLEY_TI_CL430_VERSION)
470 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
472 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
475 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
476 #undef JSON_HEDLEY_TI_ARMCL_VERSION
478 #if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
479 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
482 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
483 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
485 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
486 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
488 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
491 #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
492 #undef JSON_HEDLEY_TI_CL6X_VERSION
494 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
495 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
498 #if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
499 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
501 #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
502 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
504 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
507 #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
508 #undef JSON_HEDLEY_TI_CL7X_VERSION
510 #if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
511 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
514 #if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
515 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
517 #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
518 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
520 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
523 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
524 #undef JSON_HEDLEY_TI_CLPRU_VERSION
526 #if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
527 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
530 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
531 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
533 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
534 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
536 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
539 #if defined(JSON_HEDLEY_CRAY_VERSION)
540 #undef JSON_HEDLEY_CRAY_VERSION
543 #if defined(_RELEASE_PATCHLEVEL)
544 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
546 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
550 #if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
551 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
553 #if defined(JSON_HEDLEY_CRAY_VERSION)
554 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
556 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
559 #if defined(JSON_HEDLEY_IAR_VERSION)
560 #undef JSON_HEDLEY_IAR_VERSION
562 #if defined(__IAR_SYSTEMS_ICC__)
564 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
566 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
570 #if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
571 #undef JSON_HEDLEY_IAR_VERSION_CHECK
573 #if defined(JSON_HEDLEY_IAR_VERSION)
574 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
576 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
579 #if defined(JSON_HEDLEY_TINYC_VERSION)
580 #undef JSON_HEDLEY_TINYC_VERSION
582 #if defined(__TINYC__)
583 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
586 #if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
587 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
589 #if defined(JSON_HEDLEY_TINYC_VERSION)
590 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
592 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
595 #if defined(JSON_HEDLEY_DMC_VERSION)
596 #undef JSON_HEDLEY_DMC_VERSION
599 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
602 #if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
603 #undef JSON_HEDLEY_DMC_VERSION_CHECK
605 #if defined(JSON_HEDLEY_DMC_VERSION)
606 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
608 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
611 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
612 #undef JSON_HEDLEY_COMPCERT_VERSION
614 #if defined(__COMPCERT_VERSION__)
615 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
618 #if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
619 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
621 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
622 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
624 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
627 #if defined(JSON_HEDLEY_PELLES_VERSION)
628 #undef JSON_HEDLEY_PELLES_VERSION
630 #if defined(__POCC__)
631 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
634 #if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
635 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
637 #if defined(JSON_HEDLEY_PELLES_VERSION)
638 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
640 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
643 #if defined(JSON_HEDLEY_MCST_LCC_VERSION)
644 #undef JSON_HEDLEY_MCST_LCC_VERSION
646 #if defined(__LCC__) && defined(__LCC_MINOR__)
647 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
650 #if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
651 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
653 #if defined(JSON_HEDLEY_MCST_LCC_VERSION)
654 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
656 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
659 #if defined(JSON_HEDLEY_GCC_VERSION)
660 #undef JSON_HEDLEY_GCC_VERSION
663 defined(JSON_HEDLEY_GNUC_VERSION) && \
664 !defined(__clang__) && \
665 !defined(JSON_HEDLEY_INTEL_VERSION) && \
666 !defined(JSON_HEDLEY_PGI_VERSION) && \
667 !defined(JSON_HEDLEY_ARM_VERSION) && \
668 !defined(JSON_HEDLEY_CRAY_VERSION) && \
669 !defined(JSON_HEDLEY_TI_VERSION) && \
670 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
671 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
672 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
673 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
674 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
675 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
676 !defined(__COMPCERT__) && \
677 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
678 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
681 #if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
682 #undef JSON_HEDLEY_GCC_VERSION_CHECK
684 #if defined(JSON_HEDLEY_GCC_VERSION)
685 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
687 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
690 #if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
691 #undef JSON_HEDLEY_HAS_ATTRIBUTE
694 defined(__has_attribute) && \
696 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
698 # define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
700 # define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
703 #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
704 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
706 #if defined(__has_attribute)
707 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
709 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
712 #if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
713 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
715 #if defined(__has_attribute)
716 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
718 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
721 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
722 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
725 defined(__has_cpp_attribute) && \
726 defined(__cplusplus) && \
727 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
728 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
730 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
733 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
734 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
736 #if !defined(__cplusplus) || !defined(__has_cpp_attribute)
737 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
739 !defined(JSON_HEDLEY_PGI_VERSION) && \
740 !defined(JSON_HEDLEY_IAR_VERSION) && \
741 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
742 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
743 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
745 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
748 #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
749 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
751 #if defined(__has_cpp_attribute) && defined(__cplusplus)
752 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
754 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
757 #if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
758 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
760 #if defined(__has_cpp_attribute) && defined(__cplusplus)
761 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
763 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
766 #if defined(JSON_HEDLEY_HAS_BUILTIN)
767 #undef JSON_HEDLEY_HAS_BUILTIN
769 #if defined(__has_builtin)
770 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
772 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
775 #if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
776 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
778 #if defined(__has_builtin)
779 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
781 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
784 #if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
785 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
787 #if defined(__has_builtin)
788 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
790 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
793 #if defined(JSON_HEDLEY_HAS_FEATURE)
794 #undef JSON_HEDLEY_HAS_FEATURE
796 #if defined(__has_feature)
797 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
799 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
802 #if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
803 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
805 #if defined(__has_feature)
806 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
808 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
811 #if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
812 #undef JSON_HEDLEY_GCC_HAS_FEATURE
814 #if defined(__has_feature)
815 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
817 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
820 #if defined(JSON_HEDLEY_HAS_EXTENSION)
821 #undef JSON_HEDLEY_HAS_EXTENSION
823 #if defined(__has_extension)
824 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
826 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
829 #if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
830 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
832 #if defined(__has_extension)
833 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
835 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
838 #if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
839 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
841 #if defined(__has_extension)
842 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
844 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
847 #if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
848 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
850 #if defined(__has_declspec_attribute)
851 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
853 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
856 #if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
857 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
859 #if defined(__has_declspec_attribute)
860 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
862 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
865 #if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
866 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
868 #if defined(__has_declspec_attribute)
869 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
871 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
874 #if defined(JSON_HEDLEY_HAS_WARNING)
875 #undef JSON_HEDLEY_HAS_WARNING
877 #if defined(__has_warning)
878 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
880 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
883 #if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
884 #undef JSON_HEDLEY_GNUC_HAS_WARNING
886 #if defined(__has_warning)
887 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
889 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
892 #if defined(JSON_HEDLEY_GCC_HAS_WARNING)
893 #undef JSON_HEDLEY_GCC_HAS_WARNING
895 #if defined(__has_warning)
896 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
898 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
902 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
903 defined(__clang__) || \
904 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
905 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
906 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
907 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
908 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
909 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
910 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
911 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
912 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
913 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
914 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
915 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
916 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
917 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
918 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
919 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
920 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
921 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
922 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
924 #define JSON_HEDLEY_PRAGMA(value)
927 #if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
928 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
930 #if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
931 #undef JSON_HEDLEY_DIAGNOSTIC_POP
933 #if defined(__clang__)
934 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
935 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
936 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
937 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
938 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
939 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
940 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
941 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
943 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
944 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
945 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
946 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
947 #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
948 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
949 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
951 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
952 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
953 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
954 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
955 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
956 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
957 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
958 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
959 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
960 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
961 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
963 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
964 #define JSON_HEDLEY_DIAGNOSTIC_POP
967 /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
968 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
969 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
970 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
972 #if defined(__cplusplus)
973 # if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
974 # if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
975 # if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
976 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
977 JSON_HEDLEY_DIAGNOSTIC_PUSH \
978 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
979 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
980 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
982 JSON_HEDLEY_DIAGNOSTIC_POP
984 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
985 JSON_HEDLEY_DIAGNOSTIC_PUSH \
986 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
987 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
989 JSON_HEDLEY_DIAGNOSTIC_POP
992 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
993 JSON_HEDLEY_DIAGNOSTIC_PUSH \
994 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
996 JSON_HEDLEY_DIAGNOSTIC_POP
1000 #if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1001 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1004 #if defined(JSON_HEDLEY_CONST_CAST)
1005 #undef JSON_HEDLEY_CONST_CAST
1007 #if defined(__cplusplus)
1008 # define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1010 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1011 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1012 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1013 # define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1014 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1015 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1017 JSON_HEDLEY_DIAGNOSTIC_POP \
1020 # define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1023 #if defined(JSON_HEDLEY_REINTERPRET_CAST)
1024 #undef JSON_HEDLEY_REINTERPRET_CAST
1026 #if defined(__cplusplus)
1027 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1029 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1032 #if defined(JSON_HEDLEY_STATIC_CAST)
1033 #undef JSON_HEDLEY_STATIC_CAST
1035 #if defined(__cplusplus)
1036 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1038 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1041 #if defined(JSON_HEDLEY_CPP_CAST)
1042 #undef JSON_HEDLEY_CPP_CAST
1044 #if defined(__cplusplus)
1045 # if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1046 # define JSON_HEDLEY_CPP_CAST(T, expr) \
1047 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1048 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1050 JSON_HEDLEY_DIAGNOSTIC_POP
1051 # elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1052 # define JSON_HEDLEY_CPP_CAST(T, expr) \
1053 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1054 _Pragma("diag_suppress=Pe137") \
1055 JSON_HEDLEY_DIAGNOSTIC_POP
1057 # define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1060 # define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1063 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1064 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1066 #if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1067 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1068 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1069 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1070 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1071 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1072 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1073 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1074 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1075 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1076 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1077 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1078 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1079 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1080 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1081 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1083 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1084 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1085 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1086 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1087 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1088 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1089 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1090 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1091 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1092 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1093 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1094 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1095 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1096 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1097 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1098 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1099 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1100 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1101 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1102 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1104 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1107 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1108 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1110 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1111 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1112 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1113 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1114 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1115 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1116 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1117 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1118 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1119 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1120 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1121 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1123 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1124 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1125 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1126 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1127 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1128 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1129 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1130 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1131 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1132 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1133 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1135 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1138 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1139 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1141 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1142 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1143 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1144 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1145 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1146 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1147 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1148 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1149 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1150 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1151 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1152 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1153 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1154 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1155 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1156 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1158 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1159 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1160 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1161 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1162 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1163 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1164 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1165 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1167 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1170 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1171 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
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\"")
1180 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1183 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1184 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
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")
1195 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1198 #if defined(JSON_HEDLEY_DEPRECATED)
1199 #undef JSON_HEDLEY_DEPRECATED
1201 #if defined(JSON_HEDLEY_DEPRECATED_FOR)
1202 #undef JSON_HEDLEY_DEPRECATED_FOR
1205 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1206 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1207 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1208 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1210 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1211 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1212 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1213 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1214 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1215 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1216 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1217 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1218 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1219 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1220 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1221 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1222 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1223 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1224 #elif defined(__cplusplus) && (__cplusplus >= 201402L)
1225 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1226 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1228 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1229 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1230 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1231 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1232 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1233 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1234 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1235 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1236 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1237 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1238 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1239 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1240 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1241 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1242 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1243 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1244 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1245 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1247 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1248 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1249 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1250 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1251 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1252 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1253 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1254 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1256 #define JSON_HEDLEY_DEPRECATED(since)
1257 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1260 #if defined(JSON_HEDLEY_UNAVAILABLE)
1261 #undef JSON_HEDLEY_UNAVAILABLE
1264 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1265 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1266 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1267 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1268 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1270 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1273 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1274 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1276 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1277 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1280 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1281 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1282 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1283 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1284 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1285 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1286 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1287 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1288 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1289 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1290 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1291 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1292 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1293 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1294 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1295 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1296 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1297 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1298 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1299 #elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1300 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1301 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1302 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1303 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1304 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1305 #elif defined(_Check_return_) /* SAL */
1306 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1307 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1309 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1310 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1313 #if defined(JSON_HEDLEY_SENTINEL)
1314 #undef JSON_HEDLEY_SENTINEL
1317 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1318 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1319 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1320 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1321 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1322 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1324 #define JSON_HEDLEY_SENTINEL(position)
1327 #if defined(JSON_HEDLEY_NO_RETURN)
1328 #undef JSON_HEDLEY_NO_RETURN
1330 #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1331 #define JSON_HEDLEY_NO_RETURN __noreturn
1333 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1334 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1335 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1336 #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1337 #define JSON_HEDLEY_NO_RETURN _Noreturn
1338 #elif defined(__cplusplus) && (__cplusplus >= 201103L)
1339 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1341 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1342 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1343 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1344 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1345 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1346 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1347 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1348 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1349 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1350 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1351 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1352 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1353 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1354 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1355 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1356 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1357 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1358 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1359 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1360 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1362 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1363 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1364 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1365 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1366 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1367 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1368 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1369 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1370 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1372 #define JSON_HEDLEY_NO_RETURN
1375 #if defined(JSON_HEDLEY_NO_ESCAPE)
1376 #undef JSON_HEDLEY_NO_ESCAPE
1378 #if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1379 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1381 #define JSON_HEDLEY_NO_ESCAPE
1384 #if defined(JSON_HEDLEY_UNREACHABLE)
1385 #undef JSON_HEDLEY_UNREACHABLE
1387 #if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1388 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1390 #if defined(JSON_HEDLEY_ASSUME)
1391 #undef JSON_HEDLEY_ASSUME
1394 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1395 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1396 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1397 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1398 #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1399 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1401 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1402 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1403 #if defined(__cplusplus)
1404 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1406 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1410 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1411 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1412 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1413 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1414 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1415 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1416 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1417 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1418 #elif defined(JSON_HEDLEY_ASSUME)
1419 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1421 #if !defined(JSON_HEDLEY_ASSUME)
1422 #if defined(JSON_HEDLEY_UNREACHABLE)
1423 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1425 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1428 #if defined(JSON_HEDLEY_UNREACHABLE)
1430 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1431 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1432 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1434 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1437 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1439 #if !defined(JSON_HEDLEY_UNREACHABLE)
1440 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1443 JSON_HEDLEY_DIAGNOSTIC_PUSH
1444 #if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1445 #pragma clang diagnostic ignored "-Wpedantic"
1447 #if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1448 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1450 #if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1451 #if defined(__clang__)
1452 #pragma clang diagnostic ignored "-Wvariadic-macros"
1453 #elif defined(JSON_HEDLEY_GCC_VERSION)
1454 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1457 #if defined(JSON_HEDLEY_NON_NULL)
1458 #undef JSON_HEDLEY_NON_NULL
1461 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1462 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1463 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1464 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1465 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1467 #define JSON_HEDLEY_NON_NULL(...)
1469 JSON_HEDLEY_DIAGNOSTIC_POP
1471 #if defined(JSON_HEDLEY_PRINTF_FORMAT)
1472 #undef JSON_HEDLEY_PRINTF_FORMAT
1474 #if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1475 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1476 #elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1477 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1479 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1480 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1481 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1482 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1483 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1484 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1485 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1486 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1487 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1488 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1489 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1490 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1491 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1492 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1493 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1494 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1495 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1496 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1497 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1498 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1500 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1503 #if defined(JSON_HEDLEY_CONSTEXPR)
1504 #undef JSON_HEDLEY_CONSTEXPR
1506 #if defined(__cplusplus)
1507 #if __cplusplus >= 201103L
1508 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1511 #if !defined(JSON_HEDLEY_CONSTEXPR)
1512 #define JSON_HEDLEY_CONSTEXPR
1515 #if defined(JSON_HEDLEY_PREDICT)
1516 #undef JSON_HEDLEY_PREDICT
1518 #if defined(JSON_HEDLEY_LIKELY)
1519 #undef JSON_HEDLEY_LIKELY
1521 #if defined(JSON_HEDLEY_UNLIKELY)
1522 #undef JSON_HEDLEY_UNLIKELY
1524 #if defined(JSON_HEDLEY_UNPREDICTABLE)
1525 #undef JSON_HEDLEY_UNPREDICTABLE
1527 #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1528 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1531 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1532 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1533 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1534 # define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1535 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1536 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1537 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1538 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1540 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1541 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1542 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1543 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1544 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1545 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1546 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1547 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1548 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1549 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1550 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1551 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1552 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1553 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1554 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1555 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1556 # define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1557 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1558 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1560 double hedley_probability_ = (probability); \
1561 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1563 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1565 double hedley_probability_ = (probability); \
1566 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1568 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1569 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1571 # define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1572 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1573 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1574 # define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1575 # define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1577 #if !defined(JSON_HEDLEY_UNPREDICTABLE)
1578 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1581 #if defined(JSON_HEDLEY_MALLOC)
1582 #undef JSON_HEDLEY_MALLOC
1585 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1586 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1587 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1588 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1589 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1590 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1591 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1592 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1593 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1594 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1595 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1596 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1597 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1598 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1599 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1600 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1601 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1602 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1603 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1604 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1605 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1607 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1608 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1609 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1611 #define JSON_HEDLEY_MALLOC
1614 #if defined(JSON_HEDLEY_PURE)
1615 #undef JSON_HEDLEY_PURE
1618 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1619 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1620 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1621 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1622 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1623 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1624 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1625 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1626 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1627 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1628 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1629 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1630 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1631 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1632 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1633 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1634 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1635 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1636 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1637 # define JSON_HEDLEY_PURE __attribute__((__pure__))
1638 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1639 # define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1640 #elif defined(__cplusplus) && \
1642 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1643 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1644 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1646 # define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1648 # define JSON_HEDLEY_PURE
1651 #if defined(JSON_HEDLEY_CONST)
1652 #undef JSON_HEDLEY_CONST
1655 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1656 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1657 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1658 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1659 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1660 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1661 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1662 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1663 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1664 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1665 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1666 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1667 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1668 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1669 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1670 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1671 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1672 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1673 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1674 #define JSON_HEDLEY_CONST __attribute__((__const__))
1676 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1677 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1679 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1682 #if defined(JSON_HEDLEY_RESTRICT)
1683 #undef JSON_HEDLEY_RESTRICT
1685 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1686 #define JSON_HEDLEY_RESTRICT restrict
1688 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1689 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1690 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1691 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1692 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1693 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1694 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1695 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1696 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1697 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1698 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1699 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1700 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1701 defined(__clang__) || \
1702 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1703 #define JSON_HEDLEY_RESTRICT __restrict
1704 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1705 #define JSON_HEDLEY_RESTRICT _Restrict
1707 #define JSON_HEDLEY_RESTRICT
1710 #if defined(JSON_HEDLEY_INLINE)
1711 #undef JSON_HEDLEY_INLINE
1714 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1715 (defined(__cplusplus) && (__cplusplus >= 199711L))
1716 #define JSON_HEDLEY_INLINE inline
1718 defined(JSON_HEDLEY_GCC_VERSION) || \
1719 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1720 #define JSON_HEDLEY_INLINE __inline__
1722 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1723 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1724 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1725 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1726 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1727 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1728 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1729 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1730 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1731 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1732 #define JSON_HEDLEY_INLINE __inline
1734 #define JSON_HEDLEY_INLINE
1737 #if defined(JSON_HEDLEY_ALWAYS_INLINE)
1738 #undef JSON_HEDLEY_ALWAYS_INLINE
1741 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1742 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1743 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1744 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1745 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1746 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1747 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1748 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1749 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1750 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1751 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1752 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1753 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1754 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1755 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1756 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1757 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1758 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1759 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1760 # define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1762 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1763 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1764 # define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1765 #elif defined(__cplusplus) && \
1767 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1768 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1769 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1770 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1771 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1772 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1774 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1775 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1776 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1778 # define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1781 #if defined(JSON_HEDLEY_NEVER_INLINE)
1782 #undef JSON_HEDLEY_NEVER_INLINE
1785 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1786 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1787 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1788 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1789 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1790 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1791 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1792 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1793 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1794 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1795 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1796 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1797 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1798 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1799 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1800 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1801 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1802 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1803 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1804 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1806 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1807 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1808 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1809 #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1810 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1811 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1812 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1813 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1814 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1815 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1816 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1817 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1818 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1820 #define JSON_HEDLEY_NEVER_INLINE
1823 #if defined(JSON_HEDLEY_PRIVATE)
1824 #undef JSON_HEDLEY_PRIVATE
1826 #if defined(JSON_HEDLEY_PUBLIC)
1827 #undef JSON_HEDLEY_PUBLIC
1829 #if defined(JSON_HEDLEY_IMPORT)
1830 #undef JSON_HEDLEY_IMPORT
1832 #if defined(_WIN32) || defined(__CYGWIN__)
1833 # define JSON_HEDLEY_PRIVATE
1834 # define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1835 # define JSON_HEDLEY_IMPORT __declspec(dllimport)
1838 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1839 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1840 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1841 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1842 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1843 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1845 defined(__TI_EABI__) && \
1847 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1848 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1851 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1852 # define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1853 # define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1855 # define JSON_HEDLEY_PRIVATE
1856 # define JSON_HEDLEY_PUBLIC
1858 # define JSON_HEDLEY_IMPORT extern
1861 #if defined(JSON_HEDLEY_NO_THROW)
1862 #undef JSON_HEDLEY_NO_THROW
1865 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
1866 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1867 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1868 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1869 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
1871 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
1872 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1873 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1874 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
1876 #define JSON_HEDLEY_NO_THROW
1879 #if defined(JSON_HEDLEY_FALL_THROUGH)
1880 #undef JSON_HEDLEY_FALL_THROUGH
1883 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
1884 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
1885 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1886 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
1887 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
1888 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
1889 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
1890 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
1891 #elif defined(__fallthrough) /* SAL */
1892 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
1894 #define JSON_HEDLEY_FALL_THROUGH
1897 #if defined(JSON_HEDLEY_RETURNS_NON_NULL)
1898 #undef JSON_HEDLEY_RETURNS_NON_NULL
1901 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
1902 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
1903 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1904 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
1905 #elif defined(_Ret_notnull_) /* SAL */
1906 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
1908 #define JSON_HEDLEY_RETURNS_NON_NULL
1911 #if defined(JSON_HEDLEY_ARRAY_PARAM)
1912 #undef JSON_HEDLEY_ARRAY_PARAM
1915 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
1916 !defined(__STDC_NO_VLA__) && \
1917 !defined(__cplusplus) && \
1918 !defined(JSON_HEDLEY_PGI_VERSION) && \
1919 !defined(JSON_HEDLEY_TINYC_VERSION)
1920 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
1922 #define JSON_HEDLEY_ARRAY_PARAM(name)
1925 #if defined(JSON_HEDLEY_IS_CONSTANT)
1926 #undef JSON_HEDLEY_IS_CONSTANT
1928 #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
1929 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
1931 /* JSON_HEDLEY_IS_CONSTEXPR_ is for
1932 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1933 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1934 #undef JSON_HEDLEY_IS_CONSTEXPR_
1937 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
1938 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1939 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1940 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
1941 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1942 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1943 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1944 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
1945 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1946 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1947 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
1949 #if !defined(__cplusplus)
1951 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
1952 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1953 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1954 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1955 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1956 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1957 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
1958 #if defined(__INTPTR_TYPE__)
1959 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
1962 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
1966 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
1967 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
1968 !defined(JSON_HEDLEY_PGI_VERSION) && \
1969 !defined(JSON_HEDLEY_IAR_VERSION)) || \
1970 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1971 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
1972 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
1973 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1974 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
1975 #if defined(__INTPTR_TYPE__)
1976 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
1979 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
1982 defined(JSON_HEDLEY_GCC_VERSION) || \
1983 defined(JSON_HEDLEY_INTEL_VERSION) || \
1984 defined(JSON_HEDLEY_TINYC_VERSION) || \
1985 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
1986 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
1987 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
1988 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
1989 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
1990 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
1992 # define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
1996 ((void*) ((expr) * 0L) ) : \
1997 ((struct { char v[sizeof(void) * 2]; } *) 1) \
2003 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2004 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2005 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2007 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2009 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2010 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2012 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2015 #if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2016 #undef JSON_HEDLEY_BEGIN_C_DECLS
2018 #if defined(JSON_HEDLEY_END_C_DECLS)
2019 #undef JSON_HEDLEY_END_C_DECLS
2021 #if defined(JSON_HEDLEY_C_DECL)
2022 #undef JSON_HEDLEY_C_DECL
2024 #if defined(__cplusplus)
2025 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2026 #define JSON_HEDLEY_END_C_DECLS }
2027 #define JSON_HEDLEY_C_DECL extern "C"
2029 #define JSON_HEDLEY_BEGIN_C_DECLS
2030 #define JSON_HEDLEY_END_C_DECLS
2031 #define JSON_HEDLEY_C_DECL
2034 #if defined(JSON_HEDLEY_STATIC_ASSERT)
2035 #undef JSON_HEDLEY_STATIC_ASSERT
2038 !defined(__cplusplus) && ( \
2039 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2040 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2041 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2042 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2043 defined(_Static_assert) \
2045 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2047 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2048 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2049 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2050 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2052 # define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2055 #if defined(JSON_HEDLEY_NULL)
2056 #undef JSON_HEDLEY_NULL
2058 #if defined(__cplusplus)
2059 #if __cplusplus >= 201103L
2060 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2062 #define JSON_HEDLEY_NULL NULL
2064 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2067 #define JSON_HEDLEY_NULL NULL
2069 #define JSON_HEDLEY_NULL ((void*) 0)
2072 #if defined(JSON_HEDLEY_MESSAGE)
2073 #undef JSON_HEDLEY_MESSAGE
2075 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2076 # define JSON_HEDLEY_MESSAGE(msg) \
2077 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2078 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2079 JSON_HEDLEY_PRAGMA(message msg) \
2080 JSON_HEDLEY_DIAGNOSTIC_POP
2082 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2083 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2084 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2085 #elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2086 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2087 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2088 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2089 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2090 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2092 # define JSON_HEDLEY_MESSAGE(msg)
2095 #if defined(JSON_HEDLEY_WARNING)
2096 #undef JSON_HEDLEY_WARNING
2098 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2099 # define JSON_HEDLEY_WARNING(msg) \
2100 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2101 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2102 JSON_HEDLEY_PRAGMA(clang warning msg) \
2103 JSON_HEDLEY_DIAGNOSTIC_POP
2105 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2106 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2107 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2108 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2110 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2111 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2112 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2114 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2117 #if defined(JSON_HEDLEY_REQUIRE)
2118 #undef JSON_HEDLEY_REQUIRE
2120 #if defined(JSON_HEDLEY_REQUIRE_MSG)
2121 #undef JSON_HEDLEY_REQUIRE_MSG
2123 #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2124 # if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2125 # define JSON_HEDLEY_REQUIRE(expr) \
2126 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2127 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2128 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2129 JSON_HEDLEY_DIAGNOSTIC_POP
2130 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2131 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2132 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2133 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2134 JSON_HEDLEY_DIAGNOSTIC_POP
2136 # define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2137 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2140 # define JSON_HEDLEY_REQUIRE(expr)
2141 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2144 #if defined(JSON_HEDLEY_FLAGS)
2145 #undef JSON_HEDLEY_FLAGS
2147 #if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2148 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2150 #define JSON_HEDLEY_FLAGS
2153 #if defined(JSON_HEDLEY_FLAGS_CAST)
2154 #undef JSON_HEDLEY_FLAGS_CAST
2156 #if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2157 # define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2158 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2159 _Pragma("warning(disable:188)") \
2161 JSON_HEDLEY_DIAGNOSTIC_POP \
2164 # define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2167 #if defined(JSON_HEDLEY_EMPTY_BASES)
2168 #undef JSON_HEDLEY_EMPTY_BASES
2171 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2172 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2173 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2175 #define JSON_HEDLEY_EMPTY_BASES
2178 /* Remaining macros are deprecated. */
2180 #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2181 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2183 #if defined(__clang__)
2184 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2186 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2189 #if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2190 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2192 #define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2194 #if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2195 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2197 #define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2199 #if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2200 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2202 #define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2204 #if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2205 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2207 #define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2209 #if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2210 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2212 #define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2214 #if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2215 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2217 #define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2219 #if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2220 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2222 #define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2224 #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2226 // #include <nlohmann/detail/meta/detected.hpp>
2229 #include <type_traits>
2231 // #include <nlohmann/detail/meta/void_t.hpp>
2238 template<typename ...Ts> struct make_void
2242 template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
2243 } // namespace detail
2244 } // namespace nlohmann
2247 // https://en.cppreference.com/w/cpp/experimental/is_detected
2254 nonesuch() = delete;
2255 ~nonesuch() = delete;
2256 nonesuch(nonesuch const&) = delete;
2257 nonesuch(nonesuch const&&) = delete;
2258 void operator=(nonesuch const&) = delete;
2259 void operator=(nonesuch&&) = delete;
2262 template<class Default,
2264 template<class...> class Op,
2268 using value_t = std::false_type;
2269 using type = Default;
2272 template<class Default, template<class...> class Op, class... Args>
2273 struct detector<Default, void_t<Op<Args...>>, Op, Args...>
2275 using value_t = std::true_type;
2276 using type = Op<Args...>;
2279 template<template<class...> class Op, class... Args>
2280 using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
2282 template<template<class...> class Op, class... Args>
2283 struct is_detected_lazy : is_detected<Op, Args...> { };
2285 template<template<class...> class Op, class... Args>
2286 using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
2288 template<class Default, template<class...> class Op, class... Args>
2289 using detected_or = detector<Default, void, Op, Args...>;
2291 template<class Default, template<class...> class Op, class... Args>
2292 using detected_or_t = typename detected_or<Default, Op, Args...>::type;
2294 template<class Expected, template<class...> class Op, class... Args>
2295 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
2297 template<class To, template<class...> class Op, class... Args>
2298 using is_detected_convertible =
2299 std::is_convertible<detected_t<Op, Args...>, To>;
2300 } // namespace detail
2301 } // namespace nlohmann
2304 // This file contains all internal macro definitions
2305 // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2307 // exclude unsupported compilers
2308 #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2309 #if defined(__clang__)
2310 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2311 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2313 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2314 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2315 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2320 // C++ language standard detection
2321 // if the user manually specified the used c++ version this is skipped
2322 #if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2323 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2324 #define JSON_HAS_CPP_20
2325 #define JSON_HAS_CPP_17
2326 #define JSON_HAS_CPP_14
2327 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2328 #define JSON_HAS_CPP_17
2329 #define JSON_HAS_CPP_14
2330 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2331 #define JSON_HAS_CPP_14
2333 // the cpp 11 flag is always specified because it is the minimal required version
2334 #define JSON_HAS_CPP_11
2337 #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2338 #ifdef JSON_HAS_CPP_17
2339 #if defined(__cpp_lib_filesystem)
2340 #define JSON_HAS_FILESYSTEM 1
2341 #elif defined(__cpp_lib_experimental_filesystem)
2342 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2343 #elif !defined(__has_include)
2344 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2345 #elif __has_include(<filesystem>)
2346 #define JSON_HAS_FILESYSTEM 1
2347 #elif __has_include(<experimental/filesystem>)
2348 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2351 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2352 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2353 #undef JSON_HAS_FILESYSTEM
2354 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2357 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2358 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2359 #undef JSON_HAS_FILESYSTEM
2360 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2363 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2364 #if defined(__clang_major__) && __clang_major__ < 7
2365 #undef JSON_HAS_FILESYSTEM
2366 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2369 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2370 #if defined(_MSC_VER) && _MSC_VER < 1940
2371 #undef JSON_HAS_FILESYSTEM
2372 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2375 // no filesystem support before iOS 13
2376 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2377 #undef JSON_HAS_FILESYSTEM
2378 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2381 // no filesystem support before macOS Catalina
2382 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2383 #undef JSON_HAS_FILESYSTEM
2384 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2389 #ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2390 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2393 #ifndef JSON_HAS_FILESYSTEM
2394 #define JSON_HAS_FILESYSTEM 0
2397 // disable documentation warnings on clang
2398 #if defined(__clang__)
2399 #pragma clang diagnostic push
2400 #pragma clang diagnostic ignored "-Wdocumentation"
2401 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2404 // allow disabling exceptions
2405 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2406 #define JSON_THROW(exception) throw exception
2407 #define JSON_TRY try
2408 #define JSON_CATCH(exception) catch(exception)
2409 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2412 #define JSON_THROW(exception) std::abort()
2413 #define JSON_TRY if(true)
2414 #define JSON_CATCH(exception) if(false)
2415 #define JSON_INTERNAL_CATCH(exception) if(false)
2418 // override exception macros
2419 #if defined(JSON_THROW_USER)
2421 #define JSON_THROW JSON_THROW_USER
2423 #if defined(JSON_TRY_USER)
2425 #define JSON_TRY JSON_TRY_USER
2427 #if defined(JSON_CATCH_USER)
2429 #define JSON_CATCH JSON_CATCH_USER
2430 #undef JSON_INTERNAL_CATCH
2431 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2433 #if defined(JSON_INTERNAL_CATCH_USER)
2434 #undef JSON_INTERNAL_CATCH
2435 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2438 // allow overriding assert
2439 #if !defined(JSON_ASSERT)
2440 #include <cassert> // assert
2441 #define JSON_ASSERT(x) assert(x)
2444 // allow to access some private functions (needed by the test suite)
2445 #if defined(JSON_TESTS_PRIVATE)
2446 #define JSON_PRIVATE_UNLESS_TESTED public
2448 #define JSON_PRIVATE_UNLESS_TESTED private
2452 @brief macro to briefly define a mapping between an enum and JSON
2453 @def NLOHMANN_JSON_SERIALIZE_ENUM
2454 @since version 3.4.0
2456 #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2457 template<typename BasicJsonType> \
2458 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2460 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2461 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2462 auto it = std::find_if(std::begin(m), std::end(m), \
2463 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2465 return ej_pair.first == e; \
2467 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2469 template<typename BasicJsonType> \
2470 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2472 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2473 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2474 auto it = std::find_if(std::begin(m), std::end(m), \
2475 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2477 return ej_pair.second == j; \
2479 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2482 // Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2483 // may be removed in the future once the class is split.
2485 #define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2486 template<template<typename, typename, typename...> class ObjectType, \
2487 template<typename, typename...> class ArrayType, \
2488 class StringType, class BooleanType, class NumberIntegerType, \
2489 class NumberUnsignedType, class NumberFloatType, \
2490 template<typename> class AllocatorType, \
2491 template<typename, typename = void> class JSONSerializer, \
2494 #define NLOHMANN_BASIC_JSON_TPL \
2495 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2496 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2497 AllocatorType, JSONSerializer, BinaryType>
2499 // Macros to simplify conversion from/to types
2501 #define NLOHMANN_JSON_EXPAND( x ) x
2502 #define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
2503 #define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2504 NLOHMANN_JSON_PASTE64, \
2505 NLOHMANN_JSON_PASTE63, \
2506 NLOHMANN_JSON_PASTE62, \
2507 NLOHMANN_JSON_PASTE61, \
2508 NLOHMANN_JSON_PASTE60, \
2509 NLOHMANN_JSON_PASTE59, \
2510 NLOHMANN_JSON_PASTE58, \
2511 NLOHMANN_JSON_PASTE57, \
2512 NLOHMANN_JSON_PASTE56, \
2513 NLOHMANN_JSON_PASTE55, \
2514 NLOHMANN_JSON_PASTE54, \
2515 NLOHMANN_JSON_PASTE53, \
2516 NLOHMANN_JSON_PASTE52, \
2517 NLOHMANN_JSON_PASTE51, \
2518 NLOHMANN_JSON_PASTE50, \
2519 NLOHMANN_JSON_PASTE49, \
2520 NLOHMANN_JSON_PASTE48, \
2521 NLOHMANN_JSON_PASTE47, \
2522 NLOHMANN_JSON_PASTE46, \
2523 NLOHMANN_JSON_PASTE45, \
2524 NLOHMANN_JSON_PASTE44, \
2525 NLOHMANN_JSON_PASTE43, \
2526 NLOHMANN_JSON_PASTE42, \
2527 NLOHMANN_JSON_PASTE41, \
2528 NLOHMANN_JSON_PASTE40, \
2529 NLOHMANN_JSON_PASTE39, \
2530 NLOHMANN_JSON_PASTE38, \
2531 NLOHMANN_JSON_PASTE37, \
2532 NLOHMANN_JSON_PASTE36, \
2533 NLOHMANN_JSON_PASTE35, \
2534 NLOHMANN_JSON_PASTE34, \
2535 NLOHMANN_JSON_PASTE33, \
2536 NLOHMANN_JSON_PASTE32, \
2537 NLOHMANN_JSON_PASTE31, \
2538 NLOHMANN_JSON_PASTE30, \
2539 NLOHMANN_JSON_PASTE29, \
2540 NLOHMANN_JSON_PASTE28, \
2541 NLOHMANN_JSON_PASTE27, \
2542 NLOHMANN_JSON_PASTE26, \
2543 NLOHMANN_JSON_PASTE25, \
2544 NLOHMANN_JSON_PASTE24, \
2545 NLOHMANN_JSON_PASTE23, \
2546 NLOHMANN_JSON_PASTE22, \
2547 NLOHMANN_JSON_PASTE21, \
2548 NLOHMANN_JSON_PASTE20, \
2549 NLOHMANN_JSON_PASTE19, \
2550 NLOHMANN_JSON_PASTE18, \
2551 NLOHMANN_JSON_PASTE17, \
2552 NLOHMANN_JSON_PASTE16, \
2553 NLOHMANN_JSON_PASTE15, \
2554 NLOHMANN_JSON_PASTE14, \
2555 NLOHMANN_JSON_PASTE13, \
2556 NLOHMANN_JSON_PASTE12, \
2557 NLOHMANN_JSON_PASTE11, \
2558 NLOHMANN_JSON_PASTE10, \
2559 NLOHMANN_JSON_PASTE9, \
2560 NLOHMANN_JSON_PASTE8, \
2561 NLOHMANN_JSON_PASTE7, \
2562 NLOHMANN_JSON_PASTE6, \
2563 NLOHMANN_JSON_PASTE5, \
2564 NLOHMANN_JSON_PASTE4, \
2565 NLOHMANN_JSON_PASTE3, \
2566 NLOHMANN_JSON_PASTE2, \
2567 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2568 #define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2569 #define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2570 #define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2571 #define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2572 #define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2573 #define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2574 #define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2575 #define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2576 #define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2577 #define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2578 #define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2579 #define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2580 #define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2581 #define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2582 #define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2583 #define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2584 #define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
2585 #define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
2586 #define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
2587 #define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
2588 #define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
2589 #define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
2590 #define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
2591 #define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
2592 #define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
2593 #define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
2594 #define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
2595 #define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
2596 #define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
2597 #define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2598 #define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
2599 #define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
2600 #define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
2601 #define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
2602 #define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
2603 #define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
2604 #define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
2605 #define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
2606 #define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
2607 #define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
2608 #define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
2609 #define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
2610 #define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
2611 #define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
2612 #define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
2613 #define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
2614 #define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
2615 #define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
2616 #define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
2617 #define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
2618 #define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
2619 #define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
2620 #define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
2621 #define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2622 #define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2623 #define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2624 #define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
2625 #define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
2626 #define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
2627 #define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
2628 #define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
2629 #define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
2630 #define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
2632 #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2633 #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2637 @def NLOHMANN_DEFINE_TYPE_INTRUSIVE
2638 @since version 3.9.0
2640 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2641 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2642 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2646 @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
2647 @since version 3.9.0
2649 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2650 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2651 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2654 // inspired from https://stackoverflow.com/a/26745591
2655 // allows to call any std function as if (e.g. with begin):
2656 // using std::begin; begin(x);
2658 // it allows using the detected idiom to retrieve the return type
2659 // of such an expression
2660 #define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2661 namespace detail { \
2662 using std::std_name; \
2664 template<typename... T> \
2665 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2668 namespace detail2 { \
2669 struct std_name##_tag \
2673 template<typename... T> \
2674 std_name##_tag std_name(T&&...); \
2676 template<typename... T> \
2677 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2679 template<typename... T> \
2680 struct would_call_std_##std_name \
2682 static constexpr auto const value = ::nlohmann::detail:: \
2683 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2685 } /* namespace detail2 */ \
2687 template<typename... T> \
2688 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2692 #ifndef JSON_USE_IMPLICIT_CONVERSIONS
2693 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2696 #if JSON_USE_IMPLICIT_CONVERSIONS
2697 #define JSON_EXPLICIT
2699 #define JSON_EXPLICIT explicit
2702 #ifndef JSON_DIAGNOSTICS
2703 #define JSON_DIAGNOSTICS 0
2713 @brief replace all occurrences of a substring by another string
2715 @param[in,out] s the string to manipulate; changed so that all
2716 occurrences of @a f are replaced with @a t
2717 @param[in] f the substring to replace with @a t
2718 @param[in] t the string to replace @a f
2720 @pre The search string @a f must not be empty. **This precondition is
2721 enforced with an assertion.**
2723 @since version 2.0.0
2725 inline void replace_substring(std::string& s, const std::string& f,
2726 const std::string& t)
2728 JSON_ASSERT(!f.empty());
2729 for (auto pos = s.find(f); // find first occurrence of f
2730 pos != std::string::npos; // make sure f was found
2731 s.replace(pos, f.size(), t), // replace with t, and
2732 pos = s.find(f, pos + t.size())) // find next occurrence of f
2737 * @brief string escaping as described in RFC 6901 (Sect. 4)
2738 * @param[in] s string to escape
2739 * @return escaped string
2741 * Note the order of escaping "~" to "~0" and "/" to "~1" is important.
2743 inline std::string escape(std::string s)
2745 replace_substring(s, "~", "~0");
2746 replace_substring(s, "/", "~1");
2751 * @brief string unescaping as described in RFC 6901 (Sect. 4)
2752 * @param[in] s string to unescape
2753 * @return unescaped string
2755 * Note the order of escaping "~1" to "/" and "~0" to "~" is important.
2757 static void unescape(std::string& s)
2759 replace_substring(s, "~1", "/");
2760 replace_substring(s, "~0", "~");
2763 } // namespace detail
2764 } // namespace nlohmann
2766 // #include <nlohmann/detail/input/position_t.hpp>
2769 #include <cstddef> // size_t
2775 /// struct to capture the start position of the current token
2778 /// the total number of characters read
2779 std::size_t chars_read_total = 0;
2780 /// the number of characters read in the current line
2781 std::size_t chars_read_current_line = 0;
2782 /// the number of lines read
2783 std::size_t lines_read = 0;
2785 /// conversion to size_t to preserve SAX interface
2786 constexpr operator size_t() const
2788 return chars_read_total;
2792 } // namespace detail
2793 } // namespace nlohmann
2795 // #include <nlohmann/detail/macro_scope.hpp>
2806 /// @brief general exception of the @ref basic_json class
2807 /// @sa https://json.nlohmann.me/api/basic_json/exception/
2808 class exception : public std::exception
2811 /// returns the explanatory string
2812 const char* what() const noexcept override
2817 /// the id of the exception
2818 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
2821 JSON_HEDLEY_NON_NULL(3)
2822 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
2824 static std::string name(const std::string& ename, int id_)
2826 return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
2829 template<typename BasicJsonType>
2830 static std::string diagnostics(const BasicJsonType& leaf_element)
2832 #if JSON_DIAGNOSTICS
2833 std::vector<std::string> tokens;
2834 for (const auto* current = &leaf_element; current->m_parent != nullptr; current = current->m_parent)
2836 switch (current->m_parent->type())
2838 case value_t::array:
2840 for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
2842 if (¤t->m_parent->m_value.array->operator[](i) == current)
2844 tokens.emplace_back(std::to_string(i));
2851 case value_t::object:
2853 for (const auto& element : *current->m_parent->m_value.object)
2855 if (&element.second == current)
2857 tokens.emplace_back(element.first.c_str());
2864 case value_t::null: // LCOV_EXCL_LINE
2865 case value_t::string: // LCOV_EXCL_LINE
2866 case value_t::boolean: // LCOV_EXCL_LINE
2867 case value_t::number_integer: // LCOV_EXCL_LINE
2868 case value_t::number_unsigned: // LCOV_EXCL_LINE
2869 case value_t::number_float: // LCOV_EXCL_LINE
2870 case value_t::binary: // LCOV_EXCL_LINE
2871 case value_t::discarded: // LCOV_EXCL_LINE
2872 default: // LCOV_EXCL_LINE
2873 break; // LCOV_EXCL_LINE
2882 return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
2883 [](const std::string & a, const std::string & b)
2885 return a + "/" + detail::escape(b);
2888 static_cast<void>(leaf_element);
2894 /// an exception object as storage for error messages
2895 std::runtime_error m;
2898 /// @brief exception indicating a parse error
2899 /// @sa https://json.nlohmann.me/api/basic_json/parse_error/
2900 class parse_error : public exception
2904 @brief create a parse error exception
2905 @param[in] id_ the id of the exception
2906 @param[in] pos the position where the error occurred (or with
2907 chars_read_total=0 if the position cannot be
2909 @param[in] what_arg the explanatory string
2910 @return parse_error object
2912 template<typename BasicJsonType>
2913 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context)
2915 std::string w = exception::name("parse_error", id_) + "parse error" +
2916 position_string(pos) + ": " + exception::diagnostics(context) + what_arg;
2917 return {id_, pos.chars_read_total, w.c_str()};
2920 template<typename BasicJsonType>
2921 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context)
2923 std::string w = exception::name("parse_error", id_) + "parse error" +
2924 (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
2925 ": " + exception::diagnostics(context) + what_arg;
2926 return {id_, byte_, w.c_str()};
2930 @brief byte index of the parse error
2932 The byte index of the last read character in the input file.
2934 @note For an input with n bytes, 1 is the index of the first character and
2935 n+1 is the index of the terminating null byte or the end of file.
2936 This also holds true when reading a byte vector (CBOR or MessagePack).
2938 const std::size_t byte;
2941 parse_error(int id_, std::size_t byte_, const char* what_arg)
2942 : exception(id_, what_arg), byte(byte_) {}
2944 static std::string position_string(const position_t& pos)
2946 return " at line " + std::to_string(pos.lines_read + 1) +
2947 ", column " + std::to_string(pos.chars_read_current_line);
2951 /// @brief exception indicating errors with iterators
2952 /// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
2953 class invalid_iterator : public exception
2956 template<typename BasicJsonType>
2957 static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context)
2959 std::string w = exception::name("invalid_iterator", id_) + exception::diagnostics(context) + what_arg;
2960 return {id_, w.c_str()};
2964 JSON_HEDLEY_NON_NULL(3)
2965 invalid_iterator(int id_, const char* what_arg)
2966 : exception(id_, what_arg) {}
2969 /// @brief exception indicating executing a member function with a wrong type
2970 /// @sa https://json.nlohmann.me/api/basic_json/type_error/
2971 class type_error : public exception
2974 template<typename BasicJsonType>
2975 static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
2977 std::string w = exception::name("type_error", id_) + exception::diagnostics(context) + what_arg;
2978 return {id_, w.c_str()};
2982 JSON_HEDLEY_NON_NULL(3)
2983 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
2986 /// @brief exception indicating access out of the defined range
2987 /// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
2988 class out_of_range : public exception
2991 template<typename BasicJsonType>
2992 static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context)
2994 std::string w = exception::name("out_of_range", id_) + exception::diagnostics(context) + what_arg;
2995 return {id_, w.c_str()};
2999 JSON_HEDLEY_NON_NULL(3)
3000 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
3003 /// @brief exception indicating other library errors
3004 /// @sa https://json.nlohmann.me/api/basic_json/other_error/
3005 class other_error : public exception
3008 template<typename BasicJsonType>
3009 static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
3011 std::string w = exception::name("other_error", id_) + exception::diagnostics(context) + what_arg;
3012 return {id_, w.c_str()};
3016 JSON_HEDLEY_NON_NULL(3)
3017 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
3020 } // namespace detail
3021 } // namespace nlohmann
3023 // #include <nlohmann/detail/macro_scope.hpp>
3025 // #include <nlohmann/detail/meta/cpp_future.hpp>
3028 #include <cstddef> // size_t
3029 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3030 #include <utility> // index_sequence, make_index_sequence, index_sequence_for
3032 // #include <nlohmann/detail/macro_scope.hpp>
3040 template<typename T>
3041 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3043 #ifdef JSON_HAS_CPP_14
3045 // the following utilities are natively available in C++14
3046 using std::enable_if_t;
3047 using std::index_sequence;
3048 using std::make_index_sequence;
3049 using std::index_sequence_for;
3053 // alias templates to reduce boilerplate
3054 template<bool B, typename T = void>
3055 using enable_if_t = typename std::enable_if<B, T>::type;
3057 // The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3058 // which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3060 //// START OF CODE FROM GOOGLE ABSEIL
3064 // Class template representing a compile-time integer sequence. An instantiation
3065 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3066 // type through its template arguments (which is a common need when
3067 // working with C++11 variadic templates). `absl::integer_sequence` is designed
3068 // to be a drop-in replacement for C++14's `std::integer_sequence`.
3072 // template< class T, T... Ints >
3073 // void user_function(integer_sequence<T, Ints...>);
3077 // // user_function's `T` will be deduced to `int` and `Ints...`
3078 // // will be deduced to `0, 1, 2, 3, 4`.
3079 // user_function(make_integer_sequence<int, 5>());
3081 template <typename T, T... Ints>
3082 struct integer_sequence
3084 using value_type = T;
3085 static constexpr std::size_t size() noexcept
3087 return sizeof...(Ints);
3093 // A helper template for an `integer_sequence` of `size_t`,
3094 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3095 // `std::index_sequence`.
3096 template <size_t... Ints>
3097 using index_sequence = integer_sequence<size_t, Ints...>;
3099 namespace utility_internal
3102 template <typename Seq, size_t SeqSize, size_t Rem>
3105 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3106 template <typename T, T... Ints, size_t SeqSize>
3107 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3109 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3112 template <typename T, T... Ints, size_t SeqSize>
3113 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3115 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3118 // Recursion helper for 'make_integer_sequence<T, N>'.
3119 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3120 template <typename T, size_t N>
3124 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3127 template <typename T>
3130 using type = integer_sequence<T>;
3133 } // namespace utility_internal
3135 // Compile-time sequences of integers
3137 // make_integer_sequence
3139 // This template alias is equivalent to
3140 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3141 // replacement for C++14's `std::make_integer_sequence`.
3142 template <typename T, T N>
3143 using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
3145 // make_index_sequence
3147 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3148 // and is designed to be a drop-in replacement for C++14's
3149 // `std::make_index_sequence`.
3151 using make_index_sequence = make_integer_sequence<size_t, N>;
3153 // index_sequence_for
3155 // Converts a typename pack into an index sequence of the same length, and
3156 // is designed to be a drop-in replacement for C++14's
3157 // `std::index_sequence_for()`
3158 template <typename... Ts>
3159 using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
3161 //// END OF CODE FROM GOOGLE ABSEIL
3165 // dispatch utility (taken from ranges-v3)
3166 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3167 template<> struct priority_tag<0> {};
3169 // taken from ranges-v3
3170 template<typename T>
3173 static constexpr T value{};
3176 template<typename T>
3177 constexpr T static_const<T>::value; // NOLINT(readability-redundant-declaration)
3179 } // namespace detail
3180 } // namespace nlohmann
3182 // #include <nlohmann/detail/meta/identity_tag.hpp>
3189 // dispatching helper struct
3190 template <class T> struct identity_tag {};
3191 } // namespace detail
3192 } // namespace nlohmann
3194 // #include <nlohmann/detail/meta/type_traits.hpp>
3197 #include <limits> // numeric_limits
3198 #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3199 #include <utility> // declval
3200 #include <tuple> // tuple
3202 // #include <nlohmann/detail/macro_scope.hpp>
3205 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
3208 #include <iterator> // random_access_iterator_tag
3210 // #include <nlohmann/detail/meta/void_t.hpp>
3212 // #include <nlohmann/detail/meta/cpp_future.hpp>
3219 template<typename It, typename = void>
3220 struct iterator_types {};
3222 template<typename It>
3223 struct iterator_types <
3225 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3226 typename It::reference, typename It::iterator_category >>
3228 using difference_type = typename It::difference_type;
3229 using value_type = typename It::value_type;
3230 using pointer = typename It::pointer;
3231 using reference = typename It::reference;
3232 using iterator_category = typename It::iterator_category;
3235 // This is required as some compilers implement std::iterator_traits in a way that
3236 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3237 template<typename T, typename = void>
3238 struct iterator_traits
3242 template<typename T>
3243 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3248 template<typename T>
3249 struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
3251 using iterator_category = std::random_access_iterator_tag;
3252 using value_type = T;
3253 using difference_type = ptrdiff_t;
3255 using reference = T&;
3257 } // namespace detail
3258 } // namespace nlohmann
3260 // #include <nlohmann/detail/meta/call_std/begin.hpp>
3263 // #include <nlohmann/detail/macro_scope.hpp>
3268 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3269 } // namespace nlohmann
3271 // #include <nlohmann/detail/meta/call_std/end.hpp>
3274 // #include <nlohmann/detail/macro_scope.hpp>
3279 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3280 } // namespace nlohmann
3282 // #include <nlohmann/detail/meta/cpp_future.hpp>
3284 // #include <nlohmann/detail/meta/detected.hpp>
3286 // #include <nlohmann/json_fwd.hpp>
3287 #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3288 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3290 #include <cstdint> // int64_t, uint64_t
3291 #include <map> // map
3292 #include <memory> // allocator
3293 #include <string> // string
3294 #include <vector> // vector
3297 @brief namespace for Niels Lohmann
3298 @see https://github.com/nlohmann
3299 @since version 1.0.0
3304 @brief default JSONSerializer template argument
3306 This serializer ignores the template arguments and uses ADL
3307 ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
3310 template<typename T = void, typename SFINAE = void>
3311 struct adl_serializer;
3313 /// a class to store JSON values
3314 /// @sa https://json.nlohmann.me/api/basic_json/
3315 template<template<typename U, typename V, typename... Args> class ObjectType =
3317 template<typename U, typename... Args> class ArrayType = std::vector,
3318 class StringType = std::string, class BooleanType = bool,
3319 class NumberIntegerType = std::int64_t,
3320 class NumberUnsignedType = std::uint64_t,
3321 class NumberFloatType = double,
3322 template<typename U> class AllocatorType = std::allocator,
3323 template<typename T, typename SFINAE = void> class JSONSerializer =
3325 class BinaryType = std::vector<std::uint8_t>>
3328 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
3329 /// @sa https://json.nlohmann.me/api/json_pointer/
3330 template<typename BasicJsonType>
3334 @brief default specialization
3335 @sa https://json.nlohmann.me/api/json/
3337 using json = basic_json<>;
3339 /// @brief a minimal map-like container that preserves insertion order
3340 /// @sa https://json.nlohmann.me/api/ordered_map/
3341 template<class Key, class T, class IgnoredLess, class Allocator>
3344 /// @brief specialization that maintains the insertion order of object keys
3345 /// @sa https://json.nlohmann.me/api/ordered_json/
3346 using ordered_json = basic_json<nlohmann::ordered_map>;
3348 } // namespace nlohmann
3350 #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3356 @brief detail namespace with internal helper functions
3358 This namespace collects functions that should not be exposed,
3359 implementations of some @ref basic_json methods, and meta-programming helpers.
3361 @since version 2.1.0
3369 // Note to maintainers:
3371 // Every trait in this file expects a non CV-qualified type.
3372 // The only exceptions are in the 'aliases for detected' section
3373 // (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3375 // In this case, T has to be properly CV-qualified to constraint the function arguments
3376 // (e.g. to_json(BasicJsonType&, const T&))
3378 template<typename> struct is_basic_json : std::false_type {};
3380 NLOHMANN_BASIC_JSON_TPL_DECLARATION
3381 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3383 //////////////////////
3384 // json_ref helpers //
3385 //////////////////////
3391 struct is_json_ref : std::false_type {};
3393 template<typename T>
3394 struct is_json_ref<json_ref<T>> : std::true_type {};
3396 //////////////////////////
3397 // aliases for detected //
3398 //////////////////////////
3400 template<typename T>
3401 using mapped_type_t = typename T::mapped_type;
3403 template<typename T>
3404 using key_type_t = typename T::key_type;
3406 template<typename T>
3407 using value_type_t = typename T::value_type;
3409 template<typename T>
3410 using difference_type_t = typename T::difference_type;
3412 template<typename T>
3413 using pointer_t = typename T::pointer;
3415 template<typename T>
3416 using reference_t = typename T::reference;
3418 template<typename T>
3419 using iterator_category_t = typename T::iterator_category;
3421 template<typename T, typename... Args>
3422 using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3424 template<typename T, typename... Args>
3425 using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3427 template<typename T, typename U>
3428 using get_template_function = decltype(std::declval<T>().template get<U>());
3430 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3431 template<typename BasicJsonType, typename T, typename = void>
3432 struct has_from_json : std::false_type {};
3434 // trait checking if j.get<T> is valid
3435 // use this trait instead of std::is_constructible or std::is_convertible,
3436 // both rely on, or make use of implicit conversions, and thus fail when T
3437 // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3438 template <typename BasicJsonType, typename T>
3441 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3444 template<typename BasicJsonType, typename T>
3445 struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3447 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3449 static constexpr bool value =
3450 is_detected_exact<void, from_json_function, serializer,
3451 const BasicJsonType&, T&>::value;
3454 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
3455 // this overload is used for non-default-constructible user-defined-types
3456 template<typename BasicJsonType, typename T, typename = void>
3457 struct has_non_default_from_json : std::false_type {};
3459 template<typename BasicJsonType, typename T>
3460 struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3462 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3464 static constexpr bool value =
3465 is_detected_exact<T, from_json_function, serializer,
3466 const BasicJsonType&>::value;
3469 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3470 // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3471 template<typename BasicJsonType, typename T, typename = void>
3472 struct has_to_json : std::false_type {};
3474 template<typename BasicJsonType, typename T>
3475 struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3477 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3479 static constexpr bool value =
3480 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3489 // https://en.cppreference.com/w/cpp/types/conjunction
3490 template<class...> struct conjunction : std::true_type { };
3491 template<class B1> struct conjunction<B1> : B1 { };
3492 template<class B1, class... Bn>
3493 struct conjunction<B1, Bn...>
3494 : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
3496 // https://en.cppreference.com/w/cpp/types/negation
3497 template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3499 // Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3500 // std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3501 // This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3502 template <typename T>
3503 struct is_default_constructible : std::is_default_constructible<T> {};
3505 template <typename T1, typename T2>
3506 struct is_default_constructible<std::pair<T1, T2>>
3507 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3509 template <typename T1, typename T2>
3510 struct is_default_constructible<const std::pair<T1, T2>>
3511 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3513 template <typename... Ts>
3514 struct is_default_constructible<std::tuple<Ts...>>
3515 : conjunction<is_default_constructible<Ts>...> {};
3517 template <typename... Ts>
3518 struct is_default_constructible<const std::tuple<Ts...>>
3519 : conjunction<is_default_constructible<Ts>...> {};
3522 template <typename T, typename... Args>
3523 struct is_constructible : std::is_constructible<T, Args...> {};
3525 template <typename T1, typename T2>
3526 struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3528 template <typename T1, typename T2>
3529 struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3531 template <typename... Ts>
3532 struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3534 template <typename... Ts>
3535 struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3538 template<typename T, typename = void>
3539 struct is_iterator_traits : std::false_type {};
3541 template<typename T>
3542 struct is_iterator_traits<iterator_traits<T>>
3545 using traits = iterator_traits<T>;
3548 static constexpr auto value =
3549 is_detected<value_type_t, traits>::value &&
3550 is_detected<difference_type_t, traits>::value &&
3551 is_detected<pointer_t, traits>::value &&
3552 is_detected<iterator_category_t, traits>::value &&
3553 is_detected<reference_t, traits>::value;
3556 template<typename T>
3560 using t_ref = typename std::add_lvalue_reference<T>::type;
3562 using iterator = detected_t<result_of_begin, t_ref>;
3563 using sentinel = detected_t<result_of_end, t_ref>;
3565 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3566 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3567 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3568 static constexpr auto is_iterator_begin =
3569 is_iterator_traits<iterator_traits<iterator>>::value;
3572 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3575 template<typename R>
3576 using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3578 template<typename T>
3579 using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3581 // The following implementation of is_complete_type is taken from
3582 // https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3583 // and is written by Xiang Fan who agreed to using it in this library.
3585 template<typename T, typename = void>
3586 struct is_complete_type : std::false_type {};
3588 template<typename T>
3589 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3591 template<typename BasicJsonType, typename CompatibleObjectType,
3593 struct is_compatible_object_type_impl : std::false_type {};
3595 template<typename BasicJsonType, typename CompatibleObjectType>
3596 struct is_compatible_object_type_impl <
3597 BasicJsonType, CompatibleObjectType,
3598 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3599 is_detected<key_type_t, CompatibleObjectType>::value >>
3601 using object_t = typename BasicJsonType::object_t;
3603 // macOS's is_constructible does not play well with nonesuch...
3604 static constexpr bool value =
3605 is_constructible<typename object_t::key_type,
3606 typename CompatibleObjectType::key_type>::value &&
3607 is_constructible<typename object_t::mapped_type,
3608 typename CompatibleObjectType::mapped_type>::value;
3611 template<typename BasicJsonType, typename CompatibleObjectType>
3612 struct is_compatible_object_type
3613 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3615 template<typename BasicJsonType, typename ConstructibleObjectType,
3617 struct is_constructible_object_type_impl : std::false_type {};
3619 template<typename BasicJsonType, typename ConstructibleObjectType>
3620 struct is_constructible_object_type_impl <
3621 BasicJsonType, ConstructibleObjectType,
3622 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3623 is_detected<key_type_t, ConstructibleObjectType>::value >>
3625 using object_t = typename BasicJsonType::object_t;
3627 static constexpr bool value =
3628 (is_default_constructible<ConstructibleObjectType>::value &&
3629 (std::is_move_assignable<ConstructibleObjectType>::value ||
3630 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3631 (is_constructible<typename ConstructibleObjectType::key_type,
3632 typename object_t::key_type>::value &&
3634 typename object_t::mapped_type,
3635 typename ConstructibleObjectType::mapped_type >::value)) ||
3636 (has_from_json<BasicJsonType,
3637 typename ConstructibleObjectType::mapped_type>::value ||
3638 has_non_default_from_json <
3640 typename ConstructibleObjectType::mapped_type >::value);
3643 template<typename BasicJsonType, typename ConstructibleObjectType>
3644 struct is_constructible_object_type
3645 : is_constructible_object_type_impl<BasicJsonType,
3646 ConstructibleObjectType> {};
3648 template<typename BasicJsonType, typename CompatibleStringType>
3649 struct is_compatible_string_type
3651 static constexpr auto value =
3652 is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
3655 template<typename BasicJsonType, typename ConstructibleStringType>
3656 struct is_constructible_string_type
3658 static constexpr auto value =
3659 is_constructible<ConstructibleStringType,
3660 typename BasicJsonType::string_t>::value;
3663 template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3664 struct is_compatible_array_type_impl : std::false_type {};
3666 template<typename BasicJsonType, typename CompatibleArrayType>
3667 struct is_compatible_array_type_impl <
3668 BasicJsonType, CompatibleArrayType,
3670 is_detected<iterator_t, CompatibleArrayType>::value&&
3671 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3672 // special case for types like std::filesystem::path whose iterator's value_type are themselves
3673 // c.f. https://github.com/nlohmann/json/pull/3073
3674 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3676 static constexpr bool value =
3677 is_constructible<BasicJsonType,
3678 range_value_t<CompatibleArrayType>>::value;
3681 template<typename BasicJsonType, typename CompatibleArrayType>
3682 struct is_compatible_array_type
3683 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3685 template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3686 struct is_constructible_array_type_impl : std::false_type {};
3688 template<typename BasicJsonType, typename ConstructibleArrayType>
3689 struct is_constructible_array_type_impl <
3690 BasicJsonType, ConstructibleArrayType,
3691 enable_if_t<std::is_same<ConstructibleArrayType,
3692 typename BasicJsonType::value_type>::value >>
3693 : std::true_type {};
3695 template<typename BasicJsonType, typename ConstructibleArrayType>
3696 struct is_constructible_array_type_impl <
3697 BasicJsonType, ConstructibleArrayType,
3698 enable_if_t < !std::is_same<ConstructibleArrayType,
3699 typename BasicJsonType::value_type>::value&&
3700 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3701 is_default_constructible<ConstructibleArrayType>::value&&
3702 (std::is_move_assignable<ConstructibleArrayType>::value ||
3703 std::is_copy_assignable<ConstructibleArrayType>::value)&&
3704 is_detected<iterator_t, ConstructibleArrayType>::value&&
3705 is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3706 is_detected<range_value_t, ConstructibleArrayType>::value&&
3707 // special case for types like std::filesystem::path whose iterator's value_type are themselves
3708 // c.f. https://github.com/nlohmann/json/pull/3073
3709 !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3711 detected_t<range_value_t, ConstructibleArrayType >>::value >>
3713 using value_type = range_value_t<ConstructibleArrayType>;
3715 static constexpr bool value =
3716 std::is_same<value_type,
3717 typename BasicJsonType::array_t::value_type>::value ||
3718 has_from_json<BasicJsonType,
3719 value_type>::value ||
3720 has_non_default_from_json <
3722 value_type >::value;
3725 template<typename BasicJsonType, typename ConstructibleArrayType>
3726 struct is_constructible_array_type
3727 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3729 template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3731 struct is_compatible_integer_type_impl : std::false_type {};
3733 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3734 struct is_compatible_integer_type_impl <
3735 RealIntegerType, CompatibleNumberIntegerType,
3736 enable_if_t < std::is_integral<RealIntegerType>::value&&
3737 std::is_integral<CompatibleNumberIntegerType>::value&&
3738 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
3740 // is there an assert somewhere on overflows?
3741 using RealLimits = std::numeric_limits<RealIntegerType>;
3742 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3744 static constexpr auto value =
3745 is_constructible<RealIntegerType,
3746 CompatibleNumberIntegerType>::value &&
3747 CompatibleLimits::is_integer &&
3748 RealLimits::is_signed == CompatibleLimits::is_signed;
3751 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3752 struct is_compatible_integer_type
3753 : is_compatible_integer_type_impl<RealIntegerType,
3754 CompatibleNumberIntegerType> {};
3756 template<typename BasicJsonType, typename CompatibleType, typename = void>
3757 struct is_compatible_type_impl: std::false_type {};
3759 template<typename BasicJsonType, typename CompatibleType>
3760 struct is_compatible_type_impl <
3761 BasicJsonType, CompatibleType,
3762 enable_if_t<is_complete_type<CompatibleType>::value >>
3764 static constexpr bool value =
3765 has_to_json<BasicJsonType, CompatibleType>::value;
3768 template<typename BasicJsonType, typename CompatibleType>
3769 struct is_compatible_type
3770 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3772 template<typename T1, typename T2>
3773 struct is_constructible_tuple : std::false_type {};
3775 template<typename T1, typename... Args>
3776 struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3778 // a naive helper to check if a type is an ordered_map (exploits the fact that
3779 // ordered_map inherits capacity() from std::vector)
3780 template <typename T>
3781 struct is_ordered_map
3787 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3790 template <typename C> static one test( decltype(&C::capacity) ) ;
3791 template <typename C> static two test(...);
3793 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
3796 // to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
3797 template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
3798 T conditional_static_cast(U value)
3800 return static_cast<T>(value);
3803 template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
3804 T conditional_static_cast(U value)
3809 } // namespace detail
3810 } // namespace nlohmann
3812 // #include <nlohmann/detail/value_t.hpp>
3815 #if JSON_HAS_EXPERIMENTAL_FILESYSTEM
3816 #include <experimental/filesystem>
3817 namespace nlohmann::detail
3819 namespace std_fs = std::experimental::filesystem;
3820 } // namespace nlohmann::detail
3821 #elif JSON_HAS_FILESYSTEM
3822 #include <filesystem>
3823 namespace nlohmann::detail
3825 namespace std_fs = std::filesystem;
3826 } // namespace nlohmann::detail
3833 template<typename BasicJsonType>
3834 void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
3836 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
3838 JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j));
3843 // overloads for basic_json template parameters
3844 template < typename BasicJsonType, typename ArithmeticType,
3845 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
3846 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
3848 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
3850 switch (static_cast<value_t>(j))
3852 case value_t::number_unsigned:
3854 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
3857 case value_t::number_integer:
3859 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
3862 case value_t::number_float:
3864 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
3869 case value_t::object:
3870 case value_t::array:
3871 case value_t::string:
3872 case value_t::boolean:
3873 case value_t::binary:
3874 case value_t::discarded:
3876 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
3880 template<typename BasicJsonType>
3881 void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
3883 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
3885 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j));
3887 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
3890 template<typename BasicJsonType>
3891 void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
3893 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
3895 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
3897 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
3901 typename BasicJsonType, typename ConstructibleStringType,
3903 is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value&&
3904 !std::is_same<typename BasicJsonType::string_t,
3905 ConstructibleStringType>::value,
3907 void from_json(const BasicJsonType& j, ConstructibleStringType& s)
3909 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
3911 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
3914 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
3917 template<typename BasicJsonType>
3918 void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
3920 get_arithmetic_value(j, val);
3923 template<typename BasicJsonType>
3924 void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
3926 get_arithmetic_value(j, val);
3929 template<typename BasicJsonType>
3930 void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
3932 get_arithmetic_value(j, val);
3935 template<typename BasicJsonType, typename EnumType,
3936 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
3937 void from_json(const BasicJsonType& j, EnumType& e)
3939 typename std::underlying_type<EnumType>::type val;
3940 get_arithmetic_value(j, val);
3941 e = static_cast<EnumType>(val);
3944 // forward_list doesn't have an insert method
3945 template<typename BasicJsonType, typename T, typename Allocator,
3946 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
3947 void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
3949 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3951 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
3954 std::transform(j.rbegin(), j.rend(),
3955 std::front_inserter(l), [](const BasicJsonType & i)
3957 return i.template get<T>();
3961 // valarray doesn't have an insert method
3962 template<typename BasicJsonType, typename T,
3963 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
3964 void from_json(const BasicJsonType& j, std::valarray<T>& l)
3966 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3968 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
3971 std::transform(j.begin(), j.end(), std::begin(l),
3972 [](const BasicJsonType & elem)
3974 return elem.template get<T>();
3978 template<typename BasicJsonType, typename T, std::size_t N>
3979 auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3980 -> decltype(j.template get<T>(), void())
3982 for (std::size_t i = 0; i < N; ++i)
3984 arr[i] = j.at(i).template get<T>();
3988 template<typename BasicJsonType>
3989 void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
3991 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
3994 template<typename BasicJsonType, typename T, std::size_t N>
3995 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
3996 priority_tag<2> /*unused*/)
3997 -> decltype(j.template get<T>(), void())
3999 for (std::size_t i = 0; i < N; ++i)
4001 arr[i] = j.at(i).template get<T>();
4005 template<typename BasicJsonType, typename ConstructibleArrayType,
4007 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4009 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4011 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4012 j.template get<typename ConstructibleArrayType::value_type>(),
4017 ConstructibleArrayType ret;
4018 ret.reserve(j.size());
4019 std::transform(j.begin(), j.end(),
4020 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
4022 // get<BasicJsonType>() returns *this, this won't call a from_json
4023 // method when value_type is BasicJsonType
4024 return i.template get<typename ConstructibleArrayType::value_type>();
4026 arr = std::move(ret);
4029 template<typename BasicJsonType, typename ConstructibleArrayType,
4031 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4033 void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4034 priority_tag<0> /*unused*/)
4038 ConstructibleArrayType ret;
4040 j.begin(), j.end(), std::inserter(ret, end(ret)),
4041 [](const BasicJsonType & i)
4043 // get<BasicJsonType>() returns *this, this won't call a from_json
4044 // method when value_type is BasicJsonType
4045 return i.template get<typename ConstructibleArrayType::value_type>();
4047 arr = std::move(ret);
4050 template < typename BasicJsonType, typename ConstructibleArrayType,
4052 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4053 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4054 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4055 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4056 !is_basic_json<ConstructibleArrayType>::value,
4058 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4059 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4060 j.template get<typename ConstructibleArrayType::value_type>(),
4063 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4065 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4068 from_json_array_impl(j, arr, priority_tag<3> {});
4071 template < typename BasicJsonType, typename T, std::size_t... Idx >
4072 std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4073 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4075 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4078 template < typename BasicJsonType, typename T, std::size_t N >
4079 auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4080 -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4082 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4084 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4087 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4090 template<typename BasicJsonType>
4091 void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4093 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4095 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j));
4098 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4101 template<typename BasicJsonType, typename ConstructibleObjectType,
4102 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
4103 void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
4105 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
4107 JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j));
4110 ConstructibleObjectType ret;
4111 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4112 using value_type = typename ConstructibleObjectType::value_type;
4114 inner_object->begin(), inner_object->end(),
4115 std::inserter(ret, ret.begin()),
4116 [](typename BasicJsonType::object_t::value_type const & p)
4118 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
4120 obj = std::move(ret);
4123 // overload for arithmetic types, not chosen for basic_json template arguments
4124 // (BooleanType, etc..); note: Is it really necessary to provide explicit
4125 // overloads for boolean_t etc. in case of a custom BooleanType which is not
4126 // an arithmetic type?
4127 template < typename BasicJsonType, typename ArithmeticType,
4129 std::is_arithmetic<ArithmeticType>::value&&
4130 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
4131 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
4132 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
4133 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4135 void from_json(const BasicJsonType& j, ArithmeticType& val)
4137 switch (static_cast<value_t>(j))
4139 case value_t::number_unsigned:
4141 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4144 case value_t::number_integer:
4146 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4149 case value_t::number_float:
4151 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4154 case value_t::boolean:
4156 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
4161 case value_t::object:
4162 case value_t::array:
4163 case value_t::string:
4164 case value_t::binary:
4165 case value_t::discarded:
4167 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
4171 template<typename BasicJsonType, typename... Args, std::size_t... Idx>
4172 std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
4174 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
4177 template < typename BasicJsonType, class A1, class A2 >
4178 std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
4180 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
4181 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
4184 template<typename BasicJsonType, typename A1, typename A2>
4185 void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
4187 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
4190 template<typename BasicJsonType, typename... Args>
4191 std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
4193 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4196 template<typename BasicJsonType, typename... Args>
4197 void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
4199 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4202 template<typename BasicJsonType, typename TupleRelated>
4203 auto from_json(BasicJsonType&& j, TupleRelated&& t)
4204 -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
4206 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4208 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4211 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
4214 template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
4215 typename = enable_if_t < !std::is_constructible <
4216 typename BasicJsonType::string_t, Key >::value >>
4217 void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
4219 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4221 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4224 for (const auto& p : j)
4226 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
4228 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
4230 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4234 template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
4235 typename = enable_if_t < !std::is_constructible <
4236 typename BasicJsonType::string_t, Key >::value >>
4237 void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
4239 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4241 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4244 for (const auto& p : j)
4246 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
4248 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
4250 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4254 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4255 template<typename BasicJsonType>
4256 void from_json(const BasicJsonType& j, std_fs::path& p)
4258 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4260 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
4262 p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4268 template<typename BasicJsonType, typename T>
4269 auto operator()(const BasicJsonType& j, T&& val) const
4270 noexcept(noexcept(from_json(j, std::forward<T>(val))))
4271 -> decltype(from_json(j, std::forward<T>(val)))
4273 return from_json(j, std::forward<T>(val));
4276 } // namespace detail
4278 /// namespace to hold default `from_json` function
4279 /// to see why this is required:
4280 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
4281 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
4283 constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value; // NOLINT(misc-definitions-in-headers)
4285 } // namespace nlohmann
4287 // #include <nlohmann/detail/conversions/to_json.hpp>
4290 #include <algorithm> // copy
4291 #include <iterator> // begin, end
4292 #include <string> // string
4293 #include <tuple> // tuple, get
4294 #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
4295 #include <utility> // move, forward, declval, pair
4296 #include <valarray> // valarray
4297 #include <vector> // vector
4299 // #include <nlohmann/detail/macro_scope.hpp>
4301 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
4304 #include <cstddef> // size_t
4305 #include <iterator> // input_iterator_tag
4306 #include <string> // string, to_string
4307 #include <tuple> // tuple_size, get, tuple_element
4308 #include <utility> // move
4310 // #include <nlohmann/detail/meta/type_traits.hpp>
4312 // #include <nlohmann/detail/value_t.hpp>
4319 template<typename string_type>
4320 void int_to_string( string_type& target, std::size_t value )
4323 using std::to_string;
4324 target = to_string(value);
4326 template<typename IteratorType> class iteration_proxy_value
4329 using difference_type = std::ptrdiff_t;
4330 using value_type = iteration_proxy_value;
4331 using pointer = value_type * ;
4332 using reference = value_type & ;
4333 using iterator_category = std::input_iterator_tag;
4334 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
4338 IteratorType anchor;
4339 /// an index for arrays (used to create key names)
4340 std::size_t array_index = 0;
4341 /// last stringified array index
4342 mutable std::size_t array_index_last = 0;
4343 /// a string representation of the array index
4344 mutable string_type array_index_str = "0";
4345 /// an empty string (to return a reference for primitive values)
4346 const string_type empty_str{};
4349 explicit iteration_proxy_value(IteratorType it) noexcept
4350 : anchor(std::move(it))
4353 /// dereference operator (needed for range-based for)
4354 iteration_proxy_value& operator*()
4359 /// increment operator (needed for range-based for)
4360 iteration_proxy_value& operator++()
4368 /// equality operator (needed for InputIterator)
4369 bool operator==(const iteration_proxy_value& o) const
4371 return anchor == o.anchor;
4374 /// inequality operator (needed for range-based for)
4375 bool operator!=(const iteration_proxy_value& o) const
4377 return anchor != o.anchor;
4380 /// return key of the iterator
4381 const string_type& key() const
4383 JSON_ASSERT(anchor.m_object != nullptr);
4385 switch (anchor.m_object->type())
4387 // use integer array index as key
4388 case value_t::array:
4390 if (array_index != array_index_last)
4392 int_to_string( array_index_str, array_index );
4393 array_index_last = array_index;
4395 return array_index_str;
4398 // use key from the object
4399 case value_t::object:
4400 return anchor.key();
4402 // use an empty key for all primitive types
4404 case value_t::string:
4405 case value_t::boolean:
4406 case value_t::number_integer:
4407 case value_t::number_unsigned:
4408 case value_t::number_float:
4409 case value_t::binary:
4410 case value_t::discarded:
4416 /// return value of the iterator
4417 typename IteratorType::reference value() const
4419 return anchor.value();
4423 /// proxy class for the items() function
4424 template<typename IteratorType> class iteration_proxy
4427 /// the container to iterate
4428 typename IteratorType::reference container;
4431 /// construct iteration proxy from a container
4432 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
4433 : container(cont) {}
4435 /// return iterator begin (needed for range-based for)
4436 iteration_proxy_value<IteratorType> begin() noexcept
4438 return iteration_proxy_value<IteratorType>(container.begin());
4441 /// return iterator end (needed for range-based for)
4442 iteration_proxy_value<IteratorType> end() noexcept
4444 return iteration_proxy_value<IteratorType>(container.end());
4447 // Structured Bindings Support
4448 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
4449 // And see https://github.com/nlohmann/json/pull/1391
4450 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
4451 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
4455 // Structured Bindings Support
4456 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
4457 // And see https://github.com/nlohmann/json/pull/1391
4458 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
4459 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
4463 } // namespace detail
4464 } // namespace nlohmann
4466 // The Addition to the STD Namespace is required to add
4467 // Structured Bindings Support to the iteration_proxy_value class
4468 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
4469 // And see https://github.com/nlohmann/json/pull/1391
4472 #if defined(__clang__)
4473 // Fix: https://github.com/nlohmann/json/issues/1401
4474 #pragma clang diagnostic push
4475 #pragma clang diagnostic ignored "-Wmismatched-tags"
4477 template<typename IteratorType>
4478 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
4479 : public std::integral_constant<std::size_t, 2> {};
4481 template<std::size_t N, typename IteratorType>
4482 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
4485 using type = decltype(
4486 get<N>(std::declval <
4487 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
4489 #if defined(__clang__)
4490 #pragma clang diagnostic pop
4494 // #include <nlohmann/detail/meta/cpp_future.hpp>
4496 // #include <nlohmann/detail/meta/type_traits.hpp>
4498 // #include <nlohmann/detail/value_t.hpp>
4501 #if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4502 #include <experimental/filesystem>
4503 namespace nlohmann::detail
4505 namespace std_fs = std::experimental::filesystem;
4506 } // namespace nlohmann::detail
4507 #elif JSON_HAS_FILESYSTEM
4508 #include <filesystem>
4509 namespace nlohmann::detail
4511 namespace std_fs = std::filesystem;
4512 } // namespace nlohmann::detail
4524 * Note all external_constructor<>::construct functions need to call
4525 * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an
4526 * allocated value (e.g., a string). See bug issue
4527 * https://github.com/nlohmann/json/issues/2865 for more information.
4530 template<value_t> struct external_constructor;
4533 struct external_constructor<value_t::boolean>
4535 template<typename BasicJsonType>
4536 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
4538 j.m_value.destroy(j.m_type);
4539 j.m_type = value_t::boolean;
4541 j.assert_invariant();
4546 struct external_constructor<value_t::string>
4548 template<typename BasicJsonType>
4549 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
4551 j.m_value.destroy(j.m_type);
4552 j.m_type = value_t::string;
4554 j.assert_invariant();
4557 template<typename BasicJsonType>
4558 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
4560 j.m_value.destroy(j.m_type);
4561 j.m_type = value_t::string;
4562 j.m_value = std::move(s);
4563 j.assert_invariant();
4566 template < typename BasicJsonType, typename CompatibleStringType,
4567 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
4569 static void construct(BasicJsonType& j, const CompatibleStringType& str)
4571 j.m_value.destroy(j.m_type);
4572 j.m_type = value_t::string;
4573 j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
4574 j.assert_invariant();
4579 struct external_constructor<value_t::binary>
4581 template<typename BasicJsonType>
4582 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
4584 j.m_value.destroy(j.m_type);
4585 j.m_type = value_t::binary;
4586 j.m_value = typename BasicJsonType::binary_t(b);
4587 j.assert_invariant();
4590 template<typename BasicJsonType>
4591 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
4593 j.m_value.destroy(j.m_type);
4594 j.m_type = value_t::binary;
4595 j.m_value = typename BasicJsonType::binary_t(std::move(b));
4596 j.assert_invariant();
4601 struct external_constructor<value_t::number_float>
4603 template<typename BasicJsonType>
4604 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
4606 j.m_value.destroy(j.m_type);
4607 j.m_type = value_t::number_float;
4609 j.assert_invariant();
4614 struct external_constructor<value_t::number_unsigned>
4616 template<typename BasicJsonType>
4617 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
4619 j.m_value.destroy(j.m_type);
4620 j.m_type = value_t::number_unsigned;
4622 j.assert_invariant();
4627 struct external_constructor<value_t::number_integer>
4629 template<typename BasicJsonType>
4630 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
4632 j.m_value.destroy(j.m_type);
4633 j.m_type = value_t::number_integer;
4635 j.assert_invariant();
4640 struct external_constructor<value_t::array>
4642 template<typename BasicJsonType>
4643 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
4645 j.m_value.destroy(j.m_type);
4646 j.m_type = value_t::array;
4649 j.assert_invariant();
4652 template<typename BasicJsonType>
4653 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
4655 j.m_value.destroy(j.m_type);
4656 j.m_type = value_t::array;
4657 j.m_value = std::move(arr);
4659 j.assert_invariant();
4662 template < typename BasicJsonType, typename CompatibleArrayType,
4663 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
4665 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
4670 j.m_value.destroy(j.m_type);
4671 j.m_type = value_t::array;
4672 j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
4674 j.assert_invariant();
4677 template<typename BasicJsonType>
4678 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
4680 j.m_value.destroy(j.m_type);
4681 j.m_type = value_t::array;
4682 j.m_value = value_t::array;
4683 j.m_value.array->reserve(arr.size());
4684 for (const bool x : arr)
4686 j.m_value.array->push_back(x);
4687 j.set_parent(j.m_value.array->back());
4689 j.assert_invariant();
4692 template<typename BasicJsonType, typename T,
4693 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
4694 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
4696 j.m_value.destroy(j.m_type);
4697 j.m_type = value_t::array;
4698 j.m_value = value_t::array;
4699 j.m_value.array->resize(arr.size());
4702 std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
4705 j.assert_invariant();
4710 struct external_constructor<value_t::object>
4712 template<typename BasicJsonType>
4713 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
4715 j.m_value.destroy(j.m_type);
4716 j.m_type = value_t::object;
4719 j.assert_invariant();
4722 template<typename BasicJsonType>
4723 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
4725 j.m_value.destroy(j.m_type);
4726 j.m_type = value_t::object;
4727 j.m_value = std::move(obj);
4729 j.assert_invariant();
4732 template < typename BasicJsonType, typename CompatibleObjectType,
4733 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
4734 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
4739 j.m_value.destroy(j.m_type);
4740 j.m_type = value_t::object;
4741 j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
4743 j.assert_invariant();
4751 template<typename BasicJsonType, typename T,
4752 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
4753 void to_json(BasicJsonType& j, T b) noexcept
4755 external_constructor<value_t::boolean>::construct(j, b);
4758 template<typename BasicJsonType, typename CompatibleString,
4759 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
4760 void to_json(BasicJsonType& j, const CompatibleString& s)
4762 external_constructor<value_t::string>::construct(j, s);
4765 template<typename BasicJsonType>
4766 void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
4768 external_constructor<value_t::string>::construct(j, std::move(s));
4771 template<typename BasicJsonType, typename FloatType,
4772 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
4773 void to_json(BasicJsonType& j, FloatType val) noexcept
4775 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
4778 template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
4779 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
4780 void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
4782 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
4785 template<typename BasicJsonType, typename CompatibleNumberIntegerType,
4786 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
4787 void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
4789 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
4792 template<typename BasicJsonType, typename EnumType,
4793 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4794 void to_json(BasicJsonType& j, EnumType e) noexcept
4796 using underlying_type = typename std::underlying_type<EnumType>::type;
4797 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
4800 template<typename BasicJsonType>
4801 void to_json(BasicJsonType& j, const std::vector<bool>& e)
4803 external_constructor<value_t::array>::construct(j, e);
4806 template < typename BasicJsonType, typename CompatibleArrayType,
4807 enable_if_t < is_compatible_array_type<BasicJsonType,
4808 CompatibleArrayType>::value&&
4809 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
4810 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
4811 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
4812 !is_basic_json<CompatibleArrayType>::value,
4814 void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
4816 external_constructor<value_t::array>::construct(j, arr);
4819 template<typename BasicJsonType>
4820 void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
4822 external_constructor<value_t::binary>::construct(j, bin);
4825 template<typename BasicJsonType, typename T,
4826 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
4827 void to_json(BasicJsonType& j, const std::valarray<T>& arr)
4829 external_constructor<value_t::array>::construct(j, std::move(arr));
4832 template<typename BasicJsonType>
4833 void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
4835 external_constructor<value_t::array>::construct(j, std::move(arr));
4838 template < typename BasicJsonType, typename CompatibleObjectType,
4839 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
4840 void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
4842 external_constructor<value_t::object>::construct(j, obj);
4845 template<typename BasicJsonType>
4846 void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
4848 external_constructor<value_t::object>::construct(j, std::move(obj));
4852 typename BasicJsonType, typename T, std::size_t N,
4853 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
4854 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4856 void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4858 external_constructor<value_t::array>::construct(j, arr);
4861 template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
4862 void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
4864 j = { p.first, p.second };
4867 // for https://github.com/nlohmann/json/pull/1134
4868 template<typename BasicJsonType, typename T,
4869 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
4870 void to_json(BasicJsonType& j, const T& b)
4872 j = { {b.key(), b.value()} };
4875 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
4876 void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
4878 j = { std::get<Idx>(t)... };
4881 template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
4882 void to_json(BasicJsonType& j, const T& t)
4884 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
4887 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4888 template<typename BasicJsonType>
4889 void to_json(BasicJsonType& j, const std_fs::path& p)
4897 template<typename BasicJsonType, typename T>
4898 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
4899 -> decltype(to_json(j, std::forward<T>(val)), void())
4901 return to_json(j, std::forward<T>(val));
4904 } // namespace detail
4906 /// namespace to hold default `to_json` function
4907 /// to see why this is required:
4908 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
4909 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
4911 constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value; // NOLINT(misc-definitions-in-headers)
4913 } // namespace nlohmann
4915 // #include <nlohmann/detail/meta/identity_tag.hpp>
4917 // #include <nlohmann/detail/meta/type_traits.hpp>
4923 /// @sa https://json.nlohmann.me/api/adl_serializer/
4924 template<typename ValueType, typename>
4925 struct adl_serializer
4927 /// @brief convert a JSON value to any value type
4928 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
4929 template<typename BasicJsonType, typename TargetType = ValueType>
4930 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
4931 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
4932 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
4934 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
4937 /// @brief convert a JSON value to any value type
4938 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
4939 template<typename BasicJsonType, typename TargetType = ValueType>
4940 static auto from_json(BasicJsonType && j) noexcept(
4941 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
4942 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
4944 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
4947 /// @brief convert any value type to a JSON value
4948 /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
4949 template<typename BasicJsonType, typename TargetType = ValueType>
4950 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
4951 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
4952 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
4954 ::nlohmann::to_json(j, std::forward<TargetType>(val));
4957 } // namespace nlohmann
4959 // #include <nlohmann/byte_container_with_subtype.hpp>
4962 #include <cstdint> // uint8_t, uint64_t
4963 #include <tuple> // tie
4964 #include <utility> // move
4969 /// @brief an internal type for a backed binary type
4970 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
4971 template<typename BinaryType>
4972 class byte_container_with_subtype : public BinaryType
4975 using container_type = BinaryType;
4976 using subtype_type = std::uint64_t;
4978 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4979 byte_container_with_subtype() noexcept(noexcept(container_type()))
4983 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4984 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
4988 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4989 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
4990 : container_type(std::move(b))
4993 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4994 byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
4996 , m_subtype(subtype_)
4997 , m_has_subtype(true)
5000 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5001 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
5002 : container_type(std::move(b))
5003 , m_subtype(subtype_)
5004 , m_has_subtype(true)
5007 bool operator==(const byte_container_with_subtype& rhs) const
5009 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
5010 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5013 bool operator!=(const byte_container_with_subtype& rhs) const
5015 return !(rhs == *this);
5018 /// @brief sets the binary subtype
5019 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/
5020 void set_subtype(subtype_type subtype_) noexcept
5022 m_subtype = subtype_;
5023 m_has_subtype = true;
5026 /// @brief return the binary subtype
5027 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/
5028 constexpr subtype_type subtype() const noexcept
5030 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
5033 /// @brief return whether the value has a subtype
5034 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/
5035 constexpr bool has_subtype() const noexcept
5037 return m_has_subtype;
5040 /// @brief clears the binary subtype
5041 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/
5042 void clear_subtype() noexcept
5045 m_has_subtype = false;
5049 subtype_type m_subtype = 0;
5050 bool m_has_subtype = false;
5053 } // namespace nlohmann
5055 // #include <nlohmann/detail/conversions/from_json.hpp>
5057 // #include <nlohmann/detail/conversions/to_json.hpp>
5059 // #include <nlohmann/detail/exceptions.hpp>
5061 // #include <nlohmann/detail/hash.hpp>
5064 #include <cstdint> // uint8_t
5065 #include <cstddef> // size_t
5066 #include <functional> // hash
5068 // #include <nlohmann/detail/macro_scope.hpp>
5070 // #include <nlohmann/detail/value_t.hpp>
5078 // boost::hash_combine
5079 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
5081 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
5086 @brief hash a JSON value
5088 The hash function tries to rely on std::hash where possible. Furthermore, the
5089 type of the JSON value is taken into account to have different hash values for
5090 null, 0, 0U, and false, etc.
5092 @tparam BasicJsonType basic_json specialization
5093 @param j JSON value to hash
5094 @return hash value of j
5096 template<typename BasicJsonType>
5097 std::size_t hash(const BasicJsonType& j)
5099 using string_t = typename BasicJsonType::string_t;
5100 using number_integer_t = typename BasicJsonType::number_integer_t;
5101 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5102 using number_float_t = typename BasicJsonType::number_float_t;
5104 const auto type = static_cast<std::size_t>(j.type());
5107 case BasicJsonType::value_t::null:
5108 case BasicJsonType::value_t::discarded:
5110 return combine(type, 0);
5113 case BasicJsonType::value_t::object:
5115 auto seed = combine(type, j.size());
5116 for (const auto& element : j.items())
5118 const auto h = std::hash<string_t> {}(element.key());
5119 seed = combine(seed, h);
5120 seed = combine(seed, hash(element.value()));
5125 case BasicJsonType::value_t::array:
5127 auto seed = combine(type, j.size());
5128 for (const auto& element : j)
5130 seed = combine(seed, hash(element));
5135 case BasicJsonType::value_t::string:
5137 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
5138 return combine(type, h);
5141 case BasicJsonType::value_t::boolean:
5143 const auto h = std::hash<bool> {}(j.template get<bool>());
5144 return combine(type, h);
5147 case BasicJsonType::value_t::number_integer:
5149 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
5150 return combine(type, h);
5153 case BasicJsonType::value_t::number_unsigned:
5155 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
5156 return combine(type, h);
5159 case BasicJsonType::value_t::number_float:
5161 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
5162 return combine(type, h);
5165 case BasicJsonType::value_t::binary:
5167 auto seed = combine(type, j.get_binary().size());
5168 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
5169 seed = combine(seed, h);
5170 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
5171 for (const auto byte : j.get_binary())
5173 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
5178 default: // LCOV_EXCL_LINE
5179 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
5180 return 0; // LCOV_EXCL_LINE
5184 } // namespace detail
5185 } // namespace nlohmann
5187 // #include <nlohmann/detail/input/binary_reader.hpp>
5190 #include <algorithm> // generate_n
5191 #include <array> // array
5192 #include <cmath> // ldexp
5193 #include <cstddef> // size_t
5194 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
5195 #include <cstdio> // snprintf
5196 #include <cstring> // memcpy
5197 #include <iterator> // back_inserter
5198 #include <limits> // numeric_limits
5199 #include <string> // char_traits, string
5200 #include <utility> // make_pair, move
5201 #include <vector> // vector
5203 // #include <nlohmann/detail/exceptions.hpp>
5205 // #include <nlohmann/detail/input/input_adapters.hpp>
5208 #include <array> // array
5209 #include <cstddef> // size_t
5210 #include <cstring> // strlen
5211 #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
5212 #include <memory> // shared_ptr, make_shared, addressof
5213 #include <numeric> // accumulate
5214 #include <string> // string, char_traits
5215 #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
5216 #include <utility> // pair, declval
5219 #include <cstdio> // FILE *
5220 #include <istream> // istream
5221 #endif // JSON_NO_IO
5223 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
5225 // #include <nlohmann/detail/macro_scope.hpp>
5232 /// the supported input formats
5233 enum class input_format_t { json, cbor, msgpack, ubjson, bson };
5235 ////////////////////
5236 // input adapters //
5237 ////////////////////
5241 Input adapter for stdio file access. This adapter read only 1 byte and do not use any
5242 buffer. This adapter is a very low level adapter.
5244 class file_input_adapter
5247 using char_type = char;
5249 JSON_HEDLEY_NON_NULL(2)
5250 explicit file_input_adapter(std::FILE* f) noexcept
5254 // make class move-only
5255 file_input_adapter(const file_input_adapter&) = delete;
5256 file_input_adapter(file_input_adapter&&) noexcept = default;
5257 file_input_adapter& operator=(const file_input_adapter&) = delete;
5258 file_input_adapter& operator=(file_input_adapter&&) = delete;
5259 ~file_input_adapter() = default;
5261 std::char_traits<char>::int_type get_character() noexcept
5263 return std::fgetc(m_file);
5267 /// the file pointer to read from
5273 Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
5274 beginning of input. Does not support changing the underlying std::streambuf
5275 in mid-input. Maintains underlying std::istream and std::streambuf to support
5276 subsequent use of standard std::istream operations to process any input
5277 characters following those used in parsing the JSON input. Clears the
5278 std::istream flags; any input errors (e.g., EOF) will be detected by the first
5279 subsequent call for input from the std::istream.
5281 class input_stream_adapter
5284 using char_type = char;
5286 ~input_stream_adapter()
5288 // clear stream flags; we use underlying streambuf I/O, do not
5289 // maintain ifstream flags, except eof
5292 is->clear(is->rdstate() & std::ios::eofbit);
5296 explicit input_stream_adapter(std::istream& i)
5297 : is(&i), sb(i.rdbuf())
5300 // delete because of pointer members
5301 input_stream_adapter(const input_stream_adapter&) = delete;
5302 input_stream_adapter& operator=(input_stream_adapter&) = delete;
5303 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
5305 input_stream_adapter(input_stream_adapter&& rhs) noexcept
5306 : is(rhs.is), sb(rhs.sb)
5312 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
5313 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
5314 // end up as the same value, e.g. 0xFFFFFFFF.
5315 std::char_traits<char>::int_type get_character()
5317 auto res = sb->sbumpc();
5318 // set eof manually, as we don't use the istream interface.
5319 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
5321 is->clear(is->rdstate() | std::ios::eofbit);
5327 /// the associated input stream
5328 std::istream* is = nullptr;
5329 std::streambuf* sb = nullptr;
5331 #endif // JSON_NO_IO
5333 // General-purpose iterator-based adapter. It might not be as fast as
5334 // theoretically possible for some containers, but it is extremely versatile.
5335 template<typename IteratorType>
5336 class iterator_input_adapter
5339 using char_type = typename std::iterator_traits<IteratorType>::value_type;
5341 iterator_input_adapter(IteratorType first, IteratorType last)
5342 : current(std::move(first)), end(std::move(last))
5345 typename std::char_traits<char_type>::int_type get_character()
5347 if (JSON_HEDLEY_LIKELY(current != end))
5349 auto result = std::char_traits<char_type>::to_int_type(*current);
5350 std::advance(current, 1);
5354 return std::char_traits<char_type>::eof();
5358 IteratorType current;
5361 template<typename BaseInputAdapter, size_t T>
5362 friend struct wide_string_input_helper;
5366 return current == end;
5371 template<typename BaseInputAdapter, size_t T>
5372 struct wide_string_input_helper;
5374 template<typename BaseInputAdapter>
5375 struct wide_string_input_helper<BaseInputAdapter, 4>
5378 static void fill_buffer(BaseInputAdapter& input,
5379 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
5380 size_t& utf8_bytes_index,
5381 size_t& utf8_bytes_filled)
5383 utf8_bytes_index = 0;
5385 if (JSON_HEDLEY_UNLIKELY(input.empty()))
5387 utf8_bytes[0] = std::char_traits<char>::eof();
5388 utf8_bytes_filled = 1;
5392 // get the current character
5393 const auto wc = input.get_character();
5395 // UTF-32 to UTF-8 encoding
5398 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5399 utf8_bytes_filled = 1;
5401 else if (wc <= 0x7FF)
5403 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
5404 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5405 utf8_bytes_filled = 2;
5407 else if (wc <= 0xFFFF)
5409 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
5410 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5411 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5412 utf8_bytes_filled = 3;
5414 else if (wc <= 0x10FFFF)
5416 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
5417 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
5418 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5419 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5420 utf8_bytes_filled = 4;
5424 // unknown character
5425 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5426 utf8_bytes_filled = 1;
5432 template<typename BaseInputAdapter>
5433 struct wide_string_input_helper<BaseInputAdapter, 2>
5436 static void fill_buffer(BaseInputAdapter& input,
5437 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
5438 size_t& utf8_bytes_index,
5439 size_t& utf8_bytes_filled)
5441 utf8_bytes_index = 0;
5443 if (JSON_HEDLEY_UNLIKELY(input.empty()))
5445 utf8_bytes[0] = std::char_traits<char>::eof();
5446 utf8_bytes_filled = 1;
5450 // get the current character
5451 const auto wc = input.get_character();
5453 // UTF-16 to UTF-8 encoding
5456 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5457 utf8_bytes_filled = 1;
5459 else if (wc <= 0x7FF)
5461 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
5462 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5463 utf8_bytes_filled = 2;
5465 else if (0xD800 > wc || wc >= 0xE000)
5467 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
5468 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5469 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5470 utf8_bytes_filled = 3;
5474 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
5476 const auto wc2 = static_cast<unsigned int>(input.get_character());
5477 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
5478 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
5479 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
5480 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
5481 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
5482 utf8_bytes_filled = 4;
5486 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5487 utf8_bytes_filled = 1;
5494 // Wraps another input apdater to convert wide character types into individual bytes.
5495 template<typename BaseInputAdapter, typename WideCharType>
5496 class wide_string_input_adapter
5499 using char_type = char;
5501 wide_string_input_adapter(BaseInputAdapter base)
5502 : base_adapter(base) {}
5504 typename std::char_traits<char>::int_type get_character() noexcept
5506 // check if buffer needs to be filled
5507 if (utf8_bytes_index == utf8_bytes_filled)
5509 fill_buffer<sizeof(WideCharType)>();
5511 JSON_ASSERT(utf8_bytes_filled > 0);
5512 JSON_ASSERT(utf8_bytes_index == 0);
5516 JSON_ASSERT(utf8_bytes_filled > 0);
5517 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
5518 return utf8_bytes[utf8_bytes_index++];
5522 BaseInputAdapter base_adapter;
5527 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
5530 /// a buffer for UTF-8 bytes
5531 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
5533 /// index to the utf8_codes array for the next valid byte
5534 std::size_t utf8_bytes_index = 0;
5535 /// number of valid bytes in the utf8_codes array
5536 std::size_t utf8_bytes_filled = 0;
5540 template<typename IteratorType, typename Enable = void>
5541 struct iterator_input_adapter_factory
5543 using iterator_type = IteratorType;
5544 using char_type = typename std::iterator_traits<iterator_type>::value_type;
5545 using adapter_type = iterator_input_adapter<iterator_type>;
5547 static adapter_type create(IteratorType first, IteratorType last)
5549 return adapter_type(std::move(first), std::move(last));
5553 template<typename T>
5554 struct is_iterator_of_multibyte
5556 using value_type = typename std::iterator_traits<T>::value_type;
5559 value = sizeof(value_type) > 1
5563 template<typename IteratorType>
5564 struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
5566 using iterator_type = IteratorType;
5567 using char_type = typename std::iterator_traits<iterator_type>::value_type;
5568 using base_adapter_type = iterator_input_adapter<iterator_type>;
5569 using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
5571 static adapter_type create(IteratorType first, IteratorType last)
5573 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
5577 // General purpose iterator-based input
5578 template<typename IteratorType>
5579 typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
5581 using factory_type = iterator_input_adapter_factory<IteratorType>;
5582 return factory_type::create(first, last);
5585 // Convenience shorthand from container to iterator
5586 // Enables ADL on begin(container) and end(container)
5587 // Encloses the using declarations in namespace for not to leak them to outside scope
5589 namespace container_input_adapter_factory_impl
5595 template<typename ContainerType, typename Enable = void>
5596 struct container_input_adapter_factory {};
5598 template<typename ContainerType>
5599 struct container_input_adapter_factory< ContainerType,
5600 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
5602 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
5604 static adapter_type create(const ContainerType& container)
5606 return input_adapter(begin(container), end(container));
5610 } // namespace container_input_adapter_factory_impl
5612 template<typename ContainerType>
5613 typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
5615 return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
5619 // Special cases with fast paths
5620 inline file_input_adapter input_adapter(std::FILE* file)
5622 return file_input_adapter(file);
5625 inline input_stream_adapter input_adapter(std::istream& stream)
5627 return input_stream_adapter(stream);
5630 inline input_stream_adapter input_adapter(std::istream&& stream)
5632 return input_stream_adapter(stream);
5634 #endif // JSON_NO_IO
5636 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
5638 // Null-delimited strings, and the like.
5639 template < typename CharT,
5640 typename std::enable_if <
5641 std::is_pointer<CharT>::value&&
5642 !std::is_array<CharT>::value&&
5643 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
5644 sizeof(typename std::remove_pointer<CharT>::type) == 1,
5646 contiguous_bytes_input_adapter input_adapter(CharT b)
5648 auto length = std::strlen(reinterpret_cast<const char*>(b));
5649 const auto* ptr = reinterpret_cast<const char*>(b);
5650 return input_adapter(ptr, ptr + length);
5653 template<typename T, std::size_t N>
5654 auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5656 return input_adapter(array, array + N);
5659 // This class only handles inputs of input_buffer_adapter type.
5660 // It's required so that expressions like {ptr, len} can be implicitly cast
5661 // to the correct adapter.
5662 class span_input_adapter
5665 template < typename CharT,
5666 typename std::enable_if <
5667 std::is_pointer<CharT>::value&&
5668 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
5669 sizeof(typename std::remove_pointer<CharT>::type) == 1,
5671 span_input_adapter(CharT b, std::size_t l)
5672 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
5674 template<class IteratorType,
5675 typename std::enable_if<
5676 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
5678 span_input_adapter(IteratorType first, IteratorType last)
5679 : ia(input_adapter(first, last)) {}
5681 contiguous_bytes_input_adapter&& get()
5683 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
5687 contiguous_bytes_input_adapter ia;
5689 } // namespace detail
5690 } // namespace nlohmann
5692 // #include <nlohmann/detail/input/json_sax.hpp>
5696 #include <string> // string
5697 #include <utility> // move
5698 #include <vector> // vector
5700 // #include <nlohmann/detail/exceptions.hpp>
5702 // #include <nlohmann/detail/macro_scope.hpp>
5709 @brief SAX interface
5711 This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
5712 Each function is called in different situations while the input is parsed. The
5713 boolean return value informs the parser whether to continue processing the
5716 template<typename BasicJsonType>
5719 using number_integer_t = typename BasicJsonType::number_integer_t;
5720 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5721 using number_float_t = typename BasicJsonType::number_float_t;
5722 using string_t = typename BasicJsonType::string_t;
5723 using binary_t = typename BasicJsonType::binary_t;
5726 @brief a null value was read
5727 @return whether parsing should proceed
5729 virtual bool null() = 0;
5732 @brief a boolean value was read
5733 @param[in] val boolean value
5734 @return whether parsing should proceed
5736 virtual bool boolean(bool val) = 0;
5739 @brief an integer number was read
5740 @param[in] val integer value
5741 @return whether parsing should proceed
5743 virtual bool number_integer(number_integer_t val) = 0;
5746 @brief an unsigned integer number was read
5747 @param[in] val unsigned integer value
5748 @return whether parsing should proceed
5750 virtual bool number_unsigned(number_unsigned_t val) = 0;
5753 @brief a floating-point number was read
5754 @param[in] val floating-point value
5755 @param[in] s raw token value
5756 @return whether parsing should proceed
5758 virtual bool number_float(number_float_t val, const string_t& s) = 0;
5761 @brief a string value was read
5762 @param[in] val string value
5763 @return whether parsing should proceed
5764 @note It is safe to move the passed string value.
5766 virtual bool string(string_t& val) = 0;
5769 @brief a binary value was read
5770 @param[in] val binary value
5771 @return whether parsing should proceed
5772 @note It is safe to move the passed binary value.
5774 virtual bool binary(binary_t& val) = 0;
5777 @brief the beginning of an object was read
5778 @param[in] elements number of object elements or -1 if unknown
5779 @return whether parsing should proceed
5780 @note binary formats may report the number of elements
5782 virtual bool start_object(std::size_t elements) = 0;
5785 @brief an object key was read
5786 @param[in] val object key
5787 @return whether parsing should proceed
5788 @note It is safe to move the passed string.
5790 virtual bool key(string_t& val) = 0;
5793 @brief the end of an object was read
5794 @return whether parsing should proceed
5796 virtual bool end_object() = 0;
5799 @brief the beginning of an array was read
5800 @param[in] elements number of array elements or -1 if unknown
5801 @return whether parsing should proceed
5802 @note binary formats may report the number of elements
5804 virtual bool start_array(std::size_t elements) = 0;
5807 @brief the end of an array was read
5808 @return whether parsing should proceed
5810 virtual bool end_array() = 0;
5813 @brief a parse error occurred
5814 @param[in] position the position in the input where the error occurs
5815 @param[in] last_token the last read token
5816 @param[in] ex an exception object describing the error
5817 @return whether parsing should proceed (must return false)
5819 virtual bool parse_error(std::size_t position,
5820 const std::string& last_token,
5821 const detail::exception& ex) = 0;
5823 json_sax() = default;
5824 json_sax(const json_sax&) = default;
5825 json_sax(json_sax&&) noexcept = default;
5826 json_sax& operator=(const json_sax&) = default;
5827 json_sax& operator=(json_sax&&) noexcept = default;
5828 virtual ~json_sax() = default;
5835 @brief SAX implementation to create a JSON value from SAX events
5837 This class implements the @ref json_sax interface and processes the SAX events
5838 to create a JSON value which makes it basically a DOM parser. The structure or
5839 hierarchy of the JSON value is managed by the stack `ref_stack` which contains
5840 a pointer to the respective array or object for each recursion depth.
5842 After successful parsing, the value that is passed by reference to the
5843 constructor contains the parsed value.
5845 @tparam BasicJsonType the JSON type
5847 template<typename BasicJsonType>
5848 class json_sax_dom_parser
5851 using number_integer_t = typename BasicJsonType::number_integer_t;
5852 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5853 using number_float_t = typename BasicJsonType::number_float_t;
5854 using string_t = typename BasicJsonType::string_t;
5855 using binary_t = typename BasicJsonType::binary_t;
5858 @param[in,out] r reference to a JSON value that is manipulated while
5860 @param[in] allow_exceptions_ whether parse errors yield exceptions
5862 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
5863 : root(r), allow_exceptions(allow_exceptions_)
5866 // make class move-only
5867 json_sax_dom_parser(const json_sax_dom_parser&) = delete;
5868 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
5869 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
5870 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
5871 ~json_sax_dom_parser() = default;
5875 handle_value(nullptr);
5879 bool boolean(bool val)
5885 bool number_integer(number_integer_t val)
5891 bool number_unsigned(number_unsigned_t val)
5897 bool number_float(number_float_t val, const string_t& /*unused*/)
5903 bool string(string_t& val)
5909 bool binary(binary_t& val)
5911 handle_value(std::move(val));
5915 bool start_object(std::size_t len)
5917 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
5919 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
5921 JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
5927 bool key(string_t& val)
5929 // add null at given key and store the reference for later
5930 object_element = &(ref_stack.back()->m_value.object->operator[](val));
5936 ref_stack.back()->set_parents();
5937 ref_stack.pop_back();
5941 bool start_array(std::size_t len)
5943 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
5945 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
5947 JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
5955 ref_stack.back()->set_parents();
5956 ref_stack.pop_back();
5960 template<class Exception>
5961 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
5962 const Exception& ex)
5965 static_cast<void>(ex);
5966 if (allow_exceptions)
5973 constexpr bool is_errored() const
5980 @invariant If the ref stack is empty, then the passed value will be the new
5982 @invariant If the ref stack contains a value, then it is an array or an
5983 object to which we can add elements
5985 template<typename Value>
5986 JSON_HEDLEY_RETURNS_NON_NULL
5987 BasicJsonType* handle_value(Value&& v)
5989 if (ref_stack.empty())
5991 root = BasicJsonType(std::forward<Value>(v));
5995 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
5997 if (ref_stack.back()->is_array())
5999 ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
6000 return &(ref_stack.back()->m_value.array->back());
6003 JSON_ASSERT(ref_stack.back()->is_object());
6004 JSON_ASSERT(object_element);
6005 *object_element = BasicJsonType(std::forward<Value>(v));
6006 return object_element;
6009 /// the parsed JSON value
6010 BasicJsonType& root;
6011 /// stack to model hierarchy of values
6012 std::vector<BasicJsonType*> ref_stack {};
6013 /// helper to hold the reference for the next object element
6014 BasicJsonType* object_element = nullptr;
6015 /// whether a syntax error occurred
6016 bool errored = false;
6017 /// whether to throw exceptions in case of errors
6018 const bool allow_exceptions = true;
6021 template<typename BasicJsonType>
6022 class json_sax_dom_callback_parser
6025 using number_integer_t = typename BasicJsonType::number_integer_t;
6026 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6027 using number_float_t = typename BasicJsonType::number_float_t;
6028 using string_t = typename BasicJsonType::string_t;
6029 using binary_t = typename BasicJsonType::binary_t;
6030 using parser_callback_t = typename BasicJsonType::parser_callback_t;
6031 using parse_event_t = typename BasicJsonType::parse_event_t;
6033 json_sax_dom_callback_parser(BasicJsonType& r,
6034 const parser_callback_t cb,
6035 const bool allow_exceptions_ = true)
6036 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
6038 keep_stack.push_back(true);
6041 // make class move-only
6042 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
6043 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6044 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
6045 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6046 ~json_sax_dom_callback_parser() = default;
6050 handle_value(nullptr);
6054 bool boolean(bool val)
6060 bool number_integer(number_integer_t val)
6066 bool number_unsigned(number_unsigned_t val)
6072 bool number_float(number_float_t val, const string_t& /*unused*/)
6078 bool string(string_t& val)
6084 bool binary(binary_t& val)
6086 handle_value(std::move(val));
6090 bool start_object(std::size_t len)
6092 // check callback for object start
6093 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
6094 keep_stack.push_back(keep);
6096 auto val = handle_value(BasicJsonType::value_t::object, true);
6097 ref_stack.push_back(val.second);
6099 // check object limit
6100 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6102 JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
6108 bool key(string_t& val)
6110 BasicJsonType k = BasicJsonType(val);
6112 // check callback for key
6113 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
6114 key_keep_stack.push_back(keep);
6116 // add discarded value at given key and store the reference for later
6117 if (keep && ref_stack.back())
6119 object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
6127 if (ref_stack.back())
6129 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
6132 *ref_stack.back() = discarded;
6136 ref_stack.back()->set_parents();
6140 JSON_ASSERT(!ref_stack.empty());
6141 JSON_ASSERT(!keep_stack.empty());
6142 ref_stack.pop_back();
6143 keep_stack.pop_back();
6145 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
6147 // remove discarded value
6148 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
6150 if (it->is_discarded())
6152 ref_stack.back()->erase(it);
6161 bool start_array(std::size_t len)
6163 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
6164 keep_stack.push_back(keep);
6166 auto val = handle_value(BasicJsonType::value_t::array, true);
6167 ref_stack.push_back(val.second);
6169 // check array limit
6170 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6172 JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
6182 if (ref_stack.back())
6184 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
6187 ref_stack.back()->set_parents();
6192 *ref_stack.back() = discarded;
6196 JSON_ASSERT(!ref_stack.empty());
6197 JSON_ASSERT(!keep_stack.empty());
6198 ref_stack.pop_back();
6199 keep_stack.pop_back();
6201 // remove discarded value
6202 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
6204 ref_stack.back()->m_value.array->pop_back();
6210 template<class Exception>
6211 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
6212 const Exception& ex)
6215 static_cast<void>(ex);
6216 if (allow_exceptions)
6223 constexpr bool is_errored() const
6230 @param[in] v value to add to the JSON value we build during parsing
6231 @param[in] skip_callback whether we should skip calling the callback
6232 function; this is required after start_array() and
6233 start_object() SAX events, because otherwise we would call the
6234 callback function with an empty array or object, respectively.
6236 @invariant If the ref stack is empty, then the passed value will be the new
6238 @invariant If the ref stack contains a value, then it is an array or an
6239 object to which we can add elements
6241 @return pair of boolean (whether value should be kept) and pointer (to the
6242 passed value in the ref_stack hierarchy; nullptr if not kept)
6244 template<typename Value>
6245 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
6247 JSON_ASSERT(!keep_stack.empty());
6249 // do not handle this value if we know it would be added to a discarded
6251 if (!keep_stack.back())
6253 return {false, nullptr};
6257 auto value = BasicJsonType(std::forward<Value>(v));
6260 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
6262 // do not handle this value if we just learnt it shall be discarded
6265 return {false, nullptr};
6268 if (ref_stack.empty())
6270 root = std::move(value);
6271 return {true, &root};
6274 // skip this value if we already decided to skip the parent
6275 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
6276 if (!ref_stack.back())
6278 return {false, nullptr};
6281 // we now only expect arrays and objects
6282 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6285 if (ref_stack.back()->is_array())
6287 ref_stack.back()->m_value.array->emplace_back(std::move(value));
6288 return {true, &(ref_stack.back()->m_value.array->back())};
6292 JSON_ASSERT(ref_stack.back()->is_object());
6293 // check if we should store an element for the current key
6294 JSON_ASSERT(!key_keep_stack.empty());
6295 const bool store_element = key_keep_stack.back();
6296 key_keep_stack.pop_back();
6300 return {false, nullptr};
6303 JSON_ASSERT(object_element);
6304 *object_element = std::move(value);
6305 return {true, object_element};
6308 /// the parsed JSON value
6309 BasicJsonType& root;
6310 /// stack to model hierarchy of values
6311 std::vector<BasicJsonType*> ref_stack {};
6312 /// stack to manage which values to keep
6313 std::vector<bool> keep_stack {};
6314 /// stack to manage which object keys to keep
6315 std::vector<bool> key_keep_stack {};
6316 /// helper to hold the reference for the next object element
6317 BasicJsonType* object_element = nullptr;
6318 /// whether a syntax error occurred
6319 bool errored = false;
6320 /// callback function
6321 const parser_callback_t callback = nullptr;
6322 /// whether to throw exceptions in case of errors
6323 const bool allow_exceptions = true;
6324 /// a discarded value for the callback
6325 BasicJsonType discarded = BasicJsonType::value_t::discarded;
6328 template<typename BasicJsonType>
6329 class json_sax_acceptor
6332 using number_integer_t = typename BasicJsonType::number_integer_t;
6333 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6334 using number_float_t = typename BasicJsonType::number_float_t;
6335 using string_t = typename BasicJsonType::string_t;
6336 using binary_t = typename BasicJsonType::binary_t;
6343 bool boolean(bool /*unused*/)
6348 bool number_integer(number_integer_t /*unused*/)
6353 bool number_unsigned(number_unsigned_t /*unused*/)
6358 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
6363 bool string(string_t& /*unused*/)
6368 bool binary(binary_t& /*unused*/)
6373 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
6378 bool key(string_t& /*unused*/)
6388 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
6398 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
6403 } // namespace detail
6405 } // namespace nlohmann
6407 // #include <nlohmann/detail/input/lexer.hpp>
6410 #include <array> // array
6411 #include <clocale> // localeconv
6412 #include <cstddef> // size_t
6413 #include <cstdio> // snprintf
6414 #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
6415 #include <initializer_list> // initializer_list
6416 #include <string> // char_traits, string
6417 #include <utility> // move
6418 #include <vector> // vector
6420 // #include <nlohmann/detail/input/input_adapters.hpp>
6422 // #include <nlohmann/detail/input/position_t.hpp>
6424 // #include <nlohmann/detail/macro_scope.hpp>
6435 template<typename BasicJsonType>
6439 /// token types for the parser
6440 enum class token_type
6442 uninitialized, ///< indicating the scanner is uninitialized
6443 literal_true, ///< the `true` literal
6444 literal_false, ///< the `false` literal
6445 literal_null, ///< the `null` literal
6446 value_string, ///< a string -- use get_string() for actual value
6447 value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
6448 value_integer, ///< a signed integer -- use get_number_integer() for actual value
6449 value_float, ///< an floating point number -- use get_number_float() for actual value
6450 begin_array, ///< the character for array begin `[`
6451 begin_object, ///< the character for object begin `{`
6452 end_array, ///< the character for array end `]`
6453 end_object, ///< the character for object end `}`
6454 name_separator, ///< the name separator `:`
6455 value_separator, ///< the value separator `,`
6456 parse_error, ///< indicating a parse error
6457 end_of_input, ///< indicating the end of the input buffer
6458 literal_or_value ///< a literal or the begin of a value (only for diagnostics)
6461 /// return name of values of type token_type (only used for errors)
6462 JSON_HEDLEY_RETURNS_NON_NULL
6464 static const char* token_type_name(const token_type t) noexcept
6468 case token_type::uninitialized:
6469 return "<uninitialized>";
6470 case token_type::literal_true:
6471 return "true literal";
6472 case token_type::literal_false:
6473 return "false literal";
6474 case token_type::literal_null:
6475 return "null literal";
6476 case token_type::value_string:
6477 return "string literal";
6478 case token_type::value_unsigned:
6479 case token_type::value_integer:
6480 case token_type::value_float:
6481 return "number literal";
6482 case token_type::begin_array:
6484 case token_type::begin_object:
6486 case token_type::end_array:
6488 case token_type::end_object:
6490 case token_type::name_separator:
6492 case token_type::value_separator:
6494 case token_type::parse_error:
6495 return "<parse error>";
6496 case token_type::end_of_input:
6497 return "end of input";
6498 case token_type::literal_or_value:
6499 return "'[', '{', or a literal";
6501 default: // catch non-enum values
6502 return "unknown token";
6508 @brief lexical analysis
6510 This class organizes the lexical analysis during JSON deserialization.
6512 template<typename BasicJsonType, typename InputAdapterType>
6513 class lexer : public lexer_base<BasicJsonType>
6515 using number_integer_t = typename BasicJsonType::number_integer_t;
6516 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6517 using number_float_t = typename BasicJsonType::number_float_t;
6518 using string_t = typename BasicJsonType::string_t;
6519 using char_type = typename InputAdapterType::char_type;
6520 using char_int_type = typename std::char_traits<char_type>::int_type;
6523 using token_type = typename lexer_base<BasicJsonType>::token_type;
6525 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
6526 : ia(std::move(adapter))
6527 , ignore_comments(ignore_comments_)
6528 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
6531 // delete because of pointer members
6532 lexer(const lexer&) = delete;
6533 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6534 lexer& operator=(lexer&) = delete;
6535 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6539 /////////////////////
6541 /////////////////////
6543 /// return the locale-dependent decimal point
6545 static char get_decimal_point() noexcept
6547 const auto* loc = localeconv();
6548 JSON_ASSERT(loc != nullptr);
6549 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
6552 /////////////////////
6554 /////////////////////
6557 @brief get codepoint from 4 hex characters following `\u`
6559 For input "\u c1 c2 c3 c4" the codepoint is:
6560 (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
6561 = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
6563 Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
6564 must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
6565 conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
6566 between the ASCII value of the character and the desired integer value.
6568 @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
6573 // this function only makes sense after reading `\u`
6574 JSON_ASSERT(current == 'u');
6577 const auto factors = { 12u, 8u, 4u, 0u };
6578 for (const auto factor : factors)
6582 if (current >= '0' && current <= '9')
6584 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
6586 else if (current >= 'A' && current <= 'F')
6588 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
6590 else if (current >= 'a' && current <= 'f')
6592 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
6600 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
6605 @brief check if the next byte(s) are inside a given range
6607 Adds the current byte and, for each passed range, reads a new byte and
6608 checks if it is inside the range. If a violation was detected, set up an
6609 error message and return false. Otherwise, return true.
6611 @param[in] ranges list of integers; interpreted as list of pairs of
6612 inclusive lower and upper bound, respectively
6614 @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
6615 1, 2, or 3 pairs. This precondition is enforced by an assertion.
6617 @return true if and only if no range violation was detected
6619 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
6621 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
6624 for (auto range = ranges.begin(); range != ranges.end(); ++range)
6627 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
6633 error_message = "invalid string: ill-formed UTF-8 byte";
6642 @brief scan a string literal
6644 This function scans a string according to Sect. 7 of RFC 8259. While
6645 scanning, bytes are escaped and copied into buffer token_buffer. Then the
6646 function returns successfully, token_buffer is *not* null-terminated (as it
6647 may contain \0 bytes), and token_buffer.size() is the number of bytes in the
6650 @return token_type::value_string if string could be successfully scanned,
6651 token_type::parse_error otherwise
6653 @note In case of errors, variable error_message contains a textual
6656 token_type scan_string()
6658 // reset token_buffer (ignore opening quote)
6661 // we entered the function by reading an open quote
6662 JSON_ASSERT(current == '\"');
6666 // get next character
6669 // end of file while parsing string
6670 case std::char_traits<char_type>::eof():
6672 error_message = "invalid string: missing closing quote";
6673 return token_type::parse_error;
6679 return token_type::value_string;
6723 const int codepoint1 = get_codepoint();
6724 int codepoint = codepoint1; // start with codepoint1
6726 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
6728 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
6729 return token_type::parse_error;
6732 // check if code point is a high surrogate
6733 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
6735 // expect next \uxxxx entry
6736 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
6738 const int codepoint2 = get_codepoint();
6740 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
6742 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
6743 return token_type::parse_error;
6746 // check if codepoint2 is a low surrogate
6747 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
6749 // overwrite codepoint
6750 codepoint = static_cast<int>(
6751 // high surrogate occupies the most significant 22 bits
6752 (static_cast<unsigned int>(codepoint1) << 10u)
6753 // low surrogate occupies the least significant 15 bits
6754 + static_cast<unsigned int>(codepoint2)
6755 // there is still the 0xD800, 0xDC00 and 0x10000 noise
6756 // in the result, so we have to subtract with:
6757 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6762 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
6763 return token_type::parse_error;
6768 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
6769 return token_type::parse_error;
6774 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
6776 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
6777 return token_type::parse_error;
6781 // result of the above calculation yields a proper codepoint
6782 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
6784 // translate codepoint into bytes
6785 if (codepoint < 0x80)
6787 // 1-byte characters: 0xxxxxxx (ASCII)
6788 add(static_cast<char_int_type>(codepoint));
6790 else if (codepoint <= 0x7FF)
6792 // 2-byte characters: 110xxxxx 10xxxxxx
6793 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
6794 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6796 else if (codepoint <= 0xFFFF)
6798 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6799 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
6800 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
6801 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6805 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6806 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
6807 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
6808 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
6809 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6815 // other characters after escape
6817 error_message = "invalid string: forbidden character after backslash";
6818 return token_type::parse_error;
6824 // invalid control characters
6827 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
6828 return token_type::parse_error;
6833 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
6834 return token_type::parse_error;
6839 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
6840 return token_type::parse_error;
6845 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
6846 return token_type::parse_error;
6851 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
6852 return token_type::parse_error;
6857 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
6858 return token_type::parse_error;
6863 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
6864 return token_type::parse_error;
6869 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
6870 return token_type::parse_error;
6875 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
6876 return token_type::parse_error;
6881 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
6882 return token_type::parse_error;
6887 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
6888 return token_type::parse_error;
6893 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
6894 return token_type::parse_error;
6899 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
6900 return token_type::parse_error;
6905 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
6906 return token_type::parse_error;
6911 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
6912 return token_type::parse_error;
6917 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
6918 return token_type::parse_error;
6923 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
6924 return token_type::parse_error;
6929 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
6930 return token_type::parse_error;
6935 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
6936 return token_type::parse_error;
6941 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
6942 return token_type::parse_error;
6947 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
6948 return token_type::parse_error;
6953 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
6954 return token_type::parse_error;
6959 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
6960 return token_type::parse_error;
6965 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
6966 return token_type::parse_error;
6971 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
6972 return token_type::parse_error;
6977 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
6978 return token_type::parse_error;
6983 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
6984 return token_type::parse_error;
6989 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
6990 return token_type::parse_error;
6995 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
6996 return token_type::parse_error;
7001 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7002 return token_type::parse_error;
7007 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7008 return token_type::parse_error;
7013 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7014 return token_type::parse_error;
7017 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7117 // U+0080..U+07FF: bytes C2..DF 80..BF
7149 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
7151 return token_type::parse_error;
7156 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7159 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7161 return token_type::parse_error;
7166 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7167 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7183 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7185 return token_type::parse_error;
7190 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7193 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7195 return token_type::parse_error;
7200 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7203 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7205 return token_type::parse_error;
7210 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7215 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7217 return token_type::parse_error;
7222 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7225 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
7227 return token_type::parse_error;
7232 // remaining bytes (80..C1 and F5..FF) are ill-formed
7235 error_message = "invalid string: ill-formed UTF-8 byte";
7236 return token_type::parse_error;
7243 * @brief scan a comment
7244 * @return whether comment could be scanned successfully
7250 // single-line comments skip input until a newline or EOF is read
7259 case std::char_traits<char_type>::eof():
7269 // multi-line comments skip input until */ is read
7276 case std::char_traits<char_type>::eof():
7279 error_message = "invalid comment; missing closing '*/'";
7304 // unexpected character after reading '/'
7307 error_message = "invalid comment; expecting '/' or '*' after '/'";
7313 JSON_HEDLEY_NON_NULL(2)
7314 static void strtof(float& f, const char* str, char** endptr) noexcept
7316 f = std::strtof(str, endptr);
7319 JSON_HEDLEY_NON_NULL(2)
7320 static void strtof(double& f, const char* str, char** endptr) noexcept
7322 f = std::strtod(str, endptr);
7325 JSON_HEDLEY_NON_NULL(2)
7326 static void strtof(long double& f, const char* str, char** endptr) noexcept
7328 f = std::strtold(str, endptr);
7332 @brief scan a number literal
7334 This function scans a string according to Sect. 6 of RFC 8259.
7336 The function is realized with a deterministic finite state machine derived
7337 from the grammar described in RFC 8259. Starting in state "init", the
7338 input is read and used to determined the next state. Only state "done"
7339 accepts the number. State "error" is a trap state to model errors. In the
7340 table below, "anything" means any character but the ones listed before.
7342 state | 0 | 1-9 | e E | + | - | . | anything
7343 ---------|----------|----------|----------|---------|---------|----------|-----------
7344 init | zero | any1 | [error] | [error] | minus | [error] | [error]
7345 minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
7346 zero | done | done | exponent | done | done | decimal1 | done
7347 any1 | any1 | any1 | exponent | done | done | decimal1 | done
7348 decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error]
7349 decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
7350 exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
7351 sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
7352 any2 | any2 | any2 | done | done | done | done | done
7354 The state machine is realized with one label per state (prefixed with
7355 "scan_number_") and `goto` statements between them. The state machine
7356 contains cycles, but any cycle can be left when EOF is read. Therefore,
7357 the function is guaranteed to terminate.
7359 During scanning, the read bytes are stored in token_buffer. This string is
7360 then converted to a signed integer, an unsigned integer, or a
7361 floating-point number.
7363 @return token_type::value_unsigned, token_type::value_integer, or
7364 token_type::value_float if number could be successfully scanned,
7365 token_type::parse_error otherwise
7367 @note The scanner is independent of the current locale. Internally, the
7368 locale's decimal point is used instead of `.` to work with the
7369 locale-dependent converters.
7371 token_type scan_number() // lgtm [cpp/use-of-goto]
7373 // reset token_buffer to store the number's bytes
7376 // the type of the parsed number; initially set to unsigned; will be
7377 // changed if minus sign, decimal point or exponent is read
7378 token_type number_type = token_type::value_unsigned;
7380 // state (init): we just found out we need to scan a number
7386 goto scan_number_minus;
7392 goto scan_number_zero;
7406 goto scan_number_any1;
7409 // all other characters are rejected outside scan_number()
7410 default: // LCOV_EXCL_LINE
7411 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
7415 // state: we just parsed a leading minus sign
7416 number_type = token_type::value_integer;
7422 goto scan_number_zero;
7436 goto scan_number_any1;
7441 error_message = "invalid number; expected digit after '-'";
7442 return token_type::parse_error;
7447 // state: we just parse a zero (maybe with a leading minus sign)
7452 add(decimal_point_char);
7453 goto scan_number_decimal1;
7460 goto scan_number_exponent;
7464 goto scan_number_done;
7468 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
7483 goto scan_number_any1;
7488 add(decimal_point_char);
7489 goto scan_number_decimal1;
7496 goto scan_number_exponent;
7500 goto scan_number_done;
7503 scan_number_decimal1:
7504 // state: we just parsed a decimal point
7505 number_type = token_type::value_float;
7520 goto scan_number_decimal2;
7525 error_message = "invalid number; expected digit after '.'";
7526 return token_type::parse_error;
7530 scan_number_decimal2:
7531 // we just parsed at least one number after a decimal point
7546 goto scan_number_decimal2;
7553 goto scan_number_exponent;
7557 goto scan_number_done;
7560 scan_number_exponent:
7561 // we just parsed an exponent
7562 number_type = token_type::value_float;
7569 goto scan_number_sign;
7584 goto scan_number_any2;
7590 "invalid number; expected '+', '-', or digit after exponent";
7591 return token_type::parse_error;
7596 // we just parsed an exponent sign
7611 goto scan_number_any2;
7616 error_message = "invalid number; expected digit after exponent sign";
7617 return token_type::parse_error;
7622 // we just parsed a number after the exponent or exponent sign
7637 goto scan_number_any2;
7641 goto scan_number_done;
7645 // unget the character after the number (we only read it to know that
7646 // we are done scanning a number)
7649 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
7652 // try to parse integers first and fall back to floats
7653 if (number_type == token_type::value_unsigned)
7655 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
7657 // we checked the number format before
7658 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7662 value_unsigned = static_cast<number_unsigned_t>(x);
7663 if (value_unsigned == x)
7665 return token_type::value_unsigned;
7669 else if (number_type == token_type::value_integer)
7671 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
7673 // we checked the number format before
7674 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7678 value_integer = static_cast<number_integer_t>(x);
7679 if (value_integer == x)
7681 return token_type::value_integer;
7686 // this code is reached if we parse a floating-point number or if an
7687 // integer conversion above failed
7688 strtof(value_float, token_buffer.data(), &endptr);
7690 // we checked the number format before
7691 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7693 return token_type::value_float;
7697 @param[in] literal_text the literal text to expect
7698 @param[in] length the length of the passed literal text
7699 @param[in] return_type the token type to return on success
7701 JSON_HEDLEY_NON_NULL(2)
7702 token_type scan_literal(const char_type* literal_text, const std::size_t length,
7703 token_type return_type)
7705 JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
7706 for (std::size_t i = 1; i < length; ++i)
7708 if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
7710 error_message = "invalid literal";
7711 return token_type::parse_error;
7717 /////////////////////
7719 /////////////////////
7721 /// reset token_buffer; current character is beginning of token
7722 void reset() noexcept
7724 token_buffer.clear();
7725 token_string.clear();
7726 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
7730 @brief get next character from the input
7732 This function provides the interface to the used input adapter. It does
7733 not throw in case the input reached EOF, but returns a
7734 `std::char_traits<char>::eof()` in that case. Stores the scanned characters
7735 for use in error messages.
7737 @return character read from the input
7741 ++position.chars_read_total;
7742 ++position.chars_read_current_line;
7746 // just reset the next_unget variable and work with current
7751 current = ia.get_character();
7754 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
7756 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
7759 if (current == '\n')
7761 ++position.lines_read;
7762 position.chars_read_current_line = 0;
7769 @brief unget current character (read it again on next get)
7771 We implement unget by setting variable next_unget to true. The input is not
7772 changed - we just simulate ungetting by modifying chars_read_total,
7773 chars_read_current_line, and token_string. The next call to get() will
7774 behave as if the unget character is read again.
7780 --position.chars_read_total;
7782 // in case we "unget" a newline, we have to also decrement the lines_read
7783 if (position.chars_read_current_line == 0)
7785 if (position.lines_read > 0)
7787 --position.lines_read;
7792 --position.chars_read_current_line;
7795 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
7797 JSON_ASSERT(!token_string.empty());
7798 token_string.pop_back();
7802 /// add a character to token_buffer
7803 void add(char_int_type c)
7805 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
7809 /////////////////////
7811 /////////////////////
7813 /// return integer value
7814 constexpr number_integer_t get_number_integer() const noexcept
7816 return value_integer;
7819 /// return unsigned integer value
7820 constexpr number_unsigned_t get_number_unsigned() const noexcept
7822 return value_unsigned;
7825 /// return floating-point value
7826 constexpr number_float_t get_number_float() const noexcept
7831 /// return current string value (implicitly resets the token; useful only once)
7832 string_t& get_string()
7834 return token_buffer;
7837 /////////////////////
7839 /////////////////////
7841 /// return position of last read token
7842 constexpr position_t get_position() const noexcept
7847 /// return the last read token (for errors only). Will never contain EOF
7848 /// (an arbitrary value that is not a valid char value, often -1), because
7849 /// 255 may legitimately occur. May contain NUL, which should be escaped.
7850 std::string get_token_string() const
7852 // escape control characters
7854 for (const auto c : token_string)
7856 if (static_cast<unsigned char>(c) <= '\x1F')
7858 // escape control characters
7859 std::array<char, 9> cs{{}};
7860 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
7861 result += cs.data();
7865 // add character as is
7866 result.push_back(static_cast<std::string::value_type>(c));
7873 /// return syntax error message
7874 JSON_HEDLEY_RETURNS_NON_NULL
7875 constexpr const char* get_error_message() const noexcept
7877 return error_message;
7880 /////////////////////
7882 /////////////////////
7885 @brief skip the UTF-8 byte order mark
7886 @return true iff there is no BOM or the correct BOM has been skipped
7892 // check if we completely parse the BOM
7893 return get() == 0xBB && get() == 0xBF;
7896 // the first character is not the beginning of the BOM; unget it to
7902 void skip_whitespace()
7908 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
7913 // initially, skip the BOM
7914 if (position.chars_read_total == 0 && !skip_bom())
7916 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
7917 return token_type::parse_error;
7920 // read next character and ignore whitespace
7924 while (ignore_comments && current == '/')
7926 if (!scan_comment())
7928 return token_type::parse_error;
7931 // skip following whitespace
7937 // structural characters
7939 return token_type::begin_array;
7941 return token_type::end_array;
7943 return token_type::begin_object;
7945 return token_type::end_object;
7947 return token_type::name_separator;
7949 return token_type::value_separator;
7954 std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}};
7955 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
7959 std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}};
7960 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
7964 std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}};
7965 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
7970 return scan_string();
7984 return scan_number();
7986 // end of input (the null byte is needed when parsing from
7989 case std::char_traits<char_type>::eof():
7990 return token_type::end_of_input;
7994 error_message = "invalid literal";
7995 return token_type::parse_error;
8001 InputAdapterType ia;
8003 /// whether comments should be ignored (true) or signaled as errors (false)
8004 const bool ignore_comments = false;
8006 /// the current character
8007 char_int_type current = std::char_traits<char_type>::eof();
8009 /// whether the next get() call should just return current
8010 bool next_unget = false;
8012 /// the start position of the current token
8013 position_t position {};
8015 /// raw input token string (for error messages)
8016 std::vector<char_type> token_string {};
8018 /// buffer for variable-length tokens (numbers, strings)
8019 string_t token_buffer {};
8021 /// a description of occurred lexer errors
8022 const char* error_message = "";
8025 number_integer_t value_integer = 0;
8026 number_unsigned_t value_unsigned = 0;
8027 number_float_t value_float = 0;
8029 /// the decimal point
8030 const char_int_type decimal_point_char = '.';
8032 } // namespace detail
8033 } // namespace nlohmann
8035 // #include <nlohmann/detail/macro_scope.hpp>
8037 // #include <nlohmann/detail/meta/is_sax.hpp>
8040 #include <cstdint> // size_t
8041 #include <utility> // declval
8042 #include <string> // string
8044 // #include <nlohmann/detail/meta/detected.hpp>
8046 // #include <nlohmann/detail/meta/type_traits.hpp>
8053 template<typename T>
8054 using null_function_t = decltype(std::declval<T&>().null());
8056 template<typename T>
8057 using boolean_function_t =
8058 decltype(std::declval<T&>().boolean(std::declval<bool>()));
8060 template<typename T, typename Integer>
8061 using number_integer_function_t =
8062 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
8064 template<typename T, typename Unsigned>
8065 using number_unsigned_function_t =
8066 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
8068 template<typename T, typename Float, typename String>
8069 using number_float_function_t = decltype(std::declval<T&>().number_float(
8070 std::declval<Float>(), std::declval<const String&>()));
8072 template<typename T, typename String>
8073 using string_function_t =
8074 decltype(std::declval<T&>().string(std::declval<String&>()));
8076 template<typename T, typename Binary>
8077 using binary_function_t =
8078 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
8080 template<typename T>
8081 using start_object_function_t =
8082 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
8084 template<typename T, typename String>
8085 using key_function_t =
8086 decltype(std::declval<T&>().key(std::declval<String&>()));
8088 template<typename T>
8089 using end_object_function_t = decltype(std::declval<T&>().end_object());
8091 template<typename T>
8092 using start_array_function_t =
8093 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
8095 template<typename T>
8096 using end_array_function_t = decltype(std::declval<T&>().end_array());
8098 template<typename T, typename Exception>
8099 using parse_error_function_t = decltype(std::declval<T&>().parse_error(
8100 std::declval<std::size_t>(), std::declval<const std::string&>(),
8101 std::declval<const Exception&>()));
8103 template<typename SAX, typename BasicJsonType>
8107 static_assert(is_basic_json<BasicJsonType>::value,
8108 "BasicJsonType must be of type basic_json<...>");
8110 using number_integer_t = typename BasicJsonType::number_integer_t;
8111 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8112 using number_float_t = typename BasicJsonType::number_float_t;
8113 using string_t = typename BasicJsonType::string_t;
8114 using binary_t = typename BasicJsonType::binary_t;
8115 using exception_t = typename BasicJsonType::exception;
8118 static constexpr bool value =
8119 is_detected_exact<bool, null_function_t, SAX>::value &&
8120 is_detected_exact<bool, boolean_function_t, SAX>::value &&
8121 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
8122 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
8123 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
8124 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
8125 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
8126 is_detected_exact<bool, start_object_function_t, SAX>::value &&
8127 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
8128 is_detected_exact<bool, end_object_function_t, SAX>::value &&
8129 is_detected_exact<bool, start_array_function_t, SAX>::value &&
8130 is_detected_exact<bool, end_array_function_t, SAX>::value &&
8131 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
8134 template<typename SAX, typename BasicJsonType>
8135 struct is_sax_static_asserts
8138 static_assert(is_basic_json<BasicJsonType>::value,
8139 "BasicJsonType must be of type basic_json<...>");
8141 using number_integer_t = typename BasicJsonType::number_integer_t;
8142 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8143 using number_float_t = typename BasicJsonType::number_float_t;
8144 using string_t = typename BasicJsonType::string_t;
8145 using binary_t = typename BasicJsonType::binary_t;
8146 using exception_t = typename BasicJsonType::exception;
8149 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
8150 "Missing/invalid function: bool null()");
8151 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
8152 "Missing/invalid function: bool boolean(bool)");
8153 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
8154 "Missing/invalid function: bool boolean(bool)");
8156 is_detected_exact<bool, number_integer_function_t, SAX,
8157 number_integer_t>::value,
8158 "Missing/invalid function: bool number_integer(number_integer_t)");
8160 is_detected_exact<bool, number_unsigned_function_t, SAX,
8161 number_unsigned_t>::value,
8162 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
8163 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
8164 number_float_t, string_t>::value,
8165 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
8167 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
8168 "Missing/invalid function: bool string(string_t&)");
8170 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
8171 "Missing/invalid function: bool binary(binary_t&)");
8172 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
8173 "Missing/invalid function: bool start_object(std::size_t)");
8174 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
8175 "Missing/invalid function: bool key(string_t&)");
8176 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
8177 "Missing/invalid function: bool end_object()");
8178 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
8179 "Missing/invalid function: bool start_array(std::size_t)");
8180 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
8181 "Missing/invalid function: bool end_array()");
8183 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
8184 "Missing/invalid function: bool parse_error(std::size_t, const "
8185 "std::string&, const exception&)");
8187 } // namespace detail
8188 } // namespace nlohmann
8190 // #include <nlohmann/detail/meta/type_traits.hpp>
8192 // #include <nlohmann/detail/value_t.hpp>
8200 /// how to treat CBOR tags
8201 enum class cbor_tag_handler_t
8203 error, ///< throw a parse_error exception in case of a tag
8204 ignore, ///< ignore tags
8205 store ///< store tags as binary type
8209 @brief determine system byte order
8211 @return true if and only if system's byte order is little endian
8213 @note from https://stackoverflow.com/a/1001328/266378
8215 static inline bool little_endianness(int num = 1) noexcept
8217 return *reinterpret_cast<char*>(&num) == 1;
8226 @brief deserialization of CBOR, MessagePack, and UBJSON values
8228 template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
8231 using number_integer_t = typename BasicJsonType::number_integer_t;
8232 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8233 using number_float_t = typename BasicJsonType::number_float_t;
8234 using string_t = typename BasicJsonType::string_t;
8235 using binary_t = typename BasicJsonType::binary_t;
8236 using json_sax_t = SAX;
8237 using char_type = typename InputAdapterType::char_type;
8238 using char_int_type = typename std::char_traits<char_type>::int_type;
8242 @brief create a binary reader
8244 @param[in] adapter input adapter to read from
8246 explicit binary_reader(InputAdapterType&& adapter) noexcept : ia(std::move(adapter))
8248 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
8251 // make class move-only
8252 binary_reader(const binary_reader&) = delete;
8253 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8254 binary_reader& operator=(const binary_reader&) = delete;
8255 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8256 ~binary_reader() = default;
8259 @param[in] format the binary format to parse
8260 @param[in] sax_ a SAX event processor
8261 @param[in] strict whether to expect the input to be consumed completed
8262 @param[in] tag_handler how to treat CBOR tags
8264 @return whether parsing was successful
8266 JSON_HEDLEY_NON_NULL(3)
8267 bool sax_parse(const input_format_t format,
8269 const bool strict = true,
8270 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
8273 bool result = false;
8277 case input_format_t::bson:
8278 result = parse_bson_internal();
8281 case input_format_t::cbor:
8282 result = parse_cbor_internal(true, tag_handler);
8285 case input_format_t::msgpack:
8286 result = parse_msgpack_internal();
8289 case input_format_t::ubjson:
8290 result = parse_ubjson_internal();
8293 case input_format_t::json: // LCOV_EXCL_LINE
8294 default: // LCOV_EXCL_LINE
8295 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8298 // strict mode: next byte must be EOF
8299 if (result && strict)
8301 if (format == input_format_t::ubjson)
8310 if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
8312 return sax->parse_error(chars_read, get_token_string(),
8313 parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"), BasicJsonType()));
8326 @brief Reads in a BSON-object and passes it to the SAX-parser.
8327 @return whether a valid BSON-value was passed to the SAX parser
8329 bool parse_bson_internal()
8331 std::int32_t document_size{};
8332 get_number<std::int32_t, true>(input_format_t::bson, document_size);
8334 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
8339 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
8344 return sax->end_object();
8348 @brief Parses a C-style string from the BSON input.
8349 @param[in,out] result A reference to the string variable where the read
8350 string is to be stored.
8351 @return `true` if the \x00-byte indicating the end of the string was
8352 encountered before the EOF; false` indicates an unexpected EOF.
8354 bool get_bson_cstr(string_t& result)
8356 auto out = std::back_inserter(result);
8360 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
8364 if (current == 0x00)
8368 *out++ = static_cast<typename string_t::value_type>(current);
8373 @brief Parses a zero-terminated string of length @a len from the BSON
8375 @param[in] len The length (including the zero-byte at the end) of the
8377 @param[in,out] result A reference to the string variable where the read
8378 string is to be stored.
8379 @tparam NumberType The type of the length @a len
8381 @return `true` if the string was successfully parsed
8383 template<typename NumberType>
8384 bool get_bson_string(const NumberType len, string_t& result)
8386 if (JSON_HEDLEY_UNLIKELY(len < 1))
8388 auto last_token = get_token_string();
8389 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"), BasicJsonType()));
8392 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
8396 @brief Parses a byte array input of length @a len from the BSON input.
8397 @param[in] len The length of the byte array to be read.
8398 @param[in,out] result A reference to the binary variable where the read
8399 array is to be stored.
8400 @tparam NumberType The type of the length @a len
8402 @return `true` if the byte array was successfully parsed
8404 template<typename NumberType>
8405 bool get_bson_binary(const NumberType len, binary_t& result)
8407 if (JSON_HEDLEY_UNLIKELY(len < 0))
8409 auto last_token = get_token_string();
8410 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"), BasicJsonType()));
8413 // All BSON binary values have a subtype
8414 std::uint8_t subtype{};
8415 get_number<std::uint8_t>(input_format_t::bson, subtype);
8416 result.set_subtype(subtype);
8418 return get_binary(input_format_t::bson, len, result);
8422 @brief Read a BSON document element of the given @a element_type.
8423 @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
8424 @param[in] element_type_parse_position The position in the input stream,
8425 where the `element_type` was read.
8426 @warning Not all BSON element types are supported yet. An unsupported
8427 @a element_type will give rise to a parse_error.114:
8428 Unsupported BSON record type 0x...
8429 @return whether a valid BSON-object/array was passed to the SAX parser
8431 bool parse_bson_element_internal(const char_int_type element_type,
8432 const std::size_t element_type_parse_position)
8434 switch (element_type)
8436 case 0x01: // double
8439 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
8442 case 0x02: // string
8446 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
8449 case 0x03: // object
8451 return parse_bson_internal();
8456 return parse_bson_array();
8459 case 0x05: // binary
8463 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
8466 case 0x08: // boolean
8468 return sax->boolean(get() != 0);
8478 std::int32_t value{};
8479 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
8484 std::int64_t value{};
8485 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
8488 default: // anything else not supported (yet)
8490 std::array<char, 3> cr{{}};
8491 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8492 return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()), BasicJsonType()));
8498 @brief Read a BSON element list (as specified in the BSON-spec)
8500 The same binary layout is used for objects and arrays, hence it must be
8501 indicated with the argument @a is_array which one is expected
8502 (true --> array, false --> object).
8504 @param[in] is_array Determines if the element list being read is to be
8505 treated as an object (@a is_array == false), or as an
8506 array (@a is_array == true).
8507 @return whether a valid BSON-object/array was passed to the SAX parser
8509 bool parse_bson_element_list(const bool is_array)
8513 while (auto element_type = get())
8515 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
8520 const std::size_t element_type_parse_position = chars_read;
8521 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
8526 if (!is_array && !sax->key(key))
8531 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
8536 // get_bson_cstr only appends
8544 @brief Reads an array from the BSON input and passes it to the SAX-parser.
8545 @return whether a valid BSON-array was passed to the SAX parser
8547 bool parse_bson_array()
8549 std::int32_t document_size{};
8550 get_number<std::int32_t, true>(input_format_t::bson, document_size);
8552 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
8557 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
8562 return sax->end_array();
8570 @param[in] get_char whether a new character should be retrieved from the
8571 input (true) or whether the last read character should
8572 be considered instead (false)
8573 @param[in] tag_handler how CBOR tags should be treated
8575 @return whether a valid CBOR value was passed to the SAX parser
8577 bool parse_cbor_internal(const bool get_char,
8578 const cbor_tag_handler_t tag_handler)
8580 switch (get_char ? get() : current)
8583 case std::char_traits<char_type>::eof():
8584 return unexpect_eof(input_format_t::cbor, "value");
8586 // Integer 0x00..0x17 (0..23)
8611 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
8613 case 0x18: // Unsigned integer (one-byte uint8_t follows)
8615 std::uint8_t number{};
8616 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8619 case 0x19: // Unsigned integer (two-byte uint16_t follows)
8621 std::uint16_t number{};
8622 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8625 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
8627 std::uint32_t number{};
8628 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8631 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
8633 std::uint64_t number{};
8634 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8637 // Negative integer -1-0x00..-1-0x17 (-1..-24)
8662 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
8664 case 0x38: // Negative integer (one-byte uint8_t follows)
8666 std::uint8_t number{};
8667 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8670 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
8672 std::uint16_t number{};
8673 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8676 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
8678 std::uint32_t number{};
8679 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8682 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
8684 std::uint64_t number{};
8685 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
8686 - static_cast<number_integer_t>(number));
8689 // Binary data (0x00..0x17 bytes follow)
8714 case 0x58: // Binary data (one-byte uint8_t for n follows)
8715 case 0x59: // Binary data (two-byte uint16_t for n follow)
8716 case 0x5A: // Binary data (four-byte uint32_t for n follow)
8717 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
8718 case 0x5F: // Binary data (indefinite length)
8721 return get_cbor_binary(b) && sax->binary(b);
8724 // UTF-8 string (0x00..0x17 bytes follow)
8749 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
8750 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
8751 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
8752 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
8753 case 0x7F: // UTF-8 string (indefinite length)
8756 return get_cbor_string(s) && sax->string(s);
8759 // array (0x00..0x17 data items follow)
8784 return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
8786 case 0x98: // array (one-byte uint8_t for n follows)
8789 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8792 case 0x99: // array (two-byte uint16_t for n follow)
8794 std::uint16_t len{};
8795 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8798 case 0x9A: // array (four-byte uint32_t for n follow)
8800 std::uint32_t len{};
8801 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8804 case 0x9B: // array (eight-byte uint64_t for n follow)
8806 std::uint64_t len{};
8807 return get_number(input_format_t::cbor, len) && get_cbor_array(detail::conditional_static_cast<std::size_t>(len), tag_handler);
8810 case 0x9F: // array (indefinite length)
8811 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
8813 // map (0x00..0x17 pairs of data items follow)
8838 return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
8840 case 0xB8: // map (one-byte uint8_t for n follows)
8843 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8846 case 0xB9: // map (two-byte uint16_t for n follow)
8848 std::uint16_t len{};
8849 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8852 case 0xBA: // map (four-byte uint32_t for n follow)
8854 std::uint32_t len{};
8855 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8858 case 0xBB: // map (eight-byte uint64_t for n follow)
8860 std::uint64_t len{};
8861 return get_number(input_format_t::cbor, len) && get_cbor_object(detail::conditional_static_cast<std::size_t>(len), tag_handler);
8864 case 0xBF: // map (indefinite length)
8865 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
8867 case 0xC6: // tagged item
8882 case 0xD8: // tagged item (1 bytes follow)
8883 case 0xD9: // tagged item (2 bytes follow)
8884 case 0xDA: // tagged item (4 bytes follow)
8885 case 0xDB: // tagged item (8 bytes follow)
8887 switch (tag_handler)
8889 case cbor_tag_handler_t::error:
8891 auto last_token = get_token_string();
8892 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
8895 case cbor_tag_handler_t::ignore:
8897 // ignore binary subtype
8902 std::uint8_t subtype_to_ignore{};
8903 get_number(input_format_t::cbor, subtype_to_ignore);
8908 std::uint16_t subtype_to_ignore{};
8909 get_number(input_format_t::cbor, subtype_to_ignore);
8914 std::uint32_t subtype_to_ignore{};
8915 get_number(input_format_t::cbor, subtype_to_ignore);
8920 std::uint64_t subtype_to_ignore{};
8921 get_number(input_format_t::cbor, subtype_to_ignore);
8927 return parse_cbor_internal(true, tag_handler);
8930 case cbor_tag_handler_t::store:
8933 // use binary subtype and store in binary container
8938 std::uint8_t subtype{};
8939 get_number(input_format_t::cbor, subtype);
8940 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
8945 std::uint16_t subtype{};
8946 get_number(input_format_t::cbor, subtype);
8947 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
8952 std::uint32_t subtype{};
8953 get_number(input_format_t::cbor, subtype);
8954 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
8959 std::uint64_t subtype{};
8960 get_number(input_format_t::cbor, subtype);
8961 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
8965 return parse_cbor_internal(true, tag_handler);
8968 return get_cbor_binary(b) && sax->binary(b);
8971 default: // LCOV_EXCL_LINE
8972 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8973 return false; // LCOV_EXCL_LINE
8978 return sax->boolean(false);
8981 return sax->boolean(true);
8986 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
8988 const auto byte1_raw = get();
8989 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
8993 const auto byte2_raw = get();
8994 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
8999 const auto byte1 = static_cast<unsigned char>(byte1_raw);
9000 const auto byte2 = static_cast<unsigned char>(byte2_raw);
9002 // code from RFC 7049, Appendix D, Figure 3:
9003 // As half-precision floating-point numbers were only added
9004 // to IEEE 754 in 2008, today's programming platforms often
9005 // still only have limited support for them. It is very
9006 // easy to include at least decoding support for them even
9007 // without such support. An example of a small decoder for
9008 // half-precision floating-point numbers in the C language
9009 // is shown in Fig. 3.
9010 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
9011 const double val = [&half]
9013 const int exp = (half >> 10u) & 0x1Fu;
9014 const unsigned int mant = half & 0x3FFu;
9015 JSON_ASSERT(0 <= exp&& exp <= 32);
9016 JSON_ASSERT(mant <= 1024);
9020 return std::ldexp(mant, -24);
9023 ? std::numeric_limits<double>::infinity()
9024 : std::numeric_limits<double>::quiet_NaN();
9026 return std::ldexp(mant + 1024, exp - 25);
9029 return sax->number_float((half & 0x8000u) != 0
9030 ? static_cast<number_float_t>(-val)
9031 : static_cast<number_float_t>(val), "");
9034 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
9037 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9040 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
9043 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9046 default: // anything else (0xFF is handled inside the other types)
9048 auto last_token = get_token_string();
9049 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
9055 @brief reads a CBOR string
9057 This function first reads starting bytes to determine the expected
9058 string length and then copies this number of bytes into a string.
9059 Additionally, CBOR's strings with indefinite lengths are supported.
9061 @param[out] result created string
9063 @return whether string creation completed
9065 bool get_cbor_string(string_t& result)
9067 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
9074 // UTF-8 string (0x00..0x17 bytes follow)
9100 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
9103 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9106 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9109 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9111 std::uint16_t len{};
9112 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9115 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9117 std::uint32_t len{};
9118 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9121 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9123 std::uint64_t len{};
9124 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9127 case 0x7F: // UTF-8 string (indefinite length)
9129 while (get() != 0xFF)
9132 if (!get_cbor_string(chunk))
9136 result.append(chunk);
9143 auto last_token = get_token_string();
9144 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"), BasicJsonType()));
9150 @brief reads a CBOR byte array
9152 This function first reads starting bytes to determine the expected
9153 byte array length and then copies this number of bytes into the byte array.
9154 Additionally, CBOR's byte arrays with indefinite lengths are supported.
9156 @param[out] result created byte array
9158 @return whether byte array creation completed
9160 bool get_cbor_binary(binary_t& result)
9162 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
9169 // Binary data (0x00..0x17 bytes follow)
9195 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
9198 case 0x58: // Binary data (one-byte uint8_t for n follows)
9201 return get_number(input_format_t::cbor, len) &&
9202 get_binary(input_format_t::cbor, len, result);
9205 case 0x59: // Binary data (two-byte uint16_t for n follow)
9207 std::uint16_t len{};
9208 return get_number(input_format_t::cbor, len) &&
9209 get_binary(input_format_t::cbor, len, result);
9212 case 0x5A: // Binary data (four-byte uint32_t for n follow)
9214 std::uint32_t len{};
9215 return get_number(input_format_t::cbor, len) &&
9216 get_binary(input_format_t::cbor, len, result);
9219 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9221 std::uint64_t len{};
9222 return get_number(input_format_t::cbor, len) &&
9223 get_binary(input_format_t::cbor, len, result);
9226 case 0x5F: // Binary data (indefinite length)
9228 while (get() != 0xFF)
9231 if (!get_cbor_binary(chunk))
9235 result.insert(result.end(), chunk.begin(), chunk.end());
9242 auto last_token = get_token_string();
9243 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"), BasicJsonType()));
9249 @param[in] len the length of the array or static_cast<std::size_t>(-1) for an
9250 array of indefinite size
9251 @param[in] tag_handler how CBOR tags should be treated
9252 @return whether array creation completed
9254 bool get_cbor_array(const std::size_t len,
9255 const cbor_tag_handler_t tag_handler)
9257 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
9262 if (len != static_cast<std::size_t>(-1))
9264 for (std::size_t i = 0; i < len; ++i)
9266 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
9274 while (get() != 0xFF)
9276 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
9283 return sax->end_array();
9287 @param[in] len the length of the object or static_cast<std::size_t>(-1) for an
9288 object of indefinite size
9289 @param[in] tag_handler how CBOR tags should be treated
9290 @return whether object creation completed
9292 bool get_cbor_object(const std::size_t len,
9293 const cbor_tag_handler_t tag_handler)
9295 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
9303 if (len != static_cast<std::size_t>(-1))
9305 for (std::size_t i = 0; i < len; ++i)
9308 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
9313 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
9322 while (get() != 0xFF)
9324 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
9329 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
9338 return sax->end_object();
9346 @return whether a valid MessagePack value was passed to the SAX parser
9348 bool parse_msgpack_internal()
9353 case std::char_traits<char_type>::eof():
9354 return unexpect_eof(input_format_t::msgpack, "value");
9485 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9504 return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
9523 return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
9559 case 0xDA: // str 16
9560 case 0xDB: // str 32
9563 return get_msgpack_string(s) && sax->string(s);
9570 return sax->boolean(false);
9573 return sax->boolean(true);
9576 case 0xC5: // bin 16
9577 case 0xC6: // bin 32
9579 case 0xC8: // ext 16
9580 case 0xC9: // ext 32
9581 case 0xD4: // fixext 1
9582 case 0xD5: // fixext 2
9583 case 0xD6: // fixext 4
9584 case 0xD7: // fixext 8
9585 case 0xD8: // fixext 16
9588 return get_msgpack_binary(b) && sax->binary(b);
9591 case 0xCA: // float 32
9594 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
9597 case 0xCB: // float 64
9600 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
9603 case 0xCC: // uint 8
9605 std::uint8_t number{};
9606 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9609 case 0xCD: // uint 16
9611 std::uint16_t number{};
9612 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9615 case 0xCE: // uint 32
9617 std::uint32_t number{};
9618 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9621 case 0xCF: // uint 64
9623 std::uint64_t number{};
9624 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9629 std::int8_t number{};
9630 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9633 case 0xD1: // int 16
9635 std::int16_t number{};
9636 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9639 case 0xD2: // int 32
9641 std::int32_t number{};
9642 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9645 case 0xD3: // int 64
9647 std::int64_t number{};
9648 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9651 case 0xDC: // array 16
9653 std::uint16_t len{};
9654 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
9657 case 0xDD: // array 32
9659 std::uint32_t len{};
9660 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
9663 case 0xDE: // map 16
9665 std::uint16_t len{};
9666 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
9669 case 0xDF: // map 32
9671 std::uint32_t len{};
9672 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
9708 return sax->number_integer(static_cast<std::int8_t>(current));
9710 default: // anything else
9712 auto last_token = get_token_string();
9713 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
9719 @brief reads a MessagePack string
9721 This function first reads starting bytes to determine the expected
9722 string length and then copies this number of bytes into a string.
9724 @param[out] result created string
9726 @return whether string creation completed
9728 bool get_msgpack_string(string_t& result)
9730 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
9771 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
9777 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9780 case 0xDA: // str 16
9782 std::uint16_t len{};
9783 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9786 case 0xDB: // str 32
9788 std::uint32_t len{};
9789 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9794 auto last_token = get_token_string();
9795 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"), BasicJsonType()));
9801 @brief reads a MessagePack byte array
9803 This function first reads starting bytes to determine the expected
9804 byte array length and then copies this number of bytes into a byte array.
9806 @param[out] result created byte array
9808 @return whether byte array creation completed
9810 bool get_msgpack_binary(binary_t& result)
9812 // helper function to set the subtype
9813 auto assign_and_return_true = [&result](std::int8_t subtype)
9815 result.set_subtype(static_cast<std::uint8_t>(subtype));
9824 return get_number(input_format_t::msgpack, len) &&
9825 get_binary(input_format_t::msgpack, len, result);
9828 case 0xC5: // bin 16
9830 std::uint16_t len{};
9831 return get_number(input_format_t::msgpack, len) &&
9832 get_binary(input_format_t::msgpack, len, result);
9835 case 0xC6: // bin 32
9837 std::uint32_t len{};
9838 return get_number(input_format_t::msgpack, len) &&
9839 get_binary(input_format_t::msgpack, len, result);
9845 std::int8_t subtype{};
9846 return get_number(input_format_t::msgpack, len) &&
9847 get_number(input_format_t::msgpack, subtype) &&
9848 get_binary(input_format_t::msgpack, len, result) &&
9849 assign_and_return_true(subtype);
9852 case 0xC8: // ext 16
9854 std::uint16_t len{};
9855 std::int8_t subtype{};
9856 return get_number(input_format_t::msgpack, len) &&
9857 get_number(input_format_t::msgpack, subtype) &&
9858 get_binary(input_format_t::msgpack, len, result) &&
9859 assign_and_return_true(subtype);
9862 case 0xC9: // ext 32
9864 std::uint32_t len{};
9865 std::int8_t subtype{};
9866 return get_number(input_format_t::msgpack, len) &&
9867 get_number(input_format_t::msgpack, subtype) &&
9868 get_binary(input_format_t::msgpack, len, result) &&
9869 assign_and_return_true(subtype);
9872 case 0xD4: // fixext 1
9874 std::int8_t subtype{};
9875 return get_number(input_format_t::msgpack, subtype) &&
9876 get_binary(input_format_t::msgpack, 1, result) &&
9877 assign_and_return_true(subtype);
9880 case 0xD5: // fixext 2
9882 std::int8_t subtype{};
9883 return get_number(input_format_t::msgpack, subtype) &&
9884 get_binary(input_format_t::msgpack, 2, result) &&
9885 assign_and_return_true(subtype);
9888 case 0xD6: // fixext 4
9890 std::int8_t subtype{};
9891 return get_number(input_format_t::msgpack, subtype) &&
9892 get_binary(input_format_t::msgpack, 4, result) &&
9893 assign_and_return_true(subtype);
9896 case 0xD7: // fixext 8
9898 std::int8_t subtype{};
9899 return get_number(input_format_t::msgpack, subtype) &&
9900 get_binary(input_format_t::msgpack, 8, result) &&
9901 assign_and_return_true(subtype);
9904 case 0xD8: // fixext 16
9906 std::int8_t subtype{};
9907 return get_number(input_format_t::msgpack, subtype) &&
9908 get_binary(input_format_t::msgpack, 16, result) &&
9909 assign_and_return_true(subtype);
9912 default: // LCOV_EXCL_LINE
9913 return false; // LCOV_EXCL_LINE
9918 @param[in] len the length of the array
9919 @return whether array creation completed
9921 bool get_msgpack_array(const std::size_t len)
9923 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
9928 for (std::size_t i = 0; i < len; ++i)
9930 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
9936 return sax->end_array();
9940 @param[in] len the length of the object
9941 @return whether object creation completed
9943 bool get_msgpack_object(const std::size_t len)
9945 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
9951 for (std::size_t i = 0; i < len; ++i)
9954 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
9959 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
9966 return sax->end_object();
9974 @param[in] get_char whether a new character should be retrieved from the
9975 input (true, default) or whether the last read
9976 character should be considered instead
9978 @return whether a valid UBJSON value was passed to the SAX parser
9980 bool parse_ubjson_internal(const bool get_char = true)
9982 return get_ubjson_value(get_char ? get_ignore_noop() : current);
9986 @brief reads a UBJSON string
9988 This function is either called after reading the 'S' byte explicitly
9989 indicating a string, or in case of an object key where the 'S' byte can be
9992 @param[out] result created string
9993 @param[in] get_char whether a new character should be retrieved from the
9994 input (true, default) or whether the last read
9995 character should be considered instead
9997 @return whether string creation completed
9999 bool get_ubjson_string(string_t& result, const bool get_char = true)
10003 get(); // TODO(niels): may we ignore N here?
10006 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
10015 std::uint8_t len{};
10016 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10022 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10027 std::int16_t len{};
10028 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10033 std::int32_t len{};
10034 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10039 std::int64_t len{};
10040 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10044 auto last_token = get_token_string();
10045 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"), BasicJsonType()));
10050 @param[out] result determined size
10051 @return whether size determination completed
10053 bool get_ubjson_size_value(std::size_t& result)
10055 switch (get_ignore_noop())
10059 std::uint8_t number{};
10060 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10064 result = static_cast<std::size_t>(number);
10070 std::int8_t number{};
10071 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10075 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
10081 std::int16_t number{};
10082 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10086 result = static_cast<std::size_t>(number);
10092 std::int32_t number{};
10093 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10097 result = static_cast<std::size_t>(number);
10103 std::int64_t number{};
10104 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10108 result = static_cast<std::size_t>(number);
10114 auto last_token = get_token_string();
10115 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"), BasicJsonType()));
10121 @brief determine the type and size for a container
10123 In the optimized UBJSON format, a type and a size can be provided to allow
10124 for a more compact representation.
10126 @param[out] result pair of the size and the type
10128 @return whether pair creation completed
10130 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result)
10132 result.first = string_t::npos; // size
10133 result.second = 0; // type
10137 if (current == '$')
10139 result.second = get(); // must not ignore 'N', because 'N' maybe the type
10140 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type")))
10146 if (JSON_HEDLEY_UNLIKELY(current != '#'))
10148 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
10152 auto last_token = get_token_string();
10153 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"), BasicJsonType()));
10156 return get_ubjson_size_value(result.first);
10159 if (current == '#')
10161 return get_ubjson_size_value(result.first);
10168 @param prefix the previously read or set type prefix
10169 @return whether value creation completed
10171 bool get_ubjson_value(const char_int_type prefix)
10175 case std::char_traits<char_type>::eof(): // EOF
10176 return unexpect_eof(input_format_t::ubjson, "value");
10179 return sax->boolean(true);
10181 return sax->boolean(false);
10184 return sax->null();
10188 std::uint8_t number{};
10189 return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number);
10194 std::int8_t number{};
10195 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
10200 std::int16_t number{};
10201 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
10206 std::int32_t number{};
10207 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
10212 std::int64_t number{};
10213 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
10219 return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10225 return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10230 return get_ubjson_high_precision_number();
10236 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char")))
10240 if (JSON_HEDLEY_UNLIKELY(current > 127))
10242 auto last_token = get_token_string();
10243 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"), BasicJsonType()));
10245 string_t s(1, static_cast<typename string_t::value_type>(current));
10246 return sax->string(s);
10249 case 'S': // string
10252 return get_ubjson_string(s) && sax->string(s);
10256 return get_ubjson_array();
10258 case '{': // object
10259 return get_ubjson_object();
10261 default: // anything else
10263 auto last_token = get_token_string();
10264 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
10270 @return whether array creation completed
10272 bool get_ubjson_array()
10274 std::pair<std::size_t, char_int_type> size_and_type;
10275 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
10280 if (size_and_type.first != string_t::npos)
10282 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
10287 if (size_and_type.second != 0)
10289 if (size_and_type.second != 'N')
10291 for (std::size_t i = 0; i < size_and_type.first; ++i)
10293 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
10302 for (std::size_t i = 0; i < size_and_type.first; ++i)
10304 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
10313 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
10318 while (current != ']')
10320 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
10328 return sax->end_array();
10332 @return whether object creation completed
10334 bool get_ubjson_object()
10336 std::pair<std::size_t, char_int_type> size_and_type;
10337 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
10343 if (size_and_type.first != string_t::npos)
10345 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
10350 if (size_and_type.second != 0)
10352 for (std::size_t i = 0; i < size_and_type.first; ++i)
10354 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
10358 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
10367 for (std::size_t i = 0; i < size_and_type.first; ++i)
10369 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
10373 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
10383 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
10388 while (current != '}')
10390 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
10394 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
10403 return sax->end_object();
10406 // Note, no reader for UBJSON binary types is implemented because they do
10409 bool get_ubjson_high_precision_number()
10411 // get size of following number string
10412 std::size_t size{};
10413 auto res = get_ubjson_size_value(size);
10414 if (JSON_HEDLEY_UNLIKELY(!res))
10419 // get number string
10420 std::vector<char> number_vector;
10421 for (std::size_t i = 0; i < size; ++i)
10424 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number")))
10428 number_vector.push_back(static_cast<char>(current));
10431 // parse number string
10432 using ia_type = decltype(detail::input_adapter(number_vector));
10433 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
10434 const auto result_number = number_lexer.scan();
10435 const auto number_string = number_lexer.get_token_string();
10436 const auto result_remainder = number_lexer.scan();
10438 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
10440 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
10442 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType()));
10445 switch (result_number)
10447 case token_type::value_integer:
10448 return sax->number_integer(number_lexer.get_number_integer());
10449 case token_type::value_unsigned:
10450 return sax->number_unsigned(number_lexer.get_number_unsigned());
10451 case token_type::value_float:
10452 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
10453 case token_type::uninitialized:
10454 case token_type::literal_true:
10455 case token_type::literal_false:
10456 case token_type::literal_null:
10457 case token_type::value_string:
10458 case token_type::begin_array:
10459 case token_type::begin_object:
10460 case token_type::end_array:
10461 case token_type::end_object:
10462 case token_type::name_separator:
10463 case token_type::value_separator:
10464 case token_type::parse_error:
10465 case token_type::end_of_input:
10466 case token_type::literal_or_value:
10468 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType()));
10472 ///////////////////////
10473 // Utility functions //
10474 ///////////////////////
10477 @brief get next character from the input
10479 This function provides the interface to the used input adapter. It does
10480 not throw in case the input reached EOF, but returns a -'ve valued
10481 `std::char_traits<char_type>::eof()` in that case.
10483 @return character read from the input
10485 char_int_type get()
10488 return current = ia.get_character();
10492 @return character read from the input after ignoring all 'N' entries
10494 char_int_type get_ignore_noop()
10500 while (current == 'N');
10506 @brief read a number from the input
10508 @tparam NumberType the type of the number
10509 @param[in] format the current format (for diagnostics)
10510 @param[out] result number of type @a NumberType
10512 @return whether conversion completed
10514 @note This function needs to respect the system's endianness, because
10515 bytes in CBOR, MessagePack, and UBJSON are stored in network order
10516 (big endian) and therefore need reordering on little endian systems.
10518 template<typename NumberType, bool InputIsLittleEndian = false>
10519 bool get_number(const input_format_t format, NumberType& result)
10521 // step 1: read input into array with system's byte order
10522 std::array<std::uint8_t, sizeof(NumberType)> vec{};
10523 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
10526 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
10531 // reverse byte order prior to conversion if necessary
10532 if (is_little_endian != InputIsLittleEndian)
10534 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
10538 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
10542 // step 2: convert array into number of type T and return
10543 std::memcpy(&result, vec.data(), sizeof(NumberType));
10548 @brief create a string by reading characters from the input
10550 @tparam NumberType the type of the number
10551 @param[in] format the current format (for diagnostics)
10552 @param[in] len number of characters to read
10553 @param[out] result string created by reading @a len bytes
10555 @return whether string creation completed
10557 @note We can not reserve @a len bytes for the result, because @a len
10558 may be too large. Usually, @ref unexpect_eof() detects the end of
10559 the input before we run out of string memory.
10561 template<typename NumberType>
10562 bool get_string(const input_format_t format,
10563 const NumberType len,
10566 bool success = true;
10567 for (NumberType i = 0; i < len; i++)
10570 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
10575 result.push_back(static_cast<typename string_t::value_type>(current));
10581 @brief create a byte array by reading bytes from the input
10583 @tparam NumberType the type of the number
10584 @param[in] format the current format (for diagnostics)
10585 @param[in] len number of bytes to read
10586 @param[out] result byte array created by reading @a len bytes
10588 @return whether byte array creation completed
10590 @note We can not reserve @a len bytes for the result, because @a len
10591 may be too large. Usually, @ref unexpect_eof() detects the end of
10592 the input before we run out of memory.
10594 template<typename NumberType>
10595 bool get_binary(const input_format_t format,
10596 const NumberType len,
10599 bool success = true;
10600 for (NumberType i = 0; i < len; i++)
10603 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
10608 result.push_back(static_cast<std::uint8_t>(current));
10614 @param[in] format the current format (for diagnostics)
10615 @param[in] context further context information (for diagnostics)
10616 @return whether the last read character is not EOF
10618 JSON_HEDLEY_NON_NULL(3)
10619 bool unexpect_eof(const input_format_t format, const char* context) const
10621 if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
10623 return sax->parse_error(chars_read, "<end of file>",
10624 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), BasicJsonType()));
10630 @return a string representation of the last read byte
10632 std::string get_token_string() const
10634 std::array<char, 3> cr{{}};
10635 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
10636 return std::string{cr.data()};
10640 @param[in] format the current format
10641 @param[in] detail a detailed error message
10642 @param[in] context further context information
10643 @return a message string to use in the parse_error exceptions
10645 std::string exception_message(const input_format_t format,
10646 const std::string& detail,
10647 const std::string& context) const
10649 std::string error_msg = "syntax error while parsing ";
10653 case input_format_t::cbor:
10654 error_msg += "CBOR";
10657 case input_format_t::msgpack:
10658 error_msg += "MessagePack";
10661 case input_format_t::ubjson:
10662 error_msg += "UBJSON";
10665 case input_format_t::bson:
10666 error_msg += "BSON";
10669 case input_format_t::json: // LCOV_EXCL_LINE
10670 default: // LCOV_EXCL_LINE
10671 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10674 return error_msg + " " + context + ": " + detail;
10679 InputAdapterType ia;
10681 /// the current character
10682 char_int_type current = std::char_traits<char_type>::eof();
10684 /// the number of characters read
10685 std::size_t chars_read = 0;
10687 /// whether we can assume little endianness
10688 const bool is_little_endian = little_endianness();
10691 json_sax_t* sax = nullptr;
10693 } // namespace detail
10694 } // namespace nlohmann
10696 // #include <nlohmann/detail/input/input_adapters.hpp>
10698 // #include <nlohmann/detail/input/lexer.hpp>
10700 // #include <nlohmann/detail/input/parser.hpp>
10703 #include <cmath> // isfinite
10704 #include <cstdint> // uint8_t
10705 #include <functional> // function
10706 #include <string> // string
10707 #include <utility> // move
10708 #include <vector> // vector
10710 // #include <nlohmann/detail/exceptions.hpp>
10712 // #include <nlohmann/detail/input/input_adapters.hpp>
10714 // #include <nlohmann/detail/input/json_sax.hpp>
10716 // #include <nlohmann/detail/input/lexer.hpp>
10718 // #include <nlohmann/detail/macro_scope.hpp>
10720 // #include <nlohmann/detail/meta/is_sax.hpp>
10722 // #include <nlohmann/detail/value_t.hpp>
10733 enum class parse_event_t : std::uint8_t
10735 /// the parser read `{` and started to process a JSON object
10737 /// the parser read `}` and finished processing a JSON object
10739 /// the parser read `[` and started to process a JSON array
10741 /// the parser read `]` and finished processing a JSON array
10743 /// the parser read a key of a value in an object
10745 /// the parser finished reading a JSON value
10749 template<typename BasicJsonType>
10750 using parser_callback_t =
10751 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
10754 @brief syntax analysis
10756 This class implements a recursive descent parser.
10758 template<typename BasicJsonType, typename InputAdapterType>
10761 using number_integer_t = typename BasicJsonType::number_integer_t;
10762 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
10763 using number_float_t = typename BasicJsonType::number_float_t;
10764 using string_t = typename BasicJsonType::string_t;
10765 using lexer_t = lexer<BasicJsonType, InputAdapterType>;
10766 using token_type = typename lexer_t::token_type;
10769 /// a parser reading from an input adapter
10770 explicit parser(InputAdapterType&& adapter,
10771 const parser_callback_t<BasicJsonType> cb = nullptr,
10772 const bool allow_exceptions_ = true,
10773 const bool skip_comments = false)
10775 , m_lexer(std::move(adapter), skip_comments)
10776 , allow_exceptions(allow_exceptions_)
10778 // read first token
10783 @brief public parser interface
10785 @param[in] strict whether to expect the last token to be EOF
10786 @param[in,out] result parsed JSON value
10788 @throw parse_error.101 in case of an unexpected token
10789 @throw parse_error.102 if to_unicode fails or surrogate error
10790 @throw parse_error.103 if to_unicode fails
10792 void parse(const bool strict, BasicJsonType& result)
10796 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
10797 sax_parse_internal(&sdp);
10799 // in strict mode, input must be completely read
10800 if (strict && (get_token() != token_type::end_of_input))
10802 sdp.parse_error(m_lexer.get_position(),
10803 m_lexer.get_token_string(),
10804 parse_error::create(101, m_lexer.get_position(),
10805 exception_message(token_type::end_of_input, "value"), BasicJsonType()));
10808 // in case of an error, return discarded value
10809 if (sdp.is_errored())
10811 result = value_t::discarded;
10815 // set top-level value to null if it was discarded by the callback
10817 if (result.is_discarded())
10824 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
10825 sax_parse_internal(&sdp);
10827 // in strict mode, input must be completely read
10828 if (strict && (get_token() != token_type::end_of_input))
10830 sdp.parse_error(m_lexer.get_position(),
10831 m_lexer.get_token_string(),
10832 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
10835 // in case of an error, return discarded value
10836 if (sdp.is_errored())
10838 result = value_t::discarded;
10843 result.assert_invariant();
10847 @brief public accept interface
10849 @param[in] strict whether to expect the last token to be EOF
10850 @return whether the input is a proper JSON text
10852 bool accept(const bool strict = true)
10854 json_sax_acceptor<BasicJsonType> sax_acceptor;
10855 return sax_parse(&sax_acceptor, strict);
10858 template<typename SAX>
10859 JSON_HEDLEY_NON_NULL(2)
10860 bool sax_parse(SAX* sax, const bool strict = true)
10862 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
10863 const bool result = sax_parse_internal(sax);
10865 // strict mode: next byte must be EOF
10866 if (result && strict && (get_token() != token_type::end_of_input))
10868 return sax->parse_error(m_lexer.get_position(),
10869 m_lexer.get_token_string(),
10870 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
10877 template<typename SAX>
10878 JSON_HEDLEY_NON_NULL(2)
10879 bool sax_parse_internal(SAX* sax)
10881 // stack to remember the hierarchy of structured values we are parsing
10882 // true = array; false = object
10883 std::vector<bool> states;
10884 // value to avoid a goto (see comment where set to true)
10885 bool skip_to_state_evaluation = false;
10889 if (!skip_to_state_evaluation)
10891 // invariant: get_token() was called before each iteration
10892 switch (last_token)
10894 case token_type::begin_object:
10896 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
10901 // closing } -> we are done
10902 if (get_token() == token_type::end_object)
10904 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
10912 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
10914 return sax->parse_error(m_lexer.get_position(),
10915 m_lexer.get_token_string(),
10916 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType()));
10918 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
10923 // parse separator (:)
10924 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
10926 return sax->parse_error(m_lexer.get_position(),
10927 m_lexer.get_token_string(),
10928 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType()));
10931 // remember we are now inside an object
10932 states.push_back(false);
10939 case token_type::begin_array:
10941 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
10946 // closing ] -> we are done
10947 if (get_token() == token_type::end_array)
10949 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
10956 // remember we are now inside an array
10957 states.push_back(true);
10959 // parse values (no need to call get_token)
10963 case token_type::value_float:
10965 const auto res = m_lexer.get_number_float();
10967 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
10969 return sax->parse_error(m_lexer.get_position(),
10970 m_lexer.get_token_string(),
10971 out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'", BasicJsonType()));
10974 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
10982 case token_type::literal_false:
10984 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
10991 case token_type::literal_null:
10993 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
11000 case token_type::literal_true:
11002 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
11009 case token_type::value_integer:
11011 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
11018 case token_type::value_string:
11020 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
11027 case token_type::value_unsigned:
11029 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
11036 case token_type::parse_error:
11038 // using "uninitialized" to avoid "expected" message
11039 return sax->parse_error(m_lexer.get_position(),
11040 m_lexer.get_token_string(),
11041 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), BasicJsonType()));
11044 case token_type::uninitialized:
11045 case token_type::end_array:
11046 case token_type::end_object:
11047 case token_type::name_separator:
11048 case token_type::value_separator:
11049 case token_type::end_of_input:
11050 case token_type::literal_or_value:
11051 default: // the last token was unexpected
11053 return sax->parse_error(m_lexer.get_position(),
11054 m_lexer.get_token_string(),
11055 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), BasicJsonType()));
11061 skip_to_state_evaluation = false;
11064 // we reached this line after we successfully parsed a value
11065 if (states.empty())
11067 // empty stack: we reached the end of the hierarchy: done
11071 if (states.back()) // array
11073 // comma -> next value
11074 if (get_token() == token_type::value_separator)
11076 // parse a new value
11082 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
11084 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
11089 // We are done with this array. Before we can parse a
11090 // new value, we need to evaluate the new state first.
11091 // By setting skip_to_state_evaluation to false, we
11092 // are effectively jumping to the beginning of this if.
11093 JSON_ASSERT(!states.empty());
11095 skip_to_state_evaluation = true;
11099 return sax->parse_error(m_lexer.get_position(),
11100 m_lexer.get_token_string(),
11101 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), BasicJsonType()));
11104 // states.back() is false -> object
11106 // comma -> next value
11107 if (get_token() == token_type::value_separator)
11110 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
11112 return sax->parse_error(m_lexer.get_position(),
11113 m_lexer.get_token_string(),
11114 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType()));
11117 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
11122 // parse separator (:)
11123 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
11125 return sax->parse_error(m_lexer.get_position(),
11126 m_lexer.get_token_string(),
11127 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType()));
11136 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
11138 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
11143 // We are done with this object. Before we can parse a
11144 // new value, we need to evaluate the new state first.
11145 // By setting skip_to_state_evaluation to false, we
11146 // are effectively jumping to the beginning of this if.
11147 JSON_ASSERT(!states.empty());
11149 skip_to_state_evaluation = true;
11153 return sax->parse_error(m_lexer.get_position(),
11154 m_lexer.get_token_string(),
11155 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), BasicJsonType()));
11159 /// get next token from lexer
11160 token_type get_token()
11162 return last_token = m_lexer.scan();
11165 std::string exception_message(const token_type expected, const std::string& context)
11167 std::string error_msg = "syntax error ";
11169 if (!context.empty())
11171 error_msg += "while parsing " + context + " ";
11176 if (last_token == token_type::parse_error)
11178 error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
11179 m_lexer.get_token_string() + "'";
11183 error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
11186 if (expected != token_type::uninitialized)
11188 error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
11195 /// callback function
11196 const parser_callback_t<BasicJsonType> callback = nullptr;
11197 /// the type of the last read token
11198 token_type last_token = token_type::uninitialized;
11201 /// whether to throw exceptions in case of errors
11202 const bool allow_exceptions = true;
11205 } // namespace detail
11206 } // namespace nlohmann
11208 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
11211 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
11214 #include <cstddef> // ptrdiff_t
11215 #include <limits> // numeric_limits
11217 // #include <nlohmann/detail/macro_scope.hpp>
11225 @brief an iterator for primitive JSON types
11227 This class models an iterator for primitive JSON types (boolean, number,
11228 string). It's only purpose is to allow the iterator/const_iterator classes
11229 to "iterate" over primitive values. Internally, the iterator is modeled by
11230 a `difference_type` variable. Value begin_value (`0`) models the begin,
11231 end_value (`1`) models past the end.
11233 class primitive_iterator_t
11236 using difference_type = std::ptrdiff_t;
11237 static constexpr difference_type begin_value = 0;
11238 static constexpr difference_type end_value = begin_value + 1;
11240 JSON_PRIVATE_UNLESS_TESTED:
11241 /// iterator as signed integer type
11242 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
11245 constexpr difference_type get_value() const noexcept
11250 /// set iterator to a defined beginning
11251 void set_begin() noexcept
11253 m_it = begin_value;
11256 /// set iterator to a defined past the end
11257 void set_end() noexcept
11262 /// return whether the iterator can be dereferenced
11263 constexpr bool is_begin() const noexcept
11265 return m_it == begin_value;
11268 /// return whether the iterator is at end
11269 constexpr bool is_end() const noexcept
11271 return m_it == end_value;
11274 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
11276 return lhs.m_it == rhs.m_it;
11279 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
11281 return lhs.m_it < rhs.m_it;
11284 primitive_iterator_t operator+(difference_type n) noexcept
11286 auto result = *this;
11291 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
11293 return lhs.m_it - rhs.m_it;
11296 primitive_iterator_t& operator++() noexcept
11302 primitive_iterator_t const operator++(int) noexcept // NOLINT(readability-const-return-type)
11304 auto result = *this;
11309 primitive_iterator_t& operator--() noexcept
11315 primitive_iterator_t const operator--(int) noexcept // NOLINT(readability-const-return-type)
11317 auto result = *this;
11322 primitive_iterator_t& operator+=(difference_type n) noexcept
11328 primitive_iterator_t& operator-=(difference_type n) noexcept
11334 } // namespace detail
11335 } // namespace nlohmann
11343 @brief an iterator value
11345 @note This structure could easily be a union, but MSVC currently does not allow
11346 unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
11348 template<typename BasicJsonType> struct internal_iterator
11350 /// iterator for JSON objects
11351 typename BasicJsonType::object_t::iterator object_iterator {};
11352 /// iterator for JSON arrays
11353 typename BasicJsonType::array_t::iterator array_iterator {};
11354 /// generic iterator for all other types
11355 primitive_iterator_t primitive_iterator {};
11357 } // namespace detail
11358 } // namespace nlohmann
11360 // #include <nlohmann/detail/iterators/iter_impl.hpp>
11363 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
11364 #include <type_traits> // conditional, is_const, remove_const
11366 // #include <nlohmann/detail/exceptions.hpp>
11368 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
11370 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
11372 // #include <nlohmann/detail/macro_scope.hpp>
11374 // #include <nlohmann/detail/meta/cpp_future.hpp>
11376 // #include <nlohmann/detail/meta/type_traits.hpp>
11378 // #include <nlohmann/detail/value_t.hpp>
11385 // forward declare, to be able to friend it later on
11386 template<typename IteratorType> class iteration_proxy;
11387 template<typename IteratorType> class iteration_proxy_value;
11390 @brief a template for a bidirectional iterator for the @ref basic_json class
11391 This class implements a both iterators (iterator and const_iterator) for the
11392 @ref basic_json class.
11393 @note An iterator is called *initialized* when a pointer to a JSON value has
11394 been set (e.g., by a constructor or a copy assignment). If the iterator is
11395 default-constructed, it is *uninitialized* and most methods are undefined.
11396 **The library uses assertions to detect calls on uninitialized iterators.**
11397 @requirement The class satisfies the following concept requirements:
11399 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
11400 The iterator that can be moved can be moved in both directions (i.e.
11401 incremented and decremented).
11402 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional
11403 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
11405 template<typename BasicJsonType>
11406 class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
11408 /// the iterator with BasicJsonType of different const-ness
11409 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
11410 /// allow basic_json to access private members
11411 friend other_iter_impl;
11412 friend BasicJsonType;
11413 friend iteration_proxy<iter_impl>;
11414 friend iteration_proxy_value<iter_impl>;
11416 using object_t = typename BasicJsonType::object_t;
11417 using array_t = typename BasicJsonType::array_t;
11418 // make sure BasicJsonType is basic_json or const basic_json
11419 static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
11420 "iter_impl only accepts (const) basic_json");
11424 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
11425 /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
11426 /// A user-defined iterator should provide publicly accessible typedefs named
11427 /// iterator_category, value_type, difference_type, pointer, and reference.
11428 /// Note that value_type is required to be non-const, even for constant iterators.
11429 using iterator_category = std::bidirectional_iterator_tag;
11431 /// the type of the values when the iterator is dereferenced
11432 using value_type = typename BasicJsonType::value_type;
11433 /// a type to represent differences between iterators
11434 using difference_type = typename BasicJsonType::difference_type;
11435 /// defines a pointer to the type iterated over (value_type)
11436 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
11437 typename BasicJsonType::const_pointer,
11438 typename BasicJsonType::pointer>::type;
11439 /// defines a reference to the type iterated over (value_type)
11441 typename std::conditional<std::is_const<BasicJsonType>::value,
11442 typename BasicJsonType::const_reference,
11443 typename BasicJsonType::reference>::type;
11445 iter_impl() = default;
11446 ~iter_impl() = default;
11447 iter_impl(iter_impl&&) noexcept = default;
11448 iter_impl& operator=(iter_impl&&) noexcept = default;
11451 @brief constructor for a given JSON instance
11452 @param[in] object pointer to a JSON object for this iterator
11453 @pre object != nullptr
11454 @post The iterator is initialized; i.e. `m_object != nullptr`.
11456 explicit iter_impl(pointer object) noexcept : m_object(object)
11458 JSON_ASSERT(m_object != nullptr);
11460 switch (m_object->m_type)
11462 case value_t::object:
11464 m_it.object_iterator = typename object_t::iterator();
11468 case value_t::array:
11470 m_it.array_iterator = typename array_t::iterator();
11474 case value_t::null:
11475 case value_t::string:
11476 case value_t::boolean:
11477 case value_t::number_integer:
11478 case value_t::number_unsigned:
11479 case value_t::number_float:
11480 case value_t::binary:
11481 case value_t::discarded:
11484 m_it.primitive_iterator = primitive_iterator_t();
11491 @note The conventional copy constructor and copy assignment are implicitly
11492 defined. Combined with the following converting constructor and
11493 assignment, they support: (1) copy from iterator to iterator, (2)
11494 copy from const iterator to const iterator, and (3) conversion from
11495 iterator to const iterator. However conversion from const iterator
11496 to iterator is not defined.
11500 @brief const copy constructor
11501 @param[in] other const iterator to copy from
11502 @note This copy constructor had to be defined explicitly to circumvent a bug
11503 occurring on msvc v19.0 compiler (VS 2015) debug build. For more
11504 information refer to: https://github.com/nlohmann/json/issues/1608
11506 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
11507 : m_object(other.m_object), m_it(other.m_it)
11511 @brief converting assignment
11512 @param[in] other const iterator to copy from
11513 @return const/non-const iterator
11514 @note It is not checked whether @a other is initialized.
11516 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
11518 if (&other != this)
11520 m_object = other.m_object;
11527 @brief converting constructor
11528 @param[in] other non-const iterator to copy from
11529 @note It is not checked whether @a other is initialized.
11531 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
11532 : m_object(other.m_object), m_it(other.m_it)
11536 @brief converting assignment
11537 @param[in] other non-const iterator to copy from
11538 @return const/non-const iterator
11539 @note It is not checked whether @a other is initialized.
11541 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
11543 m_object = other.m_object;
11548 JSON_PRIVATE_UNLESS_TESTED:
11550 @brief set the iterator to the first value
11551 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11553 void set_begin() noexcept
11555 JSON_ASSERT(m_object != nullptr);
11557 switch (m_object->m_type)
11559 case value_t::object:
11561 m_it.object_iterator = m_object->m_value.object->begin();
11565 case value_t::array:
11567 m_it.array_iterator = m_object->m_value.array->begin();
11571 case value_t::null:
11573 // set to end so begin()==end() is true: null is empty
11574 m_it.primitive_iterator.set_end();
11578 case value_t::string:
11579 case value_t::boolean:
11580 case value_t::number_integer:
11581 case value_t::number_unsigned:
11582 case value_t::number_float:
11583 case value_t::binary:
11584 case value_t::discarded:
11587 m_it.primitive_iterator.set_begin();
11594 @brief set the iterator past the last value
11595 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11597 void set_end() noexcept
11599 JSON_ASSERT(m_object != nullptr);
11601 switch (m_object->m_type)
11603 case value_t::object:
11605 m_it.object_iterator = m_object->m_value.object->end();
11609 case value_t::array:
11611 m_it.array_iterator = m_object->m_value.array->end();
11615 case value_t::null:
11616 case value_t::string:
11617 case value_t::boolean:
11618 case value_t::number_integer:
11619 case value_t::number_unsigned:
11620 case value_t::number_float:
11621 case value_t::binary:
11622 case value_t::discarded:
11625 m_it.primitive_iterator.set_end();
11633 @brief return a reference to the value pointed to by the iterator
11634 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11636 reference operator*() const
11638 JSON_ASSERT(m_object != nullptr);
11640 switch (m_object->m_type)
11642 case value_t::object:
11644 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
11645 return m_it.object_iterator->second;
11648 case value_t::array:
11650 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
11651 return *m_it.array_iterator;
11654 case value_t::null:
11655 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11657 case value_t::string:
11658 case value_t::boolean:
11659 case value_t::number_integer:
11660 case value_t::number_unsigned:
11661 case value_t::number_float:
11662 case value_t::binary:
11663 case value_t::discarded:
11666 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
11671 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11677 @brief dereference the iterator
11678 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11680 pointer operator->() const
11682 JSON_ASSERT(m_object != nullptr);
11684 switch (m_object->m_type)
11686 case value_t::object:
11688 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
11689 return &(m_it.object_iterator->second);
11692 case value_t::array:
11694 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
11695 return &*m_it.array_iterator;
11698 case value_t::null:
11699 case value_t::string:
11700 case value_t::boolean:
11701 case value_t::number_integer:
11702 case value_t::number_unsigned:
11703 case value_t::number_float:
11704 case value_t::binary:
11705 case value_t::discarded:
11708 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
11713 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11719 @brief post-increment (it++)
11720 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11722 iter_impl const operator++(int) // NOLINT(readability-const-return-type)
11724 auto result = *this;
11730 @brief pre-increment (++it)
11731 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11733 iter_impl& operator++()
11735 JSON_ASSERT(m_object != nullptr);
11737 switch (m_object->m_type)
11739 case value_t::object:
11741 std::advance(m_it.object_iterator, 1);
11745 case value_t::array:
11747 std::advance(m_it.array_iterator, 1);
11751 case value_t::null:
11752 case value_t::string:
11753 case value_t::boolean:
11754 case value_t::number_integer:
11755 case value_t::number_unsigned:
11756 case value_t::number_float:
11757 case value_t::binary:
11758 case value_t::discarded:
11761 ++m_it.primitive_iterator;
11770 @brief post-decrement (it--)
11771 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11773 iter_impl const operator--(int) // NOLINT(readability-const-return-type)
11775 auto result = *this;
11781 @brief pre-decrement (--it)
11782 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11784 iter_impl& operator--()
11786 JSON_ASSERT(m_object != nullptr);
11788 switch (m_object->m_type)
11790 case value_t::object:
11792 std::advance(m_it.object_iterator, -1);
11796 case value_t::array:
11798 std::advance(m_it.array_iterator, -1);
11802 case value_t::null:
11803 case value_t::string:
11804 case value_t::boolean:
11805 case value_t::number_integer:
11806 case value_t::number_unsigned:
11807 case value_t::number_float:
11808 case value_t::binary:
11809 case value_t::discarded:
11812 --m_it.primitive_iterator;
11821 @brief comparison: equal
11822 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11824 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
11825 bool operator==(const IterImpl& other) const
11827 // if objects are not the same, the comparison is undefined
11828 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
11830 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
11833 JSON_ASSERT(m_object != nullptr);
11835 switch (m_object->m_type)
11837 case value_t::object:
11838 return (m_it.object_iterator == other.m_it.object_iterator);
11840 case value_t::array:
11841 return (m_it.array_iterator == other.m_it.array_iterator);
11843 case value_t::null:
11844 case value_t::string:
11845 case value_t::boolean:
11846 case value_t::number_integer:
11847 case value_t::number_unsigned:
11848 case value_t::number_float:
11849 case value_t::binary:
11850 case value_t::discarded:
11852 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
11857 @brief comparison: not equal
11858 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11860 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
11861 bool operator!=(const IterImpl& other) const
11863 return !operator==(other);
11867 @brief comparison: smaller
11868 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11870 bool operator<(const iter_impl& other) const
11872 // if objects are not the same, the comparison is undefined
11873 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
11875 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
11878 JSON_ASSERT(m_object != nullptr);
11880 switch (m_object->m_type)
11882 case value_t::object:
11883 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object));
11885 case value_t::array:
11886 return (m_it.array_iterator < other.m_it.array_iterator);
11888 case value_t::null:
11889 case value_t::string:
11890 case value_t::boolean:
11891 case value_t::number_integer:
11892 case value_t::number_unsigned:
11893 case value_t::number_float:
11894 case value_t::binary:
11895 case value_t::discarded:
11897 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
11902 @brief comparison: less than or equal
11903 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11905 bool operator<=(const iter_impl& other) const
11907 return !other.operator < (*this);
11911 @brief comparison: greater than
11912 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11914 bool operator>(const iter_impl& other) const
11916 return !operator<=(other);
11920 @brief comparison: greater than or equal
11921 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11923 bool operator>=(const iter_impl& other) const
11925 return !operator<(other);
11929 @brief add to iterator
11930 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11932 iter_impl& operator+=(difference_type i)
11934 JSON_ASSERT(m_object != nullptr);
11936 switch (m_object->m_type)
11938 case value_t::object:
11939 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
11941 case value_t::array:
11943 std::advance(m_it.array_iterator, i);
11947 case value_t::null:
11948 case value_t::string:
11949 case value_t::boolean:
11950 case value_t::number_integer:
11951 case value_t::number_unsigned:
11952 case value_t::number_float:
11953 case value_t::binary:
11954 case value_t::discarded:
11957 m_it.primitive_iterator += i;
11966 @brief subtract from iterator
11967 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11969 iter_impl& operator-=(difference_type i)
11971 return operator+=(-i);
11975 @brief add to iterator
11976 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11978 iter_impl operator+(difference_type i) const
11980 auto result = *this;
11986 @brief addition of distance and iterator
11987 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11989 friend iter_impl operator+(difference_type i, const iter_impl& it)
11997 @brief subtract from iterator
11998 @pre The iterator is initialized; i.e. `m_object != nullptr`.
12000 iter_impl operator-(difference_type i) const
12002 auto result = *this;
12008 @brief return difference
12009 @pre The iterator is initialized; i.e. `m_object != nullptr`.
12011 difference_type operator-(const iter_impl& other) const
12013 JSON_ASSERT(m_object != nullptr);
12015 switch (m_object->m_type)
12017 case value_t::object:
12018 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
12020 case value_t::array:
12021 return m_it.array_iterator - other.m_it.array_iterator;
12023 case value_t::null:
12024 case value_t::string:
12025 case value_t::boolean:
12026 case value_t::number_integer:
12027 case value_t::number_unsigned:
12028 case value_t::number_float:
12029 case value_t::binary:
12030 case value_t::discarded:
12032 return m_it.primitive_iterator - other.m_it.primitive_iterator;
12037 @brief access to successor
12038 @pre The iterator is initialized; i.e. `m_object != nullptr`.
12040 reference operator[](difference_type n) const
12042 JSON_ASSERT(m_object != nullptr);
12044 switch (m_object->m_type)
12046 case value_t::object:
12047 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object));
12049 case value_t::array:
12050 return *std::next(m_it.array_iterator, n);
12052 case value_t::null:
12053 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
12055 case value_t::string:
12056 case value_t::boolean:
12057 case value_t::number_integer:
12058 case value_t::number_unsigned:
12059 case value_t::number_float:
12060 case value_t::binary:
12061 case value_t::discarded:
12064 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
12069 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
12075 @brief return the key of an object iterator
12076 @pre The iterator is initialized; i.e. `m_object != nullptr`.
12078 const typename object_t::key_type& key() const
12080 JSON_ASSERT(m_object != nullptr);
12082 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
12084 return m_it.object_iterator->first;
12087 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object));
12091 @brief return the value of an iterator
12092 @pre The iterator is initialized; i.e. `m_object != nullptr`.
12094 reference value() const
12096 return operator*();
12099 JSON_PRIVATE_UNLESS_TESTED:
12100 /// associated JSON instance
12101 pointer m_object = nullptr;
12102 /// the actual iterator of the associated instance
12103 internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
12105 } // namespace detail
12106 } // namespace nlohmann
12108 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
12110 // #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
12113 #include <cstddef> // ptrdiff_t
12114 #include <iterator> // reverse_iterator
12115 #include <utility> // declval
12121 //////////////////////
12122 // reverse_iterator //
12123 //////////////////////
12126 @brief a template for a reverse iterator class
12128 @tparam Base the base iterator type to reverse. Valid types are @ref
12129 iterator (to create @ref reverse_iterator) and @ref const_iterator (to
12130 create @ref const_reverse_iterator).
12132 @requirement The class satisfies the following concept requirements:
12134 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
12135 The iterator that can be moved can be moved in both directions (i.e.
12136 incremented and decremented).
12137 - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
12138 It is possible to write to the pointed-to element (only if @a Base is
12141 @since version 1.0.0
12143 template<typename Base>
12144 class json_reverse_iterator : public std::reverse_iterator<Base>
12147 using difference_type = std::ptrdiff_t;
12148 /// shortcut to the reverse iterator adapter
12149 using base_iterator = std::reverse_iterator<Base>;
12150 /// the reference type for the pointed-to element
12151 using reference = typename Base::reference;
12153 /// create reverse iterator from iterator
12154 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
12155 : base_iterator(it) {}
12157 /// create reverse iterator from base class
12158 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
12160 /// post-increment (it++)
12161 json_reverse_iterator const operator++(int) // NOLINT(readability-const-return-type)
12163 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
12166 /// pre-increment (++it)
12167 json_reverse_iterator& operator++()
12169 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
12172 /// post-decrement (it--)
12173 json_reverse_iterator const operator--(int) // NOLINT(readability-const-return-type)
12175 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
12178 /// pre-decrement (--it)
12179 json_reverse_iterator& operator--()
12181 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
12184 /// add to iterator
12185 json_reverse_iterator& operator+=(difference_type i)
12187 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
12190 /// add to iterator
12191 json_reverse_iterator operator+(difference_type i) const
12193 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
12196 /// subtract from iterator
12197 json_reverse_iterator operator-(difference_type i) const
12199 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
12202 /// return difference
12203 difference_type operator-(const json_reverse_iterator& other) const
12205 return base_iterator(*this) - base_iterator(other);
12208 /// access to successor
12209 reference operator[](difference_type n) const
12211 return *(this->operator+(n));
12214 /// return the key of an object iterator
12215 auto key() const -> decltype(std::declval<Base>().key())
12217 auto it = --this->base();
12221 /// return the value of an iterator
12222 reference value() const
12224 auto it = --this->base();
12225 return it.operator * ();
12228 } // namespace detail
12229 } // namespace nlohmann
12231 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12233 // #include <nlohmann/detail/json_pointer.hpp>
12236 #include <algorithm> // all_of
12237 #include <cctype> // isdigit
12238 #include <limits> // max
12239 #include <numeric> // accumulate
12240 #include <string> // string
12241 #include <utility> // move
12242 #include <vector> // vector
12244 // #include <nlohmann/detail/exceptions.hpp>
12246 // #include <nlohmann/detail/macro_scope.hpp>
12248 // #include <nlohmann/detail/string_escape.hpp>
12250 // #include <nlohmann/detail/value_t.hpp>
12256 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
12257 /// @sa https://json.nlohmann.me/api/json_pointer/
12258 template<typename BasicJsonType>
12261 // allow basic_json to access private members
12262 NLOHMANN_BASIC_JSON_TPL_DECLARATION
12263 friend class basic_json;
12266 /// @brief create JSON pointer
12267 /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
12268 explicit json_pointer(const std::string& s = "")
12269 : reference_tokens(split(s))
12272 /// @brief return a string representation of the JSON pointer
12273 /// @sa https://json.nlohmann.me/api/json_pointer/to_string/
12274 std::string to_string() const
12276 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
12278 [](const std::string & a, const std::string & b)
12280 return a + "/" + detail::escape(b);
12284 /// @brief return a string representation of the JSON pointer
12285 /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
12286 operator std::string() const
12288 return to_string();
12291 /// @brief append another JSON pointer at the end of this JSON pointer
12292 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
12293 json_pointer& operator/=(const json_pointer& ptr)
12295 reference_tokens.insert(reference_tokens.end(),
12296 ptr.reference_tokens.begin(),
12297 ptr.reference_tokens.end());
12301 /// @brief append an unescaped reference token at the end of this JSON pointer
12302 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
12303 json_pointer& operator/=(std::string token)
12305 push_back(std::move(token));
12309 /// @brief append an array index at the end of this JSON pointer
12310 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
12311 json_pointer& operator/=(std::size_t array_idx)
12313 return *this /= std::to_string(array_idx);
12316 /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
12317 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
12318 friend json_pointer operator/(const json_pointer& lhs,
12319 const json_pointer& rhs)
12321 return json_pointer(lhs) /= rhs;
12324 /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
12325 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
12326 friend json_pointer operator/(const json_pointer& lhs, std::string token) // NOLINT(performance-unnecessary-value-param)
12328 return json_pointer(lhs) /= std::move(token);
12331 /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
12332 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
12333 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
12335 return json_pointer(lhs) /= array_idx;
12338 /// @brief returns the parent of this JSON pointer
12339 /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
12340 json_pointer parent_pointer() const
12347 json_pointer res = *this;
12352 /// @brief remove last reference token
12353 /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
12356 if (JSON_HEDLEY_UNLIKELY(empty()))
12358 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
12361 reference_tokens.pop_back();
12364 /// @brief return last reference token
12365 /// @sa https://json.nlohmann.me/api/json_pointer/back/
12366 const std::string& back() const
12368 if (JSON_HEDLEY_UNLIKELY(empty()))
12370 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
12373 return reference_tokens.back();
12376 /// @brief append an unescaped token at the end of the reference pointer
12377 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
12378 void push_back(const std::string& token)
12380 reference_tokens.push_back(token);
12383 /// @brief append an unescaped token at the end of the reference pointer
12384 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
12385 void push_back(std::string&& token)
12387 reference_tokens.push_back(std::move(token));
12390 /// @brief return whether pointer points to the root document
12391 /// @sa https://json.nlohmann.me/api/json_pointer/empty/
12392 bool empty() const noexcept
12394 return reference_tokens.empty();
12399 @param[in] s reference token to be converted into an array index
12401 @return integer representation of @a s
12403 @throw parse_error.106 if an array index begins with '0'
12404 @throw parse_error.109 if an array index begins not with a digit
12405 @throw out_of_range.404 if string @a s could not be converted to an integer
12406 @throw out_of_range.410 if an array index exceeds size_type
12408 static typename BasicJsonType::size_type array_index(const std::string& s)
12410 using size_type = typename BasicJsonType::size_type;
12412 // error condition (cf. RFC 6901, Sect. 4)
12413 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
12415 JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", BasicJsonType()));
12418 // error condition (cf. RFC 6901, Sect. 4)
12419 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
12421 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType()));
12424 std::size_t processed_chars = 0;
12425 unsigned long long res = 0; // NOLINT(runtime/int)
12428 res = std::stoull(s, &processed_chars);
12430 JSON_CATCH(std::out_of_range&)
12432 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
12435 // check if the string was completely read
12436 if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
12438 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
12441 // only triggered on special platforms (like 32bit), see also
12442 // https://github.com/nlohmann/json/pull/2203
12443 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
12445 JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", BasicJsonType())); // LCOV_EXCL_LINE
12448 return static_cast<size_type>(res);
12451 JSON_PRIVATE_UNLESS_TESTED:
12452 json_pointer top() const
12454 if (JSON_HEDLEY_UNLIKELY(empty()))
12456 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
12459 json_pointer result = *this;
12460 result.reference_tokens = {reference_tokens[0]};
12466 @brief create and return a reference to the pointed to value
12468 @complexity Linear in the number of reference tokens.
12470 @throw parse_error.109 if array index is not a number
12471 @throw type_error.313 if value cannot be unflattened
12473 BasicJsonType& get_and_create(BasicJsonType& j) const
12477 // in case no reference tokens exist, return a reference to the JSON value
12478 // j which will be overwritten by a primitive value
12479 for (const auto& reference_token : reference_tokens)
12481 switch (result->type())
12483 case detail::value_t::null:
12485 if (reference_token == "0")
12487 // start a new array if reference token is 0
12488 result = &result->operator[](0);
12492 // start a new object otherwise
12493 result = &result->operator[](reference_token);
12498 case detail::value_t::object:
12500 // create an entry in the object
12501 result = &result->operator[](reference_token);
12505 case detail::value_t::array:
12507 // create an entry in the array
12508 result = &result->operator[](array_index(reference_token));
12513 The following code is only reached if there exists a reference
12514 token _and_ the current value is primitive. In this case, we have
12515 an error situation, because primitive values may only occur as
12516 single value; that is, with an empty list of reference tokens.
12518 case detail::value_t::string:
12519 case detail::value_t::boolean:
12520 case detail::value_t::number_integer:
12521 case detail::value_t::number_unsigned:
12522 case detail::value_t::number_float:
12523 case detail::value_t::binary:
12524 case detail::value_t::discarded:
12526 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j));
12534 @brief return a reference to the pointed to value
12536 @note This version does not throw if a value is not present, but tries to
12537 create nested values instead. For instance, calling this function
12538 with pointer `"/this/that"` on a null value is equivalent to calling
12539 `operator[]("this").operator[]("that")` on that value, effectively
12540 changing the null value to an object.
12542 @param[in] ptr a JSON value
12544 @return reference to the JSON value pointed to by the JSON pointer
12546 @complexity Linear in the length of the JSON pointer.
12548 @throw parse_error.106 if an array index begins with '0'
12549 @throw parse_error.109 if an array index was not a number
12550 @throw out_of_range.404 if the JSON pointer can not be resolved
12552 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
12554 for (const auto& reference_token : reference_tokens)
12556 // convert null values to arrays or objects before continuing
12557 if (ptr->is_null())
12559 // check if reference token is a number
12561 std::all_of(reference_token.begin(), reference_token.end(),
12562 [](const unsigned char x)
12564 return std::isdigit(x);
12567 // change value to array for numbers or "-" or to object otherwise
12568 *ptr = (nums || reference_token == "-")
12569 ? detail::value_t::array
12570 : detail::value_t::object;
12573 switch (ptr->type())
12575 case detail::value_t::object:
12577 // use unchecked object access
12578 ptr = &ptr->operator[](reference_token);
12582 case detail::value_t::array:
12584 if (reference_token == "-")
12586 // explicitly treat "-" as index beyond the end
12587 ptr = &ptr->operator[](ptr->m_value.array->size());
12591 // convert array index to number; unchecked access
12592 ptr = &ptr->operator[](array_index(reference_token));
12597 case detail::value_t::null:
12598 case detail::value_t::string:
12599 case detail::value_t::boolean:
12600 case detail::value_t::number_integer:
12601 case detail::value_t::number_unsigned:
12602 case detail::value_t::number_float:
12603 case detail::value_t::binary:
12604 case detail::value_t::discarded:
12606 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
12614 @throw parse_error.106 if an array index begins with '0'
12615 @throw parse_error.109 if an array index was not a number
12616 @throw out_of_range.402 if the array index '-' is used
12617 @throw out_of_range.404 if the JSON pointer can not be resolved
12619 BasicJsonType& get_checked(BasicJsonType* ptr) const
12621 for (const auto& reference_token : reference_tokens)
12623 switch (ptr->type())
12625 case detail::value_t::object:
12627 // note: at performs range check
12628 ptr = &ptr->at(reference_token);
12632 case detail::value_t::array:
12634 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12636 // "-" always fails the range check
12637 JSON_THROW(detail::out_of_range::create(402,
12638 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12639 ") is out of range", *ptr));
12642 // note: at performs range check
12643 ptr = &ptr->at(array_index(reference_token));
12647 case detail::value_t::null:
12648 case detail::value_t::string:
12649 case detail::value_t::boolean:
12650 case detail::value_t::number_integer:
12651 case detail::value_t::number_unsigned:
12652 case detail::value_t::number_float:
12653 case detail::value_t::binary:
12654 case detail::value_t::discarded:
12656 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
12664 @brief return a const reference to the pointed to value
12666 @param[in] ptr a JSON value
12668 @return const reference to the JSON value pointed to by the JSON
12671 @throw parse_error.106 if an array index begins with '0'
12672 @throw parse_error.109 if an array index was not a number
12673 @throw out_of_range.402 if the array index '-' is used
12674 @throw out_of_range.404 if the JSON pointer can not be resolved
12676 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
12678 for (const auto& reference_token : reference_tokens)
12680 switch (ptr->type())
12682 case detail::value_t::object:
12684 // use unchecked object access
12685 ptr = &ptr->operator[](reference_token);
12689 case detail::value_t::array:
12691 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12693 // "-" cannot be used for const access
12694 JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range", *ptr));
12697 // use unchecked array access
12698 ptr = &ptr->operator[](array_index(reference_token));
12702 case detail::value_t::null:
12703 case detail::value_t::string:
12704 case detail::value_t::boolean:
12705 case detail::value_t::number_integer:
12706 case detail::value_t::number_unsigned:
12707 case detail::value_t::number_float:
12708 case detail::value_t::binary:
12709 case detail::value_t::discarded:
12711 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
12719 @throw parse_error.106 if an array index begins with '0'
12720 @throw parse_error.109 if an array index was not a number
12721 @throw out_of_range.402 if the array index '-' is used
12722 @throw out_of_range.404 if the JSON pointer can not be resolved
12724 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
12726 for (const auto& reference_token : reference_tokens)
12728 switch (ptr->type())
12730 case detail::value_t::object:
12732 // note: at performs range check
12733 ptr = &ptr->at(reference_token);
12737 case detail::value_t::array:
12739 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12741 // "-" always fails the range check
12742 JSON_THROW(detail::out_of_range::create(402,
12743 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12744 ") is out of range", *ptr));
12747 // note: at performs range check
12748 ptr = &ptr->at(array_index(reference_token));
12752 case detail::value_t::null:
12753 case detail::value_t::string:
12754 case detail::value_t::boolean:
12755 case detail::value_t::number_integer:
12756 case detail::value_t::number_unsigned:
12757 case detail::value_t::number_float:
12758 case detail::value_t::binary:
12759 case detail::value_t::discarded:
12761 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
12769 @throw parse_error.106 if an array index begins with '0'
12770 @throw parse_error.109 if an array index was not a number
12772 bool contains(const BasicJsonType* ptr) const
12774 for (const auto& reference_token : reference_tokens)
12776 switch (ptr->type())
12778 case detail::value_t::object:
12780 if (!ptr->contains(reference_token))
12782 // we did not find the key in the object
12786 ptr = &ptr->operator[](reference_token);
12790 case detail::value_t::array:
12792 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12794 // "-" always fails the range check
12797 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
12802 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
12804 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
12806 // first char should be between '1' and '9'
12809 for (std::size_t i = 1; i < reference_token.size(); i++)
12811 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
12813 // other char should be between '0' and '9'
12819 const auto idx = array_index(reference_token);
12820 if (idx >= ptr->size())
12822 // index out of range
12826 ptr = &ptr->operator[](idx);
12830 case detail::value_t::null:
12831 case detail::value_t::string:
12832 case detail::value_t::boolean:
12833 case detail::value_t::number_integer:
12834 case detail::value_t::number_unsigned:
12835 case detail::value_t::number_float:
12836 case detail::value_t::binary:
12837 case detail::value_t::discarded:
12840 // we do not expect primitive values if there is still a
12841 // reference token to process
12847 // no reference token left means we found a primitive value
12852 @brief split the string input to reference tokens
12854 @note This function is only called by the json_pointer constructor.
12855 All exceptions below are documented there.
12857 @throw parse_error.107 if the pointer is not empty or begins with '/'
12858 @throw parse_error.108 if character '~' is not followed by '0' or '1'
12860 static std::vector<std::string> split(const std::string& reference_string)
12862 std::vector<std::string> result;
12864 // special case: empty reference string -> no reference tokens
12865 if (reference_string.empty())
12870 // check if nonempty reference string begins with slash
12871 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
12873 JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", BasicJsonType()));
12876 // extract the reference tokens:
12877 // - slash: position of the last read slash (or end of string)
12878 // - start: position after the previous slash
12880 // search for the first slash after the first character
12881 std::size_t slash = reference_string.find_first_of('/', 1),
12882 // set the beginning of the first reference token
12884 // we can stop if start == 0 (if slash == std::string::npos)
12886 // set the beginning of the next reference token
12887 // (will eventually be 0 if slash == std::string::npos)
12888 start = (slash == std::string::npos) ? 0 : slash + 1,
12890 slash = reference_string.find_first_of('/', start))
12892 // use the text between the beginning of the reference token
12893 // (start) and the last slash (slash).
12894 auto reference_token = reference_string.substr(start, slash - start);
12896 // check reference tokens are properly escaped
12897 for (std::size_t pos = reference_token.find_first_of('~');
12898 pos != std::string::npos;
12899 pos = reference_token.find_first_of('~', pos + 1))
12901 JSON_ASSERT(reference_token[pos] == '~');
12903 // ~ must be followed by 0 or 1
12904 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
12905 (reference_token[pos + 1] != '0' &&
12906 reference_token[pos + 1] != '1')))
12908 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType()));
12912 // finally, store the reference token
12913 detail::unescape(reference_token);
12914 result.push_back(reference_token);
12922 @param[in] reference_string the reference string to the current value
12923 @param[in] value the value to consider
12924 @param[in,out] result the result object to insert values to
12926 @note Empty objects or arrays are flattened to `null`.
12928 static void flatten(const std::string& reference_string,
12929 const BasicJsonType& value,
12930 BasicJsonType& result)
12932 switch (value.type())
12934 case detail::value_t::array:
12936 if (value.m_value.array->empty())
12938 // flatten empty array as null
12939 result[reference_string] = nullptr;
12943 // iterate array and use index as reference string
12944 for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
12946 flatten(reference_string + "/" + std::to_string(i),
12947 value.m_value.array->operator[](i), result);
12953 case detail::value_t::object:
12955 if (value.m_value.object->empty())
12957 // flatten empty object as null
12958 result[reference_string] = nullptr;
12962 // iterate object and use keys as reference string
12963 for (const auto& element : *value.m_value.object)
12965 flatten(reference_string + "/" + detail::escape(element.first), element.second, result);
12971 case detail::value_t::null:
12972 case detail::value_t::string:
12973 case detail::value_t::boolean:
12974 case detail::value_t::number_integer:
12975 case detail::value_t::number_unsigned:
12976 case detail::value_t::number_float:
12977 case detail::value_t::binary:
12978 case detail::value_t::discarded:
12981 // add primitive value with its reference string
12982 result[reference_string] = value;
12989 @param[in] value flattened JSON
12991 @return unflattened JSON
12993 @throw parse_error.109 if array index is not a number
12994 @throw type_error.314 if value is not an object
12995 @throw type_error.315 if object values are not primitive
12996 @throw type_error.313 if value cannot be unflattened
12998 static BasicJsonType
12999 unflatten(const BasicJsonType& value)
13001 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
13003 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value));
13006 BasicJsonType result;
13008 // iterate the JSON object values
13009 for (const auto& element : *value.m_value.object)
13011 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
13013 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second));
13016 // assign value to reference pointed to by JSON pointer; Note that if
13017 // the JSON pointer is "" (i.e., points to the whole value), function
13018 // get_and_create returns a reference to result itself. An assignment
13019 // will then create a primitive value.
13020 json_pointer(element.first).get_and_create(result) = element.second;
13027 @brief compares two JSON pointers for equality
13029 @param[in] lhs JSON pointer to compare
13030 @param[in] rhs JSON pointer to compare
13031 @return whether @a lhs is equal to @a rhs
13033 @complexity Linear in the length of the JSON pointer
13035 @exceptionsafety No-throw guarantee: this function never throws exceptions.
13037 friend bool operator==(json_pointer const& lhs,
13038 json_pointer const& rhs) noexcept
13040 return lhs.reference_tokens == rhs.reference_tokens;
13044 @brief compares two JSON pointers for inequality
13046 @param[in] lhs JSON pointer to compare
13047 @param[in] rhs JSON pointer to compare
13048 @return whether @a lhs is not equal @a rhs
13050 @complexity Linear in the length of the JSON pointer
13052 @exceptionsafety No-throw guarantee: this function never throws exceptions.
13054 friend bool operator!=(json_pointer const& lhs,
13055 json_pointer const& rhs) noexcept
13057 return !(lhs == rhs);
13060 /// the reference tokens
13061 std::vector<std::string> reference_tokens;
13063 } // namespace nlohmann
13065 // #include <nlohmann/detail/json_ref.hpp>
13068 #include <initializer_list>
13071 // #include <nlohmann/detail/meta/type_traits.hpp>
13078 template<typename BasicJsonType>
13082 using value_type = BasicJsonType;
13084 json_ref(value_type&& value)
13085 : owned_value(std::move(value))
13088 json_ref(const value_type& value)
13089 : value_ref(&value)
13092 json_ref(std::initializer_list<json_ref> init)
13093 : owned_value(init)
13098 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
13099 json_ref(Args && ... args)
13100 : owned_value(std::forward<Args>(args)...)
13103 // class should be movable only
13104 json_ref(json_ref&&) noexcept = default;
13105 json_ref(const json_ref&) = delete;
13106 json_ref& operator=(const json_ref&) = delete;
13107 json_ref& operator=(json_ref&&) = delete;
13108 ~json_ref() = default;
13110 value_type moved_or_copied() const
13112 if (value_ref == nullptr)
13114 return std::move(owned_value);
13119 value_type const& operator*() const
13121 return value_ref ? *value_ref : owned_value;
13124 value_type const* operator->() const
13130 mutable value_type owned_value = nullptr;
13131 value_type const* value_ref = nullptr;
13133 } // namespace detail
13134 } // namespace nlohmann
13136 // #include <nlohmann/detail/macro_scope.hpp>
13138 // #include <nlohmann/detail/string_escape.hpp>
13140 // #include <nlohmann/detail/meta/cpp_future.hpp>
13142 // #include <nlohmann/detail/meta/type_traits.hpp>
13144 // #include <nlohmann/detail/output/binary_writer.hpp>
13147 #include <algorithm> // reverse
13148 #include <array> // array
13149 #include <cmath> // isnan, isinf
13150 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
13151 #include <cstring> // memcpy
13152 #include <limits> // numeric_limits
13153 #include <string> // string
13154 #include <utility> // move
13156 // #include <nlohmann/detail/input/binary_reader.hpp>
13158 // #include <nlohmann/detail/macro_scope.hpp>
13160 // #include <nlohmann/detail/output/output_adapters.hpp>
13163 #include <algorithm> // copy
13164 #include <cstddef> // size_t
13165 #include <iterator> // back_inserter
13166 #include <memory> // shared_ptr, make_shared
13167 #include <string> // basic_string
13168 #include <vector> // vector
13171 #include <ios> // streamsize
13172 #include <ostream> // basic_ostream
13173 #endif // JSON_NO_IO
13175 // #include <nlohmann/detail/macro_scope.hpp>
13182 /// abstract output adapter interface
13183 template<typename CharType> struct output_adapter_protocol
13185 virtual void write_character(CharType c) = 0;
13186 virtual void write_characters(const CharType* s, std::size_t length) = 0;
13187 virtual ~output_adapter_protocol() = default;
13189 output_adapter_protocol() = default;
13190 output_adapter_protocol(const output_adapter_protocol&) = default;
13191 output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
13192 output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
13193 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
13196 /// a type to simplify interfaces
13197 template<typename CharType>
13198 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
13200 /// output adapter for byte vectors
13201 template<typename CharType, typename AllocatorType = std::allocator<CharType>>
13202 class output_vector_adapter : public output_adapter_protocol<CharType>
13205 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
13209 void write_character(CharType c) override
13214 JSON_HEDLEY_NON_NULL(2)
13215 void write_characters(const CharType* s, std::size_t length) override
13217 std::copy(s, s + length, std::back_inserter(v));
13221 std::vector<CharType, AllocatorType>& v;
13225 /// output adapter for output streams
13226 template<typename CharType>
13227 class output_stream_adapter : public output_adapter_protocol<CharType>
13230 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
13234 void write_character(CharType c) override
13239 JSON_HEDLEY_NON_NULL(2)
13240 void write_characters(const CharType* s, std::size_t length) override
13242 stream.write(s, static_cast<std::streamsize>(length));
13246 std::basic_ostream<CharType>& stream;
13248 #endif // JSON_NO_IO
13250 /// output adapter for basic_string
13251 template<typename CharType, typename StringType = std::basic_string<CharType>>
13252 class output_string_adapter : public output_adapter_protocol<CharType>
13255 explicit output_string_adapter(StringType& s) noexcept
13259 void write_character(CharType c) override
13264 JSON_HEDLEY_NON_NULL(2)
13265 void write_characters(const CharType* s, std::size_t length) override
13267 str.append(s, length);
13274 template<typename CharType, typename StringType = std::basic_string<CharType>>
13275 class output_adapter
13278 template<typename AllocatorType = std::allocator<CharType>>
13279 output_adapter(std::vector<CharType, AllocatorType>& vec)
13280 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
13283 output_adapter(std::basic_ostream<CharType>& s)
13284 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
13285 #endif // JSON_NO_IO
13287 output_adapter(StringType& s)
13288 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
13290 operator output_adapter_t<CharType>()
13296 output_adapter_t<CharType> oa = nullptr;
13298 } // namespace detail
13299 } // namespace nlohmann
13306 ///////////////////
13307 // binary writer //
13308 ///////////////////
13311 @brief serialization to CBOR and MessagePack values
13313 template<typename BasicJsonType, typename CharType>
13314 class binary_writer
13316 using string_t = typename BasicJsonType::string_t;
13317 using binary_t = typename BasicJsonType::binary_t;
13318 using number_float_t = typename BasicJsonType::number_float_t;
13322 @brief create a binary writer
13324 @param[in] adapter output adapter to write to
13326 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
13332 @param[in] j JSON value to serialize
13333 @pre j.type() == value_t::object
13335 void write_bson(const BasicJsonType& j)
13339 case value_t::object:
13341 write_bson_object(*j.m_value.object);
13345 case value_t::null:
13346 case value_t::array:
13347 case value_t::string:
13348 case value_t::boolean:
13349 case value_t::number_integer:
13350 case value_t::number_unsigned:
13351 case value_t::number_float:
13352 case value_t::binary:
13353 case value_t::discarded:
13356 JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j));
13362 @param[in] j JSON value to serialize
13364 void write_cbor(const BasicJsonType& j)
13368 case value_t::null:
13370 oa->write_character(to_char_type(0xF6));
13374 case value_t::boolean:
13376 oa->write_character(j.m_value.boolean
13377 ? to_char_type(0xF5)
13378 : to_char_type(0xF4));
13382 case value_t::number_integer:
13384 if (j.m_value.number_integer >= 0)
13386 // CBOR does not differentiate between positive signed
13387 // integers and unsigned integers. Therefore, we used the
13388 // code from the value_t::number_unsigned case here.
13389 if (j.m_value.number_integer <= 0x17)
13391 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13393 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
13395 oa->write_character(to_char_type(0x18));
13396 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13398 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
13400 oa->write_character(to_char_type(0x19));
13401 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13403 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
13405 oa->write_character(to_char_type(0x1A));
13406 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13410 oa->write_character(to_char_type(0x1B));
13411 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13416 // The conversions below encode the sign in the first
13417 // byte, and the value is converted to a positive number.
13418 const auto positive_number = -1 - j.m_value.number_integer;
13419 if (j.m_value.number_integer >= -24)
13421 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
13423 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
13425 oa->write_character(to_char_type(0x38));
13426 write_number(static_cast<std::uint8_t>(positive_number));
13428 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
13430 oa->write_character(to_char_type(0x39));
13431 write_number(static_cast<std::uint16_t>(positive_number));
13433 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
13435 oa->write_character(to_char_type(0x3A));
13436 write_number(static_cast<std::uint32_t>(positive_number));
13440 oa->write_character(to_char_type(0x3B));
13441 write_number(static_cast<std::uint64_t>(positive_number));
13447 case value_t::number_unsigned:
13449 if (j.m_value.number_unsigned <= 0x17)
13451 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
13453 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
13455 oa->write_character(to_char_type(0x18));
13456 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
13458 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
13460 oa->write_character(to_char_type(0x19));
13461 write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
13463 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
13465 oa->write_character(to_char_type(0x1A));
13466 write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
13470 oa->write_character(to_char_type(0x1B));
13471 write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
13476 case value_t::number_float:
13478 if (std::isnan(j.m_value.number_float))
13480 // NaN is 0xf97e00 in CBOR
13481 oa->write_character(to_char_type(0xF9));
13482 oa->write_character(to_char_type(0x7E));
13483 oa->write_character(to_char_type(0x00));
13485 else if (std::isinf(j.m_value.number_float))
13487 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
13488 oa->write_character(to_char_type(0xf9));
13489 oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
13490 oa->write_character(to_char_type(0x00));
13494 write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
13499 case value_t::string:
13501 // step 1: write control byte and the string length
13502 const auto N = j.m_value.string->size();
13505 write_number(static_cast<std::uint8_t>(0x60 + N));
13507 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13509 oa->write_character(to_char_type(0x78));
13510 write_number(static_cast<std::uint8_t>(N));
13512 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13514 oa->write_character(to_char_type(0x79));
13515 write_number(static_cast<std::uint16_t>(N));
13517 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13519 oa->write_character(to_char_type(0x7A));
13520 write_number(static_cast<std::uint32_t>(N));
13523 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13525 oa->write_character(to_char_type(0x7B));
13526 write_number(static_cast<std::uint64_t>(N));
13530 // step 2: write the string
13531 oa->write_characters(
13532 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
13533 j.m_value.string->size());
13537 case value_t::array:
13539 // step 1: write control byte and the array size
13540 const auto N = j.m_value.array->size();
13543 write_number(static_cast<std::uint8_t>(0x80 + N));
13545 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13547 oa->write_character(to_char_type(0x98));
13548 write_number(static_cast<std::uint8_t>(N));
13550 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13552 oa->write_character(to_char_type(0x99));
13553 write_number(static_cast<std::uint16_t>(N));
13555 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13557 oa->write_character(to_char_type(0x9A));
13558 write_number(static_cast<std::uint32_t>(N));
13561 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13563 oa->write_character(to_char_type(0x9B));
13564 write_number(static_cast<std::uint64_t>(N));
13568 // step 2: write each element
13569 for (const auto& el : *j.m_value.array)
13576 case value_t::binary:
13578 if (j.m_value.binary->has_subtype())
13580 if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
13582 write_number(static_cast<std::uint8_t>(0xd8));
13583 write_number(static_cast<std::uint8_t>(j.m_value.binary->subtype()));
13585 else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
13587 write_number(static_cast<std::uint8_t>(0xd9));
13588 write_number(static_cast<std::uint16_t>(j.m_value.binary->subtype()));
13590 else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
13592 write_number(static_cast<std::uint8_t>(0xda));
13593 write_number(static_cast<std::uint32_t>(j.m_value.binary->subtype()));
13595 else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
13597 write_number(static_cast<std::uint8_t>(0xdb));
13598 write_number(static_cast<std::uint64_t>(j.m_value.binary->subtype()));
13602 // step 1: write control byte and the binary array size
13603 const auto N = j.m_value.binary->size();
13606 write_number(static_cast<std::uint8_t>(0x40 + N));
13608 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13610 oa->write_character(to_char_type(0x58));
13611 write_number(static_cast<std::uint8_t>(N));
13613 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13615 oa->write_character(to_char_type(0x59));
13616 write_number(static_cast<std::uint16_t>(N));
13618 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13620 oa->write_character(to_char_type(0x5A));
13621 write_number(static_cast<std::uint32_t>(N));
13624 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13626 oa->write_character(to_char_type(0x5B));
13627 write_number(static_cast<std::uint64_t>(N));
13631 // step 2: write each element
13632 oa->write_characters(
13633 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13639 case value_t::object:
13641 // step 1: write control byte and the object size
13642 const auto N = j.m_value.object->size();
13645 write_number(static_cast<std::uint8_t>(0xA0 + N));
13647 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13649 oa->write_character(to_char_type(0xB8));
13650 write_number(static_cast<std::uint8_t>(N));
13652 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13654 oa->write_character(to_char_type(0xB9));
13655 write_number(static_cast<std::uint16_t>(N));
13657 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13659 oa->write_character(to_char_type(0xBA));
13660 write_number(static_cast<std::uint32_t>(N));
13663 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13665 oa->write_character(to_char_type(0xBB));
13666 write_number(static_cast<std::uint64_t>(N));
13670 // step 2: write each element
13671 for (const auto& el : *j.m_value.object)
13673 write_cbor(el.first);
13674 write_cbor(el.second);
13679 case value_t::discarded:
13686 @param[in] j JSON value to serialize
13688 void write_msgpack(const BasicJsonType& j)
13692 case value_t::null: // nil
13694 oa->write_character(to_char_type(0xC0));
13698 case value_t::boolean: // true and false
13700 oa->write_character(j.m_value.boolean
13701 ? to_char_type(0xC3)
13702 : to_char_type(0xC2));
13706 case value_t::number_integer:
13708 if (j.m_value.number_integer >= 0)
13710 // MessagePack does not differentiate between positive
13711 // signed integers and unsigned integers. Therefore, we used
13712 // the code from the value_t::number_unsigned case here.
13713 if (j.m_value.number_unsigned < 128)
13716 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13718 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
13721 oa->write_character(to_char_type(0xCC));
13722 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13724 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
13727 oa->write_character(to_char_type(0xCD));
13728 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13730 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
13733 oa->write_character(to_char_type(0xCE));
13734 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13736 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
13739 oa->write_character(to_char_type(0xCF));
13740 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13745 if (j.m_value.number_integer >= -32)
13748 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
13750 else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
13751 j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
13754 oa->write_character(to_char_type(0xD0));
13755 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
13757 else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
13758 j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
13761 oa->write_character(to_char_type(0xD1));
13762 write_number(static_cast<std::int16_t>(j.m_value.number_integer));
13764 else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
13765 j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
13768 oa->write_character(to_char_type(0xD2));
13769 write_number(static_cast<std::int32_t>(j.m_value.number_integer));
13771 else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
13772 j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
13775 oa->write_character(to_char_type(0xD3));
13776 write_number(static_cast<std::int64_t>(j.m_value.number_integer));
13782 case value_t::number_unsigned:
13784 if (j.m_value.number_unsigned < 128)
13787 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13789 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
13792 oa->write_character(to_char_type(0xCC));
13793 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13795 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
13798 oa->write_character(to_char_type(0xCD));
13799 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13801 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
13804 oa->write_character(to_char_type(0xCE));
13805 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13807 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
13810 oa->write_character(to_char_type(0xCF));
13811 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13816 case value_t::number_float:
13818 write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
13822 case value_t::string:
13824 // step 1: write control byte and the string length
13825 const auto N = j.m_value.string->size();
13829 write_number(static_cast<std::uint8_t>(0xA0 | N));
13831 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13834 oa->write_character(to_char_type(0xD9));
13835 write_number(static_cast<std::uint8_t>(N));
13837 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13840 oa->write_character(to_char_type(0xDA));
13841 write_number(static_cast<std::uint16_t>(N));
13843 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13846 oa->write_character(to_char_type(0xDB));
13847 write_number(static_cast<std::uint32_t>(N));
13850 // step 2: write the string
13851 oa->write_characters(
13852 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
13853 j.m_value.string->size());
13857 case value_t::array:
13859 // step 1: write control byte and the array size
13860 const auto N = j.m_value.array->size();
13864 write_number(static_cast<std::uint8_t>(0x90 | N));
13866 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13869 oa->write_character(to_char_type(0xDC));
13870 write_number(static_cast<std::uint16_t>(N));
13872 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13875 oa->write_character(to_char_type(0xDD));
13876 write_number(static_cast<std::uint32_t>(N));
13879 // step 2: write each element
13880 for (const auto& el : *j.m_value.array)
13887 case value_t::binary:
13889 // step 0: determine if the binary type has a set subtype to
13890 // determine whether or not to use the ext or fixext types
13891 const bool use_ext = j.m_value.binary->has_subtype();
13893 // step 1: write control byte and the byte string length
13894 const auto N = j.m_value.binary->size();
13895 if (N <= (std::numeric_limits<std::uint8_t>::max)())
13897 std::uint8_t output_type{};
13904 output_type = 0xD4; // fixext 1
13907 output_type = 0xD5; // fixext 2
13910 output_type = 0xD6; // fixext 4
13913 output_type = 0xD7; // fixext 8
13916 output_type = 0xD8; // fixext 16
13919 output_type = 0xC7; // ext 8
13927 output_type = 0xC4; // bin 8
13931 oa->write_character(to_char_type(output_type));
13934 write_number(static_cast<std::uint8_t>(N));
13937 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13939 std::uint8_t output_type = use_ext
13943 oa->write_character(to_char_type(output_type));
13944 write_number(static_cast<std::uint16_t>(N));
13946 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13948 std::uint8_t output_type = use_ext
13952 oa->write_character(to_char_type(output_type));
13953 write_number(static_cast<std::uint32_t>(N));
13956 // step 1.5: if this is an ext type, write the subtype
13959 write_number(static_cast<std::int8_t>(j.m_value.binary->subtype()));
13962 // step 2: write the byte string
13963 oa->write_characters(
13964 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13970 case value_t::object:
13972 // step 1: write control byte and the object size
13973 const auto N = j.m_value.object->size();
13977 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
13979 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13982 oa->write_character(to_char_type(0xDE));
13983 write_number(static_cast<std::uint16_t>(N));
13985 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13988 oa->write_character(to_char_type(0xDF));
13989 write_number(static_cast<std::uint32_t>(N));
13992 // step 2: write each element
13993 for (const auto& el : *j.m_value.object)
13995 write_msgpack(el.first);
13996 write_msgpack(el.second);
14001 case value_t::discarded:
14008 @param[in] j JSON value to serialize
14009 @param[in] use_count whether to use '#' prefixes (optimized format)
14010 @param[in] use_type whether to use '$' prefixes (optimized format)
14011 @param[in] add_prefix whether prefixes need to be used for this value
14013 void write_ubjson(const BasicJsonType& j, const bool use_count,
14014 const bool use_type, const bool add_prefix = true)
14018 case value_t::null:
14022 oa->write_character(to_char_type('Z'));
14027 case value_t::boolean:
14031 oa->write_character(j.m_value.boolean
14032 ? to_char_type('T')
14033 : to_char_type('F'));
14038 case value_t::number_integer:
14040 write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
14044 case value_t::number_unsigned:
14046 write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
14050 case value_t::number_float:
14052 write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
14056 case value_t::string:
14060 oa->write_character(to_char_type('S'));
14062 write_number_with_ubjson_prefix(j.m_value.string->size(), true);
14063 oa->write_characters(
14064 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
14065 j.m_value.string->size());
14069 case value_t::array:
14073 oa->write_character(to_char_type('['));
14076 bool prefix_required = true;
14077 if (use_type && !j.m_value.array->empty())
14079 JSON_ASSERT(use_count);
14080 const CharType first_prefix = ubjson_prefix(j.front());
14081 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
14082 [this, first_prefix](const BasicJsonType & v)
14084 return ubjson_prefix(v) == first_prefix;
14089 prefix_required = false;
14090 oa->write_character(to_char_type('$'));
14091 oa->write_character(first_prefix);
14097 oa->write_character(to_char_type('#'));
14098 write_number_with_ubjson_prefix(j.m_value.array->size(), true);
14101 for (const auto& el : *j.m_value.array)
14103 write_ubjson(el, use_count, use_type, prefix_required);
14108 oa->write_character(to_char_type(']'));
14114 case value_t::binary:
14118 oa->write_character(to_char_type('['));
14121 if (use_type && !j.m_value.binary->empty())
14123 JSON_ASSERT(use_count);
14124 oa->write_character(to_char_type('$'));
14125 oa->write_character('U');
14130 oa->write_character(to_char_type('#'));
14131 write_number_with_ubjson_prefix(j.m_value.binary->size(), true);
14136 oa->write_characters(
14137 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
14138 j.m_value.binary->size());
14142 for (size_t i = 0; i < j.m_value.binary->size(); ++i)
14144 oa->write_character(to_char_type('U'));
14145 oa->write_character(j.m_value.binary->data()[i]);
14151 oa->write_character(to_char_type(']'));
14157 case value_t::object:
14161 oa->write_character(to_char_type('{'));
14164 bool prefix_required = true;
14165 if (use_type && !j.m_value.object->empty())
14167 JSON_ASSERT(use_count);
14168 const CharType first_prefix = ubjson_prefix(j.front());
14169 const bool same_prefix = std::all_of(j.begin(), j.end(),
14170 [this, first_prefix](const BasicJsonType & v)
14172 return ubjson_prefix(v) == first_prefix;
14177 prefix_required = false;
14178 oa->write_character(to_char_type('$'));
14179 oa->write_character(first_prefix);
14185 oa->write_character(to_char_type('#'));
14186 write_number_with_ubjson_prefix(j.m_value.object->size(), true);
14189 for (const auto& el : *j.m_value.object)
14191 write_number_with_ubjson_prefix(el.first.size(), true);
14192 oa->write_characters(
14193 reinterpret_cast<const CharType*>(el.first.c_str()),
14195 write_ubjson(el.second, use_count, use_type, prefix_required);
14200 oa->write_character(to_char_type('}'));
14206 case value_t::discarded:
14218 @return The size of a BSON document entry header, including the id marker
14219 and the entry name size (and its null-terminator).
14221 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
14223 const auto it = name.find(static_cast<typename string_t::value_type>(0));
14224 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
14226 JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j));
14227 static_cast<void>(j);
14230 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
14234 @brief Writes the given @a element_type and @a name to the output adapter
14236 void write_bson_entry_header(const string_t& name,
14237 const std::uint8_t element_type)
14239 oa->write_character(to_char_type(element_type)); // boolean
14240 oa->write_characters(
14241 reinterpret_cast<const CharType*>(name.c_str()),
14246 @brief Writes a BSON element with key @a name and boolean value @a value
14248 void write_bson_boolean(const string_t& name,
14251 write_bson_entry_header(name, 0x08);
14252 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
14256 @brief Writes a BSON element with key @a name and double value @a value
14258 void write_bson_double(const string_t& name,
14259 const double value)
14261 write_bson_entry_header(name, 0x01);
14262 write_number<double, true>(value);
14266 @return The size of the BSON-encoded string in @a value
14268 static std::size_t calc_bson_string_size(const string_t& value)
14270 return sizeof(std::int32_t) + value.size() + 1ul;
14274 @brief Writes a BSON element with key @a name and string value @a value
14276 void write_bson_string(const string_t& name,
14277 const string_t& value)
14279 write_bson_entry_header(name, 0x02);
14281 write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
14282 oa->write_characters(
14283 reinterpret_cast<const CharType*>(value.c_str()),
14288 @brief Writes a BSON element with key @a name and null value
14290 void write_bson_null(const string_t& name)
14292 write_bson_entry_header(name, 0x0A);
14296 @return The size of the BSON-encoded integer @a value
14298 static std::size_t calc_bson_integer_size(const std::int64_t value)
14300 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
14301 ? sizeof(std::int32_t)
14302 : sizeof(std::int64_t);
14306 @brief Writes a BSON element with key @a name and integer @a value
14308 void write_bson_integer(const string_t& name,
14309 const std::int64_t value)
14311 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
14313 write_bson_entry_header(name, 0x10); // int32
14314 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
14318 write_bson_entry_header(name, 0x12); // int64
14319 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
14324 @return The size of the BSON-encoded unsigned integer in @a j
14326 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
14328 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14329 ? sizeof(std::int32_t)
14330 : sizeof(std::int64_t);
14334 @brief Writes a BSON element with key @a name and unsigned @a value
14336 void write_bson_unsigned(const string_t& name,
14337 const BasicJsonType& j)
14339 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14341 write_bson_entry_header(name, 0x10 /* int32 */);
14342 write_number<std::int32_t, true>(static_cast<std::int32_t>(j.m_value.number_unsigned));
14344 else if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14346 write_bson_entry_header(name, 0x12 /* int64 */);
14347 write_number<std::int64_t, true>(static_cast<std::int64_t>(j.m_value.number_unsigned));
14351 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", j));
14356 @brief Writes a BSON element with key @a name and object @a value
14358 void write_bson_object_entry(const string_t& name,
14359 const typename BasicJsonType::object_t& value)
14361 write_bson_entry_header(name, 0x03); // object
14362 write_bson_object(value);
14366 @return The size of the BSON-encoded array @a value
14368 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
14370 std::size_t array_index = 0ul;
14372 const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
14374 return result + calc_bson_element_size(std::to_string(array_index++), el);
14377 return sizeof(std::int32_t) + embedded_document_size + 1ul;
14381 @return The size of the BSON-encoded binary array @a value
14383 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
14385 return sizeof(std::int32_t) + value.size() + 1ul;
14389 @brief Writes a BSON element with key @a name and array @a value
14391 void write_bson_array(const string_t& name,
14392 const typename BasicJsonType::array_t& value)
14394 write_bson_entry_header(name, 0x04); // array
14395 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
14397 std::size_t array_index = 0ul;
14399 for (const auto& el : value)
14401 write_bson_element(std::to_string(array_index++), el);
14404 oa->write_character(to_char_type(0x00));
14408 @brief Writes a BSON element with key @a name and binary value @a value
14410 void write_bson_binary(const string_t& name,
14411 const binary_t& value)
14413 write_bson_entry_header(name, 0x05);
14415 write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
14416 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
14418 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
14422 @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
14423 @return The calculated size for the BSON document entry for @a j with the given @a name.
14425 static std::size_t calc_bson_element_size(const string_t& name,
14426 const BasicJsonType& j)
14428 const auto header_size = calc_bson_entry_header_size(name, j);
14431 case value_t::object:
14432 return header_size + calc_bson_object_size(*j.m_value.object);
14434 case value_t::array:
14435 return header_size + calc_bson_array_size(*j.m_value.array);
14437 case value_t::binary:
14438 return header_size + calc_bson_binary_size(*j.m_value.binary);
14440 case value_t::boolean:
14441 return header_size + 1ul;
14443 case value_t::number_float:
14444 return header_size + 8ul;
14446 case value_t::number_integer:
14447 return header_size + calc_bson_integer_size(j.m_value.number_integer);
14449 case value_t::number_unsigned:
14450 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
14452 case value_t::string:
14453 return header_size + calc_bson_string_size(*j.m_value.string);
14455 case value_t::null:
14456 return header_size + 0ul;
14459 case value_t::discarded:
14461 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
14468 @brief Serializes the JSON value @a j to BSON and associates it with the
14470 @param name The name to associate with the JSON entity @a j within the
14471 current BSON document
14473 void write_bson_element(const string_t& name,
14474 const BasicJsonType& j)
14478 case value_t::object:
14479 return write_bson_object_entry(name, *j.m_value.object);
14481 case value_t::array:
14482 return write_bson_array(name, *j.m_value.array);
14484 case value_t::binary:
14485 return write_bson_binary(name, *j.m_value.binary);
14487 case value_t::boolean:
14488 return write_bson_boolean(name, j.m_value.boolean);
14490 case value_t::number_float:
14491 return write_bson_double(name, j.m_value.number_float);
14493 case value_t::number_integer:
14494 return write_bson_integer(name, j.m_value.number_integer);
14496 case value_t::number_unsigned:
14497 return write_bson_unsigned(name, j);
14499 case value_t::string:
14500 return write_bson_string(name, *j.m_value.string);
14502 case value_t::null:
14503 return write_bson_null(name);
14506 case value_t::discarded:
14508 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
14515 @brief Calculates the size of the BSON serialization of the given
14517 @param[in] value JSON value to serialize
14518 @pre value.type() == value_t::object
14520 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
14522 std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
14523 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
14525 return result += calc_bson_element_size(el.first, el.second);
14528 return sizeof(std::int32_t) + document_size + 1ul;
14532 @param[in] value JSON value to serialize
14533 @pre value.type() == value_t::object
14535 void write_bson_object(const typename BasicJsonType::object_t& value)
14537 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
14539 for (const auto& el : value)
14541 write_bson_element(el.first, el.second);
14544 oa->write_character(to_char_type(0x00));
14551 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
14553 return to_char_type(0xFA); // Single-Precision Float
14556 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
14558 return to_char_type(0xFB); // Double-Precision Float
14565 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
14567 return to_char_type(0xCA); // float 32
14570 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
14572 return to_char_type(0xCB); // float 64
14579 // UBJSON: write number (floating point)
14580 template<typename NumberType, typename std::enable_if<
14581 std::is_floating_point<NumberType>::value, int>::type = 0>
14582 void write_number_with_ubjson_prefix(const NumberType n,
14583 const bool add_prefix)
14587 oa->write_character(get_ubjson_float_prefix(n));
14592 // UBJSON: write number (unsigned integer)
14593 template<typename NumberType, typename std::enable_if<
14594 std::is_unsigned<NumberType>::value, int>::type = 0>
14595 void write_number_with_ubjson_prefix(const NumberType n,
14596 const bool add_prefix)
14598 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
14602 oa->write_character(to_char_type('i')); // int8
14604 write_number(static_cast<std::uint8_t>(n));
14606 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
14610 oa->write_character(to_char_type('U')); // uint8
14612 write_number(static_cast<std::uint8_t>(n));
14614 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
14618 oa->write_character(to_char_type('I')); // int16
14620 write_number(static_cast<std::int16_t>(n));
14622 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14626 oa->write_character(to_char_type('l')); // int32
14628 write_number(static_cast<std::int32_t>(n));
14630 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14634 oa->write_character(to_char_type('L')); // int64
14636 write_number(static_cast<std::int64_t>(n));
14642 oa->write_character(to_char_type('H')); // high-precision number
14645 const auto number = BasicJsonType(n).dump();
14646 write_number_with_ubjson_prefix(number.size(), true);
14647 for (std::size_t i = 0; i < number.size(); ++i)
14649 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
14654 // UBJSON: write number (signed integer)
14655 template < typename NumberType, typename std::enable_if <
14656 std::is_signed<NumberType>::value&&
14657 !std::is_floating_point<NumberType>::value, int >::type = 0 >
14658 void write_number_with_ubjson_prefix(const NumberType n,
14659 const bool add_prefix)
14661 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
14665 oa->write_character(to_char_type('i')); // int8
14667 write_number(static_cast<std::int8_t>(n));
14669 else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
14673 oa->write_character(to_char_type('U')); // uint8
14675 write_number(static_cast<std::uint8_t>(n));
14677 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
14681 oa->write_character(to_char_type('I')); // int16
14683 write_number(static_cast<std::int16_t>(n));
14685 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
14689 oa->write_character(to_char_type('l')); // int32
14691 write_number(static_cast<std::int32_t>(n));
14693 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
14697 oa->write_character(to_char_type('L')); // int64
14699 write_number(static_cast<std::int64_t>(n));
14706 oa->write_character(to_char_type('H')); // high-precision number
14709 const auto number = BasicJsonType(n).dump();
14710 write_number_with_ubjson_prefix(number.size(), true);
14711 for (std::size_t i = 0; i < number.size(); ++i)
14713 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
14720 @brief determine the type prefix of container values
14722 CharType ubjson_prefix(const BasicJsonType& j) const noexcept
14726 case value_t::null:
14729 case value_t::boolean:
14730 return j.m_value.boolean ? 'T' : 'F';
14732 case value_t::number_integer:
14734 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
14738 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
14742 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
14746 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
14750 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
14754 // anything else is treated as high-precision number
14755 return 'H'; // LCOV_EXCL_LINE
14758 case value_t::number_unsigned:
14760 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
14764 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
14768 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
14772 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14776 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14780 // anything else is treated as high-precision number
14781 return 'H'; // LCOV_EXCL_LINE
14784 case value_t::number_float:
14785 return get_ubjson_float_prefix(j.m_value.number_float);
14787 case value_t::string:
14790 case value_t::array: // fallthrough
14791 case value_t::binary:
14794 case value_t::object:
14797 case value_t::discarded:
14798 default: // discarded values
14803 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
14805 return 'd'; // float 32
14808 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
14810 return 'D'; // float 64
14813 ///////////////////////
14814 // Utility functions //
14815 ///////////////////////
14818 @brief write a number to output input
14819 @param[in] n number of type @a NumberType
14820 @tparam NumberType the type of the number
14821 @tparam OutputIsLittleEndian Set to true if output data is
14822 required to be little endian
14824 @note This function needs to respect the system's endianness, because bytes
14825 in CBOR, MessagePack, and UBJSON are stored in network order (big
14826 endian) and therefore need reordering on little endian systems.
14828 template<typename NumberType, bool OutputIsLittleEndian = false>
14829 void write_number(const NumberType n)
14831 // step 1: write number to array of length NumberType
14832 std::array<CharType, sizeof(NumberType)> vec{};
14833 std::memcpy(vec.data(), &n, sizeof(NumberType));
14835 // step 2: write array to output (with possible reordering)
14836 if (is_little_endian != OutputIsLittleEndian)
14838 // reverse byte order prior to conversion if necessary
14839 std::reverse(vec.begin(), vec.end());
14842 oa->write_characters(vec.data(), sizeof(NumberType));
14845 void write_compact_float(const number_float_t n, detail::input_format_t format)
14848 #pragma GCC diagnostic push
14849 #pragma GCC diagnostic ignored "-Wfloat-equal"
14851 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
14852 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
14853 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
14855 oa->write_character(format == detail::input_format_t::cbor
14856 ? get_cbor_float_prefix(static_cast<float>(n))
14857 : get_msgpack_float_prefix(static_cast<float>(n)));
14858 write_number(static_cast<float>(n));
14862 oa->write_character(format == detail::input_format_t::cbor
14863 ? get_cbor_float_prefix(n)
14864 : get_msgpack_float_prefix(n));
14868 #pragma GCC diagnostic pop
14873 // The following to_char_type functions are implement the conversion
14874 // between uint8_t and CharType. In case CharType is not unsigned,
14875 // such a conversion is required to allow values greater than 128.
14876 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
14877 template < typename C = CharType,
14878 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
14879 static constexpr CharType to_char_type(std::uint8_t x) noexcept
14881 return *reinterpret_cast<char*>(&x);
14884 template < typename C = CharType,
14885 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
14886 static CharType to_char_type(std::uint8_t x) noexcept
14888 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
14889 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
14891 std::memcpy(&result, &x, sizeof(x));
14895 template<typename C = CharType,
14896 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
14897 static constexpr CharType to_char_type(std::uint8_t x) noexcept
14902 template < typename InputCharType, typename C = CharType,
14904 std::is_signed<C>::value &&
14905 std::is_signed<char>::value &&
14906 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
14908 static constexpr CharType to_char_type(InputCharType x) noexcept
14914 /// whether we can assume little endianness
14915 const bool is_little_endian = little_endianness();
14918 output_adapter_t<CharType> oa = nullptr;
14920 } // namespace detail
14921 } // namespace nlohmann
14923 // #include <nlohmann/detail/output/output_adapters.hpp>
14925 // #include <nlohmann/detail/output/serializer.hpp>
14928 #include <algorithm> // reverse, remove, fill, find, none_of
14929 #include <array> // array
14930 #include <clocale> // localeconv, lconv
14931 #include <cmath> // labs, isfinite, isnan, signbit
14932 #include <cstddef> // size_t, ptrdiff_t
14933 #include <cstdint> // uint8_t
14934 #include <cstdio> // snprintf
14935 #include <limits> // numeric_limits
14936 #include <string> // string, char_traits
14937 #include <iomanip> // setfill, setw
14938 #include <sstream> // stringstream
14939 #include <type_traits> // is_same
14940 #include <utility> // move
14942 // #include <nlohmann/detail/conversions/to_chars.hpp>
14945 #include <array> // array
14946 #include <cmath> // signbit, isfinite
14947 #include <cstdint> // intN_t, uintN_t
14948 #include <cstring> // memcpy, memmove
14949 #include <limits> // numeric_limits
14950 #include <type_traits> // conditional
14952 // #include <nlohmann/detail/macro_scope.hpp>
14961 @brief implements the Grisu2 algorithm for binary to decimal floating-point
14964 This implementation is a slightly modified version of the reference
14965 implementation which may be obtained from
14966 http://florian.loitsch.com/publications (bench.tar.gz).
14968 The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
14970 For a detailed description of the algorithm see:
14972 [1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
14973 Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
14974 Language Design and Implementation, PLDI 2010
14975 [2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
14976 Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
14977 Design and Implementation, PLDI 1996
14979 namespace dtoa_impl
14982 template<typename Target, typename Source>
14983 Target reinterpret_bits(const Source source)
14985 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
14988 std::memcpy(&target, &source, sizeof(Source));
14992 struct diyfp // f * 2^e
14994 static constexpr int kPrecision = 64; // = q
14996 std::uint64_t f = 0;
14999 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
15002 @brief returns x - y
15003 @pre x.e == y.e and x.f >= y.f
15005 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
15007 JSON_ASSERT(x.e == y.e);
15008 JSON_ASSERT(x.f >= y.f);
15010 return {x.f - y.f, x.e};
15014 @brief returns x * y
15015 @note The result is rounded. (Only the upper q bits are returned.)
15017 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
15019 static_assert(kPrecision == 64, "internal error");
15022 // f = round((x.f * y.f) / 2^q)
15023 // e = x.e + y.e + q
15025 // Emulate the 64-bit * 64-bit multiplication:
15028 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
15029 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
15030 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
15031 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
15032 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
15033 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
15034 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
15036 // (Since Q might be larger than 2^32 - 1)
15038 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
15040 // (Q_hi + H does not overflow a 64-bit int)
15042 // = p_lo + 2^64 p_hi
15044 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
15045 const std::uint64_t u_hi = x.f >> 32u;
15046 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
15047 const std::uint64_t v_hi = y.f >> 32u;
15049 const std::uint64_t p0 = u_lo * v_lo;
15050 const std::uint64_t p1 = u_lo * v_hi;
15051 const std::uint64_t p2 = u_hi * v_lo;
15052 const std::uint64_t p3 = u_hi * v_hi;
15054 const std::uint64_t p0_hi = p0 >> 32u;
15055 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
15056 const std::uint64_t p1_hi = p1 >> 32u;
15057 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
15058 const std::uint64_t p2_hi = p2 >> 32u;
15060 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
15062 // The full product might now be computed as
15064 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
15065 // p_lo = p0_lo + (Q << 32)
15067 // But in this particular case here, the full p_lo is not required.
15068 // Effectively we only need to add the highest bit in p_lo to p_hi (and
15069 // Q_hi + 1 does not overflow).
15071 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
15073 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
15075 return {h, x.e + y.e + 64};
15079 @brief normalize x such that the significand is >= 2^(q-1)
15082 static diyfp normalize(diyfp x) noexcept
15084 JSON_ASSERT(x.f != 0);
15086 while ((x.f >> 63u) == 0)
15096 @brief normalize x such that the result has the exponent E
15097 @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
15099 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
15101 const int delta = x.e - target_exponent;
15103 JSON_ASSERT(delta >= 0);
15104 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
15106 return {x.f << delta, target_exponent};
15118 Compute the (normalized) diyfp representing the input number 'value' and its
15121 @pre value must be finite and positive
15123 template<typename FloatType>
15124 boundaries compute_boundaries(FloatType value)
15126 JSON_ASSERT(std::isfinite(value));
15127 JSON_ASSERT(value > 0);
15129 // Convert the IEEE representation into a diyfp.
15131 // If v is denormal:
15132 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
15133 // If v is normalized:
15134 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
15136 static_assert(std::numeric_limits<FloatType>::is_iec559,
15137 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
15139 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
15140 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
15141 constexpr int kMinExp = 1 - kBias;
15142 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
15144 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
15146 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
15147 const std::uint64_t E = bits >> (kPrecision - 1);
15148 const std::uint64_t F = bits & (kHiddenBit - 1);
15150 const bool is_denormal = E == 0;
15151 const diyfp v = is_denormal
15152 ? diyfp(F, kMinExp)
15153 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
15155 // Compute the boundaries m- and m+ of the floating-point value
15158 // Determine v- and v+, the floating-point predecessor and successor if v,
15161 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
15162 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
15166 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
15167 // between m- and m+ round to v, regardless of how the input rounding
15168 // algorithm breaks ties.
15170 // ---+-------------+-------------+-------------+-------------+--- (A)
15173 // -----------------+------+------+-------------+-------------+--- (B)
15176 const bool lower_boundary_is_closer = F == 0 && E > 1;
15177 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
15178 const diyfp m_minus = lower_boundary_is_closer
15179 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
15180 : diyfp(2 * v.f - 1, v.e - 1); // (A)
15182 // Determine the normalized w+ = m+.
15183 const diyfp w_plus = diyfp::normalize(m_plus);
15185 // Determine w- = m- such that e_(w-) = e_(w+).
15186 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
15188 return {diyfp::normalize(v), w_minus, w_plus};
15191 // Given normalized diyfp w, Grisu needs to find a (normalized) cached
15192 // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
15193 // within a certain range [alpha, gamma] (Definition 3.2 from [1])
15195 // alpha <= e = e_c + e_w + q <= gamma
15199 // f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
15200 // <= f_c * f_w * 2^gamma
15202 // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
15204 // 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
15208 // 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
15210 // The choice of (alpha,gamma) determines the size of the table and the form of
15211 // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
15214 // The idea is to cut the number c * w = f * 2^e into two parts, which can be
15215 // processed independently: An integral part p1, and a fractional part p2:
15217 // f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
15218 // = (f div 2^-e) + (f mod 2^-e) * 2^e
15221 // The conversion of p1 into decimal form requires a series of divisions and
15222 // modulos by (a power of) 10. These operations are faster for 32-bit than for
15223 // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
15224 // achieved by choosing
15226 // -e >= 32 or e <= -32 := gamma
15228 // In order to convert the fractional part
15230 // p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
15232 // into decimal form, the fraction is repeatedly multiplied by 10 and the digits
15233 // d[-i] are extracted in order:
15235 // (10 * p2) div 2^-e = d[-1]
15236 // (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
15238 // The multiplication by 10 must not overflow. It is sufficient to choose
15240 // 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
15242 // Since p2 = f mod 2^-e < 2^-e,
15244 // -e <= 60 or e >= -60 := alpha
15246 constexpr int kAlpha = -60;
15247 constexpr int kGamma = -32;
15249 struct cached_power // c = f * 2^e ~= 10^k
15257 For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
15258 power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
15259 satisfies (Definition 3.2 from [1])
15261 alpha <= e_c + e + q <= gamma.
15263 inline cached_power get_cached_power_for_binary_exponent(int e)
15267 // alpha <= e_c + e + q <= gamma (1)
15268 // ==> f_c * 2^alpha <= c * 2^e * 2^q
15270 // and since the c's are normalized, 2^(q-1) <= f_c,
15272 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
15273 // ==> 2^(alpha - e - 1) <= c
15275 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
15277 // k = ceil( log_10( 2^(alpha - e - 1) ) )
15278 // = ceil( (alpha - e - 1) * log_10(2) )
15281 // "In theory the result of the procedure could be wrong since c is rounded,
15282 // and the computation itself is approximated [...]. In practice, however,
15283 // this simple function is sufficient."
15285 // For IEEE double precision floating-point numbers converted into
15286 // normalized diyfp's w = f * 2^e, with q = 64,
15288 // e >= -1022 (min IEEE exponent)
15290 // -52 (p - 1, possibly normalize denormal IEEE numbers)
15291 // -11 (normalize the diyfp)
15296 // e <= +1023 (max IEEE exponent)
15298 // -11 (normalize the diyfp)
15301 // This binary exponent range [-1137,960] results in a decimal exponent
15302 // range [-307,324]. One does not need to store a cached power for each
15303 // k in this range. For each such k it suffices to find a cached power
15304 // such that the exponent of the product lies in [alpha,gamma].
15305 // This implies that the difference of the decimal exponents of adjacent
15306 // table entries must be less than or equal to
15308 // floor( (gamma - alpha) * log_10(2) ) = 8.
15310 // (A smaller distance gamma-alpha would require a larger table.)
15313 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
15315 constexpr int kCachedPowersMinDecExp = -300;
15316 constexpr int kCachedPowersDecStep = 8;
15318 static constexpr std::array<cached_power, 79> kCachedPowers =
15321 { 0xAB70FE17C79AC6CA, -1060, -300 },
15322 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
15323 { 0xBE5691EF416BD60C, -1007, -284 },
15324 { 0x8DD01FAD907FFC3C, -980, -276 },
15325 { 0xD3515C2831559A83, -954, -268 },
15326 { 0x9D71AC8FADA6C9B5, -927, -260 },
15327 { 0xEA9C227723EE8BCB, -901, -252 },
15328 { 0xAECC49914078536D, -874, -244 },
15329 { 0x823C12795DB6CE57, -847, -236 },
15330 { 0xC21094364DFB5637, -821, -228 },
15331 { 0x9096EA6F3848984F, -794, -220 },
15332 { 0xD77485CB25823AC7, -768, -212 },
15333 { 0xA086CFCD97BF97F4, -741, -204 },
15334 { 0xEF340A98172AACE5, -715, -196 },
15335 { 0xB23867FB2A35B28E, -688, -188 },
15336 { 0x84C8D4DFD2C63F3B, -661, -180 },
15337 { 0xC5DD44271AD3CDBA, -635, -172 },
15338 { 0x936B9FCEBB25C996, -608, -164 },
15339 { 0xDBAC6C247D62A584, -582, -156 },
15340 { 0xA3AB66580D5FDAF6, -555, -148 },
15341 { 0xF3E2F893DEC3F126, -529, -140 },
15342 { 0xB5B5ADA8AAFF80B8, -502, -132 },
15343 { 0x87625F056C7C4A8B, -475, -124 },
15344 { 0xC9BCFF6034C13053, -449, -116 },
15345 { 0x964E858C91BA2655, -422, -108 },
15346 { 0xDFF9772470297EBD, -396, -100 },
15347 { 0xA6DFBD9FB8E5B88F, -369, -92 },
15348 { 0xF8A95FCF88747D94, -343, -84 },
15349 { 0xB94470938FA89BCF, -316, -76 },
15350 { 0x8A08F0F8BF0F156B, -289, -68 },
15351 { 0xCDB02555653131B6, -263, -60 },
15352 { 0x993FE2C6D07B7FAC, -236, -52 },
15353 { 0xE45C10C42A2B3B06, -210, -44 },
15354 { 0xAA242499697392D3, -183, -36 },
15355 { 0xFD87B5F28300CA0E, -157, -28 },
15356 { 0xBCE5086492111AEB, -130, -20 },
15357 { 0x8CBCCC096F5088CC, -103, -12 },
15358 { 0xD1B71758E219652C, -77, -4 },
15359 { 0x9C40000000000000, -50, 4 },
15360 { 0xE8D4A51000000000, -24, 12 },
15361 { 0xAD78EBC5AC620000, 3, 20 },
15362 { 0x813F3978F8940984, 30, 28 },
15363 { 0xC097CE7BC90715B3, 56, 36 },
15364 { 0x8F7E32CE7BEA5C70, 83, 44 },
15365 { 0xD5D238A4ABE98068, 109, 52 },
15366 { 0x9F4F2726179A2245, 136, 60 },
15367 { 0xED63A231D4C4FB27, 162, 68 },
15368 { 0xB0DE65388CC8ADA8, 189, 76 },
15369 { 0x83C7088E1AAB65DB, 216, 84 },
15370 { 0xC45D1DF942711D9A, 242, 92 },
15371 { 0x924D692CA61BE758, 269, 100 },
15372 { 0xDA01EE641A708DEA, 295, 108 },
15373 { 0xA26DA3999AEF774A, 322, 116 },
15374 { 0xF209787BB47D6B85, 348, 124 },
15375 { 0xB454E4A179DD1877, 375, 132 },
15376 { 0x865B86925B9BC5C2, 402, 140 },
15377 { 0xC83553C5C8965D3D, 428, 148 },
15378 { 0x952AB45CFA97A0B3, 455, 156 },
15379 { 0xDE469FBD99A05FE3, 481, 164 },
15380 { 0xA59BC234DB398C25, 508, 172 },
15381 { 0xF6C69A72A3989F5C, 534, 180 },
15382 { 0xB7DCBF5354E9BECE, 561, 188 },
15383 { 0x88FCF317F22241E2, 588, 196 },
15384 { 0xCC20CE9BD35C78A5, 614, 204 },
15385 { 0x98165AF37B2153DF, 641, 212 },
15386 { 0xE2A0B5DC971F303A, 667, 220 },
15387 { 0xA8D9D1535CE3B396, 694, 228 },
15388 { 0xFB9B7CD9A4A7443C, 720, 236 },
15389 { 0xBB764C4CA7A44410, 747, 244 },
15390 { 0x8BAB8EEFB6409C1A, 774, 252 },
15391 { 0xD01FEF10A657842C, 800, 260 },
15392 { 0x9B10A4E5E9913129, 827, 268 },
15393 { 0xE7109BFBA19C0C9D, 853, 276 },
15394 { 0xAC2820D9623BF429, 880, 284 },
15395 { 0x80444B5E7AA7CF85, 907, 292 },
15396 { 0xBF21E44003ACDD2D, 933, 300 },
15397 { 0x8E679C2F5E44FF8F, 960, 308 },
15398 { 0xD433179D9C8CB841, 986, 316 },
15399 { 0x9E19DB92B4E31BA9, 1013, 324 },
15403 // This computation gives exactly the same results for k as
15404 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
15405 // for |e| <= 1500, but doesn't require floating-point operations.
15406 // NB: log_10(2) ~= 78913 / 2^18
15407 JSON_ASSERT(e >= -1500);
15408 JSON_ASSERT(e <= 1500);
15409 const int f = kAlpha - e - 1;
15410 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
15412 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
15413 JSON_ASSERT(index >= 0);
15414 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
15416 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
15417 JSON_ASSERT(kAlpha <= cached.e + e + 64);
15418 JSON_ASSERT(kGamma >= cached.e + e + 64);
15424 For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
15425 For n == 0, returns 1 and sets pow10 := 1.
15427 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
15430 if (n >= 1000000000)
15432 pow10 = 1000000000;
15436 if (n >= 100000000)
15481 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
15482 std::uint64_t rest, std::uint64_t ten_k)
15484 JSON_ASSERT(len >= 1);
15485 JSON_ASSERT(dist <= delta);
15486 JSON_ASSERT(rest <= delta);
15487 JSON_ASSERT(ten_k > 0);
15489 // <--------------------------- delta ---->
15490 // <---- dist --------->
15491 // --------------[------------------+-------------------]--------------
15496 // <---- rest ---->
15497 // --------------[------------------+----+--------------]--------------
15501 // ten_k represents a unit-in-the-last-place in the decimal representation
15503 // Decrement buf by ten_k while this takes buf closer to w.
15505 // The tests are written in this order to avoid overflow in unsigned
15506 // integer arithmetic.
15509 && delta - rest >= ten_k
15510 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
15512 JSON_ASSERT(buf[len - 1] != '0');
15519 Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
15520 M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
15522 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
15523 diyfp M_minus, diyfp w, diyfp M_plus)
15525 static_assert(kAlpha >= -60, "internal error");
15526 static_assert(kGamma <= -32, "internal error");
15528 // Generates the digits (and the exponent) of a decimal floating-point
15529 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
15530 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
15532 // <--------------------------- delta ---->
15533 // <---- dist --------->
15534 // --------------[------------------+-------------------]--------------
15537 // Grisu2 generates the digits of M+ from left to right and stops as soon as
15538 // V is in [M-,M+].
15540 JSON_ASSERT(M_plus.e >= kAlpha);
15541 JSON_ASSERT(M_plus.e <= kGamma);
15543 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
15544 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
15546 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
15549 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
15550 // = ((p1 ) * 2^-e + (p2 )) * 2^e
15553 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
15555 auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
15556 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
15560 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
15562 JSON_ASSERT(p1 > 0);
15564 std::uint32_t pow10{};
15565 const int k = find_largest_pow10(p1, pow10);
15567 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
15569 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
15570 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
15572 // M+ = p1 + p2 * 2^e
15573 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
15574 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
15575 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
15577 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
15579 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
15581 // but stop as soon as
15583 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
15589 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
15590 // pow10 = 10^(n-1) <= p1 < 10^n
15592 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
15593 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
15595 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
15596 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
15598 JSON_ASSERT(d <= 9);
15599 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
15601 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
15606 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
15610 // Now check if enough digits have been generated.
15613 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
15616 // Since rest and delta share the same exponent e, it suffices to
15617 // compare the significands.
15618 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
15621 // V = buffer * 10^n, with M- <= V <= M+.
15623 decimal_exponent += n;
15625 // We may now just stop. But instead look if the buffer could be
15626 // decremented to bring V closer to w.
15628 // pow10 = 10^n is now 1 ulp in the decimal representation V.
15629 // The rounding procedure works with diyfp's with an implicit
15632 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
15634 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
15635 grisu2_round(buffer, length, dist, delta, rest, ten_n);
15642 // pow10 = 10^(n-1) <= p1 < 10^n
15643 // Invariants restored.
15648 // The digits of the integral part have been generated:
15650 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
15651 // = buffer + p2 * 2^e
15653 // Now generate the digits of the fractional part p2 * 2^e.
15656 // No decimal point is generated: the exponent is adjusted instead.
15658 // p2 actually represents the fraction
15662 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
15664 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
15666 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
15667 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
15671 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
15672 // = ( d) * 2^-e + ( r)
15675 // 10^m * p2 * 2^e = d + r * 2^e
15679 // M+ = buffer + p2 * 2^e
15680 // = buffer + 10^-m * (d + r * 2^e)
15681 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
15683 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
15685 JSON_ASSERT(p2 > delta);
15691 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
15692 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
15693 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
15694 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
15696 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
15698 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
15699 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
15701 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
15702 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
15703 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
15705 JSON_ASSERT(d <= 9);
15706 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
15708 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
15713 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
15714 // Invariant restored.
15716 // Check if enough digits have been generated.
15718 // 10^-m * p2 * 2^e <= delta * 2^e
15719 // p2 * 2^e <= 10^m * delta * 2^e
15720 // p2 <= 10^m * delta
15729 // V = buffer * 10^-m, with M- <= V <= M+.
15731 decimal_exponent -= m;
15733 // 1 ulp in the decimal representation is now 10^-m.
15734 // Since delta and dist are now scaled by 10^m, we need to do the
15735 // same with ulp in order to keep the units in sync.
15737 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
15739 const std::uint64_t ten_m = one.f;
15740 grisu2_round(buffer, length, dist, delta, p2, ten_m);
15742 // By construction this algorithm generates the shortest possible decimal
15743 // number (Loitsch, Theorem 6.2) which rounds back to w.
15744 // For an input number of precision p, at least
15746 // N = 1 + ceil(p * log_10(2))
15748 // decimal digits are sufficient to identify all binary floating-point
15749 // numbers (Matula, "In-and-Out conversions").
15750 // This implies that the algorithm does not produce more than N decimal
15753 // N = 17 for p = 53 (IEEE double precision)
15754 // N = 9 for p = 24 (IEEE single precision)
15758 v = buf * 10^decimal_exponent
15759 len is the length of the buffer (number of decimal digits)
15760 The buffer must be large enough, i.e. >= max_digits10.
15762 JSON_HEDLEY_NON_NULL(1)
15763 inline void grisu2(char* buf, int& len, int& decimal_exponent,
15764 diyfp m_minus, diyfp v, diyfp m_plus)
15766 JSON_ASSERT(m_plus.e == m_minus.e);
15767 JSON_ASSERT(m_plus.e == v.e);
15769 // --------(-----------------------+-----------------------)-------- (A)
15772 // --------------------(-----------+-----------------------)-------- (B)
15775 // First scale v (and m- and m+) such that the exponent is in the range
15778 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
15780 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
15782 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
15783 const diyfp w = diyfp::mul(v, c_minus_k);
15784 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
15785 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
15787 // ----(---+---)---------------(---+---)---------------(---+---)----
15789 // = c*m- = c*v = c*m+
15791 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
15792 // w+ are now off by a small amount.
15795 // w - v * 10^k < 1 ulp
15797 // To account for this inaccuracy, add resp. subtract 1 ulp.
15799 // --------+---[---------------(---+---)---------------]---+--------
15802 // Now any number in [M-, M+] (bounds included) will round to w when input,
15803 // regardless of how the input rounding algorithm breaks ties.
15805 // And digit_gen generates the shortest possible such number in [M-, M+].
15806 // Note that this does not mean that Grisu2 always generates the shortest
15807 // possible number in the interval (m-, m+).
15808 const diyfp M_minus(w_minus.f + 1, w_minus.e);
15809 const diyfp M_plus (w_plus.f - 1, w_plus.e );
15811 decimal_exponent = -cached.k; // = -(-k) = k
15813 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
15817 v = buf * 10^decimal_exponent
15818 len is the length of the buffer (number of decimal digits)
15819 The buffer must be large enough, i.e. >= max_digits10.
15821 template<typename FloatType>
15822 JSON_HEDLEY_NON_NULL(1)
15823 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
15825 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
15826 "internal error: not enough precision");
15828 JSON_ASSERT(std::isfinite(value));
15829 JSON_ASSERT(value > 0);
15831 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
15832 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
15833 // decimal representations are not exactly "short".
15835 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
15836 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
15837 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
15839 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
15840 // representation using the corresponding std::from_chars function recovers value exactly". That
15841 // indicates that single precision floating-point numbers should be recovered using
15844 // NB: If the neighbors are computed for single-precision numbers, there is a single float
15845 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
15846 // value is off by 1 ulp.
15848 const boundaries w = compute_boundaries(static_cast<double>(value));
15850 const boundaries w = compute_boundaries(value);
15853 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
15857 @brief appends a decimal representation of e to buf
15858 @return a pointer to the element following the exponent.
15859 @pre -1000 < e < 1000
15861 JSON_HEDLEY_NON_NULL(1)
15862 JSON_HEDLEY_RETURNS_NON_NULL
15863 inline char* append_exponent(char* buf, int e)
15865 JSON_ASSERT(e > -1000);
15866 JSON_ASSERT(e < 1000);
15878 auto k = static_cast<std::uint32_t>(e);
15881 // Always print at least two digits in the exponent.
15882 // This is for compatibility with printf("%g").
15884 *buf++ = static_cast<char>('0' + k);
15888 *buf++ = static_cast<char>('0' + k / 10);
15890 *buf++ = static_cast<char>('0' + k);
15894 *buf++ = static_cast<char>('0' + k / 100);
15896 *buf++ = static_cast<char>('0' + k / 10);
15898 *buf++ = static_cast<char>('0' + k);
15905 @brief prettify v = buf * 10^decimal_exponent
15907 If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
15908 notation. Otherwise it will be printed in exponential notation.
15913 JSON_HEDLEY_NON_NULL(1)
15914 JSON_HEDLEY_RETURNS_NON_NULL
15915 inline char* format_buffer(char* buf, int len, int decimal_exponent,
15916 int min_exp, int max_exp)
15918 JSON_ASSERT(min_exp < 0);
15919 JSON_ASSERT(max_exp > 0);
15922 const int n = len + decimal_exponent;
15924 // v = buf * 10^(n-k)
15925 // k is the length of the buffer (number of decimal digits)
15926 // n is the position of the decimal point relative to the start of the buffer.
15928 if (k <= n && n <= max_exp)
15931 // len <= max_exp + 2
15933 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
15934 // Make it look like a floating-point number (#362, #378)
15937 return buf + (static_cast<size_t>(n) + 2);
15940 if (0 < n && n <= max_exp)
15943 // len <= max_digits10 + 1
15945 JSON_ASSERT(k > n);
15947 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
15949 return buf + (static_cast<size_t>(k) + 1U);
15952 if (min_exp < n && n <= 0)
15955 // len <= 2 + (-min_exp - 1) + max_digits10
15957 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
15960 std::memset(buf + 2, '0', static_cast<size_t>(-n));
15961 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
15974 // len <= max_digits10 + 1 + 5
15976 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
15978 buf += 1 + static_cast<size_t>(k);
15982 return append_exponent(buf, n - 1);
15985 } // namespace dtoa_impl
15988 @brief generates a decimal representation of the floating-point number value in [first, last).
15990 The format of the resulting decimal representation is similar to printf's %g
15991 format. Returns an iterator pointing past-the-end of the decimal representation.
15993 @note The input number must be finite, i.e. NaN's and Inf's are not supported.
15994 @note The buffer must be large enough.
15995 @note The result is NOT null-terminated.
15997 template<typename FloatType>
15998 JSON_HEDLEY_NON_NULL(1, 2)
15999 JSON_HEDLEY_RETURNS_NON_NULL
16000 char* to_chars(char* first, const char* last, FloatType value)
16002 static_cast<void>(last); // maybe unused - fix warning
16003 JSON_ASSERT(std::isfinite(value));
16005 // Use signbit(value) instead of (value < 0) since signbit works for -0.
16006 if (std::signbit(value))
16013 #pragma GCC diagnostic push
16014 #pragma GCC diagnostic ignored "-Wfloat-equal"
16016 if (value == 0) // +-0
16019 // Make it look like a floating-point number (#362, #378)
16025 #pragma GCC diagnostic pop
16028 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
16030 // Compute v = buffer * 10^decimal_exponent.
16031 // The decimal digits are stored in the buffer, which needs to be interpreted
16032 // as an unsigned decimal integer.
16033 // len is the length of the buffer, i.e. the number of decimal digits.
16035 int decimal_exponent = 0;
16036 dtoa_impl::grisu2(first, len, decimal_exponent, value);
16038 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
16040 // Format the buffer like printf("%.*g", prec, value)
16041 constexpr int kMinExp = -4;
16042 // Use digits10 here to increase compatibility with version 2.
16043 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
16045 JSON_ASSERT(last - first >= kMaxExp + 2);
16046 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
16047 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
16049 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
16052 } // namespace detail
16053 } // namespace nlohmann
16055 // #include <nlohmann/detail/exceptions.hpp>
16057 // #include <nlohmann/detail/macro_scope.hpp>
16059 // #include <nlohmann/detail/meta/cpp_future.hpp>
16061 // #include <nlohmann/detail/output/binary_writer.hpp>
16063 // #include <nlohmann/detail/output/output_adapters.hpp>
16065 // #include <nlohmann/detail/value_t.hpp>
16072 ///////////////////
16073 // serialization //
16074 ///////////////////
16076 /// how to treat decoding errors
16077 enum class error_handler_t
16079 strict, ///< throw a type_error exception in case of invalid UTF-8
16080 replace, ///< replace invalid UTF-8 sequences with U+FFFD
16081 ignore ///< ignore invalid UTF-8 sequences
16084 template<typename BasicJsonType>
16087 using string_t = typename BasicJsonType::string_t;
16088 using number_float_t = typename BasicJsonType::number_float_t;
16089 using number_integer_t = typename BasicJsonType::number_integer_t;
16090 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
16091 using binary_char_t = typename BasicJsonType::binary_t::value_type;
16092 static constexpr std::uint8_t UTF8_ACCEPT = 0;
16093 static constexpr std::uint8_t UTF8_REJECT = 1;
16097 @param[in] s output stream to serialize to
16098 @param[in] ichar indentation character to use
16099 @param[in] error_handler_ how to react on decoding errors
16101 serializer(output_adapter_t<char> s, const char ichar,
16102 error_handler_t error_handler_ = error_handler_t::strict)
16104 , loc(std::localeconv())
16105 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
16106 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
16107 , indent_char(ichar)
16108 , indent_string(512, indent_char)
16109 , error_handler(error_handler_)
16112 // delete because of pointer members
16113 serializer(const serializer&) = delete;
16114 serializer& operator=(const serializer&) = delete;
16115 serializer(serializer&&) = delete;
16116 serializer& operator=(serializer&&) = delete;
16117 ~serializer() = default;
16120 @brief internal implementation of the serialization function
16122 This function is called by the public member function dump and organizes
16123 the serialization internally. The indentation level is propagated as
16124 additional parameter. In case of arrays and objects, the function is
16125 called recursively.
16127 - strings and object keys are escaped using `escape_string()`
16128 - integer numbers are converted implicitly via `operator<<`
16129 - floating-point numbers are converted to a string using `"%g"` format
16130 - binary values are serialized as objects containing the subtype and the
16133 @param[in] val value to serialize
16134 @param[in] pretty_print whether the output shall be pretty-printed
16135 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
16136 in the output are escaped with `\uXXXX` sequences, and the result consists
16137 of ASCII characters only.
16138 @param[in] indent_step the indent level
16139 @param[in] current_indent the current indent level (only used internally)
16141 void dump(const BasicJsonType& val,
16142 const bool pretty_print,
16143 const bool ensure_ascii,
16144 const unsigned int indent_step,
16145 const unsigned int current_indent = 0)
16147 switch (val.m_type)
16149 case value_t::object:
16151 if (val.m_value.object->empty())
16153 o->write_characters("{}", 2);
16159 o->write_characters("{\n", 2);
16161 // variable to hold indentation for recursive calls
16162 const auto new_indent = current_indent + indent_step;
16163 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
16165 indent_string.resize(indent_string.size() * 2, ' ');
16168 // first n-1 elements
16169 auto i = val.m_value.object->cbegin();
16170 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
16172 o->write_characters(indent_string.c_str(), new_indent);
16173 o->write_character('\"');
16174 dump_escaped(i->first, ensure_ascii);
16175 o->write_characters("\": ", 3);
16176 dump(i->second, true, ensure_ascii, indent_step, new_indent);
16177 o->write_characters(",\n", 2);
16181 JSON_ASSERT(i != val.m_value.object->cend());
16182 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
16183 o->write_characters(indent_string.c_str(), new_indent);
16184 o->write_character('\"');
16185 dump_escaped(i->first, ensure_ascii);
16186 o->write_characters("\": ", 3);
16187 dump(i->second, true, ensure_ascii, indent_step, new_indent);
16189 o->write_character('\n');
16190 o->write_characters(indent_string.c_str(), current_indent);
16191 o->write_character('}');
16195 o->write_character('{');
16197 // first n-1 elements
16198 auto i = val.m_value.object->cbegin();
16199 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
16201 o->write_character('\"');
16202 dump_escaped(i->first, ensure_ascii);
16203 o->write_characters("\":", 2);
16204 dump(i->second, false, ensure_ascii, indent_step, current_indent);
16205 o->write_character(',');
16209 JSON_ASSERT(i != val.m_value.object->cend());
16210 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
16211 o->write_character('\"');
16212 dump_escaped(i->first, ensure_ascii);
16213 o->write_characters("\":", 2);
16214 dump(i->second, false, ensure_ascii, indent_step, current_indent);
16216 o->write_character('}');
16222 case value_t::array:
16224 if (val.m_value.array->empty())
16226 o->write_characters("[]", 2);
16232 o->write_characters("[\n", 2);
16234 // variable to hold indentation for recursive calls
16235 const auto new_indent = current_indent + indent_step;
16236 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
16238 indent_string.resize(indent_string.size() * 2, ' ');
16241 // first n-1 elements
16242 for (auto i = val.m_value.array->cbegin();
16243 i != val.m_value.array->cend() - 1; ++i)
16245 o->write_characters(indent_string.c_str(), new_indent);
16246 dump(*i, true, ensure_ascii, indent_step, new_indent);
16247 o->write_characters(",\n", 2);
16251 JSON_ASSERT(!val.m_value.array->empty());
16252 o->write_characters(indent_string.c_str(), new_indent);
16253 dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
16255 o->write_character('\n');
16256 o->write_characters(indent_string.c_str(), current_indent);
16257 o->write_character(']');
16261 o->write_character('[');
16263 // first n-1 elements
16264 for (auto i = val.m_value.array->cbegin();
16265 i != val.m_value.array->cend() - 1; ++i)
16267 dump(*i, false, ensure_ascii, indent_step, current_indent);
16268 o->write_character(',');
16272 JSON_ASSERT(!val.m_value.array->empty());
16273 dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
16275 o->write_character(']');
16281 case value_t::string:
16283 o->write_character('\"');
16284 dump_escaped(*val.m_value.string, ensure_ascii);
16285 o->write_character('\"');
16289 case value_t::binary:
16293 o->write_characters("{\n", 2);
16295 // variable to hold indentation for recursive calls
16296 const auto new_indent = current_indent + indent_step;
16297 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
16299 indent_string.resize(indent_string.size() * 2, ' ');
16302 o->write_characters(indent_string.c_str(), new_indent);
16304 o->write_characters("\"bytes\": [", 10);
16306 if (!val.m_value.binary->empty())
16308 for (auto i = val.m_value.binary->cbegin();
16309 i != val.m_value.binary->cend() - 1; ++i)
16312 o->write_characters(", ", 2);
16314 dump_integer(val.m_value.binary->back());
16317 o->write_characters("],\n", 3);
16318 o->write_characters(indent_string.c_str(), new_indent);
16320 o->write_characters("\"subtype\": ", 11);
16321 if (val.m_value.binary->has_subtype())
16323 dump_integer(val.m_value.binary->subtype());
16327 o->write_characters("null", 4);
16329 o->write_character('\n');
16330 o->write_characters(indent_string.c_str(), current_indent);
16331 o->write_character('}');
16335 o->write_characters("{\"bytes\":[", 10);
16337 if (!val.m_value.binary->empty())
16339 for (auto i = val.m_value.binary->cbegin();
16340 i != val.m_value.binary->cend() - 1; ++i)
16343 o->write_character(',');
16345 dump_integer(val.m_value.binary->back());
16348 o->write_characters("],\"subtype\":", 12);
16349 if (val.m_value.binary->has_subtype())
16351 dump_integer(val.m_value.binary->subtype());
16352 o->write_character('}');
16356 o->write_characters("null}", 5);
16362 case value_t::boolean:
16364 if (val.m_value.boolean)
16366 o->write_characters("true", 4);
16370 o->write_characters("false", 5);
16375 case value_t::number_integer:
16377 dump_integer(val.m_value.number_integer);
16381 case value_t::number_unsigned:
16383 dump_integer(val.m_value.number_unsigned);
16387 case value_t::number_float:
16389 dump_float(val.m_value.number_float);
16393 case value_t::discarded:
16395 o->write_characters("<discarded>", 11);
16399 case value_t::null:
16401 o->write_characters("null", 4);
16405 default: // LCOV_EXCL_LINE
16406 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16410 JSON_PRIVATE_UNLESS_TESTED:
16412 @brief dump escaped string
16414 Escape a string by replacing certain special characters by a sequence of an
16415 escape character (backslash) and another character and other control
16416 characters by a sequence of "\u" followed by a four-digit hex
16417 representation. The escaped string is written to output stream @a o.
16419 @param[in] s the string to escape
16420 @param[in] ensure_ascii whether to escape non-ASCII characters with
16423 @complexity Linear in the length of string @a s.
16425 void dump_escaped(const string_t& s, const bool ensure_ascii)
16427 std::uint32_t codepoint{};
16428 std::uint8_t state = UTF8_ACCEPT;
16429 std::size_t bytes = 0; // number of bytes written to string_buffer
16431 // number of bytes written at the point of the last valid byte
16432 std::size_t bytes_after_last_accept = 0;
16433 std::size_t undumped_chars = 0;
16435 for (std::size_t i = 0; i < s.size(); ++i)
16437 const auto byte = static_cast<std::uint8_t>(s[i]);
16439 switch (decode(state, codepoint, byte))
16441 case UTF8_ACCEPT: // decode found a new code point
16445 case 0x08: // backspace
16447 string_buffer[bytes++] = '\\';
16448 string_buffer[bytes++] = 'b';
16452 case 0x09: // horizontal tab
16454 string_buffer[bytes++] = '\\';
16455 string_buffer[bytes++] = 't';
16459 case 0x0A: // newline
16461 string_buffer[bytes++] = '\\';
16462 string_buffer[bytes++] = 'n';
16466 case 0x0C: // formfeed
16468 string_buffer[bytes++] = '\\';
16469 string_buffer[bytes++] = 'f';
16473 case 0x0D: // carriage return
16475 string_buffer[bytes++] = '\\';
16476 string_buffer[bytes++] = 'r';
16480 case 0x22: // quotation mark
16482 string_buffer[bytes++] = '\\';
16483 string_buffer[bytes++] = '\"';
16487 case 0x5C: // reverse solidus
16489 string_buffer[bytes++] = '\\';
16490 string_buffer[bytes++] = '\\';
16496 // escape control characters (0x00..0x1F) or, if
16497 // ensure_ascii parameter is used, non-ASCII characters
16498 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
16500 if (codepoint <= 0xFFFF)
16502 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
16503 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
16504 static_cast<std::uint16_t>(codepoint)));
16509 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
16510 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
16511 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
16512 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
16518 // copy byte to buffer (all previous bytes
16519 // been copied have in default case above)
16520 string_buffer[bytes++] = s[i];
16526 // write buffer and reset index; there must be 13 bytes
16527 // left, as this is the maximal number of bytes to be
16528 // written ("\uxxxx\uxxxx\0") for one code point
16529 if (string_buffer.size() - bytes < 13)
16531 o->write_characters(string_buffer.data(), bytes);
16535 // remember the byte position of this accept
16536 bytes_after_last_accept = bytes;
16537 undumped_chars = 0;
16541 case UTF8_REJECT: // decode found invalid UTF-8 byte
16543 switch (error_handler)
16545 case error_handler_t::strict:
16547 std::stringstream ss;
16548 ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (byte | 0);
16549 JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + ss.str(), BasicJsonType()));
16552 case error_handler_t::ignore:
16553 case error_handler_t::replace:
16555 // in case we saw this character the first time, we
16556 // would like to read it again, because the byte
16557 // may be OK for itself, but just not OK for the
16558 // previous sequence
16559 if (undumped_chars > 0)
16564 // reset length buffer to the last accepted index;
16565 // thus removing/ignoring the invalid characters
16566 bytes = bytes_after_last_accept;
16568 if (error_handler == error_handler_t::replace)
16570 // add a replacement character
16573 string_buffer[bytes++] = '\\';
16574 string_buffer[bytes++] = 'u';
16575 string_buffer[bytes++] = 'f';
16576 string_buffer[bytes++] = 'f';
16577 string_buffer[bytes++] = 'f';
16578 string_buffer[bytes++] = 'd';
16582 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
16583 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
16584 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
16587 // write buffer and reset index; there must be 13 bytes
16588 // left, as this is the maximal number of bytes to be
16589 // written ("\uxxxx\uxxxx\0") for one code point
16590 if (string_buffer.size() - bytes < 13)
16592 o->write_characters(string_buffer.data(), bytes);
16596 bytes_after_last_accept = bytes;
16599 undumped_chars = 0;
16601 // continue processing the string
16602 state = UTF8_ACCEPT;
16606 default: // LCOV_EXCL_LINE
16607 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16612 default: // decode found yet incomplete multi-byte code point
16616 // code point will not be escaped - copy byte to buffer
16617 string_buffer[bytes++] = s[i];
16625 // we finished processing the string
16626 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
16631 o->write_characters(string_buffer.data(), bytes);
16636 // we finish reading, but do not accept: string was incomplete
16637 switch (error_handler)
16639 case error_handler_t::strict:
16641 std::stringstream ss;
16642 ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (static_cast<std::uint8_t>(s.back()) | 0);
16643 JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + ss.str(), BasicJsonType()));
16646 case error_handler_t::ignore:
16648 // write all accepted bytes
16649 o->write_characters(string_buffer.data(), bytes_after_last_accept);
16653 case error_handler_t::replace:
16655 // write all accepted bytes
16656 o->write_characters(string_buffer.data(), bytes_after_last_accept);
16657 // add a replacement character
16660 o->write_characters("\\ufffd", 6);
16664 o->write_characters("\xEF\xBF\xBD", 3);
16669 default: // LCOV_EXCL_LINE
16670 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16677 @brief count digits
16679 Count the number of decimal (base 10) digits for an input unsigned integer.
16681 @param[in] x unsigned integer number to count its digits
16682 @return number of decimal digits
16684 inline unsigned int count_digits(number_unsigned_t x) noexcept
16686 unsigned int n_digits = 1;
16695 return n_digits + 1;
16699 return n_digits + 2;
16703 return n_digits + 3;
16710 // templates to avoid warnings about useless casts
16711 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
16712 bool is_negative_number(NumberType x)
16717 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
16718 bool is_negative_number(NumberType /*unused*/)
16724 @brief dump an integer
16726 Dump a given integer to output stream @a o. Works internally with
16729 @param[in] x integer number (signed or unsigned) to dump
16730 @tparam NumberType either @a number_integer_t or @a number_unsigned_t
16732 template < typename NumberType, detail::enable_if_t <
16733 std::is_integral<NumberType>::value ||
16734 std::is_same<NumberType, number_unsigned_t>::value ||
16735 std::is_same<NumberType, number_integer_t>::value ||
16736 std::is_same<NumberType, binary_char_t>::value,
16738 void dump_integer(NumberType x)
16740 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
16743 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
16744 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
16745 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
16746 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
16747 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
16748 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
16749 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
16750 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
16751 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
16752 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
16756 // special case for "0"
16759 o->write_character('0');
16763 // use a pointer to fill the buffer
16764 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
16766 number_unsigned_t abs_value;
16768 unsigned int n_chars{};
16770 if (is_negative_number(x))
16773 abs_value = remove_sign(static_cast<number_integer_t>(x));
16775 // account one more byte for the minus sign
16776 n_chars = 1 + count_digits(abs_value);
16780 abs_value = static_cast<number_unsigned_t>(x);
16781 n_chars = count_digits(abs_value);
16784 // spare 1 byte for '\0'
16785 JSON_ASSERT(n_chars < number_buffer.size() - 1);
16787 // jump to the end to generate the string from backward,
16788 // so we later avoid reversing the result
16789 buffer_ptr += n_chars;
16791 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
16792 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
16793 while (abs_value >= 100)
16795 const auto digits_index = static_cast<unsigned>((abs_value % 100));
16797 *(--buffer_ptr) = digits_to_99[digits_index][1];
16798 *(--buffer_ptr) = digits_to_99[digits_index][0];
16801 if (abs_value >= 10)
16803 const auto digits_index = static_cast<unsigned>(abs_value);
16804 *(--buffer_ptr) = digits_to_99[digits_index][1];
16805 *(--buffer_ptr) = digits_to_99[digits_index][0];
16809 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
16812 o->write_characters(number_buffer.data(), n_chars);
16816 @brief dump a floating-point number
16818 Dump a given floating-point number to output stream @a o. Works internally
16819 with @a number_buffer.
16821 @param[in] x floating-point number to dump
16823 void dump_float(number_float_t x)
16826 if (!std::isfinite(x))
16828 o->write_characters("null", 4);
16832 // If number_float_t is an IEEE-754 single or double precision number,
16833 // use the Grisu2 algorithm to produce short numbers which are
16834 // guaranteed to round-trip, using strtof and strtod, resp.
16836 // NB: The test below works if <long double> == <double>.
16837 static constexpr bool is_ieee_single_or_double
16838 = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
16839 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
16841 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
16844 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
16846 auto* begin = number_buffer.data();
16847 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
16849 o->write_characters(begin, static_cast<size_t>(end - begin));
16852 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
16854 // get number of digits for a float -> text -> float round-trip
16855 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
16857 // the actual conversion
16858 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
16859 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
16861 // negative value indicates an error
16862 JSON_ASSERT(len > 0);
16863 // check if buffer was large enough
16864 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
16866 // erase thousands separator
16867 if (thousands_sep != '\0')
16869 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
16870 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
16871 std::fill(end, number_buffer.end(), '\0');
16872 JSON_ASSERT((end - number_buffer.begin()) <= len);
16873 len = (end - number_buffer.begin());
16876 // convert decimal point to '.'
16877 if (decimal_point != '\0' && decimal_point != '.')
16879 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
16880 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
16881 if (dec_pos != number_buffer.end())
16887 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
16889 // determine if we need to append ".0"
16890 const bool value_is_int_like =
16891 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
16894 return c == '.' || c == 'e';
16897 if (value_is_int_like)
16899 o->write_characters(".0", 2);
16904 @brief check whether a string is UTF-8 encoded
16906 The function checks each byte of a string whether it is UTF-8 encoded. The
16907 result of the check is stored in the @a state parameter. The function must
16908 be called initially with state 0 (accept). State 1 means the string must
16909 be rejected, because the current byte is not allowed. If the string is
16910 completely processed, but the state is non-zero, the string ended
16911 prematurely; that is, the last byte indicated more bytes should have
16914 @param[in,out] state the state of the decoding
16915 @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
16916 @param[in] byte next byte to decode
16919 @note The function has been edited: a std::array is used.
16921 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
16922 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
16924 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
16926 static const std::array<std::uint8_t, 400> utf8d =
16929 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
16930 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
16931 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
16932 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
16933 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
16934 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
16935 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
16936 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
16937 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
16938 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
16939 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
16940 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
16941 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
16942 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
16946 JSON_ASSERT(byte < utf8d.size());
16947 const std::uint8_t type = utf8d[byte];
16949 codep = (state != UTF8_ACCEPT)
16950 ? (byte & 0x3fu) | (codep << 6u)
16951 : (0xFFu >> type) & (byte);
16953 std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
16954 JSON_ASSERT(index < 400);
16955 state = utf8d[index];
16960 * Overload to make the compiler happy while it is instantiating
16961 * dump_integer for number_unsigned_t.
16962 * Must never be called.
16964 number_unsigned_t remove_sign(number_unsigned_t x)
16966 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16967 return x; // LCOV_EXCL_LINE
16971 * Helper function for dump_integer
16973 * This function takes a negative signed integer and returns its absolute
16974 * value as unsigned integer. The plus/minus shuffling is necessary as we can
16975 * not directly remove the sign of an arbitrary signed integer as the
16976 * absolute values of INT_MIN and INT_MAX are usually not the same. See
16977 * #1708 for details.
16979 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
16981 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
16982 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
16986 /// the output of the serializer
16987 output_adapter_t<char> o = nullptr;
16989 /// a (hopefully) large enough character buffer
16990 std::array<char, 64> number_buffer{{}};
16993 const std::lconv* loc = nullptr;
16994 /// the locale's thousand separator character
16995 const char thousands_sep = '\0';
16996 /// the locale's decimal point character
16997 const char decimal_point = '\0';
17000 std::array<char, 512> string_buffer{{}};
17002 /// the indentation character
17003 const char indent_char;
17004 /// the indentation string
17005 string_t indent_string;
17007 /// error_handler how to react on decoding errors
17008 const error_handler_t error_handler;
17010 } // namespace detail
17011 } // namespace nlohmann
17013 // #include <nlohmann/detail/value_t.hpp>
17015 // #include <nlohmann/json_fwd.hpp>
17017 // #include <nlohmann/ordered_map.hpp>
17020 #include <functional> // less
17021 #include <initializer_list> // initializer_list
17022 #include <iterator> // input_iterator_tag, iterator_traits
17023 #include <memory> // allocator
17024 #include <stdexcept> // for out_of_range
17025 #include <type_traits> // enable_if, is_convertible
17026 #include <utility> // pair
17027 #include <vector> // vector
17029 // #include <nlohmann/detail/macro_scope.hpp>
17035 /// ordered_map: a minimal map-like container that preserves insertion order
17036 /// for use within nlohmann::basic_json<ordered_map>
17037 template <class Key, class T, class IgnoredLess = std::less<Key>,
17038 class Allocator = std::allocator<std::pair<const Key, T>>>
17039 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
17041 using key_type = Key;
17042 using mapped_type = T;
17043 using Container = std::vector<std::pair<const Key, T>, Allocator>;
17044 using iterator = typename Container::iterator;
17045 using const_iterator = typename Container::const_iterator;
17046 using size_type = typename Container::size_type;
17047 using value_type = typename Container::value_type;
17049 // Explicit constructors instead of `using Container::Container`
17050 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
17051 ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {}
17052 template <class It>
17053 ordered_map(It first, It last, const Allocator& alloc = Allocator())
17054 : Container{first, last, alloc} {}
17055 ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator() )
17056 : Container{init, alloc} {}
17058 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
17060 for (auto it = this->begin(); it != this->end(); ++it)
17062 if (it->first == key)
17064 return {it, false};
17067 Container::emplace_back(key, t);
17068 return {--this->end(), true};
17071 T& operator[](const Key& key)
17073 return emplace(key, T{}).first->second;
17076 const T& operator[](const Key& key) const
17081 T& at(const Key& key)
17083 for (auto it = this->begin(); it != this->end(); ++it)
17085 if (it->first == key)
17091 JSON_THROW(std::out_of_range("key not found"));
17094 const T& at(const Key& key) const
17096 for (auto it = this->begin(); it != this->end(); ++it)
17098 if (it->first == key)
17104 JSON_THROW(std::out_of_range("key not found"));
17107 size_type erase(const Key& key)
17109 for (auto it = this->begin(); it != this->end(); ++it)
17111 if (it->first == key)
17113 // Since we cannot move const Keys, re-construct them in place
17114 for (auto next = it; ++next != this->end(); ++it)
17116 it->~value_type(); // Destroy but keep allocation
17117 new (&*it) value_type{std::move(*next)};
17119 Container::pop_back();
17126 iterator erase(iterator pos)
17128 return erase(pos, std::next(pos));
17131 iterator erase(iterator first, iterator last)
17133 const auto elements_affected = std::distance(first, last);
17134 const auto offset = std::distance(Container::begin(), first);
17136 // This is the start situation. We need to delete elements_affected
17137 // elements (3 in this example: e, f, g), and need to return an
17138 // iterator past the last deleted element (h in this example).
17139 // Note that offset is the distance from the start of the vector
17140 // to first. We will need this later.
17142 // [ a, b, c, d, e, f, g, h, i, j ]
17146 // Since we cannot move const Keys, we re-construct them in place.
17147 // We start at first and re-construct (viz. copy) the elements from
17148 // the back of the vector. Example for first iteration:
17151 // v | destroy e and re-construct with h
17152 // [ a, b, c, d, e, f, g, h, i, j ]
17154 // it it + elements_affected
17156 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
17158 it->~value_type(); // destroy but keep allocation
17159 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
17162 // [ a, b, c, d, h, i, j, h, i, j ]
17166 // remove the unneeded elements at the end of the vector
17167 Container::resize(this->size() - static_cast<size_type>(elements_affected));
17169 // [ a, b, c, d, h, i, j ]
17173 // first is now pointing past the last deleted element, but we cannot
17174 // use this iterator, because it may have been invalidated by the
17175 // resize call. Instead, we can return begin() + offset.
17176 return Container::begin() + offset;
17179 size_type count(const Key& key) const
17181 for (auto it = this->begin(); it != this->end(); ++it)
17183 if (it->first == key)
17191 iterator find(const Key& key)
17193 for (auto it = this->begin(); it != this->end(); ++it)
17195 if (it->first == key)
17200 return Container::end();
17203 const_iterator find(const Key& key) const
17205 for (auto it = this->begin(); it != this->end(); ++it)
17207 if (it->first == key)
17212 return Container::end();
17215 std::pair<iterator, bool> insert( value_type&& value )
17217 return emplace(value.first, std::move(value.second));
17220 std::pair<iterator, bool> insert( const value_type& value )
17222 for (auto it = this->begin(); it != this->end(); ++it)
17224 if (it->first == value.first)
17226 return {it, false};
17229 Container::push_back(value);
17230 return {--this->end(), true};
17233 template<typename InputIt>
17234 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
17235 std::input_iterator_tag>::value>::type;
17237 template<typename InputIt, typename = require_input_iter<InputIt>>
17238 void insert(InputIt first, InputIt last)
17240 for (auto it = first; it != last; ++it)
17247 } // namespace nlohmann
17250 #if defined(JSON_HAS_CPP_17)
17251 #include <string_view>
17255 @brief namespace for Niels Lohmann
17256 @see https://github.com/nlohmann
17257 @since version 1.0.0
17263 @brief a class to store JSON values
17266 @invariant The member variables @a m_value and @a m_type have the following
17268 - If `m_type == value_t::object`, then `m_value.object != nullptr`.
17269 - If `m_type == value_t::array`, then `m_value.array != nullptr`.
17270 - If `m_type == value_t::string`, then `m_value.string != nullptr`.
17271 The invariants are checked by member function assert_invariant().
17273 @note ObjectType trick from https://stackoverflow.com/a/9860911
17276 @since version 1.0.0
17280 NLOHMANN_BASIC_JSON_TPL_DECLARATION
17281 class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
17284 template<detail::value_t> friend struct detail::external_constructor;
17285 friend ::nlohmann::json_pointer<basic_json>;
17287 template<typename BasicJsonType, typename InputType>
17288 friend class ::nlohmann::detail::parser;
17289 friend ::nlohmann::detail::serializer<basic_json>;
17290 template<typename BasicJsonType>
17291 friend class ::nlohmann::detail::iter_impl;
17292 template<typename BasicJsonType, typename CharType>
17293 friend class ::nlohmann::detail::binary_writer;
17294 template<typename BasicJsonType, typename InputType, typename SAX>
17295 friend class ::nlohmann::detail::binary_reader;
17296 template<typename BasicJsonType>
17297 friend class ::nlohmann::detail::json_sax_dom_parser;
17298 template<typename BasicJsonType>
17299 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
17300 friend class ::nlohmann::detail::exception;
17302 /// workaround type for MSVC
17303 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
17305 JSON_PRIVATE_UNLESS_TESTED:
17306 // convenience aliases for types residing in namespace detail;
17307 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
17309 template<typename InputAdapterType>
17310 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
17311 InputAdapterType adapter,
17312 detail::parser_callback_t<basic_json>cb = nullptr,
17313 const bool allow_exceptions = true,
17314 const bool ignore_comments = false
17317 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
17318 std::move(cb), allow_exceptions, ignore_comments);
17322 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
17323 template<typename BasicJsonType>
17324 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
17325 template<typename BasicJsonType>
17326 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
17327 template<typename Iterator>
17328 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
17329 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
17331 template<typename CharType>
17332 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
17334 template<typename InputType>
17335 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
17336 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
17338 JSON_PRIVATE_UNLESS_TESTED:
17339 using serializer = ::nlohmann::detail::serializer<basic_json>;
17342 using value_t = detail::value_t;
17343 /// JSON Pointer, see @ref nlohmann::json_pointer
17344 using json_pointer = ::nlohmann::json_pointer<basic_json>;
17345 template<typename T, typename SFINAE>
17346 using json_serializer = JSONSerializer<T, SFINAE>;
17347 /// how to treat decoding errors
17348 using error_handler_t = detail::error_handler_t;
17349 /// how to treat CBOR tags
17350 using cbor_tag_handler_t = detail::cbor_tag_handler_t;
17351 /// helper type for initializer lists of basic_json values
17352 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
17354 using input_format_t = detail::input_format_t;
17355 /// SAX interface type, see @ref nlohmann::json_sax
17356 using json_sax_t = json_sax<basic_json>;
17362 /// @name exceptions
17363 /// Classes to implement user-defined exceptions.
17366 using exception = detail::exception;
17367 using parse_error = detail::parse_error;
17368 using invalid_iterator = detail::invalid_iterator;
17369 using type_error = detail::type_error;
17370 using out_of_range = detail::out_of_range;
17371 using other_error = detail::other_error;
17376 /////////////////////
17377 // container types //
17378 /////////////////////
17380 /// @name container types
17381 /// The canonic container types to use @ref basic_json like any other STL
17385 /// the type of elements in a basic_json container
17386 using value_type = basic_json;
17388 /// the type of an element reference
17389 using reference = value_type&;
17390 /// the type of an element const reference
17391 using const_reference = const value_type&;
17393 /// a type to represent differences between iterators
17394 using difference_type = std::ptrdiff_t;
17395 /// a type to represent container sizes
17396 using size_type = std::size_t;
17398 /// the allocator type
17399 using allocator_type = AllocatorType<basic_json>;
17401 /// the type of an element pointer
17402 using pointer = typename std::allocator_traits<allocator_type>::pointer;
17403 /// the type of an element const pointer
17404 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
17406 /// an iterator for a basic_json container
17407 using iterator = iter_impl<basic_json>;
17408 /// a const iterator for a basic_json container
17409 using const_iterator = iter_impl<const basic_json>;
17410 /// a reverse iterator for a basic_json container
17411 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
17412 /// a const reverse iterator for a basic_json container
17413 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
17418 /// @brief returns the allocator associated with the container
17419 /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
17420 static allocator_type get_allocator()
17422 return allocator_type();
17425 /// @brief returns version information on the library
17426 /// @sa https://json.nlohmann.me/api/basic_json/meta/
17427 JSON_HEDLEY_WARN_UNUSED_RESULT
17428 static basic_json meta()
17432 result["copyright"] = "(C) 2013-2022 Niels Lohmann";
17433 result["name"] = "JSON for Modern C++";
17434 result["url"] = "https://github.com/nlohmann/json";
17435 result["version"]["string"] =
17436 std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
17437 std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
17438 std::to_string(NLOHMANN_JSON_VERSION_PATCH);
17439 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
17440 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
17441 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
17444 result["platform"] = "win32";
17445 #elif defined __linux__
17446 result["platform"] = "linux";
17447 #elif defined __APPLE__
17448 result["platform"] = "apple";
17449 #elif defined __unix__
17450 result["platform"] = "unix";
17452 result["platform"] = "unknown";
17455 #if defined(__ICC) || defined(__INTEL_COMPILER)
17456 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
17457 #elif defined(__clang__)
17458 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
17459 #elif defined(__GNUC__) || defined(__GNUG__)
17460 result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
17461 #elif defined(__HP_cc) || defined(__HP_aCC)
17462 result["compiler"] = "hp"
17463 #elif defined(__IBMCPP__)
17464 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
17465 #elif defined(_MSC_VER)
17466 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
17467 #elif defined(__PGI)
17468 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
17469 #elif defined(__SUNPRO_CC)
17470 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
17472 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
17476 result["compiler"]["c++"] = std::to_string(__cplusplus);
17478 result["compiler"]["c++"] = "unknown";
17484 ///////////////////////////
17485 // JSON value data types //
17486 ///////////////////////////
17488 /// @name JSON value data types
17489 /// The data types to store a JSON value. These types are derived from
17490 /// the template arguments passed to class @ref basic_json.
17493 /// @brief object key comparator type
17494 /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
17495 #if defined(JSON_HAS_CPP_14)
17496 // Use transparent comparator if possible, combined with perfect forwarding
17497 // on find() and count() calls prevents unnecessary string construction.
17498 using object_comparator_t = std::less<>;
17500 using object_comparator_t = std::less<StringType>;
17503 /// @brief a type for an object
17504 /// @sa https://json.nlohmann.me/api/basic_json/object_t/
17505 using object_t = ObjectType<StringType,
17507 object_comparator_t,
17508 AllocatorType<std::pair<const StringType,
17511 /// @brief a type for an array
17512 /// @sa https://json.nlohmann.me/api/basic_json/array_t/
17513 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
17515 /// @brief a type for a string
17516 /// @sa https://json.nlohmann.me/api/basic_json/string_t/
17517 using string_t = StringType;
17519 /// @brief a type for a boolean
17520 /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
17521 using boolean_t = BooleanType;
17523 /// @brief a type for a number (integer)
17524 /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
17525 using number_integer_t = NumberIntegerType;
17527 /// @brief a type for a number (unsigned)
17528 /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
17529 using number_unsigned_t = NumberUnsignedType;
17531 /// @brief a type for a number (floating-point)
17532 /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
17533 using number_float_t = NumberFloatType;
17535 /// @brief a type for a packed binary type
17536 /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
17537 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
17543 /// helper for exception-safe object creation
17544 template<typename T, typename... Args>
17545 JSON_HEDLEY_RETURNS_NON_NULL
17546 static T* create(Args&& ... args)
17548 AllocatorType<T> alloc;
17549 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
17551 auto deleter = [&](T * obj)
17553 AllocatorTraits::deallocate(alloc, obj, 1);
17555 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
17556 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
17557 JSON_ASSERT(obj != nullptr);
17558 return obj.release();
17561 ////////////////////////
17562 // JSON value storage //
17563 ////////////////////////
17565 JSON_PRIVATE_UNLESS_TESTED:
17567 @brief a JSON value
17569 The actual storage for a JSON value of the @ref basic_json class. This
17570 union combines the different storage types for the JSON value types
17571 defined in @ref value_t.
17573 JSON type | value_t type | used type
17574 --------- | --------------- | ------------------------
17575 object | object | pointer to @ref object_t
17576 array | array | pointer to @ref array_t
17577 string | string | pointer to @ref string_t
17578 boolean | boolean | @ref boolean_t
17579 number | number_integer | @ref number_integer_t
17580 number | number_unsigned | @ref number_unsigned_t
17581 number | number_float | @ref number_float_t
17582 binary | binary | pointer to @ref binary_t
17583 null | null | *no value is stored*
17585 @note Variable-length types (objects, arrays, and strings) are stored as
17586 pointers. The size of the union should not exceed 64 bits if the default
17587 value types are used.
17589 @since version 1.0.0
17593 /// object (stored with pointer to save storage)
17595 /// array (stored with pointer to save storage)
17597 /// string (stored with pointer to save storage)
17599 /// binary (stored with pointer to save storage)
17603 /// number (integer)
17604 number_integer_t number_integer;
17605 /// number (unsigned integer)
17606 number_unsigned_t number_unsigned;
17607 /// number (floating-point)
17608 number_float_t number_float;
17610 /// default constructor (for null values)
17611 json_value() = default;
17612 /// constructor for booleans
17613 json_value(boolean_t v) noexcept : boolean(v) {}
17614 /// constructor for numbers (integer)
17615 json_value(number_integer_t v) noexcept : number_integer(v) {}
17616 /// constructor for numbers (unsigned)
17617 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
17618 /// constructor for numbers (floating-point)
17619 json_value(number_float_t v) noexcept : number_float(v) {}
17620 /// constructor for empty values of a given type
17621 json_value(value_t t)
17625 case value_t::object:
17627 object = create<object_t>();
17631 case value_t::array:
17633 array = create<array_t>();
17637 case value_t::string:
17639 string = create<string_t>("");
17643 case value_t::binary:
17645 binary = create<binary_t>();
17649 case value_t::boolean:
17651 boolean = static_cast<boolean_t>(false);
17655 case value_t::number_integer:
17657 number_integer = static_cast<number_integer_t>(0);
17661 case value_t::number_unsigned:
17663 number_unsigned = static_cast<number_unsigned_t>(0);
17667 case value_t::number_float:
17669 number_float = static_cast<number_float_t>(0.0);
17673 case value_t::null:
17675 object = nullptr; // silence warning, see #821
17679 case value_t::discarded:
17682 object = nullptr; // silence warning, see #821
17683 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
17685 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5", basic_json())); // LCOV_EXCL_LINE
17692 /// constructor for strings
17693 json_value(const string_t& value) : string(create<string_t>(value)) {}
17695 /// constructor for rvalue strings
17696 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
17698 /// constructor for objects
17699 json_value(const object_t& value) : object(create<object_t>(value)) {}
17701 /// constructor for rvalue objects
17702 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
17704 /// constructor for arrays
17705 json_value(const array_t& value) : array(create<array_t>(value)) {}
17707 /// constructor for rvalue arrays
17708 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
17710 /// constructor for binary arrays
17711 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
17713 /// constructor for rvalue binary arrays
17714 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
17716 /// constructor for binary arrays (internal type)
17717 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
17719 /// constructor for rvalue binary arrays (internal type)
17720 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
17722 void destroy(value_t t)
17724 if (t == value_t::array || t == value_t::object)
17726 // flatten the current json_value to a heap-allocated stack
17727 std::vector<basic_json> stack;
17729 // move the top-level items to stack
17730 if (t == value_t::array)
17732 stack.reserve(array->size());
17733 std::move(array->begin(), array->end(), std::back_inserter(stack));
17737 stack.reserve(object->size());
17738 for (auto&& it : *object)
17740 stack.push_back(std::move(it.second));
17744 while (!stack.empty())
17746 // move the last item to local variable to be processed
17747 basic_json current_item(std::move(stack.back()));
17750 // if current_item is array/object, move
17751 // its children to the stack to be processed later
17752 if (current_item.is_array())
17754 std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack));
17756 current_item.m_value.array->clear();
17758 else if (current_item.is_object())
17760 for (auto&& it : *current_item.m_value.object)
17762 stack.push_back(std::move(it.second));
17765 current_item.m_value.object->clear();
17768 // it's now safe that current_item get destructed
17769 // since it doesn't have any children
17775 case value_t::object:
17777 AllocatorType<object_t> alloc;
17778 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
17779 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
17783 case value_t::array:
17785 AllocatorType<array_t> alloc;
17786 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
17787 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
17791 case value_t::string:
17793 AllocatorType<string_t> alloc;
17794 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
17795 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
17799 case value_t::binary:
17801 AllocatorType<binary_t> alloc;
17802 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
17803 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
17807 case value_t::null:
17808 case value_t::boolean:
17809 case value_t::number_integer:
17810 case value_t::number_unsigned:
17811 case value_t::number_float:
17812 case value_t::discarded:
17823 @brief checks the class invariants
17825 This function asserts the class invariants. It needs to be called at the
17826 end of every constructor to make sure that created objects respect the
17827 invariant. Furthermore, it has to be called each time the type of a JSON
17828 value is changed, because the invariant expresses a relationship between
17829 @a m_type and @a m_value.
17831 Furthermore, the parent relation is checked for arrays and objects: If
17832 @a check_parents true and the value is an array or object, then the
17833 container's elements must have the current value as parent.
17835 @param[in] check_parents whether the parent relation should be checked.
17836 The value is true by default and should only be set to false
17837 during destruction of objects when the invariant does not
17840 void assert_invariant(bool check_parents = true) const noexcept
17842 JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
17843 JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
17844 JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
17845 JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
17847 #if JSON_DIAGNOSTICS
17850 // cppcheck-suppress assertWithSideEffect
17851 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
17853 return j.m_parent == this;
17856 JSON_CATCH(...) {} // LCOV_EXCL_LINE
17858 static_cast<void>(check_parents);
17863 #if JSON_DIAGNOSTICS
17866 case value_t::array:
17868 for (auto& element : *m_value.array)
17870 element.m_parent = this;
17875 case value_t::object:
17877 for (auto& element : *m_value.object)
17879 element.second.m_parent = this;
17884 case value_t::null:
17885 case value_t::string:
17886 case value_t::boolean:
17887 case value_t::number_integer:
17888 case value_t::number_unsigned:
17889 case value_t::number_float:
17890 case value_t::binary:
17891 case value_t::discarded:
17898 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
17900 #if JSON_DIAGNOSTICS
17901 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
17903 (it + i)->m_parent = this;
17906 static_cast<void>(count_set_parents);
17911 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
17913 #if JSON_DIAGNOSTICS
17914 if (old_capacity != static_cast<std::size_t>(-1))
17916 // see https://github.com/nlohmann/json/issues/2838
17917 JSON_ASSERT(type() == value_t::array);
17918 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
17920 // capacity has changed: update all parents
17926 // ordered_json uses a vector internally, so pointers could have
17927 // been invalidated; see https://github.com/nlohmann/json/issues/2962
17928 #ifdef JSON_HEDLEY_MSVC_VERSION
17929 #pragma warning(push )
17930 #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
17932 if (detail::is_ordered_map<object_t>::value)
17937 #ifdef JSON_HEDLEY_MSVC_VERSION
17938 #pragma warning( pop )
17943 static_cast<void>(j);
17944 static_cast<void>(old_capacity);
17950 //////////////////////////
17951 // JSON parser callback //
17952 //////////////////////////
17954 /// @brief parser event types
17955 /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
17956 using parse_event_t = detail::parse_event_t;
17958 /// @brief per-element parser callback type
17959 /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
17960 using parser_callback_t = detail::parser_callback_t<basic_json>;
17966 /// @name constructors and destructors
17967 /// Constructors of class @ref basic_json, copy/move constructor, copy
17968 /// assignment, static functions creating objects, and the destructor.
17971 /// @brief create an empty value with a given type
17972 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
17973 basic_json(const value_t v)
17974 : m_type(v), m_value(v)
17976 assert_invariant();
17979 /// @brief create a null object
17980 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
17981 basic_json(std::nullptr_t = nullptr) noexcept
17982 : basic_json(value_t::null)
17984 assert_invariant();
17987 /// @brief create a JSON value from compatible types
17988 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
17989 template < typename CompatibleType,
17990 typename U = detail::uncvref_t<CompatibleType>,
17991 detail::enable_if_t <
17992 !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
17993 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
17994 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
17995 std::forward<CompatibleType>(val))))
17997 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
17999 assert_invariant();
18002 /// @brief create a JSON value from an existing one
18003 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18004 template < typename BasicJsonType,
18005 detail::enable_if_t <
18006 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
18007 basic_json(const BasicJsonType& val)
18009 using other_boolean_t = typename BasicJsonType::boolean_t;
18010 using other_number_float_t = typename BasicJsonType::number_float_t;
18011 using other_number_integer_t = typename BasicJsonType::number_integer_t;
18012 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18013 using other_string_t = typename BasicJsonType::string_t;
18014 using other_object_t = typename BasicJsonType::object_t;
18015 using other_array_t = typename BasicJsonType::array_t;
18016 using other_binary_t = typename BasicJsonType::binary_t;
18018 switch (val.type())
18020 case value_t::boolean:
18021 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
18023 case value_t::number_float:
18024 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
18026 case value_t::number_integer:
18027 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
18029 case value_t::number_unsigned:
18030 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
18032 case value_t::string:
18033 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
18035 case value_t::object:
18036 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
18038 case value_t::array:
18039 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
18041 case value_t::binary:
18042 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
18044 case value_t::null:
18047 case value_t::discarded:
18048 m_type = value_t::discarded;
18050 default: // LCOV_EXCL_LINE
18051 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18054 assert_invariant();
18057 /// @brief create a container (array or object) from an initializer list
18058 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18059 basic_json(initializer_list_t init,
18060 bool type_deduction = true,
18061 value_t manual_type = value_t::array)
18063 // check if each element is an array with two elements whose first
18064 // element is a string
18065 bool is_an_object = std::all_of(init.begin(), init.end(),
18066 [](const detail::json_ref<basic_json>& element_ref)
18068 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
18071 // adjust type if type deduction is not wanted
18072 if (!type_deduction)
18074 // if array is wanted, do not create an object though possible
18075 if (manual_type == value_t::array)
18077 is_an_object = false;
18080 // if object is wanted but impossible, throw an exception
18081 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
18083 JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json()));
18089 // the initializer list is a list of pairs -> create object
18090 m_type = value_t::object;
18091 m_value = value_t::object;
18093 for (auto& element_ref : init)
18095 auto element = element_ref.moved_or_copied();
18096 m_value.object->emplace(
18097 std::move(*((*element.m_value.array)[0].m_value.string)),
18098 std::move((*element.m_value.array)[1]));
18103 // the initializer list describes an array -> create array
18104 m_type = value_t::array;
18105 m_value.array = create<array_t>(init.begin(), init.end());
18109 assert_invariant();
18112 /// @brief explicitly create a binary array (without subtype)
18113 /// @sa https://json.nlohmann.me/api/basic_json/binary/
18114 JSON_HEDLEY_WARN_UNUSED_RESULT
18115 static basic_json binary(const typename binary_t::container_type& init)
18117 auto res = basic_json();
18118 res.m_type = value_t::binary;
18119 res.m_value = init;
18123 /// @brief explicitly create a binary array (with subtype)
18124 /// @sa https://json.nlohmann.me/api/basic_json/binary/
18125 JSON_HEDLEY_WARN_UNUSED_RESULT
18126 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
18128 auto res = basic_json();
18129 res.m_type = value_t::binary;
18130 res.m_value = binary_t(init, subtype);
18134 /// @brief explicitly create a binary array
18135 /// @sa https://json.nlohmann.me/api/basic_json/binary/
18136 JSON_HEDLEY_WARN_UNUSED_RESULT
18137 static basic_json binary(typename binary_t::container_type&& init)
18139 auto res = basic_json();
18140 res.m_type = value_t::binary;
18141 res.m_value = std::move(init);
18145 /// @brief explicitly create a binary array (with subtype)
18146 /// @sa https://json.nlohmann.me/api/basic_json/binary/
18147 JSON_HEDLEY_WARN_UNUSED_RESULT
18148 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
18150 auto res = basic_json();
18151 res.m_type = value_t::binary;
18152 res.m_value = binary_t(std::move(init), subtype);
18156 /// @brief explicitly create an array from an initializer list
18157 /// @sa https://json.nlohmann.me/api/basic_json/array/
18158 JSON_HEDLEY_WARN_UNUSED_RESULT
18159 static basic_json array(initializer_list_t init = {})
18161 return basic_json(init, false, value_t::array);
18164 /// @brief explicitly create an object from an initializer list
18165 /// @sa https://json.nlohmann.me/api/basic_json/object/
18166 JSON_HEDLEY_WARN_UNUSED_RESULT
18167 static basic_json object(initializer_list_t init = {})
18169 return basic_json(init, false, value_t::object);
18172 /// @brief construct an array with count copies of given value
18173 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18174 basic_json(size_type cnt, const basic_json& val)
18175 : m_type(value_t::array)
18177 m_value.array = create<array_t>(cnt, val);
18179 assert_invariant();
18182 /// @brief construct a JSON container given an iterator range
18183 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18184 template < class InputIT, typename std::enable_if <
18185 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
18186 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
18187 basic_json(InputIT first, InputIT last)
18189 JSON_ASSERT(first.m_object != nullptr);
18190 JSON_ASSERT(last.m_object != nullptr);
18192 // make sure iterator fits the current value
18193 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
18195 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json()));
18198 // copy type from first iterator
18199 m_type = first.m_object->m_type;
18201 // check if iterator range is complete for primitive values
18204 case value_t::boolean:
18205 case value_t::number_float:
18206 case value_t::number_integer:
18207 case value_t::number_unsigned:
18208 case value_t::string:
18210 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
18211 || !last.m_it.primitive_iterator.is_end()))
18213 JSON_THROW(invalid_iterator::create(204, "iterators out of range", *first.m_object));
18218 case value_t::null:
18219 case value_t::object:
18220 case value_t::array:
18221 case value_t::binary:
18222 case value_t::discarded:
18229 case value_t::number_integer:
18231 m_value.number_integer = first.m_object->m_value.number_integer;
18235 case value_t::number_unsigned:
18237 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
18241 case value_t::number_float:
18243 m_value.number_float = first.m_object->m_value.number_float;
18247 case value_t::boolean:
18249 m_value.boolean = first.m_object->m_value.boolean;
18253 case value_t::string:
18255 m_value = *first.m_object->m_value.string;
18259 case value_t::object:
18261 m_value.object = create<object_t>(first.m_it.object_iterator,
18262 last.m_it.object_iterator);
18266 case value_t::array:
18268 m_value.array = create<array_t>(first.m_it.array_iterator,
18269 last.m_it.array_iterator);
18273 case value_t::binary:
18275 m_value = *first.m_object->m_value.binary;
18279 case value_t::null:
18280 case value_t::discarded:
18282 JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), *first.m_object));
18286 assert_invariant();
18290 ///////////////////////////////////////
18291 // other constructors and destructor //
18292 ///////////////////////////////////////
18294 template<typename JsonRef,
18295 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
18296 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
18297 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
18299 /// @brief copy constructor
18300 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18301 basic_json(const basic_json& other)
18302 : m_type(other.m_type)
18304 // check of passed value is valid
18305 other.assert_invariant();
18309 case value_t::object:
18311 m_value = *other.m_value.object;
18315 case value_t::array:
18317 m_value = *other.m_value.array;
18321 case value_t::string:
18323 m_value = *other.m_value.string;
18327 case value_t::boolean:
18329 m_value = other.m_value.boolean;
18333 case value_t::number_integer:
18335 m_value = other.m_value.number_integer;
18339 case value_t::number_unsigned:
18341 m_value = other.m_value.number_unsigned;
18345 case value_t::number_float:
18347 m_value = other.m_value.number_float;
18351 case value_t::binary:
18353 m_value = *other.m_value.binary;
18357 case value_t::null:
18358 case value_t::discarded:
18364 assert_invariant();
18367 /// @brief move constructor
18368 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18369 basic_json(basic_json&& other) noexcept
18370 : m_type(std::move(other.m_type)),
18371 m_value(std::move(other.m_value))
18373 // check that passed value is valid
18374 other.assert_invariant(false);
18376 // invalidate payload
18377 other.m_type = value_t::null;
18378 other.m_value = {};
18381 assert_invariant();
18384 /// @brief copy assignment
18385 /// @sa https://json.nlohmann.me/api/basic_json/operator=/
18386 basic_json& operator=(basic_json other) noexcept (
18387 std::is_nothrow_move_constructible<value_t>::value&&
18388 std::is_nothrow_move_assignable<value_t>::value&&
18389 std::is_nothrow_move_constructible<json_value>::value&&
18390 std::is_nothrow_move_assignable<json_value>::value
18393 // check that passed value is valid
18394 other.assert_invariant();
18397 swap(m_type, other.m_type);
18398 swap(m_value, other.m_value);
18401 assert_invariant();
18405 /// @brief destructor
18406 /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
18407 ~basic_json() noexcept
18409 assert_invariant(false);
18410 m_value.destroy(m_type);
18416 ///////////////////////
18417 // object inspection //
18418 ///////////////////////
18420 /// @name object inspection
18421 /// Functions to inspect the type of a JSON value.
18424 /// @brief serialization
18425 /// @sa https://json.nlohmann.me/api/basic_json/dump/
18426 string_t dump(const int indent = -1,
18427 const char indent_char = ' ',
18428 const bool ensure_ascii = false,
18429 const error_handler_t error_handler = error_handler_t::strict) const
18432 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
18436 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
18440 s.dump(*this, false, ensure_ascii, 0);
18446 /// @brief return the type of the JSON value (explicit)
18447 /// @sa https://json.nlohmann.me/api/basic_json/type/
18448 constexpr value_t type() const noexcept
18453 /// @brief return whether type is primitive
18454 /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
18455 constexpr bool is_primitive() const noexcept
18457 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
18460 /// @brief return whether type is structured
18461 /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
18462 constexpr bool is_structured() const noexcept
18464 return is_array() || is_object();
18467 /// @brief return whether value is null
18468 /// @sa https://json.nlohmann.me/api/basic_json/is_null/
18469 constexpr bool is_null() const noexcept
18471 return m_type == value_t::null;
18474 /// @brief return whether value is a boolean
18475 /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
18476 constexpr bool is_boolean() const noexcept
18478 return m_type == value_t::boolean;
18481 /// @brief return whether value is a number
18482 /// @sa https://json.nlohmann.me/api/basic_json/is_number/
18483 constexpr bool is_number() const noexcept
18485 return is_number_integer() || is_number_float();
18488 /// @brief return whether value is an integer number
18489 /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
18490 constexpr bool is_number_integer() const noexcept
18492 return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
18495 /// @brief return whether value is an unsigned integer number
18496 /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
18497 constexpr bool is_number_unsigned() const noexcept
18499 return m_type == value_t::number_unsigned;
18502 /// @brief return whether value is a floating-point number
18503 /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
18504 constexpr bool is_number_float() const noexcept
18506 return m_type == value_t::number_float;
18509 /// @brief return whether value is an object
18510 /// @sa https://json.nlohmann.me/api/basic_json/is_object/
18511 constexpr bool is_object() const noexcept
18513 return m_type == value_t::object;
18516 /// @brief return whether value is an array
18517 /// @sa https://json.nlohmann.me/api/basic_json/is_array/
18518 constexpr bool is_array() const noexcept
18520 return m_type == value_t::array;
18523 /// @brief return whether value is a string
18524 /// @sa https://json.nlohmann.me/api/basic_json/is_string/
18525 constexpr bool is_string() const noexcept
18527 return m_type == value_t::string;
18530 /// @brief return whether value is a binary array
18531 /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
18532 constexpr bool is_binary() const noexcept
18534 return m_type == value_t::binary;
18537 /// @brief return whether value is discarded
18538 /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
18539 constexpr bool is_discarded() const noexcept
18541 return m_type == value_t::discarded;
18544 /// @brief return the type of the JSON value (implicit)
18545 /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
18546 constexpr operator value_t() const noexcept
18558 /// get a boolean (explicit)
18559 boolean_t get_impl(boolean_t* /*unused*/) const
18561 if (JSON_HEDLEY_LIKELY(is_boolean()))
18563 return m_value.boolean;
18566 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this));
18569 /// get a pointer to the value (object)
18570 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
18572 return is_object() ? m_value.object : nullptr;
18575 /// get a pointer to the value (object)
18576 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
18578 return is_object() ? m_value.object : nullptr;
18581 /// get a pointer to the value (array)
18582 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
18584 return is_array() ? m_value.array : nullptr;
18587 /// get a pointer to the value (array)
18588 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
18590 return is_array() ? m_value.array : nullptr;
18593 /// get a pointer to the value (string)
18594 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
18596 return is_string() ? m_value.string : nullptr;
18599 /// get a pointer to the value (string)
18600 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
18602 return is_string() ? m_value.string : nullptr;
18605 /// get a pointer to the value (boolean)
18606 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
18608 return is_boolean() ? &m_value.boolean : nullptr;
18611 /// get a pointer to the value (boolean)
18612 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
18614 return is_boolean() ? &m_value.boolean : nullptr;
18617 /// get a pointer to the value (integer number)
18618 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
18620 return is_number_integer() ? &m_value.number_integer : nullptr;
18623 /// get a pointer to the value (integer number)
18624 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
18626 return is_number_integer() ? &m_value.number_integer : nullptr;
18629 /// get a pointer to the value (unsigned number)
18630 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
18632 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
18635 /// get a pointer to the value (unsigned number)
18636 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
18638 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
18641 /// get a pointer to the value (floating-point number)
18642 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
18644 return is_number_float() ? &m_value.number_float : nullptr;
18647 /// get a pointer to the value (floating-point number)
18648 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
18650 return is_number_float() ? &m_value.number_float : nullptr;
18653 /// get a pointer to the value (binary)
18654 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
18656 return is_binary() ? m_value.binary : nullptr;
18659 /// get a pointer to the value (binary)
18660 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
18662 return is_binary() ? m_value.binary : nullptr;
18666 @brief helper function to implement get_ref()
18668 This function helps to implement get_ref() without code duplication for
18669 const and non-const overloads
18671 @tparam ThisType will be deduced as `basic_json` or `const basic_json`
18673 @throw type_error.303 if ReferenceType does not match underlying value
18674 type of the current JSON
18676 template<typename ReferenceType, typename ThisType>
18677 static ReferenceType get_ref_impl(ThisType& obj)
18679 // delegate the call to get_ptr<>()
18680 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
18682 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
18687 JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj));
18691 /// @name value access
18692 /// Direct access to the stored value of a JSON value.
18695 /// @brief get a pointer value (implicit)
18696 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
18697 template<typename PointerType, typename std::enable_if<
18698 std::is_pointer<PointerType>::value, int>::type = 0>
18699 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
18701 // delegate the call to get_impl_ptr<>()
18702 return get_impl_ptr(static_cast<PointerType>(nullptr));
18705 /// @brief get a pointer value (implicit)
18706 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
18707 template < typename PointerType, typename std::enable_if <
18708 std::is_pointer<PointerType>::value&&
18709 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
18710 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
18712 // delegate the call to get_impl_ptr<>() const
18713 return get_impl_ptr(static_cast<PointerType>(nullptr));
18718 @brief get a value (explicit)
18720 Explicit type conversion between the JSON value and a compatible value
18721 which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
18722 and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
18723 The value is converted by calling the @ref json_serializer<ValueType>
18724 `from_json()` method.
18726 The function is equivalent to executing
18729 JSONSerializer<ValueType>::from_json(*this, ret);
18733 This overloads is chosen if:
18734 - @a ValueType is not @ref basic_json,
18735 - @ref json_serializer<ValueType> has a `from_json()` method of the form
18736 `void from_json(const basic_json&, ValueType&)`, and
18737 - @ref json_serializer<ValueType> does not have a `from_json()` method of
18738 the form `ValueType from_json(const basic_json&)`
18740 @tparam ValueType the returned value type
18742 @return copy of the JSON value, converted to @a ValueType
18744 @throw what @ref json_serializer<ValueType> `from_json()` method throws
18746 @liveexample{The example below shows several conversions from JSON values
18747 to other types. There a few things to note: (1) Floating-point numbers can
18748 be converted to integers\, (2) A JSON array can be converted to a standard
18749 `std::vector<short>`\, (3) A JSON object can be converted to C++
18750 associative containers such as `std::unordered_map<std::string\,
18751 json>`.,get__ValueType_const}
18753 @since version 2.1.0
18755 template < typename ValueType,
18756 detail::enable_if_t <
18757 detail::is_default_constructible<ValueType>::value&&
18758 detail::has_from_json<basic_json_t, ValueType>::value,
18760 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
18761 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
18763 auto ret = ValueType();
18764 JSONSerializer<ValueType>::from_json(*this, ret);
18769 @brief get a value (explicit); special case
18771 Explicit type conversion between the JSON value and a compatible value
18772 which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
18773 and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
18774 The value is converted by calling the @ref json_serializer<ValueType>
18775 `from_json()` method.
18777 The function is equivalent to executing
18779 return JSONSerializer<ValueType>::from_json(*this);
18782 This overloads is chosen if:
18783 - @a ValueType is not @ref basic_json and
18784 - @ref json_serializer<ValueType> has a `from_json()` method of the form
18785 `ValueType from_json(const basic_json&)`
18787 @note If @ref json_serializer<ValueType> has both overloads of
18788 `from_json()`, this one is chosen.
18790 @tparam ValueType the returned value type
18792 @return copy of the JSON value, converted to @a ValueType
18794 @throw what @ref json_serializer<ValueType> `from_json()` method throws
18796 @since version 2.1.0
18798 template < typename ValueType,
18799 detail::enable_if_t <
18800 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
18802 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
18803 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
18805 return JSONSerializer<ValueType>::from_json(*this);
18809 @brief get special-case overload
18811 This overloads converts the current @ref basic_json in a different
18812 @ref basic_json type
18814 @tparam BasicJsonType == @ref basic_json
18816 @return a copy of *this, converted into @a BasicJsonType
18818 @complexity Depending on the implementation of the called `from_json()`
18821 @since version 3.2.0
18823 template < typename BasicJsonType,
18824 detail::enable_if_t <
18825 detail::is_basic_json<BasicJsonType>::value,
18827 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
18833 @brief get special-case overload
18835 This overloads avoids a lot of template boilerplate, it can be seen as the
18838 @tparam BasicJsonType == @ref basic_json
18840 @return a copy of *this
18842 @complexity Constant.
18844 @since version 2.1.0
18846 template<typename BasicJsonType,
18847 detail::enable_if_t<
18848 std::is_same<BasicJsonType, basic_json_t>::value,
18850 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
18856 @brief get a pointer value (explicit)
18859 template<typename PointerType,
18860 detail::enable_if_t<
18861 std::is_pointer<PointerType>::value,
18863 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
18864 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
18866 // delegate the call to get_ptr
18867 return get_ptr<PointerType>();
18872 @brief get a (pointer) value (explicit)
18874 Performs explicit type conversion between the JSON value and a compatible value if required.
18876 - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
18877 No copies are made.
18879 - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
18880 from the current @ref basic_json.
18882 - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
18885 @tparam ValueTypeCV the provided value type
18886 @tparam ValueType the returned value type
18888 @return copy of the JSON value, converted to @tparam ValueType if necessary
18890 @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
18892 @since version 2.1.0
18894 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
18895 #if defined(JSON_HAS_CPP_14)
18898 auto get() const noexcept(
18899 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
18900 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
18902 // we cannot static_assert on ValueTypeCV being non-const, because
18903 // there is support for get<const basic_json_t>(), which is why we
18904 // still need the uncvref
18905 static_assert(!std::is_reference<ValueTypeCV>::value,
18906 "get() cannot be used with reference types, you might want to use get_ref()");
18907 return get_impl<ValueType>(detail::priority_tag<4> {});
18911 @brief get a pointer value (explicit)
18913 Explicit pointer access to the internally stored JSON value. No copies are
18916 @warning The pointer becomes invalid if the underlying JSON object
18919 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
18920 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
18921 @ref number_unsigned_t, or @ref number_float_t.
18923 @return pointer to the internally stored JSON value if the requested
18924 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
18926 @complexity Constant.
18928 @liveexample{The example below shows how pointers to internal values of a
18929 JSON value can be requested. Note that no type conversions are made and a
18930 `nullptr` is returned if the value and the requested pointer type does not
18931 match.,get__PointerType}
18933 @sa see @ref get_ptr() for explicit pointer-member access
18935 @since version 1.0.0
18937 template<typename PointerType, typename std::enable_if<
18938 std::is_pointer<PointerType>::value, int>::type = 0>
18939 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
18941 // delegate the call to get_ptr
18942 return get_ptr<PointerType>();
18945 /// @brief get a value (explicit)
18946 /// @sa https://json.nlohmann.me/api/basic_json/get_to/
18947 template < typename ValueType,
18948 detail::enable_if_t <
18949 !detail::is_basic_json<ValueType>::value&&
18950 detail::has_from_json<basic_json_t, ValueType>::value,
18952 ValueType & get_to(ValueType& v) const noexcept(noexcept(
18953 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
18955 JSONSerializer<ValueType>::from_json(*this, v);
18959 // specialization to allow calling get_to with a basic_json value
18960 // see https://github.com/nlohmann/json/issues/2175
18961 template<typename ValueType,
18962 detail::enable_if_t <
18963 detail::is_basic_json<ValueType>::value,
18965 ValueType & get_to(ValueType& v) const
18972 typename T, std::size_t N,
18973 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
18974 detail::enable_if_t <
18975 detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
18976 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
18977 noexcept(noexcept(JSONSerializer<Array>::from_json(
18978 std::declval<const basic_json_t&>(), v)))
18980 JSONSerializer<Array>::from_json(*this, v);
18984 /// @brief get a reference value (implicit)
18985 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
18986 template<typename ReferenceType, typename std::enable_if<
18987 std::is_reference<ReferenceType>::value, int>::type = 0>
18988 ReferenceType get_ref()
18990 // delegate call to get_ref_impl
18991 return get_ref_impl<ReferenceType>(*this);
18994 /// @brief get a reference value (implicit)
18995 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
18996 template < typename ReferenceType, typename std::enable_if <
18997 std::is_reference<ReferenceType>::value&&
18998 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
18999 ReferenceType get_ref() const
19001 // delegate call to get_ref_impl
19002 return get_ref_impl<ReferenceType>(*this);
19006 @brief get a value (implicit)
19008 Implicit type conversion between the JSON value and a compatible value.
19009 The call is realized by calling @ref get() const.
19011 @tparam ValueType non-pointer type compatible to the JSON value, for
19012 instance `int` for JSON integer numbers, `bool` for JSON booleans, or
19013 `std::vector` types for JSON arrays. The character type of @ref string_t
19014 as well as an initializer list of this type is excluded to avoid
19015 ambiguities as these types implicitly convert to `std::string`.
19017 @return copy of the JSON value, converted to type @a ValueType
19019 @throw type_error.302 in case passed type @a ValueType is incompatible
19020 to the JSON value type (e.g., the JSON value is of type boolean, but a
19021 string is requested); see example below
19023 @complexity Linear in the size of the JSON value.
19025 @liveexample{The example below shows several conversions from JSON values
19026 to other types. There a few things to note: (1) Floating-point numbers can
19027 be converted to integers\, (2) A JSON array can be converted to a standard
19028 `std::vector<short>`\, (3) A JSON object can be converted to C++
19029 associative containers such as `std::unordered_map<std::string\,
19030 json>`.,operator__ValueType}
19032 @since version 1.0.0
19034 template < typename ValueType, typename std::enable_if <
19035 detail::conjunction <
19036 detail::negation<std::is_pointer<ValueType>>,
19037 detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
19038 detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
19039 detail::negation<detail::is_basic_json<ValueType>>,
19040 detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
19042 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
19043 detail::negation<std::is_same<ValueType, std::string_view>>,
19045 detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
19046 >::value, int >::type = 0 >
19047 JSON_EXPLICIT operator ValueType() const
19049 // delegate the call to get<>() const
19050 return get<ValueType>();
19053 /// @brief get a binary value
19054 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
19055 binary_t& get_binary()
19059 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
19062 return *get_ptr<binary_t*>();
19065 /// @brief get a binary value
19066 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
19067 const binary_t& get_binary() const
19071 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
19074 return *get_ptr<const binary_t*>();
19080 ////////////////////
19081 // element access //
19082 ////////////////////
19084 /// @name element access
19085 /// Access to the JSON value.
19088 /// @brief access specified array element with bounds checking
19089 /// @sa https://json.nlohmann.me/api/basic_json/at/
19090 reference at(size_type idx)
19092 // at only works for arrays
19093 if (JSON_HEDLEY_LIKELY(is_array()))
19097 return set_parent(m_value.array->at(idx));
19099 JSON_CATCH (std::out_of_range&)
19101 // create better exception explanation
19102 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
19107 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
19111 /// @brief access specified array element with bounds checking
19112 /// @sa https://json.nlohmann.me/api/basic_json/at/
19113 const_reference at(size_type idx) const
19115 // at only works for arrays
19116 if (JSON_HEDLEY_LIKELY(is_array()))
19120 return m_value.array->at(idx);
19122 JSON_CATCH (std::out_of_range&)
19124 // create better exception explanation
19125 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
19130 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
19134 /// @brief access specified object element with bounds checking
19135 /// @sa https://json.nlohmann.me/api/basic_json/at/
19136 reference at(const typename object_t::key_type& key)
19138 // at only works for objects
19139 if (JSON_HEDLEY_LIKELY(is_object()))
19143 return set_parent(m_value.object->at(key));
19145 JSON_CATCH (std::out_of_range&)
19147 // create better exception explanation
19148 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
19153 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
19157 /// @brief access specified object element with bounds checking
19158 /// @sa https://json.nlohmann.me/api/basic_json/at/
19159 const_reference at(const typename object_t::key_type& key) const
19161 // at only works for objects
19162 if (JSON_HEDLEY_LIKELY(is_object()))
19166 return m_value.object->at(key);
19168 JSON_CATCH (std::out_of_range&)
19170 // create better exception explanation
19171 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
19176 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
19180 /// @brief access specified array element
19181 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19182 reference operator[](size_type idx)
19184 // implicitly convert null value to an empty array
19187 m_type = value_t::array;
19188 m_value.array = create<array_t>();
19189 assert_invariant();
19192 // operator[] only works for arrays
19193 if (JSON_HEDLEY_LIKELY(is_array()))
19195 // fill up array with null values if given idx is outside range
19196 if (idx >= m_value.array->size())
19198 #if JSON_DIAGNOSTICS
19199 // remember array size & capacity before resizing
19200 const auto old_size = m_value.array->size();
19201 const auto old_capacity = m_value.array->capacity();
19203 m_value.array->resize(idx + 1);
19205 #if JSON_DIAGNOSTICS
19206 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
19208 // capacity has changed: update all parents
19213 // set parent for values added above
19214 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
19217 assert_invariant();
19220 return m_value.array->operator[](idx);
19223 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
19226 /// @brief access specified array element
19227 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19228 const_reference operator[](size_type idx) const
19230 // const operator[] only works for arrays
19231 if (JSON_HEDLEY_LIKELY(is_array()))
19233 return m_value.array->operator[](idx);
19236 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
19239 /// @brief access specified object element
19240 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19241 reference operator[](const typename object_t::key_type& key)
19243 // implicitly convert null value to an empty object
19246 m_type = value_t::object;
19247 m_value.object = create<object_t>();
19248 assert_invariant();
19251 // operator[] only works for objects
19252 if (JSON_HEDLEY_LIKELY(is_object()))
19254 return set_parent(m_value.object->operator[](key));
19257 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
19260 /// @brief access specified object element
19261 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19262 const_reference operator[](const typename object_t::key_type& key) const
19264 // const operator[] only works for objects
19265 if (JSON_HEDLEY_LIKELY(is_object()))
19267 JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
19268 return m_value.object->find(key)->second;
19271 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
19274 /// @brief access specified object element
19275 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19276 template<typename T>
19277 JSON_HEDLEY_NON_NULL(2)
19278 reference operator[](T* key)
19280 // implicitly convert null to object
19283 m_type = value_t::object;
19284 m_value = value_t::object;
19285 assert_invariant();
19288 // at only works for objects
19289 if (JSON_HEDLEY_LIKELY(is_object()))
19291 return set_parent(m_value.object->operator[](key));
19294 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
19297 /// @brief access specified object element
19298 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19299 template<typename T>
19300 JSON_HEDLEY_NON_NULL(2)
19301 const_reference operator[](T* key) const
19303 // at only works for objects
19304 if (JSON_HEDLEY_LIKELY(is_object()))
19306 JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
19307 return m_value.object->find(key)->second;
19310 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
19313 /// @brief access specified object element with default value
19314 /// @sa https://json.nlohmann.me/api/basic_json/value/
19315 /// using std::is_convertible in a std::enable_if will fail when using explicit conversions
19316 template < class ValueType, typename std::enable_if <
19317 detail::is_getable<basic_json_t, ValueType>::value
19318 && !std::is_same<value_t, ValueType>::value, int >::type = 0 >
19319 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
19321 // at only works for objects
19322 if (JSON_HEDLEY_LIKELY(is_object()))
19324 // if key is found, return value and given default value otherwise
19325 const auto it = find(key);
19328 return it->template get<ValueType>();
19331 return default_value;
19334 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
19337 /// @brief access specified object element with default value
19338 /// @sa https://json.nlohmann.me/api/basic_json/value/
19339 /// overload for a default value of type const char*
19340 string_t value(const typename object_t::key_type& key, const char* default_value) const
19342 return value(key, string_t(default_value));
19345 /// @brief access specified object element via JSON Pointer with default value
19346 /// @sa https://json.nlohmann.me/api/basic_json/value/
19347 template<class ValueType, typename std::enable_if<
19348 detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
19349 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
19351 // at only works for objects
19352 if (JSON_HEDLEY_LIKELY(is_object()))
19354 // if pointer resolves a value, return it or use default value
19357 return ptr.get_checked(this).template get<ValueType>();
19359 JSON_INTERNAL_CATCH (out_of_range&)
19361 return default_value;
19365 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
19368 /// @brief access specified object element via JSON Pointer with default value
19369 /// @sa https://json.nlohmann.me/api/basic_json/value/
19370 /// overload for a default value of type const char*
19371 JSON_HEDLEY_NON_NULL(3)
19372 string_t value(const json_pointer& ptr, const char* default_value) const
19374 return value(ptr, string_t(default_value));
19377 /// @brief access the first element
19378 /// @sa https://json.nlohmann.me/api/basic_json/front/
19384 /// @brief access the first element
19385 /// @sa https://json.nlohmann.me/api/basic_json/front/
19386 const_reference front() const
19391 /// @brief access the last element
19392 /// @sa https://json.nlohmann.me/api/basic_json/back/
19400 /// @brief access the last element
19401 /// @sa https://json.nlohmann.me/api/basic_json/back/
19402 const_reference back() const
19409 /// @brief remove element given an iterator
19410 /// @sa https://json.nlohmann.me/api/basic_json/erase/
19411 template < class IteratorType, typename std::enable_if <
19412 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
19413 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
19415 IteratorType erase(IteratorType pos)
19417 // make sure iterator fits the current value
19418 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
19420 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
19423 IteratorType result = end();
19427 case value_t::boolean:
19428 case value_t::number_float:
19429 case value_t::number_integer:
19430 case value_t::number_unsigned:
19431 case value_t::string:
19432 case value_t::binary:
19434 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
19436 JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this));
19441 AllocatorType<string_t> alloc;
19442 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
19443 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
19444 m_value.string = nullptr;
19446 else if (is_binary())
19448 AllocatorType<binary_t> alloc;
19449 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
19450 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
19451 m_value.binary = nullptr;
19454 m_type = value_t::null;
19455 assert_invariant();
19459 case value_t::object:
19461 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
19465 case value_t::array:
19467 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
19471 case value_t::null:
19472 case value_t::discarded:
19474 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
19480 /// @brief remove elements given an iterator range
19481 /// @sa https://json.nlohmann.me/api/basic_json/erase/
19482 template < class IteratorType, typename std::enable_if <
19483 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
19484 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
19486 IteratorType erase(IteratorType first, IteratorType last)
19488 // make sure iterator fits the current value
19489 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
19491 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this));
19494 IteratorType result = end();
19498 case value_t::boolean:
19499 case value_t::number_float:
19500 case value_t::number_integer:
19501 case value_t::number_unsigned:
19502 case value_t::string:
19503 case value_t::binary:
19505 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
19506 || !last.m_it.primitive_iterator.is_end()))
19508 JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this));
19513 AllocatorType<string_t> alloc;
19514 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
19515 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
19516 m_value.string = nullptr;
19518 else if (is_binary())
19520 AllocatorType<binary_t> alloc;
19521 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
19522 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
19523 m_value.binary = nullptr;
19526 m_type = value_t::null;
19527 assert_invariant();
19531 case value_t::object:
19533 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
19534 last.m_it.object_iterator);
19538 case value_t::array:
19540 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
19541 last.m_it.array_iterator);
19545 case value_t::null:
19546 case value_t::discarded:
19548 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
19554 /// @brief remove element from a JSON object given a key
19555 /// @sa https://json.nlohmann.me/api/basic_json/erase/
19556 size_type erase(const typename object_t::key_type& key)
19558 // this erase only works for objects
19559 if (JSON_HEDLEY_LIKELY(is_object()))
19561 return m_value.object->erase(key);
19564 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
19567 /// @brief remove element from a JSON array given an index
19568 /// @sa https://json.nlohmann.me/api/basic_json/erase/
19569 void erase(const size_type idx)
19571 // this erase only works for arrays
19572 if (JSON_HEDLEY_LIKELY(is_array()))
19574 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
19576 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
19579 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
19583 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
19597 /// @brief find an element in a JSON object
19598 /// @sa https://json.nlohmann.me/api/basic_json/find/
19599 template<typename KeyT>
19600 iterator find(KeyT&& key)
19602 auto result = end();
19606 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
19612 /// @brief find an element in a JSON object
19613 /// @sa https://json.nlohmann.me/api/basic_json/find/
19614 template<typename KeyT>
19615 const_iterator find(KeyT&& key) const
19617 auto result = cend();
19621 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
19627 /// @brief returns the number of occurrences of a key in a JSON object
19628 /// @sa https://json.nlohmann.me/api/basic_json/count/
19629 template<typename KeyT>
19630 size_type count(KeyT&& key) const
19632 // return 0 for all nonobject types
19633 return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
19636 /// @brief check the existence of an element in a JSON object
19637 /// @sa https://json.nlohmann.me/api/basic_json/contains/
19638 template < typename KeyT, typename std::enable_if <
19639 !std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int >::type = 0 >
19640 bool contains(KeyT && key) const
19642 return is_object() && m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
19645 /// @brief check the existence of an element in a JSON object given a JSON pointer
19646 /// @sa https://json.nlohmann.me/api/basic_json/contains/
19647 bool contains(const json_pointer& ptr) const
19649 return ptr.contains(this);
19659 /// @name iterators
19662 /// @brief returns an iterator to the first element
19663 /// @sa https://json.nlohmann.me/api/basic_json/begin/
19664 iterator begin() noexcept
19666 iterator result(this);
19667 result.set_begin();
19671 /// @brief returns an iterator to the first element
19672 /// @sa https://json.nlohmann.me/api/basic_json/begin/
19673 const_iterator begin() const noexcept
19678 /// @brief returns a const iterator to the first element
19679 /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
19680 const_iterator cbegin() const noexcept
19682 const_iterator result(this);
19683 result.set_begin();
19687 /// @brief returns an iterator to one past the last element
19688 /// @sa https://json.nlohmann.me/api/basic_json/end/
19689 iterator end() noexcept
19691 iterator result(this);
19696 /// @brief returns an iterator to one past the last element
19697 /// @sa https://json.nlohmann.me/api/basic_json/end/
19698 const_iterator end() const noexcept
19703 /// @brief returns an iterator to one past the last element
19704 /// @sa https://json.nlohmann.me/api/basic_json/cend/
19705 const_iterator cend() const noexcept
19707 const_iterator result(this);
19712 /// @brief returns an iterator to the reverse-beginning
19713 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
19714 reverse_iterator rbegin() noexcept
19716 return reverse_iterator(end());
19719 /// @brief returns an iterator to the reverse-beginning
19720 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
19721 const_reverse_iterator rbegin() const noexcept
19726 /// @brief returns an iterator to the reverse-end
19727 /// @sa https://json.nlohmann.me/api/basic_json/rend/
19728 reverse_iterator rend() noexcept
19730 return reverse_iterator(begin());
19733 /// @brief returns an iterator to the reverse-end
19734 /// @sa https://json.nlohmann.me/api/basic_json/rend/
19735 const_reverse_iterator rend() const noexcept
19740 /// @brief returns a const reverse iterator to the last element
19741 /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
19742 const_reverse_iterator crbegin() const noexcept
19744 return const_reverse_iterator(cend());
19747 /// @brief returns a const reverse iterator to one before the first
19748 /// @sa https://json.nlohmann.me/api/basic_json/crend/
19749 const_reverse_iterator crend() const noexcept
19751 return const_reverse_iterator(cbegin());
19755 /// @brief wrapper to access iterator member functions in range-based for
19756 /// @sa https://json.nlohmann.me/api/basic_json/items/
19757 /// @deprecated This function is deprecated since 3.1.0 and will be removed in
19758 /// version 4.0.0 of the library. Please use @ref items() instead;
19759 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
19760 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
19761 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
19763 return ref.items();
19766 /// @brief wrapper to access iterator member functions in range-based for
19767 /// @sa https://json.nlohmann.me/api/basic_json/items/
19768 /// @deprecated This function is deprecated since 3.1.0 and will be removed in
19769 /// version 4.0.0 of the library. Please use @ref items() instead;
19770 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
19771 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
19772 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
19774 return ref.items();
19777 /// @brief helper to access iterator member functions in range-based for
19778 /// @sa https://json.nlohmann.me/api/basic_json/items/
19779 iteration_proxy<iterator> items() noexcept
19781 return iteration_proxy<iterator>(*this);
19784 /// @brief helper to access iterator member functions in range-based for
19785 /// @sa https://json.nlohmann.me/api/basic_json/items/
19786 iteration_proxy<const_iterator> items() const noexcept
19788 return iteration_proxy<const_iterator>(*this);
19801 /// @brief checks whether the container is empty.
19802 /// @sa https://json.nlohmann.me/api/basic_json/empty/
19803 bool empty() const noexcept
19807 case value_t::null:
19809 // null values are empty
19813 case value_t::array:
19815 // delegate call to array_t::empty()
19816 return m_value.array->empty();
19819 case value_t::object:
19821 // delegate call to object_t::empty()
19822 return m_value.object->empty();
19825 case value_t::string:
19826 case value_t::boolean:
19827 case value_t::number_integer:
19828 case value_t::number_unsigned:
19829 case value_t::number_float:
19830 case value_t::binary:
19831 case value_t::discarded:
19834 // all other types are nonempty
19840 /// @brief returns the number of elements
19841 /// @sa https://json.nlohmann.me/api/basic_json/size/
19842 size_type size() const noexcept
19846 case value_t::null:
19848 // null values are empty
19852 case value_t::array:
19854 // delegate call to array_t::size()
19855 return m_value.array->size();
19858 case value_t::object:
19860 // delegate call to object_t::size()
19861 return m_value.object->size();
19864 case value_t::string:
19865 case value_t::boolean:
19866 case value_t::number_integer:
19867 case value_t::number_unsigned:
19868 case value_t::number_float:
19869 case value_t::binary:
19870 case value_t::discarded:
19873 // all other types have size 1
19879 /// @brief returns the maximum possible number of elements
19880 /// @sa https://json.nlohmann.me/api/basic_json/max_size/
19881 size_type max_size() const noexcept
19885 case value_t::array:
19887 // delegate call to array_t::max_size()
19888 return m_value.array->max_size();
19891 case value_t::object:
19893 // delegate call to object_t::max_size()
19894 return m_value.object->max_size();
19897 case value_t::null:
19898 case value_t::string:
19899 case value_t::boolean:
19900 case value_t::number_integer:
19901 case value_t::number_unsigned:
19902 case value_t::number_float:
19903 case value_t::binary:
19904 case value_t::discarded:
19907 // all other types have max_size() == size()
19920 /// @name modifiers
19923 /// @brief clears the contents
19924 /// @sa https://json.nlohmann.me/api/basic_json/clear/
19925 void clear() noexcept
19929 case value_t::number_integer:
19931 m_value.number_integer = 0;
19935 case value_t::number_unsigned:
19937 m_value.number_unsigned = 0;
19941 case value_t::number_float:
19943 m_value.number_float = 0.0;
19947 case value_t::boolean:
19949 m_value.boolean = false;
19953 case value_t::string:
19955 m_value.string->clear();
19959 case value_t::binary:
19961 m_value.binary->clear();
19965 case value_t::array:
19967 m_value.array->clear();
19971 case value_t::object:
19973 m_value.object->clear();
19977 case value_t::null:
19978 case value_t::discarded:
19984 /// @brief add an object to an array
19985 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
19986 void push_back(basic_json&& val)
19988 // push_back only works for null objects or arrays
19989 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
19991 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
19994 // transform null object into an array
19997 m_type = value_t::array;
19998 m_value = value_t::array;
19999 assert_invariant();
20002 // add element to array (move semantics)
20003 const auto old_capacity = m_value.array->capacity();
20004 m_value.array->push_back(std::move(val));
20005 set_parent(m_value.array->back(), old_capacity);
20006 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
20009 /// @brief add an object to an array
20010 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
20011 reference operator+=(basic_json&& val)
20013 push_back(std::move(val));
20017 /// @brief add an object to an array
20018 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
20019 void push_back(const basic_json& val)
20021 // push_back only works for null objects or arrays
20022 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
20024 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
20027 // transform null object into an array
20030 m_type = value_t::array;
20031 m_value = value_t::array;
20032 assert_invariant();
20035 // add element to array
20036 const auto old_capacity = m_value.array->capacity();
20037 m_value.array->push_back(val);
20038 set_parent(m_value.array->back(), old_capacity);
20041 /// @brief add an object to an array
20042 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
20043 reference operator+=(const basic_json& val)
20049 /// @brief add an object to an object
20050 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
20051 void push_back(const typename object_t::value_type& val)
20053 // push_back only works for null objects or objects
20054 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
20056 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
20059 // transform null object into an object
20062 m_type = value_t::object;
20063 m_value = value_t::object;
20064 assert_invariant();
20067 // add element to object
20068 auto res = m_value.object->insert(val);
20069 set_parent(res.first->second);
20072 /// @brief add an object to an object
20073 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
20074 reference operator+=(const typename object_t::value_type& val)
20080 /// @brief add an object to an object
20081 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
20082 void push_back(initializer_list_t init)
20084 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
20086 basic_json&& key = init.begin()->moved_or_copied();
20087 push_back(typename object_t::value_type(
20088 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
20092 push_back(basic_json(init));
20096 /// @brief add an object to an object
20097 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
20098 reference operator+=(initializer_list_t init)
20104 /// @brief add an object to an array
20105 /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
20106 template<class... Args>
20107 reference emplace_back(Args&& ... args)
20109 // emplace_back only works for null objects or arrays
20110 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
20112 JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this));
20115 // transform null object into an array
20118 m_type = value_t::array;
20119 m_value = value_t::array;
20120 assert_invariant();
20123 // add element to array (perfect forwarding)
20124 const auto old_capacity = m_value.array->capacity();
20125 m_value.array->emplace_back(std::forward<Args>(args)...);
20126 return set_parent(m_value.array->back(), old_capacity);
20129 /// @brief add an object to an object if key does not exist
20130 /// @sa https://json.nlohmann.me/api/basic_json/emplace/
20131 template<class... Args>
20132 std::pair<iterator, bool> emplace(Args&& ... args)
20134 // emplace only works for null objects or arrays
20135 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
20137 JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this));
20140 // transform null object into an object
20143 m_type = value_t::object;
20144 m_value = value_t::object;
20145 assert_invariant();
20148 // add element to array (perfect forwarding)
20149 auto res = m_value.object->emplace(std::forward<Args>(args)...);
20150 set_parent(res.first->second);
20152 // create result iterator and set iterator to the result of emplace
20154 it.m_it.object_iterator = res.first;
20156 // return pair of iterator and boolean
20157 return {it, res.second};
20160 /// Helper for insertion of an iterator
20161 /// @note: This uses std::distance to support GCC 4.8,
20162 /// see https://github.com/nlohmann/json/pull/1257
20163 template<typename... Args>
20164 iterator insert_iterator(const_iterator pos, Args&& ... args)
20166 iterator result(this);
20167 JSON_ASSERT(m_value.array != nullptr);
20169 auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
20170 m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
20171 result.m_it.array_iterator = m_value.array->begin() + insert_pos;
20173 // This could have been written as:
20174 // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
20175 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
20181 /// @brief inserts element into array
20182 /// @sa https://json.nlohmann.me/api/basic_json/insert/
20183 iterator insert(const_iterator pos, const basic_json& val)
20185 // insert only works for arrays
20186 if (JSON_HEDLEY_LIKELY(is_array()))
20188 // check if iterator pos fits to this JSON value
20189 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
20191 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
20194 // insert to array and return iterator
20195 return insert_iterator(pos, val);
20198 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20201 /// @brief inserts element into array
20202 /// @sa https://json.nlohmann.me/api/basic_json/insert/
20203 iterator insert(const_iterator pos, basic_json&& val)
20205 return insert(pos, val);
20208 /// @brief inserts copies of element into array
20209 /// @sa https://json.nlohmann.me/api/basic_json/insert/
20210 iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
20212 // insert only works for arrays
20213 if (JSON_HEDLEY_LIKELY(is_array()))
20215 // check if iterator pos fits to this JSON value
20216 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
20218 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
20221 // insert to array and return iterator
20222 return insert_iterator(pos, cnt, val);
20225 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20228 /// @brief inserts range of elements into array
20229 /// @sa https://json.nlohmann.me/api/basic_json/insert/
20230 iterator insert(const_iterator pos, const_iterator first, const_iterator last)
20232 // insert only works for arrays
20233 if (JSON_HEDLEY_UNLIKELY(!is_array()))
20235 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20238 // check if iterator pos fits to this JSON value
20239 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
20241 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
20244 // check if range iterators belong to the same JSON object
20245 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20247 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
20250 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
20252 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this));
20255 // insert to array and return iterator
20256 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
20259 /// @brief inserts elements from initializer list into array
20260 /// @sa https://json.nlohmann.me/api/basic_json/insert/
20261 iterator insert(const_iterator pos, initializer_list_t ilist)
20263 // insert only works for arrays
20264 if (JSON_HEDLEY_UNLIKELY(!is_array()))
20266 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20269 // check if iterator pos fits to this JSON value
20270 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
20272 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
20275 // insert to array and return iterator
20276 return insert_iterator(pos, ilist.begin(), ilist.end());
20279 /// @brief inserts range of elements into object
20280 /// @sa https://json.nlohmann.me/api/basic_json/insert/
20281 void insert(const_iterator first, const_iterator last)
20283 // insert only works for objects
20284 if (JSON_HEDLEY_UNLIKELY(!is_object()))
20286 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20289 // check if range iterators belong to the same JSON object
20290 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20292 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
20295 // passed iterators must belong to objects
20296 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
20298 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this));
20301 m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
20304 /// @brief updates a JSON object from another object, overwriting existing keys
20305 /// @sa https://json.nlohmann.me/api/basic_json/update/
20306 void update(const_reference j, bool merge_objects = false)
20308 update(j.begin(), j.end(), merge_objects);
20311 /// @brief updates a JSON object from another object, overwriting existing keys
20312 /// @sa https://json.nlohmann.me/api/basic_json/update/
20313 void update(const_iterator first, const_iterator last, bool merge_objects = false)
20315 // implicitly convert null value to an empty object
20318 m_type = value_t::object;
20319 m_value.object = create<object_t>();
20320 assert_invariant();
20323 if (JSON_HEDLEY_UNLIKELY(!is_object()))
20325 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this));
20328 // check if range iterators belong to the same JSON object
20329 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20331 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
20334 // passed iterators must belong to objects
20335 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
20337 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(first.m_object->type_name()), *first.m_object));
20340 for (auto it = first; it != last; ++it)
20342 if (merge_objects && it.value().is_object())
20344 auto it2 = m_value.object->find(it.key());
20345 if (it2 != m_value.object->end())
20347 it2->second.update(it.value(), true);
20351 m_value.object->operator[](it.key()) = it.value();
20352 #if JSON_DIAGNOSTICS
20353 m_value.object->operator[](it.key()).m_parent = this;
20358 /// @brief exchanges the values
20359 /// @sa https://json.nlohmann.me/api/basic_json/swap/
20360 void swap(reference other) noexcept (
20361 std::is_nothrow_move_constructible<value_t>::value&&
20362 std::is_nothrow_move_assignable<value_t>::value&&
20363 std::is_nothrow_move_constructible<json_value>::value&&
20364 std::is_nothrow_move_assignable<json_value>::value
20367 std::swap(m_type, other.m_type);
20368 std::swap(m_value, other.m_value);
20371 other.set_parents();
20372 assert_invariant();
20375 /// @brief exchanges the values
20376 /// @sa https://json.nlohmann.me/api/basic_json/swap/
20377 friend void swap(reference left, reference right) noexcept (
20378 std::is_nothrow_move_constructible<value_t>::value&&
20379 std::is_nothrow_move_assignable<value_t>::value&&
20380 std::is_nothrow_move_constructible<json_value>::value&&
20381 std::is_nothrow_move_assignable<json_value>::value
20387 /// @brief exchanges the values
20388 /// @sa https://json.nlohmann.me/api/basic_json/swap/
20389 void swap(array_t& other) // NOLINT(bugprone-exception-escape)
20391 // swap only works for arrays
20392 if (JSON_HEDLEY_LIKELY(is_array()))
20394 std::swap(*(m_value.array), other);
20398 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20402 /// @brief exchanges the values
20403 /// @sa https://json.nlohmann.me/api/basic_json/swap/
20404 void swap(object_t& other) // NOLINT(bugprone-exception-escape)
20406 // swap only works for objects
20407 if (JSON_HEDLEY_LIKELY(is_object()))
20409 std::swap(*(m_value.object), other);
20413 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20417 /// @brief exchanges the values
20418 /// @sa https://json.nlohmann.me/api/basic_json/swap/
20419 void swap(string_t& other) // NOLINT(bugprone-exception-escape)
20421 // swap only works for strings
20422 if (JSON_HEDLEY_LIKELY(is_string()))
20424 std::swap(*(m_value.string), other);
20428 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20432 /// @brief exchanges the values
20433 /// @sa https://json.nlohmann.me/api/basic_json/swap/
20434 void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
20436 // swap only works for strings
20437 if (JSON_HEDLEY_LIKELY(is_binary()))
20439 std::swap(*(m_value.binary), other);
20443 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20447 /// @brief exchanges the values
20448 /// @sa https://json.nlohmann.me/api/basic_json/swap/
20449 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
20451 // swap only works for strings
20452 if (JSON_HEDLEY_LIKELY(is_binary()))
20454 std::swap(*(m_value.binary), other);
20458 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20465 //////////////////////////////////////////
20466 // lexicographical comparison operators //
20467 //////////////////////////////////////////
20469 /// @name lexicographical comparison operators
20472 /// @brief comparison: equal
20473 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
20474 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
20477 #pragma GCC diagnostic push
20478 #pragma GCC diagnostic ignored "-Wfloat-equal"
20480 const auto lhs_type = lhs.type();
20481 const auto rhs_type = rhs.type();
20483 if (lhs_type == rhs_type)
20487 case value_t::array:
20488 return *lhs.m_value.array == *rhs.m_value.array;
20490 case value_t::object:
20491 return *lhs.m_value.object == *rhs.m_value.object;
20493 case value_t::null:
20496 case value_t::string:
20497 return *lhs.m_value.string == *rhs.m_value.string;
20499 case value_t::boolean:
20500 return lhs.m_value.boolean == rhs.m_value.boolean;
20502 case value_t::number_integer:
20503 return lhs.m_value.number_integer == rhs.m_value.number_integer;
20505 case value_t::number_unsigned:
20506 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
20508 case value_t::number_float:
20509 return lhs.m_value.number_float == rhs.m_value.number_float;
20511 case value_t::binary:
20512 return *lhs.m_value.binary == *rhs.m_value.binary;
20514 case value_t::discarded:
20519 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
20521 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
20523 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
20525 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
20527 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
20529 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
20531 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
20533 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
20535 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
20537 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
20539 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
20541 return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
20546 #pragma GCC diagnostic pop
20550 /// @brief comparison: equal
20551 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
20552 template<typename ScalarType, typename std::enable_if<
20553 std::is_scalar<ScalarType>::value, int>::type = 0>
20554 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
20556 return lhs == basic_json(rhs);
20559 /// @brief comparison: equal
20560 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
20561 template<typename ScalarType, typename std::enable_if<
20562 std::is_scalar<ScalarType>::value, int>::type = 0>
20563 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
20565 return basic_json(lhs) == rhs;
20568 /// @brief comparison: not equal
20569 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
20570 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
20572 return !(lhs == rhs);
20575 /// @brief comparison: not equal
20576 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
20577 template<typename ScalarType, typename std::enable_if<
20578 std::is_scalar<ScalarType>::value, int>::type = 0>
20579 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
20581 return lhs != basic_json(rhs);
20584 /// @brief comparison: not equal
20585 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
20586 template<typename ScalarType, typename std::enable_if<
20587 std::is_scalar<ScalarType>::value, int>::type = 0>
20588 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
20590 return basic_json(lhs) != rhs;
20593 /// @brief comparison: less than
20594 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
20595 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
20597 const auto lhs_type = lhs.type();
20598 const auto rhs_type = rhs.type();
20600 if (lhs_type == rhs_type)
20604 case value_t::array:
20605 // note parentheses are necessary, see
20606 // https://github.com/nlohmann/json/issues/1530
20607 return (*lhs.m_value.array) < (*rhs.m_value.array);
20609 case value_t::object:
20610 return (*lhs.m_value.object) < (*rhs.m_value.object);
20612 case value_t::null:
20615 case value_t::string:
20616 return (*lhs.m_value.string) < (*rhs.m_value.string);
20618 case value_t::boolean:
20619 return (lhs.m_value.boolean) < (rhs.m_value.boolean);
20621 case value_t::number_integer:
20622 return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
20624 case value_t::number_unsigned:
20625 return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned);
20627 case value_t::number_float:
20628 return (lhs.m_value.number_float) < (rhs.m_value.number_float);
20630 case value_t::binary:
20631 return (*lhs.m_value.binary) < (*rhs.m_value.binary);
20633 case value_t::discarded:
20638 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
20640 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
20642 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
20644 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
20646 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
20648 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
20650 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
20652 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
20654 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
20656 return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
20658 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
20660 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
20663 // We only reach this line if we cannot compare values. In that case,
20664 // we compare types. Note we have to call the operator explicitly,
20665 // because MSVC has problems otherwise.
20666 return operator<(lhs_type, rhs_type);
20669 /// @brief comparison: less than
20670 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
20671 template<typename ScalarType, typename std::enable_if<
20672 std::is_scalar<ScalarType>::value, int>::type = 0>
20673 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
20675 return lhs < basic_json(rhs);
20678 /// @brief comparison: less than
20679 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
20680 template<typename ScalarType, typename std::enable_if<
20681 std::is_scalar<ScalarType>::value, int>::type = 0>
20682 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
20684 return basic_json(lhs) < rhs;
20687 /// @brief comparison: less than or equal
20688 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
20689 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
20691 return !(rhs < lhs);
20694 /// @brief comparison: less than or equal
20695 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
20696 template<typename ScalarType, typename std::enable_if<
20697 std::is_scalar<ScalarType>::value, int>::type = 0>
20698 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
20700 return lhs <= basic_json(rhs);
20703 /// @brief comparison: less than or equal
20704 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
20705 template<typename ScalarType, typename std::enable_if<
20706 std::is_scalar<ScalarType>::value, int>::type = 0>
20707 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
20709 return basic_json(lhs) <= rhs;
20712 /// @brief comparison: greater than
20713 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
20714 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
20716 return !(lhs <= rhs);
20719 /// @brief comparison: greater than
20720 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
20721 template<typename ScalarType, typename std::enable_if<
20722 std::is_scalar<ScalarType>::value, int>::type = 0>
20723 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
20725 return lhs > basic_json(rhs);
20728 /// @brief comparison: greater than
20729 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
20730 template<typename ScalarType, typename std::enable_if<
20731 std::is_scalar<ScalarType>::value, int>::type = 0>
20732 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
20734 return basic_json(lhs) > rhs;
20737 /// @brief comparison: greater than or equal
20738 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
20739 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
20741 return !(lhs < rhs);
20744 /// @brief comparison: greater than or equal
20745 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
20746 template<typename ScalarType, typename std::enable_if<
20747 std::is_scalar<ScalarType>::value, int>::type = 0>
20748 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
20750 return lhs >= basic_json(rhs);
20753 /// @brief comparison: greater than or equal
20754 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
20755 template<typename ScalarType, typename std::enable_if<
20756 std::is_scalar<ScalarType>::value, int>::type = 0>
20757 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
20759 return basic_json(lhs) >= rhs;
20764 ///////////////////
20765 // serialization //
20766 ///////////////////
20768 /// @name serialization
20771 /// @brief serialize to stream
20772 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
20773 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
20775 // read width member and use it as indentation parameter if nonzero
20776 const bool pretty_print = o.width() > 0;
20777 const auto indentation = pretty_print ? o.width() : 0;
20779 // reset width to 0 for subsequent calls to this stream
20782 // do the actual serialization
20783 serializer s(detail::output_adapter<char>(o), o.fill());
20784 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
20788 /// @brief serialize to stream
20789 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
20790 /// @deprecated This function is deprecated since 3.0.0 and will be removed in
20791 /// version 4.0.0 of the library. Please use
20792 /// operator<<(std::ostream&, const basic_json&) instead; that is,
20793 /// replace calls like `j >> o;` with `o << j;`.
20794 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
20795 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
20799 #endif // JSON_NO_IO
20803 /////////////////////
20804 // deserialization //
20805 /////////////////////
20807 /// @name deserialization
20810 /// @brief deserialize from a compatible input
20811 /// @sa https://json.nlohmann.me/api/basic_json/parse/
20812 template<typename InputType>
20813 JSON_HEDLEY_WARN_UNUSED_RESULT
20814 static basic_json parse(InputType&& i,
20815 const parser_callback_t cb = nullptr,
20816 const bool allow_exceptions = true,
20817 const bool ignore_comments = false)
20820 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
20824 /// @brief deserialize from a pair of character iterators
20825 /// @sa https://json.nlohmann.me/api/basic_json/parse/
20826 template<typename IteratorType>
20827 JSON_HEDLEY_WARN_UNUSED_RESULT
20828 static basic_json parse(IteratorType first,
20830 const parser_callback_t cb = nullptr,
20831 const bool allow_exceptions = true,
20832 const bool ignore_comments = false)
20835 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
20839 JSON_HEDLEY_WARN_UNUSED_RESULT
20840 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
20841 static basic_json parse(detail::span_input_adapter&& i,
20842 const parser_callback_t cb = nullptr,
20843 const bool allow_exceptions = true,
20844 const bool ignore_comments = false)
20847 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
20851 /// @brief check if the input is valid JSON
20852 /// @sa https://json.nlohmann.me/api/basic_json/accept/
20853 template<typename InputType>
20854 static bool accept(InputType&& i,
20855 const bool ignore_comments = false)
20857 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
20860 /// @brief check if the input is valid JSON
20861 /// @sa https://json.nlohmann.me/api/basic_json/accept/
20862 template<typename IteratorType>
20863 static bool accept(IteratorType first, IteratorType last,
20864 const bool ignore_comments = false)
20866 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
20869 JSON_HEDLEY_WARN_UNUSED_RESULT
20870 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
20871 static bool accept(detail::span_input_adapter&& i,
20872 const bool ignore_comments = false)
20874 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
20877 /// @brief generate SAX events
20878 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
20879 template <typename InputType, typename SAX>
20880 JSON_HEDLEY_NON_NULL(2)
20881 static bool sax_parse(InputType&& i, SAX* sax,
20882 input_format_t format = input_format_t::json,
20883 const bool strict = true,
20884 const bool ignore_comments = false)
20886 auto ia = detail::input_adapter(std::forward<InputType>(i));
20887 return format == input_format_t::json
20888 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
20889 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
20892 /// @brief generate SAX events
20893 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
20894 template<class IteratorType, class SAX>
20895 JSON_HEDLEY_NON_NULL(3)
20896 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
20897 input_format_t format = input_format_t::json,
20898 const bool strict = true,
20899 const bool ignore_comments = false)
20901 auto ia = detail::input_adapter(std::move(first), std::move(last));
20902 return format == input_format_t::json
20903 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
20904 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
20907 /// @brief generate SAX events
20908 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
20909 /// @deprecated This function is deprecated since 3.8.0 and will be removed in
20910 /// version 4.0.0 of the library. Please use
20911 /// sax_parse(ptr, ptr + len) instead.
20912 template <typename SAX>
20913 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
20914 JSON_HEDLEY_NON_NULL(2)
20915 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
20916 input_format_t format = input_format_t::json,
20917 const bool strict = true,
20918 const bool ignore_comments = false)
20921 return format == input_format_t::json
20922 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
20923 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
20924 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
20925 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
20928 /// @brief deserialize from stream
20929 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
20930 /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
20931 /// version 4.0.0 of the library. Please use
20932 /// operator>>(std::istream&, basic_json&) instead; that is,
20933 /// replace calls like `j << i;` with `i >> j;`.
20934 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
20935 friend std::istream& operator<<(basic_json& j, std::istream& i)
20937 return operator>>(i, j);
20940 /// @brief deserialize from stream
20941 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
20942 friend std::istream& operator>>(std::istream& i, basic_json& j)
20944 parser(detail::input_adapter(i)).parse(false, j);
20947 #endif // JSON_NO_IO
20950 ///////////////////////////
20951 // convenience functions //
20952 ///////////////////////////
20954 /// @brief return the type as string
20955 /// @sa https://json.nlohmann.me/api/basic_json/type_name/
20956 JSON_HEDLEY_RETURNS_NON_NULL
20957 const char* type_name() const noexcept
20961 case value_t::null:
20963 case value_t::object:
20965 case value_t::array:
20967 case value_t::string:
20969 case value_t::boolean:
20971 case value_t::binary:
20973 case value_t::discarded:
20974 return "discarded";
20975 case value_t::number_integer:
20976 case value_t::number_unsigned:
20977 case value_t::number_float:
20984 JSON_PRIVATE_UNLESS_TESTED:
20985 //////////////////////
20986 // member variables //
20987 //////////////////////
20989 /// the type of the current element
20990 value_t m_type = value_t::null;
20992 /// the value of the current element
20993 json_value m_value = {};
20995 #if JSON_DIAGNOSTICS
20996 /// a pointer to a parent value (for debugging purposes)
20997 basic_json* m_parent = nullptr;
21000 //////////////////////////////////////////
21001 // binary serialization/deserialization //
21002 //////////////////////////////////////////
21004 /// @name binary serialization/deserialization support
21008 /// @brief create a CBOR serialization of a given JSON value
21009 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
21010 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
21012 std::vector<std::uint8_t> result;
21013 to_cbor(j, result);
21017 /// @brief create a CBOR serialization of a given JSON value
21018 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
21019 static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
21021 binary_writer<std::uint8_t>(o).write_cbor(j);
21024 /// @brief create a CBOR serialization of a given JSON value
21025 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
21026 static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
21028 binary_writer<char>(o).write_cbor(j);
21031 /// @brief create a MessagePack serialization of a given JSON value
21032 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
21033 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
21035 std::vector<std::uint8_t> result;
21036 to_msgpack(j, result);
21040 /// @brief create a MessagePack serialization of a given JSON value
21041 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
21042 static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
21044 binary_writer<std::uint8_t>(o).write_msgpack(j);
21047 /// @brief create a MessagePack serialization of a given JSON value
21048 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
21049 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
21051 binary_writer<char>(o).write_msgpack(j);
21054 /// @brief create a UBJSON serialization of a given JSON value
21055 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
21056 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
21057 const bool use_size = false,
21058 const bool use_type = false)
21060 std::vector<std::uint8_t> result;
21061 to_ubjson(j, result, use_size, use_type);
21065 /// @brief create a UBJSON serialization of a given JSON value
21066 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
21067 static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
21068 const bool use_size = false, const bool use_type = false)
21070 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
21073 /// @brief create a UBJSON serialization of a given JSON value
21074 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
21075 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
21076 const bool use_size = false, const bool use_type = false)
21078 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
21081 /// @brief create a BSON serialization of a given JSON value
21082 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
21083 static std::vector<std::uint8_t> to_bson(const basic_json& j)
21085 std::vector<std::uint8_t> result;
21086 to_bson(j, result);
21090 /// @brief create a BSON serialization of a given JSON value
21091 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
21092 static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
21094 binary_writer<std::uint8_t>(o).write_bson(j);
21097 /// @brief create a BSON serialization of a given JSON value
21098 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
21099 static void to_bson(const basic_json& j, detail::output_adapter<char> o)
21101 binary_writer<char>(o).write_bson(j);
21104 /// @brief create a JSON value from an input in CBOR format
21105 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
21106 template<typename InputType>
21107 JSON_HEDLEY_WARN_UNUSED_RESULT
21108 static basic_json from_cbor(InputType&& i,
21109 const bool strict = true,
21110 const bool allow_exceptions = true,
21111 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
21114 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21115 auto ia = detail::input_adapter(std::forward<InputType>(i));
21116 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
21117 return res ? result : basic_json(value_t::discarded);
21120 /// @brief create a JSON value from an input in CBOR format
21121 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
21122 template<typename IteratorType>
21123 JSON_HEDLEY_WARN_UNUSED_RESULT
21124 static basic_json from_cbor(IteratorType first, IteratorType last,
21125 const bool strict = true,
21126 const bool allow_exceptions = true,
21127 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
21130 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21131 auto ia = detail::input_adapter(std::move(first), std::move(last));
21132 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
21133 return res ? result : basic_json(value_t::discarded);
21136 template<typename T>
21137 JSON_HEDLEY_WARN_UNUSED_RESULT
21138 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
21139 static basic_json from_cbor(const T* ptr, std::size_t len,
21140 const bool strict = true,
21141 const bool allow_exceptions = true,
21142 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
21144 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
21148 JSON_HEDLEY_WARN_UNUSED_RESULT
21149 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
21150 static basic_json from_cbor(detail::span_input_adapter&& i,
21151 const bool strict = true,
21152 const bool allow_exceptions = true,
21153 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
21156 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21158 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21159 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
21160 return res ? result : basic_json(value_t::discarded);
21163 /// @brief create a JSON value from an input in MessagePack format
21164 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
21165 template<typename InputType>
21166 JSON_HEDLEY_WARN_UNUSED_RESULT
21167 static basic_json from_msgpack(InputType&& i,
21168 const bool strict = true,
21169 const bool allow_exceptions = true)
21172 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21173 auto ia = detail::input_adapter(std::forward<InputType>(i));
21174 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
21175 return res ? result : basic_json(value_t::discarded);
21178 /// @brief create a JSON value from an input in MessagePack format
21179 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
21180 template<typename IteratorType>
21181 JSON_HEDLEY_WARN_UNUSED_RESULT
21182 static basic_json from_msgpack(IteratorType first, IteratorType last,
21183 const bool strict = true,
21184 const bool allow_exceptions = true)
21187 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21188 auto ia = detail::input_adapter(std::move(first), std::move(last));
21189 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
21190 return res ? result : basic_json(value_t::discarded);
21193 template<typename T>
21194 JSON_HEDLEY_WARN_UNUSED_RESULT
21195 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
21196 static basic_json from_msgpack(const T* ptr, std::size_t len,
21197 const bool strict = true,
21198 const bool allow_exceptions = true)
21200 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
21203 JSON_HEDLEY_WARN_UNUSED_RESULT
21204 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
21205 static basic_json from_msgpack(detail::span_input_adapter&& i,
21206 const bool strict = true,
21207 const bool allow_exceptions = true)
21210 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21212 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21213 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
21214 return res ? result : basic_json(value_t::discarded);
21217 /// @brief create a JSON value from an input in UBJSON format
21218 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
21219 template<typename InputType>
21220 JSON_HEDLEY_WARN_UNUSED_RESULT
21221 static basic_json from_ubjson(InputType&& i,
21222 const bool strict = true,
21223 const bool allow_exceptions = true)
21226 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21227 auto ia = detail::input_adapter(std::forward<InputType>(i));
21228 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
21229 return res ? result : basic_json(value_t::discarded);
21232 /// @brief create a JSON value from an input in UBJSON format
21233 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
21234 template<typename IteratorType>
21235 JSON_HEDLEY_WARN_UNUSED_RESULT
21236 static basic_json from_ubjson(IteratorType first, IteratorType last,
21237 const bool strict = true,
21238 const bool allow_exceptions = true)
21241 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21242 auto ia = detail::input_adapter(std::move(first), std::move(last));
21243 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
21244 return res ? result : basic_json(value_t::discarded);
21247 template<typename T>
21248 JSON_HEDLEY_WARN_UNUSED_RESULT
21249 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
21250 static basic_json from_ubjson(const T* ptr, std::size_t len,
21251 const bool strict = true,
21252 const bool allow_exceptions = true)
21254 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
21257 JSON_HEDLEY_WARN_UNUSED_RESULT
21258 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
21259 static basic_json from_ubjson(detail::span_input_adapter&& i,
21260 const bool strict = true,
21261 const bool allow_exceptions = true)
21264 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21266 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21267 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
21268 return res ? result : basic_json(value_t::discarded);
21271 /// @brief create a JSON value from an input in BSON format
21272 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
21273 template<typename InputType>
21274 JSON_HEDLEY_WARN_UNUSED_RESULT
21275 static basic_json from_bson(InputType&& i,
21276 const bool strict = true,
21277 const bool allow_exceptions = true)
21280 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21281 auto ia = detail::input_adapter(std::forward<InputType>(i));
21282 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
21283 return res ? result : basic_json(value_t::discarded);
21286 /// @brief create a JSON value from an input in BSON format
21287 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
21288 template<typename IteratorType>
21289 JSON_HEDLEY_WARN_UNUSED_RESULT
21290 static basic_json from_bson(IteratorType first, IteratorType last,
21291 const bool strict = true,
21292 const bool allow_exceptions = true)
21295 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21296 auto ia = detail::input_adapter(std::move(first), std::move(last));
21297 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
21298 return res ? result : basic_json(value_t::discarded);
21301 template<typename T>
21302 JSON_HEDLEY_WARN_UNUSED_RESULT
21303 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
21304 static basic_json from_bson(const T* ptr, std::size_t len,
21305 const bool strict = true,
21306 const bool allow_exceptions = true)
21308 return from_bson(ptr, ptr + len, strict, allow_exceptions);
21311 JSON_HEDLEY_WARN_UNUSED_RESULT
21312 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
21313 static basic_json from_bson(detail::span_input_adapter&& i,
21314 const bool strict = true,
21315 const bool allow_exceptions = true)
21318 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21320 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21321 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
21322 return res ? result : basic_json(value_t::discarded);
21326 //////////////////////////
21327 // JSON Pointer support //
21328 //////////////////////////
21330 /// @name JSON Pointer functions
21333 /// @brief access specified element via JSON Pointer
21334 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21335 reference operator[](const json_pointer& ptr)
21337 return ptr.get_unchecked(this);
21340 /// @brief access specified element via JSON Pointer
21341 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21342 const_reference operator[](const json_pointer& ptr) const
21344 return ptr.get_unchecked(this);
21347 /// @brief access specified element via JSON Pointer
21348 /// @sa https://json.nlohmann.me/api/basic_json/at/
21349 reference at(const json_pointer& ptr)
21351 return ptr.get_checked(this);
21354 /// @brief access specified element via JSON Pointer
21355 /// @sa https://json.nlohmann.me/api/basic_json/at/
21356 const_reference at(const json_pointer& ptr) const
21358 return ptr.get_checked(this);
21361 /// @brief return flattened JSON value
21362 /// @sa https://json.nlohmann.me/api/basic_json/flatten/
21363 basic_json flatten() const
21365 basic_json result(value_t::object);
21366 json_pointer::flatten("", *this, result);
21370 /// @brief unflatten a previously flattened JSON value
21371 /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
21372 basic_json unflatten() const
21374 return json_pointer::unflatten(*this);
21379 //////////////////////////
21380 // JSON Patch functions //
21381 //////////////////////////
21383 /// @name JSON Patch functions
21386 /// @brief applies a JSON patch
21387 /// @sa https://json.nlohmann.me/api/basic_json/patch/
21388 basic_json patch(const basic_json& json_patch) const
21390 // make a working copy to apply the patch to
21391 basic_json result = *this;
21393 // the valid JSON Patch operations
21394 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
21396 const auto get_op = [](const std::string & op)
21400 return patch_operations::add;
21402 if (op == "remove")
21404 return patch_operations::remove;
21406 if (op == "replace")
21408 return patch_operations::replace;
21412 return patch_operations::move;
21416 return patch_operations::copy;
21420 return patch_operations::test;
21423 return patch_operations::invalid;
21426 // wrapper for "add" operation; add value at ptr
21427 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
21429 // adding to the root of the target document means replacing it
21436 // make sure the top element of the pointer exists
21437 json_pointer top_pointer = ptr.top();
21438 if (top_pointer != ptr)
21440 result.at(top_pointer);
21443 // get reference to parent of JSON pointer ptr
21444 const auto last_path = ptr.back();
21446 basic_json& parent = result[ptr];
21448 switch (parent.m_type)
21450 case value_t::null:
21451 case value_t::object:
21453 // use operator[] to add value
21454 parent[last_path] = val;
21458 case value_t::array:
21460 if (last_path == "-")
21462 // special case: append to back
21463 parent.push_back(val);
21467 const auto idx = json_pointer::array_index(last_path);
21468 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
21470 // avoid undefined behavior
21471 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", parent));
21474 // default case: insert add offset
21475 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
21480 // if there exists a parent it cannot be primitive
21481 case value_t::string: // LCOV_EXCL_LINE
21482 case value_t::boolean: // LCOV_EXCL_LINE
21483 case value_t::number_integer: // LCOV_EXCL_LINE
21484 case value_t::number_unsigned: // LCOV_EXCL_LINE
21485 case value_t::number_float: // LCOV_EXCL_LINE
21486 case value_t::binary: // LCOV_EXCL_LINE
21487 case value_t::discarded: // LCOV_EXCL_LINE
21488 default: // LCOV_EXCL_LINE
21489 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
21493 // wrapper for "remove" operation; remove value at ptr
21494 const auto operation_remove = [this, &result](json_pointer & ptr)
21496 // get reference to parent of JSON pointer ptr
21497 const auto last_path = ptr.back();
21499 basic_json& parent = result.at(ptr);
21502 if (parent.is_object())
21504 // perform range check
21505 auto it = parent.find(last_path);
21506 if (JSON_HEDLEY_LIKELY(it != parent.end()))
21512 JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", *this));
21515 else if (parent.is_array())
21517 // note erase performs range check
21518 parent.erase(json_pointer::array_index(last_path));
21522 // type check: top level value must be an array
21523 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
21525 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", json_patch));
21528 // iterate and apply the operations
21529 for (const auto& val : json_patch)
21531 // wrapper to get a value for an operation
21532 const auto get_value = [&val](const std::string & op,
21533 const std::string & member,
21534 bool string_type) -> basic_json &
21537 auto it = val.m_value.object->find(member);
21539 // context-sensitive error message
21540 const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
21542 // check if desired value is present
21543 if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
21545 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
21546 JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", val));
21549 // check if result is of type string
21550 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
21552 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
21553 JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", val));
21556 // no error: return value
21560 // type check: every element of the array must be an object
21561 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
21563 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", val));
21566 // collect mandatory members
21567 const auto op = get_value("op", "op", true).template get<std::string>();
21568 const auto path = get_value(op, "path", true).template get<std::string>();
21569 json_pointer ptr(path);
21571 switch (get_op(op))
21573 case patch_operations::add:
21575 operation_add(ptr, get_value("add", "value", false));
21579 case patch_operations::remove:
21581 operation_remove(ptr);
21585 case patch_operations::replace:
21587 // the "path" location must exist - use at()
21588 result.at(ptr) = get_value("replace", "value", false);
21592 case patch_operations::move:
21594 const auto from_path = get_value("move", "from", true).template get<std::string>();
21595 json_pointer from_ptr(from_path);
21597 // the "from" location must exist - use at()
21598 basic_json v = result.at(from_ptr);
21600 // The move operation is functionally identical to a
21601 // "remove" operation on the "from" location, followed
21602 // immediately by an "add" operation at the target
21603 // location with the value that was just removed.
21604 operation_remove(from_ptr);
21605 operation_add(ptr, v);
21609 case patch_operations::copy:
21611 const auto from_path = get_value("copy", "from", true).template get<std::string>();
21612 const json_pointer from_ptr(from_path);
21614 // the "from" location must exist - use at()
21615 basic_json v = result.at(from_ptr);
21617 // The copy is functionally identical to an "add"
21618 // operation at the target location using the value
21619 // specified in the "from" member.
21620 operation_add(ptr, v);
21624 case patch_operations::test:
21626 bool success = false;
21629 // check if "value" matches the one at "path"
21630 // the "path" location must exist - use at()
21631 success = (result.at(ptr) == get_value("test", "value", false));
21633 JSON_INTERNAL_CATCH (out_of_range&)
21635 // ignore out of range errors: success remains false
21638 // throw an exception if test fails
21639 if (JSON_HEDLEY_UNLIKELY(!success))
21641 JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), val));
21647 case patch_operations::invalid:
21650 // op must be "add", "remove", "replace", "move", "copy", or
21652 JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid", val));
21660 /// @brief creates a diff as a JSON patch
21661 /// @sa https://json.nlohmann.me/api/basic_json/diff/
21662 JSON_HEDLEY_WARN_UNUSED_RESULT
21663 static basic_json diff(const basic_json& source, const basic_json& target,
21664 const std::string& path = "")
21667 basic_json result(value_t::array);
21669 // if the values are the same, return empty patch
21670 if (source == target)
21675 if (source.type() != target.type())
21677 // different types: replace value
21680 {"op", "replace"}, {"path", path}, {"value", target}
21685 switch (source.type())
21687 case value_t::array:
21689 // first pass: traverse common elements
21691 while (i < source.size() && i < target.size())
21693 // recursive call to compare array values at index i
21694 auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
21695 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
21699 // We now reached the end of at least one array
21700 // in a second pass, traverse the remaining elements
21702 // remove my remaining elements
21703 const auto end_index = static_cast<difference_type>(result.size());
21704 while (i < source.size())
21706 // add operations in reverse order to avoid invalid
21708 result.insert(result.begin() + end_index, object(
21711 {"path", path + "/" + std::to_string(i)}
21716 // add other remaining elements
21717 while (i < target.size())
21722 {"path", path + "/-"},
21723 {"value", target[i]}
21731 case value_t::object:
21733 // first pass: traverse this object's elements
21734 for (auto it = source.cbegin(); it != source.cend(); ++it)
21736 // escape the key name to be used in a JSON patch
21737 const auto path_key = path + "/" + detail::escape(it.key());
21739 if (target.find(it.key()) != target.end())
21741 // recursive call to compare object values at key it
21742 auto temp_diff = diff(it.value(), target[it.key()], path_key);
21743 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
21747 // found a key that is not in o -> remove it
21748 result.push_back(object(
21750 {"op", "remove"}, {"path", path_key}
21755 // second pass: traverse other object's elements
21756 for (auto it = target.cbegin(); it != target.cend(); ++it)
21758 if (source.find(it.key()) == source.end())
21760 // found a key that is not in this -> add it
21761 const auto path_key = path + "/" + detail::escape(it.key());
21764 {"op", "add"}, {"path", path_key},
21765 {"value", it.value()}
21773 case value_t::null:
21774 case value_t::string:
21775 case value_t::boolean:
21776 case value_t::number_integer:
21777 case value_t::number_unsigned:
21778 case value_t::number_float:
21779 case value_t::binary:
21780 case value_t::discarded:
21783 // both primitive type: replace value
21786 {"op", "replace"}, {"path", path}, {"value", target}
21797 ////////////////////////////////
21798 // JSON Merge Patch functions //
21799 ////////////////////////////////
21801 /// @name JSON Merge Patch functions
21804 /// @brief applies a JSON Merge Patch
21805 /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
21806 void merge_patch(const basic_json& apply_patch)
21808 if (apply_patch.is_object())
21814 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
21816 if (it.value().is_null())
21822 operator[](it.key()).merge_patch(it.value());
21828 *this = apply_patch;
21835 /// @brief user-defined to_string function for JSON values
21836 /// @sa https://json.nlohmann.me/api/basic_json/to_string/
21837 NLOHMANN_BASIC_JSON_TPL_DECLARATION
21838 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
21843 } // namespace nlohmann
21845 ///////////////////////
21846 // nonmember support //
21847 ///////////////////////
21849 namespace std // NOLINT(cert-dcl58-cpp)
21852 /// @brief hash value for JSON objects
21853 /// @sa https://json.nlohmann.me/api/basic_json/std_hash/
21854 NLOHMANN_BASIC_JSON_TPL_DECLARATION
21855 struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL>
21857 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
21859 return nlohmann::detail::hash(j);
21863 // specialization for std::less<value_t>
21865 struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
21868 @brief compare two value_t enum values
21869 @since version 3.0.0
21871 bool operator()(nlohmann::detail::value_t lhs,
21872 nlohmann::detail::value_t rhs) const noexcept
21874 return nlohmann::detail::operator<(lhs, rhs);
21878 // C++20 prohibit function specialization in the std namespace.
21879 #ifndef JSON_HAS_CPP_20
21881 /// @brief exchanges the values of two JSON objects
21882 /// @sa https://json.nlohmann.me/api/basic_json/std_swap/
21883 NLOHMANN_BASIC_JSON_TPL_DECLARATION
21884 inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name)
21885 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression)
21886 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
21895 /// @brief user-defined string literal for JSON values
21896 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
21897 JSON_HEDLEY_NON_NULL(1)
21898 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
21900 return nlohmann::json::parse(s, s + n);
21903 /// @brief user-defined string literal for JSON pointer
21904 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
21905 JSON_HEDLEY_NON_NULL(1)
21906 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
21908 return nlohmann::json::json_pointer(std::string(s, n));
21911 // #include <nlohmann/detail/macro_unscope.hpp>
21914 // restore clang diagnostic settings
21915 #if defined(__clang__)
21916 #pragma clang diagnostic pop
21921 #undef JSON_INTERNAL_CATCH
21925 #undef JSON_PRIVATE_UNLESS_TESTED
21926 #undef JSON_HAS_CPP_11
21927 #undef JSON_HAS_CPP_14
21928 #undef JSON_HAS_CPP_17
21929 #undef JSON_HAS_CPP_20
21930 #undef JSON_HAS_FILESYSTEM
21931 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
21932 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
21933 #undef NLOHMANN_BASIC_JSON_TPL
21934 #undef JSON_EXPLICIT
21935 #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
21937 // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
21940 #undef JSON_HEDLEY_ALWAYS_INLINE
21941 #undef JSON_HEDLEY_ARM_VERSION
21942 #undef JSON_HEDLEY_ARM_VERSION_CHECK
21943 #undef JSON_HEDLEY_ARRAY_PARAM
21944 #undef JSON_HEDLEY_ASSUME
21945 #undef JSON_HEDLEY_BEGIN_C_DECLS
21946 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
21947 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
21948 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
21949 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
21950 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
21951 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
21952 #undef JSON_HEDLEY_CLANG_HAS_WARNING
21953 #undef JSON_HEDLEY_COMPCERT_VERSION
21954 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
21955 #undef JSON_HEDLEY_CONCAT
21956 #undef JSON_HEDLEY_CONCAT3
21957 #undef JSON_HEDLEY_CONCAT3_EX
21958 #undef JSON_HEDLEY_CONCAT_EX
21959 #undef JSON_HEDLEY_CONST
21960 #undef JSON_HEDLEY_CONSTEXPR
21961 #undef JSON_HEDLEY_CONST_CAST
21962 #undef JSON_HEDLEY_CPP_CAST
21963 #undef JSON_HEDLEY_CRAY_VERSION
21964 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
21965 #undef JSON_HEDLEY_C_DECL
21966 #undef JSON_HEDLEY_DEPRECATED
21967 #undef JSON_HEDLEY_DEPRECATED_FOR
21968 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
21969 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
21970 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
21971 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
21972 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
21973 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
21974 #undef JSON_HEDLEY_DIAGNOSTIC_POP
21975 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
21976 #undef JSON_HEDLEY_DMC_VERSION
21977 #undef JSON_HEDLEY_DMC_VERSION_CHECK
21978 #undef JSON_HEDLEY_EMPTY_BASES
21979 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
21980 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
21981 #undef JSON_HEDLEY_END_C_DECLS
21982 #undef JSON_HEDLEY_FLAGS
21983 #undef JSON_HEDLEY_FLAGS_CAST
21984 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
21985 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
21986 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
21987 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
21988 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
21989 #undef JSON_HEDLEY_GCC_HAS_FEATURE
21990 #undef JSON_HEDLEY_GCC_HAS_WARNING
21991 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
21992 #undef JSON_HEDLEY_GCC_VERSION
21993 #undef JSON_HEDLEY_GCC_VERSION_CHECK
21994 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
21995 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
21996 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
21997 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
21998 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
21999 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
22000 #undef JSON_HEDLEY_GNUC_HAS_WARNING
22001 #undef JSON_HEDLEY_GNUC_VERSION
22002 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
22003 #undef JSON_HEDLEY_HAS_ATTRIBUTE
22004 #undef JSON_HEDLEY_HAS_BUILTIN
22005 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
22006 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
22007 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
22008 #undef JSON_HEDLEY_HAS_EXTENSION
22009 #undef JSON_HEDLEY_HAS_FEATURE
22010 #undef JSON_HEDLEY_HAS_WARNING
22011 #undef JSON_HEDLEY_IAR_VERSION
22012 #undef JSON_HEDLEY_IAR_VERSION_CHECK
22013 #undef JSON_HEDLEY_IBM_VERSION
22014 #undef JSON_HEDLEY_IBM_VERSION_CHECK
22015 #undef JSON_HEDLEY_IMPORT
22016 #undef JSON_HEDLEY_INLINE
22017 #undef JSON_HEDLEY_INTEL_CL_VERSION
22018 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
22019 #undef JSON_HEDLEY_INTEL_VERSION
22020 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
22021 #undef JSON_HEDLEY_IS_CONSTANT
22022 #undef JSON_HEDLEY_IS_CONSTEXPR_
22023 #undef JSON_HEDLEY_LIKELY
22024 #undef JSON_HEDLEY_MALLOC
22025 #undef JSON_HEDLEY_MCST_LCC_VERSION
22026 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
22027 #undef JSON_HEDLEY_MESSAGE
22028 #undef JSON_HEDLEY_MSVC_VERSION
22029 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
22030 #undef JSON_HEDLEY_NEVER_INLINE
22031 #undef JSON_HEDLEY_NON_NULL
22032 #undef JSON_HEDLEY_NO_ESCAPE
22033 #undef JSON_HEDLEY_NO_RETURN
22034 #undef JSON_HEDLEY_NO_THROW
22035 #undef JSON_HEDLEY_NULL
22036 #undef JSON_HEDLEY_PELLES_VERSION
22037 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
22038 #undef JSON_HEDLEY_PGI_VERSION
22039 #undef JSON_HEDLEY_PGI_VERSION_CHECK
22040 #undef JSON_HEDLEY_PREDICT
22041 #undef JSON_HEDLEY_PRINTF_FORMAT
22042 #undef JSON_HEDLEY_PRIVATE
22043 #undef JSON_HEDLEY_PUBLIC
22044 #undef JSON_HEDLEY_PURE
22045 #undef JSON_HEDLEY_REINTERPRET_CAST
22046 #undef JSON_HEDLEY_REQUIRE
22047 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
22048 #undef JSON_HEDLEY_REQUIRE_MSG
22049 #undef JSON_HEDLEY_RESTRICT
22050 #undef JSON_HEDLEY_RETURNS_NON_NULL
22051 #undef JSON_HEDLEY_SENTINEL
22052 #undef JSON_HEDLEY_STATIC_ASSERT
22053 #undef JSON_HEDLEY_STATIC_CAST
22054 #undef JSON_HEDLEY_STRINGIFY
22055 #undef JSON_HEDLEY_STRINGIFY_EX
22056 #undef JSON_HEDLEY_SUNPRO_VERSION
22057 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
22058 #undef JSON_HEDLEY_TINYC_VERSION
22059 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
22060 #undef JSON_HEDLEY_TI_ARMCL_VERSION
22061 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
22062 #undef JSON_HEDLEY_TI_CL2000_VERSION
22063 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
22064 #undef JSON_HEDLEY_TI_CL430_VERSION
22065 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
22066 #undef JSON_HEDLEY_TI_CL6X_VERSION
22067 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
22068 #undef JSON_HEDLEY_TI_CL7X_VERSION
22069 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
22070 #undef JSON_HEDLEY_TI_CLPRU_VERSION
22071 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
22072 #undef JSON_HEDLEY_TI_VERSION
22073 #undef JSON_HEDLEY_TI_VERSION_CHECK
22074 #undef JSON_HEDLEY_UNAVAILABLE
22075 #undef JSON_HEDLEY_UNLIKELY
22076 #undef JSON_HEDLEY_UNPREDICTABLE
22077 #undef JSON_HEDLEY_UNREACHABLE
22078 #undef JSON_HEDLEY_UNREACHABLE_RETURN
22079 #undef JSON_HEDLEY_VERSION
22080 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
22081 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
22082 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
22083 #undef JSON_HEDLEY_VERSION_ENCODE
22084 #undef JSON_HEDLEY_WARNING
22085 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
22086 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
22087 #undef JSON_HEDLEY_FALL_THROUGH
22091 #endif // INCLUDE_NLOHMANN_JSON_HPP_