fix: relayd: unaligned access in trace_chunk_registry_ht_key_hash
[lttng-tools.git] / src / vendor / nlohmann / json.hpp
1 /*
2 __ _____ _____ _____
3 __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 3.10.5
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 SPDX-License-Identifier: MIT
9 Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
10
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
28 */
29
30 /****************************************************************************\
31 * Note on documentation: The source files contain links to the online *
32 * documentation of the public API at https://json.nlohmann.me. This URL *
33 * contains the most recent documentation and should also be applicable to *
34 * previous versions; documentation for deprecated functions is not *
35 * removed, but marked deprecated. See "Generate documentation" section in *
36 * file doc/README.md. *
37 \****************************************************************************/
38
39 #ifndef INCLUDE_NLOHMANN_JSON_HPP_
40 #define INCLUDE_NLOHMANN_JSON_HPP_
41
42 #define NLOHMANN_JSON_VERSION_MAJOR 3
43 #define NLOHMANN_JSON_VERSION_MINOR 10
44 #define NLOHMANN_JSON_VERSION_PATCH 5
45
46 #include <algorithm> // all_of, find, for_each
47 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
48 #include <functional> // hash, less
49 #include <initializer_list> // initializer_list
50 #ifndef JSON_NO_IO
51 #include <iosfwd> // istream, ostream
52 #endif // JSON_NO_IO
53 #include <iterator> // random_access_iterator_tag
54 #include <memory> // unique_ptr
55 #include <numeric> // accumulate
56 #include <string> // string, stoi, to_string
57 #include <utility> // declval, forward, move, pair, swap
58 #include <vector> // vector
59
60 // #include <nlohmann/adl_serializer.hpp>
61
62
63 #include <type_traits>
64 #include <utility>
65
66 // #include <nlohmann/detail/conversions/from_json.hpp>
67
68
69 #include <algorithm> // transform
70 #include <array> // array
71 #include <forward_list> // forward_list
72 #include <iterator> // inserter, front_inserter, end
73 #include <map> // map
74 #include <string> // string
75 #include <tuple> // tuple, make_tuple
76 #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
77 #include <unordered_map> // unordered_map
78 #include <utility> // pair, declval
79 #include <valarray> // valarray
80
81 // #include <nlohmann/detail/exceptions.hpp>
82
83
84 #include <exception> // exception
85 #include <stdexcept> // runtime_error
86 #include <string> // to_string
87 #include <vector> // vector
88
89 // #include <nlohmann/detail/value_t.hpp>
90
91
92 #include <array> // array
93 #include <cstddef> // size_t
94 #include <cstdint> // uint8_t
95 #include <string> // string
96
97 namespace nlohmann
98 {
99 namespace detail
100 {
101 ///////////////////////////
102 // JSON type enumeration //
103 ///////////////////////////
104
105 /*!
106 @brief the JSON type enumeration
107
108 This enumeration collects the different JSON types. It is internally used to
109 distinguish the stored values, and the functions @ref basic_json::is_null(),
110 @ref basic_json::is_object(), @ref basic_json::is_array(),
111 @ref basic_json::is_string(), @ref basic_json::is_boolean(),
112 @ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
113 @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
114 @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
115 @ref basic_json::is_structured() rely on it.
116
117 @note There are three enumeration entries (number_integer, number_unsigned, and
118 number_float), because the library distinguishes these three types for numbers:
119 @ref basic_json::number_unsigned_t is used for unsigned integers,
120 @ref basic_json::number_integer_t is used for signed integers, and
121 @ref basic_json::number_float_t is used for floating-point numbers or to
122 approximate integers which do not fit in the limits of their respective type.
123
124 @sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
125 value with the default value for a given type
126
127 @since version 1.0.0
128 */
129 enum class value_t : std::uint8_t
130 {
131 null, ///< null value
132 object, ///< object (unordered set of name/value pairs)
133 array, ///< array (ordered collection of values)
134 string, ///< string value
135 boolean, ///< boolean value
136 number_integer, ///< number value (signed integer)
137 number_unsigned, ///< number value (unsigned integer)
138 number_float, ///< number value (floating-point)
139 binary, ///< binary array (ordered collection of bytes)
140 discarded ///< discarded by the parser callback function
141 };
142
143 /*!
144 @brief comparison operator for JSON types
145
146 Returns an ordering that is similar to Python:
147 - order: null < boolean < number < object < array < string < binary
148 - furthermore, each type is not smaller than itself
149 - discarded values are not comparable
150 - binary is represented as a b"" string in python and directly comparable to a
151 string; however, making a binary array directly comparable with a string would
152 be surprising behavior in a JSON file.
153
154 @since version 1.0.0
155 */
156 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
157 {
158 static constexpr std::array<std::uint8_t, 9> order = {{
159 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
160 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
161 6 /* binary */
162 }
163 };
164
165 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];
168 }
169 } // namespace detail
170 } // namespace nlohmann
171
172 // #include <nlohmann/detail/string_escape.hpp>
173
174
175 #include <string>
176 // #include <nlohmann/detail/macro_scope.hpp>
177
178
179 #include <utility> // declval, pair
180 // #include <nlohmann/thirdparty/hedley/hedley.hpp>
181
182
183 /* Hedley - https://nemequ.github.io/hedley
184 * Created by Evan Nemerson <evan@nemerson.com>
185 *
186 * To the extent possible under law, the author(s) have dedicated all
187 * copyright and related and neighboring rights to this software to
188 * the public domain worldwide. This software is distributed without
189 * any warranty.
190 *
191 * For details, see <http://creativecommons.org/publicdomain/zero/1.0/>.
192 * SPDX-License-Identifier: CC0-1.0
193 */
194
195 #if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
196 #if defined(JSON_HEDLEY_VERSION)
197 #undef JSON_HEDLEY_VERSION
198 #endif
199 #define JSON_HEDLEY_VERSION 15
200
201 #if defined(JSON_HEDLEY_STRINGIFY_EX)
202 #undef JSON_HEDLEY_STRINGIFY_EX
203 #endif
204 #define JSON_HEDLEY_STRINGIFY_EX(x) #x
205
206 #if defined(JSON_HEDLEY_STRINGIFY)
207 #undef JSON_HEDLEY_STRINGIFY
208 #endif
209 #define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
210
211 #if defined(JSON_HEDLEY_CONCAT_EX)
212 #undef JSON_HEDLEY_CONCAT_EX
213 #endif
214 #define JSON_HEDLEY_CONCAT_EX(a,b) a##b
215
216 #if defined(JSON_HEDLEY_CONCAT)
217 #undef JSON_HEDLEY_CONCAT
218 #endif
219 #define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
220
221 #if defined(JSON_HEDLEY_CONCAT3_EX)
222 #undef JSON_HEDLEY_CONCAT3_EX
223 #endif
224 #define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
225
226 #if defined(JSON_HEDLEY_CONCAT3)
227 #undef JSON_HEDLEY_CONCAT3
228 #endif
229 #define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
230
231 #if defined(JSON_HEDLEY_VERSION_ENCODE)
232 #undef JSON_HEDLEY_VERSION_ENCODE
233 #endif
234 #define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
235
236 #if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
237 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
238 #endif
239 #define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
240
241 #if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
242 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
243 #endif
244 #define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
245
246 #if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
247 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
248 #endif
249 #define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
250
251 #if defined(JSON_HEDLEY_GNUC_VERSION)
252 #undef JSON_HEDLEY_GNUC_VERSION
253 #endif
254 #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
255 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
256 #elif defined(__GNUC__)
257 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
258 #endif
259
260 #if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
261 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
262 #endif
263 #if defined(JSON_HEDLEY_GNUC_VERSION)
264 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
265 #else
266 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
267 #endif
268
269 #if defined(JSON_HEDLEY_MSVC_VERSION)
270 #undef JSON_HEDLEY_MSVC_VERSION
271 #endif
272 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
273 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
274 #elif defined(_MSC_FULL_VER) && !defined(__ICL)
275 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
276 #elif defined(_MSC_VER) && !defined(__ICL)
277 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
278 #endif
279
280 #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
281 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
282 #endif
283 #if !defined(JSON_HEDLEY_MSVC_VERSION)
284 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
285 #elif defined(_MSC_VER) && (_MSC_VER >= 1400)
286 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
287 #elif defined(_MSC_VER) && (_MSC_VER >= 1200)
288 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
289 #else
290 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
291 #endif
292
293 #if defined(JSON_HEDLEY_INTEL_VERSION)
294 #undef JSON_HEDLEY_INTEL_VERSION
295 #endif
296 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
297 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
298 #elif defined(__INTEL_COMPILER) && !defined(__ICL)
299 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
300 #endif
301
302 #if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
303 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
304 #endif
305 #if defined(JSON_HEDLEY_INTEL_VERSION)
306 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
307 #else
308 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
309 #endif
310
311 #if defined(JSON_HEDLEY_INTEL_CL_VERSION)
312 #undef JSON_HEDLEY_INTEL_CL_VERSION
313 #endif
314 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
315 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
316 #endif
317
318 #if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
319 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
320 #endif
321 #if defined(JSON_HEDLEY_INTEL_CL_VERSION)
322 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
323 #else
324 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
325 #endif
326
327 #if defined(JSON_HEDLEY_PGI_VERSION)
328 #undef JSON_HEDLEY_PGI_VERSION
329 #endif
330 #if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
331 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
332 #endif
333
334 #if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
335 #undef JSON_HEDLEY_PGI_VERSION_CHECK
336 #endif
337 #if defined(JSON_HEDLEY_PGI_VERSION)
338 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
339 #else
340 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
341 #endif
342
343 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
344 #undef JSON_HEDLEY_SUNPRO_VERSION
345 #endif
346 #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
347 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
348 #elif defined(__SUNPRO_C)
349 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
350 #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
351 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
352 #elif defined(__SUNPRO_CC)
353 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
354 #endif
355
356 #if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
357 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
358 #endif
359 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
360 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
361 #else
362 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
363 #endif
364
365 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
366 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
367 #endif
368 #if defined(__EMSCRIPTEN__)
369 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
370 #endif
371
372 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
373 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
374 #endif
375 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
376 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
377 #else
378 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
379 #endif
380
381 #if defined(JSON_HEDLEY_ARM_VERSION)
382 #undef JSON_HEDLEY_ARM_VERSION
383 #endif
384 #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
385 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
386 #elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
387 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
388 #endif
389
390 #if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
391 #undef JSON_HEDLEY_ARM_VERSION_CHECK
392 #endif
393 #if defined(JSON_HEDLEY_ARM_VERSION)
394 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
395 #else
396 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
397 #endif
398
399 #if defined(JSON_HEDLEY_IBM_VERSION)
400 #undef JSON_HEDLEY_IBM_VERSION
401 #endif
402 #if defined(__ibmxl__)
403 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
404 #elif defined(__xlC__) && defined(__xlC_ver__)
405 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
406 #elif defined(__xlC__)
407 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
408 #endif
409
410 #if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
411 #undef JSON_HEDLEY_IBM_VERSION_CHECK
412 #endif
413 #if defined(JSON_HEDLEY_IBM_VERSION)
414 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
415 #else
416 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
417 #endif
418
419 #if defined(JSON_HEDLEY_TI_VERSION)
420 #undef JSON_HEDLEY_TI_VERSION
421 #endif
422 #if \
423 defined(__TI_COMPILER_VERSION__) && \
424 ( \
425 defined(__TMS470__) || defined(__TI_ARM__) || \
426 defined(__MSP430__) || \
427 defined(__TMS320C2000__) \
428 )
429 #if (__TI_COMPILER_VERSION__ >= 16000000)
430 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
431 #endif
432 #endif
433
434 #if defined(JSON_HEDLEY_TI_VERSION_CHECK)
435 #undef JSON_HEDLEY_TI_VERSION_CHECK
436 #endif
437 #if defined(JSON_HEDLEY_TI_VERSION)
438 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
439 #else
440 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
441 #endif
442
443 #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
444 #undef JSON_HEDLEY_TI_CL2000_VERSION
445 #endif
446 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
447 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
448 #endif
449
450 #if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
451 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
452 #endif
453 #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
454 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
455 #else
456 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
457 #endif
458
459 #if defined(JSON_HEDLEY_TI_CL430_VERSION)
460 #undef JSON_HEDLEY_TI_CL430_VERSION
461 #endif
462 #if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
463 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
464 #endif
465
466 #if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
467 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
468 #endif
469 #if defined(JSON_HEDLEY_TI_CL430_VERSION)
470 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
471 #else
472 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
473 #endif
474
475 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
476 #undef JSON_HEDLEY_TI_ARMCL_VERSION
477 #endif
478 #if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
479 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
480 #endif
481
482 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
483 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
484 #endif
485 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
486 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
487 #else
488 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
489 #endif
490
491 #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
492 #undef JSON_HEDLEY_TI_CL6X_VERSION
493 #endif
494 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
495 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
496 #endif
497
498 #if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
499 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
500 #endif
501 #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
502 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
503 #else
504 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
505 #endif
506
507 #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
508 #undef JSON_HEDLEY_TI_CL7X_VERSION
509 #endif
510 #if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
511 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
512 #endif
513
514 #if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
515 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
516 #endif
517 #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
518 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
519 #else
520 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
521 #endif
522
523 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
524 #undef JSON_HEDLEY_TI_CLPRU_VERSION
525 #endif
526 #if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
527 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
528 #endif
529
530 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
531 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
532 #endif
533 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
534 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
535 #else
536 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
537 #endif
538
539 #if defined(JSON_HEDLEY_CRAY_VERSION)
540 #undef JSON_HEDLEY_CRAY_VERSION
541 #endif
542 #if defined(_CRAYC)
543 #if defined(_RELEASE_PATCHLEVEL)
544 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
545 #else
546 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
547 #endif
548 #endif
549
550 #if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
551 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
552 #endif
553 #if defined(JSON_HEDLEY_CRAY_VERSION)
554 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
555 #else
556 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
557 #endif
558
559 #if defined(JSON_HEDLEY_IAR_VERSION)
560 #undef JSON_HEDLEY_IAR_VERSION
561 #endif
562 #if defined(__IAR_SYSTEMS_ICC__)
563 #if __VER__ > 1000
564 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
565 #else
566 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
567 #endif
568 #endif
569
570 #if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
571 #undef JSON_HEDLEY_IAR_VERSION_CHECK
572 #endif
573 #if defined(JSON_HEDLEY_IAR_VERSION)
574 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
575 #else
576 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
577 #endif
578
579 #if defined(JSON_HEDLEY_TINYC_VERSION)
580 #undef JSON_HEDLEY_TINYC_VERSION
581 #endif
582 #if defined(__TINYC__)
583 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
584 #endif
585
586 #if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
587 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
588 #endif
589 #if defined(JSON_HEDLEY_TINYC_VERSION)
590 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
591 #else
592 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
593 #endif
594
595 #if defined(JSON_HEDLEY_DMC_VERSION)
596 #undef JSON_HEDLEY_DMC_VERSION
597 #endif
598 #if defined(__DMC__)
599 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
600 #endif
601
602 #if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
603 #undef JSON_HEDLEY_DMC_VERSION_CHECK
604 #endif
605 #if defined(JSON_HEDLEY_DMC_VERSION)
606 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
607 #else
608 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
609 #endif
610
611 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
612 #undef JSON_HEDLEY_COMPCERT_VERSION
613 #endif
614 #if defined(__COMPCERT_VERSION__)
615 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
616 #endif
617
618 #if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
619 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
620 #endif
621 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
622 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
623 #else
624 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
625 #endif
626
627 #if defined(JSON_HEDLEY_PELLES_VERSION)
628 #undef JSON_HEDLEY_PELLES_VERSION
629 #endif
630 #if defined(__POCC__)
631 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
632 #endif
633
634 #if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
635 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
636 #endif
637 #if defined(JSON_HEDLEY_PELLES_VERSION)
638 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
639 #else
640 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
641 #endif
642
643 #if defined(JSON_HEDLEY_MCST_LCC_VERSION)
644 #undef JSON_HEDLEY_MCST_LCC_VERSION
645 #endif
646 #if defined(__LCC__) && defined(__LCC_MINOR__)
647 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
648 #endif
649
650 #if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
651 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
652 #endif
653 #if defined(JSON_HEDLEY_MCST_LCC_VERSION)
654 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
655 #else
656 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
657 #endif
658
659 #if defined(JSON_HEDLEY_GCC_VERSION)
660 #undef JSON_HEDLEY_GCC_VERSION
661 #endif
662 #if \
663 defined(JSON_HEDLEY_GNUC_VERSION) && \
664 !defined(__clang__) && \
665 !defined(JSON_HEDLEY_INTEL_VERSION) && \
666 !defined(JSON_HEDLEY_PGI_VERSION) && \
667 !defined(JSON_HEDLEY_ARM_VERSION) && \
668 !defined(JSON_HEDLEY_CRAY_VERSION) && \
669 !defined(JSON_HEDLEY_TI_VERSION) && \
670 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
671 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
672 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
673 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
674 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
675 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
676 !defined(__COMPCERT__) && \
677 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
678 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
679 #endif
680
681 #if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
682 #undef JSON_HEDLEY_GCC_VERSION_CHECK
683 #endif
684 #if defined(JSON_HEDLEY_GCC_VERSION)
685 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
686 #else
687 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
688 #endif
689
690 #if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
691 #undef JSON_HEDLEY_HAS_ATTRIBUTE
692 #endif
693 #if \
694 defined(__has_attribute) && \
695 ( \
696 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
697 )
698 # define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
699 #else
700 # define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
701 #endif
702
703 #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
704 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
705 #endif
706 #if defined(__has_attribute)
707 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
708 #else
709 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
710 #endif
711
712 #if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
713 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
714 #endif
715 #if defined(__has_attribute)
716 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
717 #else
718 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
719 #endif
720
721 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
722 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
723 #endif
724 #if \
725 defined(__has_cpp_attribute) && \
726 defined(__cplusplus) && \
727 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
728 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
729 #else
730 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
731 #endif
732
733 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
734 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
735 #endif
736 #if !defined(__cplusplus) || !defined(__has_cpp_attribute)
737 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
738 #elif \
739 !defined(JSON_HEDLEY_PGI_VERSION) && \
740 !defined(JSON_HEDLEY_IAR_VERSION) && \
741 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
742 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
743 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
744 #else
745 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
746 #endif
747
748 #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
749 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
750 #endif
751 #if defined(__has_cpp_attribute) && defined(__cplusplus)
752 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
753 #else
754 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
755 #endif
756
757 #if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
758 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
759 #endif
760 #if defined(__has_cpp_attribute) && defined(__cplusplus)
761 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
762 #else
763 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
764 #endif
765
766 #if defined(JSON_HEDLEY_HAS_BUILTIN)
767 #undef JSON_HEDLEY_HAS_BUILTIN
768 #endif
769 #if defined(__has_builtin)
770 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
771 #else
772 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
773 #endif
774
775 #if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
776 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
777 #endif
778 #if defined(__has_builtin)
779 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
780 #else
781 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
782 #endif
783
784 #if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
785 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
786 #endif
787 #if defined(__has_builtin)
788 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
789 #else
790 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
791 #endif
792
793 #if defined(JSON_HEDLEY_HAS_FEATURE)
794 #undef JSON_HEDLEY_HAS_FEATURE
795 #endif
796 #if defined(__has_feature)
797 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
798 #else
799 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
800 #endif
801
802 #if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
803 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
804 #endif
805 #if defined(__has_feature)
806 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
807 #else
808 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
809 #endif
810
811 #if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
812 #undef JSON_HEDLEY_GCC_HAS_FEATURE
813 #endif
814 #if defined(__has_feature)
815 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
816 #else
817 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
818 #endif
819
820 #if defined(JSON_HEDLEY_HAS_EXTENSION)
821 #undef JSON_HEDLEY_HAS_EXTENSION
822 #endif
823 #if defined(__has_extension)
824 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
825 #else
826 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
827 #endif
828
829 #if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
830 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
831 #endif
832 #if defined(__has_extension)
833 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
834 #else
835 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
836 #endif
837
838 #if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
839 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
840 #endif
841 #if defined(__has_extension)
842 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
843 #else
844 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
845 #endif
846
847 #if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
848 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
849 #endif
850 #if defined(__has_declspec_attribute)
851 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
852 #else
853 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
854 #endif
855
856 #if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
857 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
858 #endif
859 #if defined(__has_declspec_attribute)
860 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
861 #else
862 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
863 #endif
864
865 #if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
866 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
867 #endif
868 #if defined(__has_declspec_attribute)
869 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
870 #else
871 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
872 #endif
873
874 #if defined(JSON_HEDLEY_HAS_WARNING)
875 #undef JSON_HEDLEY_HAS_WARNING
876 #endif
877 #if defined(__has_warning)
878 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
879 #else
880 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
881 #endif
882
883 #if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
884 #undef JSON_HEDLEY_GNUC_HAS_WARNING
885 #endif
886 #if defined(__has_warning)
887 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
888 #else
889 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
890 #endif
891
892 #if defined(JSON_HEDLEY_GCC_HAS_WARNING)
893 #undef JSON_HEDLEY_GCC_HAS_WARNING
894 #endif
895 #if defined(__has_warning)
896 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
897 #else
898 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
899 #endif
900
901 #if \
902 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
903 defined(__clang__) || \
904 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
905 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
906 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
907 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
908 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
909 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
910 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
911 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
912 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
913 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
914 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
915 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
916 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
917 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
918 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
919 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
920 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
921 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
922 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
923 #else
924 #define JSON_HEDLEY_PRAGMA(value)
925 #endif
926
927 #if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
928 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
929 #endif
930 #if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
931 #undef JSON_HEDLEY_DIAGNOSTIC_POP
932 #endif
933 #if defined(__clang__)
934 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
935 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
936 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
937 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
938 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
939 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
940 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
941 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
942 #elif \
943 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
944 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
945 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
946 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
947 #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
948 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
949 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
950 #elif \
951 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
952 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
953 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
954 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
955 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
956 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
957 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
958 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
959 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
960 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
961 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
962 #else
963 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
964 #define JSON_HEDLEY_DIAGNOSTIC_POP
965 #endif
966
967 /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
968 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
969 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
970 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
971 #endif
972 #if defined(__cplusplus)
973 # if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
974 # if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
975 # if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
976 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
977 JSON_HEDLEY_DIAGNOSTIC_PUSH \
978 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
979 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
980 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
981 xpr \
982 JSON_HEDLEY_DIAGNOSTIC_POP
983 # else
984 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
985 JSON_HEDLEY_DIAGNOSTIC_PUSH \
986 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
987 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
988 xpr \
989 JSON_HEDLEY_DIAGNOSTIC_POP
990 # endif
991 # else
992 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
993 JSON_HEDLEY_DIAGNOSTIC_PUSH \
994 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
995 xpr \
996 JSON_HEDLEY_DIAGNOSTIC_POP
997 # endif
998 # endif
999 #endif
1000 #if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1001 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1002 #endif
1003
1004 #if defined(JSON_HEDLEY_CONST_CAST)
1005 #undef JSON_HEDLEY_CONST_CAST
1006 #endif
1007 #if defined(__cplusplus)
1008 # define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1009 #elif \
1010 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1011 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1012 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1013 # define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1014 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1015 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1016 ((T) (expr)); \
1017 JSON_HEDLEY_DIAGNOSTIC_POP \
1018 }))
1019 #else
1020 # define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1021 #endif
1022
1023 #if defined(JSON_HEDLEY_REINTERPRET_CAST)
1024 #undef JSON_HEDLEY_REINTERPRET_CAST
1025 #endif
1026 #if defined(__cplusplus)
1027 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1028 #else
1029 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1030 #endif
1031
1032 #if defined(JSON_HEDLEY_STATIC_CAST)
1033 #undef JSON_HEDLEY_STATIC_CAST
1034 #endif
1035 #if defined(__cplusplus)
1036 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1037 #else
1038 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1039 #endif
1040
1041 #if defined(JSON_HEDLEY_CPP_CAST)
1042 #undef JSON_HEDLEY_CPP_CAST
1043 #endif
1044 #if defined(__cplusplus)
1045 # if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1046 # define JSON_HEDLEY_CPP_CAST(T, expr) \
1047 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1048 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1049 ((T) (expr)) \
1050 JSON_HEDLEY_DIAGNOSTIC_POP
1051 # elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1052 # define JSON_HEDLEY_CPP_CAST(T, expr) \
1053 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1054 _Pragma("diag_suppress=Pe137") \
1055 JSON_HEDLEY_DIAGNOSTIC_POP
1056 # else
1057 # define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1058 # endif
1059 #else
1060 # define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1061 #endif
1062
1063 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1064 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1065 #endif
1066 #if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1067 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1068 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1069 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1070 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1071 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1072 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1073 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1074 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1075 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1076 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1077 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1078 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1079 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1080 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1081 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1082 #elif \
1083 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1084 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1085 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1086 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1087 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1088 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1089 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1090 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1091 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1092 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1093 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1094 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1095 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1096 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1097 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1098 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1099 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1100 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1101 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1102 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1103 #else
1104 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1105 #endif
1106
1107 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1108 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1109 #endif
1110 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1111 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1112 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1113 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1114 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1115 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1116 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1117 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1118 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1119 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1120 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1121 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1122 #elif \
1123 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1124 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1125 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1126 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1127 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1128 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1129 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1130 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1131 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1132 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1133 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1134 #else
1135 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1136 #endif
1137
1138 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1139 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1140 #endif
1141 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1142 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1143 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1144 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1145 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1146 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1147 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1148 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1149 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1150 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1151 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1152 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1153 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1154 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1155 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1156 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1157 #elif \
1158 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1159 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1160 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1161 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1162 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1163 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1164 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1165 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1166 #else
1167 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1168 #endif
1169
1170 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1171 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1172 #endif
1173 #if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1174 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1175 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1176 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1177 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1178 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1179 #else
1180 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1181 #endif
1182
1183 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1184 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1185 #endif
1186 #if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1187 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1188 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1189 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1190 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1191 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1192 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1193 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1194 #else
1195 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1196 #endif
1197
1198 #if defined(JSON_HEDLEY_DEPRECATED)
1199 #undef JSON_HEDLEY_DEPRECATED
1200 #endif
1201 #if defined(JSON_HEDLEY_DEPRECATED_FOR)
1202 #undef JSON_HEDLEY_DEPRECATED_FOR
1203 #endif
1204 #if \
1205 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1206 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1207 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1208 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1209 #elif \
1210 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1211 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1212 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1213 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1214 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1215 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1216 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1217 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1218 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1219 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1220 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1221 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1222 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1223 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1224 #elif defined(__cplusplus) && (__cplusplus >= 201402L)
1225 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1226 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1227 #elif \
1228 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1229 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1230 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1231 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1232 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1233 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1234 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1235 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1236 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1237 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1238 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1239 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1240 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1241 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1242 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1243 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1244 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1245 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1246 #elif \
1247 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1248 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1249 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1250 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1251 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1252 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1253 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1254 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1255 #else
1256 #define JSON_HEDLEY_DEPRECATED(since)
1257 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1258 #endif
1259
1260 #if defined(JSON_HEDLEY_UNAVAILABLE)
1261 #undef JSON_HEDLEY_UNAVAILABLE
1262 #endif
1263 #if \
1264 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1265 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1266 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1267 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1268 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1269 #else
1270 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1271 #endif
1272
1273 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1274 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1275 #endif
1276 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1277 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1278 #endif
1279 #if \
1280 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1281 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1282 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1283 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1284 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1285 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1286 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1287 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1288 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1289 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1290 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1291 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1292 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1293 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1294 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1295 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1296 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1297 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1298 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1299 #elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1300 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1301 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1302 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1303 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1304 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1305 #elif defined(_Check_return_) /* SAL */
1306 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1307 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1308 #else
1309 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1310 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1311 #endif
1312
1313 #if defined(JSON_HEDLEY_SENTINEL)
1314 #undef JSON_HEDLEY_SENTINEL
1315 #endif
1316 #if \
1317 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1318 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1319 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1320 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1321 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1322 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1323 #else
1324 #define JSON_HEDLEY_SENTINEL(position)
1325 #endif
1326
1327 #if defined(JSON_HEDLEY_NO_RETURN)
1328 #undef JSON_HEDLEY_NO_RETURN
1329 #endif
1330 #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1331 #define JSON_HEDLEY_NO_RETURN __noreturn
1332 #elif \
1333 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1334 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1335 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1336 #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1337 #define JSON_HEDLEY_NO_RETURN _Noreturn
1338 #elif defined(__cplusplus) && (__cplusplus >= 201103L)
1339 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1340 #elif \
1341 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1342 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1343 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1344 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1345 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1346 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1347 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1348 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1349 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1350 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1351 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1352 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1353 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1354 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1355 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1356 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1357 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1358 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1359 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1360 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1361 #elif \
1362 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1363 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1364 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1365 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1366 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1367 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1368 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1369 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1370 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1371 #else
1372 #define JSON_HEDLEY_NO_RETURN
1373 #endif
1374
1375 #if defined(JSON_HEDLEY_NO_ESCAPE)
1376 #undef JSON_HEDLEY_NO_ESCAPE
1377 #endif
1378 #if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1379 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1380 #else
1381 #define JSON_HEDLEY_NO_ESCAPE
1382 #endif
1383
1384 #if defined(JSON_HEDLEY_UNREACHABLE)
1385 #undef JSON_HEDLEY_UNREACHABLE
1386 #endif
1387 #if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1388 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1389 #endif
1390 #if defined(JSON_HEDLEY_ASSUME)
1391 #undef JSON_HEDLEY_ASSUME
1392 #endif
1393 #if \
1394 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1395 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1396 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1397 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1398 #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1399 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1400 #elif \
1401 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1402 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1403 #if defined(__cplusplus)
1404 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1405 #else
1406 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1407 #endif
1408 #endif
1409 #if \
1410 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1411 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1412 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1413 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1414 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1415 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1416 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1417 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1418 #elif defined(JSON_HEDLEY_ASSUME)
1419 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1420 #endif
1421 #if !defined(JSON_HEDLEY_ASSUME)
1422 #if defined(JSON_HEDLEY_UNREACHABLE)
1423 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1424 #else
1425 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1426 #endif
1427 #endif
1428 #if defined(JSON_HEDLEY_UNREACHABLE)
1429 #if \
1430 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1431 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1432 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1433 #else
1434 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1435 #endif
1436 #else
1437 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1438 #endif
1439 #if !defined(JSON_HEDLEY_UNREACHABLE)
1440 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1441 #endif
1442
1443 JSON_HEDLEY_DIAGNOSTIC_PUSH
1444 #if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1445 #pragma clang diagnostic ignored "-Wpedantic"
1446 #endif
1447 #if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1448 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1449 #endif
1450 #if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1451 #if defined(__clang__)
1452 #pragma clang diagnostic ignored "-Wvariadic-macros"
1453 #elif defined(JSON_HEDLEY_GCC_VERSION)
1454 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1455 #endif
1456 #endif
1457 #if defined(JSON_HEDLEY_NON_NULL)
1458 #undef JSON_HEDLEY_NON_NULL
1459 #endif
1460 #if \
1461 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1462 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1463 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1464 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1465 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1466 #else
1467 #define JSON_HEDLEY_NON_NULL(...)
1468 #endif
1469 JSON_HEDLEY_DIAGNOSTIC_POP
1470
1471 #if defined(JSON_HEDLEY_PRINTF_FORMAT)
1472 #undef JSON_HEDLEY_PRINTF_FORMAT
1473 #endif
1474 #if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1475 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1476 #elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1477 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1478 #elif \
1479 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1480 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1481 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1482 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1483 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1484 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1485 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1486 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1487 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1488 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1489 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1490 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1491 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1492 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1493 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1494 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1495 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1496 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1497 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1498 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1499 #else
1500 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1501 #endif
1502
1503 #if defined(JSON_HEDLEY_CONSTEXPR)
1504 #undef JSON_HEDLEY_CONSTEXPR
1505 #endif
1506 #if defined(__cplusplus)
1507 #if __cplusplus >= 201103L
1508 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1509 #endif
1510 #endif
1511 #if !defined(JSON_HEDLEY_CONSTEXPR)
1512 #define JSON_HEDLEY_CONSTEXPR
1513 #endif
1514
1515 #if defined(JSON_HEDLEY_PREDICT)
1516 #undef JSON_HEDLEY_PREDICT
1517 #endif
1518 #if defined(JSON_HEDLEY_LIKELY)
1519 #undef JSON_HEDLEY_LIKELY
1520 #endif
1521 #if defined(JSON_HEDLEY_UNLIKELY)
1522 #undef JSON_HEDLEY_UNLIKELY
1523 #endif
1524 #if defined(JSON_HEDLEY_UNPREDICTABLE)
1525 #undef JSON_HEDLEY_UNPREDICTABLE
1526 #endif
1527 #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1528 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1529 #endif
1530 #if \
1531 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1532 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1533 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1534 # define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1535 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1536 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1537 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1538 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1539 #elif \
1540 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1541 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1542 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1543 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1544 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1545 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1546 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1547 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1548 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1549 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1550 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1551 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1552 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1553 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1554 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1555 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1556 # define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1557 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1558 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1559 (__extension__ ({ \
1560 double hedley_probability_ = (probability); \
1561 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1562 }))
1563 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1564 (__extension__ ({ \
1565 double hedley_probability_ = (probability); \
1566 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1567 }))
1568 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1569 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1570 #else
1571 # define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1572 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1573 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1574 # define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1575 # define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1576 #endif
1577 #if !defined(JSON_HEDLEY_UNPREDICTABLE)
1578 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1579 #endif
1580
1581 #if defined(JSON_HEDLEY_MALLOC)
1582 #undef JSON_HEDLEY_MALLOC
1583 #endif
1584 #if \
1585 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1586 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1587 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1588 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1589 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1590 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1591 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1592 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1593 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1594 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1595 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1596 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1597 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1598 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1599 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1600 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1601 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1602 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1603 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1604 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1605 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1606 #elif \
1607 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1608 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1609 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1610 #else
1611 #define JSON_HEDLEY_MALLOC
1612 #endif
1613
1614 #if defined(JSON_HEDLEY_PURE)
1615 #undef JSON_HEDLEY_PURE
1616 #endif
1617 #if \
1618 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1619 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1620 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1621 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1622 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1623 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1624 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1625 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1626 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1627 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1628 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1629 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1630 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1631 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1632 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1633 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1634 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1635 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1636 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1637 # define JSON_HEDLEY_PURE __attribute__((__pure__))
1638 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1639 # define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1640 #elif defined(__cplusplus) && \
1641 ( \
1642 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1643 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1644 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1645 )
1646 # define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1647 #else
1648 # define JSON_HEDLEY_PURE
1649 #endif
1650
1651 #if defined(JSON_HEDLEY_CONST)
1652 #undef JSON_HEDLEY_CONST
1653 #endif
1654 #if \
1655 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1656 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1657 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1658 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1659 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1660 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1661 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1662 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1663 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1664 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1665 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1666 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1667 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1668 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1669 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1670 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1671 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1672 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1673 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1674 #define JSON_HEDLEY_CONST __attribute__((__const__))
1675 #elif \
1676 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1677 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1678 #else
1679 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1680 #endif
1681
1682 #if defined(JSON_HEDLEY_RESTRICT)
1683 #undef JSON_HEDLEY_RESTRICT
1684 #endif
1685 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1686 #define JSON_HEDLEY_RESTRICT restrict
1687 #elif \
1688 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1689 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1690 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1691 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1692 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1693 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1694 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1695 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1696 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1697 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1698 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1699 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1700 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1701 defined(__clang__) || \
1702 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1703 #define JSON_HEDLEY_RESTRICT __restrict
1704 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1705 #define JSON_HEDLEY_RESTRICT _Restrict
1706 #else
1707 #define JSON_HEDLEY_RESTRICT
1708 #endif
1709
1710 #if defined(JSON_HEDLEY_INLINE)
1711 #undef JSON_HEDLEY_INLINE
1712 #endif
1713 #if \
1714 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1715 (defined(__cplusplus) && (__cplusplus >= 199711L))
1716 #define JSON_HEDLEY_INLINE inline
1717 #elif \
1718 defined(JSON_HEDLEY_GCC_VERSION) || \
1719 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1720 #define JSON_HEDLEY_INLINE __inline__
1721 #elif \
1722 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1723 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1724 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1725 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1726 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1727 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1728 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1729 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1730 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1731 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1732 #define JSON_HEDLEY_INLINE __inline
1733 #else
1734 #define JSON_HEDLEY_INLINE
1735 #endif
1736
1737 #if defined(JSON_HEDLEY_ALWAYS_INLINE)
1738 #undef JSON_HEDLEY_ALWAYS_INLINE
1739 #endif
1740 #if \
1741 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1742 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1743 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1744 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1745 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1746 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1747 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1748 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1749 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1750 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1751 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1752 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1753 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1754 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1755 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1756 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1757 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1758 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1759 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1760 # define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1761 #elif \
1762 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1763 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1764 # define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1765 #elif defined(__cplusplus) && \
1766 ( \
1767 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1768 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1769 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1770 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1771 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1772 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1773 )
1774 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1775 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1776 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1777 #else
1778 # define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1779 #endif
1780
1781 #if defined(JSON_HEDLEY_NEVER_INLINE)
1782 #undef JSON_HEDLEY_NEVER_INLINE
1783 #endif
1784 #if \
1785 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1786 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1787 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1788 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1789 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1790 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1791 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1792 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1793 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1794 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1795 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1796 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1797 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1798 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1799 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1800 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1801 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1802 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1803 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1804 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1805 #elif \
1806 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1807 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1808 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1809 #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1810 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1811 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1812 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1813 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1814 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1815 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1816 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1817 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1818 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1819 #else
1820 #define JSON_HEDLEY_NEVER_INLINE
1821 #endif
1822
1823 #if defined(JSON_HEDLEY_PRIVATE)
1824 #undef JSON_HEDLEY_PRIVATE
1825 #endif
1826 #if defined(JSON_HEDLEY_PUBLIC)
1827 #undef JSON_HEDLEY_PUBLIC
1828 #endif
1829 #if defined(JSON_HEDLEY_IMPORT)
1830 #undef JSON_HEDLEY_IMPORT
1831 #endif
1832 #if defined(_WIN32) || defined(__CYGWIN__)
1833 # define JSON_HEDLEY_PRIVATE
1834 # define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1835 # define JSON_HEDLEY_IMPORT __declspec(dllimport)
1836 #else
1837 # if \
1838 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1839 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1840 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1841 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1842 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1843 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1844 ( \
1845 defined(__TI_EABI__) && \
1846 ( \
1847 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1848 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1849 ) \
1850 ) || \
1851 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1852 # define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1853 # define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1854 # else
1855 # define JSON_HEDLEY_PRIVATE
1856 # define JSON_HEDLEY_PUBLIC
1857 # endif
1858 # define JSON_HEDLEY_IMPORT extern
1859 #endif
1860
1861 #if defined(JSON_HEDLEY_NO_THROW)
1862 #undef JSON_HEDLEY_NO_THROW
1863 #endif
1864 #if \
1865 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
1866 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1867 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1868 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1869 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
1870 #elif \
1871 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
1872 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1873 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1874 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
1875 #else
1876 #define JSON_HEDLEY_NO_THROW
1877 #endif
1878
1879 #if defined(JSON_HEDLEY_FALL_THROUGH)
1880 #undef JSON_HEDLEY_FALL_THROUGH
1881 #endif
1882 #if \
1883 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
1884 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
1885 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1886 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
1887 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
1888 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
1889 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
1890 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
1891 #elif defined(__fallthrough) /* SAL */
1892 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
1893 #else
1894 #define JSON_HEDLEY_FALL_THROUGH
1895 #endif
1896
1897 #if defined(JSON_HEDLEY_RETURNS_NON_NULL)
1898 #undef JSON_HEDLEY_RETURNS_NON_NULL
1899 #endif
1900 #if \
1901 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
1902 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
1903 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1904 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
1905 #elif defined(_Ret_notnull_) /* SAL */
1906 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
1907 #else
1908 #define JSON_HEDLEY_RETURNS_NON_NULL
1909 #endif
1910
1911 #if defined(JSON_HEDLEY_ARRAY_PARAM)
1912 #undef JSON_HEDLEY_ARRAY_PARAM
1913 #endif
1914 #if \
1915 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
1916 !defined(__STDC_NO_VLA__) && \
1917 !defined(__cplusplus) && \
1918 !defined(JSON_HEDLEY_PGI_VERSION) && \
1919 !defined(JSON_HEDLEY_TINYC_VERSION)
1920 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
1921 #else
1922 #define JSON_HEDLEY_ARRAY_PARAM(name)
1923 #endif
1924
1925 #if defined(JSON_HEDLEY_IS_CONSTANT)
1926 #undef JSON_HEDLEY_IS_CONSTANT
1927 #endif
1928 #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
1929 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
1930 #endif
1931 /* JSON_HEDLEY_IS_CONSTEXPR_ is for
1932 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1933 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1934 #undef JSON_HEDLEY_IS_CONSTEXPR_
1935 #endif
1936 #if \
1937 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
1938 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1939 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1940 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
1941 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1942 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1943 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1944 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
1945 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1946 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1947 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
1948 #endif
1949 #if !defined(__cplusplus)
1950 # if \
1951 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
1952 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1953 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1954 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1955 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1956 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1957 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
1958 #if defined(__INTPTR_TYPE__)
1959 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
1960 #else
1961 #include <stdint.h>
1962 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
1963 #endif
1964 # elif \
1965 ( \
1966 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
1967 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
1968 !defined(JSON_HEDLEY_PGI_VERSION) && \
1969 !defined(JSON_HEDLEY_IAR_VERSION)) || \
1970 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1971 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
1972 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
1973 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1974 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
1975 #if defined(__INTPTR_TYPE__)
1976 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
1977 #else
1978 #include <stdint.h>
1979 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
1980 #endif
1981 # elif \
1982 defined(JSON_HEDLEY_GCC_VERSION) || \
1983 defined(JSON_HEDLEY_INTEL_VERSION) || \
1984 defined(JSON_HEDLEY_TINYC_VERSION) || \
1985 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
1986 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
1987 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
1988 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
1989 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
1990 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
1991 defined(__clang__)
1992 # define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
1993 sizeof(void) != \
1994 sizeof(*( \
1995 1 ? \
1996 ((void*) ((expr) * 0L) ) : \
1997 ((struct { char v[sizeof(void) * 2]; } *) 1) \
1998 ) \
1999 ) \
2000 )
2001 # endif
2002 #endif
2003 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2004 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2005 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2006 #endif
2007 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2008 #else
2009 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2010 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2011 #endif
2012 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2013 #endif
2014
2015 #if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2016 #undef JSON_HEDLEY_BEGIN_C_DECLS
2017 #endif
2018 #if defined(JSON_HEDLEY_END_C_DECLS)
2019 #undef JSON_HEDLEY_END_C_DECLS
2020 #endif
2021 #if defined(JSON_HEDLEY_C_DECL)
2022 #undef JSON_HEDLEY_C_DECL
2023 #endif
2024 #if defined(__cplusplus)
2025 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2026 #define JSON_HEDLEY_END_C_DECLS }
2027 #define JSON_HEDLEY_C_DECL extern "C"
2028 #else
2029 #define JSON_HEDLEY_BEGIN_C_DECLS
2030 #define JSON_HEDLEY_END_C_DECLS
2031 #define JSON_HEDLEY_C_DECL
2032 #endif
2033
2034 #if defined(JSON_HEDLEY_STATIC_ASSERT)
2035 #undef JSON_HEDLEY_STATIC_ASSERT
2036 #endif
2037 #if \
2038 !defined(__cplusplus) && ( \
2039 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2040 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2041 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2042 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2043 defined(_Static_assert) \
2044 )
2045 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2046 #elif \
2047 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2048 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2049 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2050 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2051 #else
2052 # define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2053 #endif
2054
2055 #if defined(JSON_HEDLEY_NULL)
2056 #undef JSON_HEDLEY_NULL
2057 #endif
2058 #if defined(__cplusplus)
2059 #if __cplusplus >= 201103L
2060 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2061 #elif defined(NULL)
2062 #define JSON_HEDLEY_NULL NULL
2063 #else
2064 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2065 #endif
2066 #elif defined(NULL)
2067 #define JSON_HEDLEY_NULL NULL
2068 #else
2069 #define JSON_HEDLEY_NULL ((void*) 0)
2070 #endif
2071
2072 #if defined(JSON_HEDLEY_MESSAGE)
2073 #undef JSON_HEDLEY_MESSAGE
2074 #endif
2075 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2076 # define JSON_HEDLEY_MESSAGE(msg) \
2077 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2078 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2079 JSON_HEDLEY_PRAGMA(message msg) \
2080 JSON_HEDLEY_DIAGNOSTIC_POP
2081 #elif \
2082 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2083 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2084 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2085 #elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2086 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2087 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2088 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2089 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2090 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2091 #else
2092 # define JSON_HEDLEY_MESSAGE(msg)
2093 #endif
2094
2095 #if defined(JSON_HEDLEY_WARNING)
2096 #undef JSON_HEDLEY_WARNING
2097 #endif
2098 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2099 # define JSON_HEDLEY_WARNING(msg) \
2100 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2101 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2102 JSON_HEDLEY_PRAGMA(clang warning msg) \
2103 JSON_HEDLEY_DIAGNOSTIC_POP
2104 #elif \
2105 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2106 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2107 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2108 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2109 #elif \
2110 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2111 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2112 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2113 #else
2114 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2115 #endif
2116
2117 #if defined(JSON_HEDLEY_REQUIRE)
2118 #undef JSON_HEDLEY_REQUIRE
2119 #endif
2120 #if defined(JSON_HEDLEY_REQUIRE_MSG)
2121 #undef JSON_HEDLEY_REQUIRE_MSG
2122 #endif
2123 #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2124 # if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2125 # define JSON_HEDLEY_REQUIRE(expr) \
2126 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2127 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2128 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2129 JSON_HEDLEY_DIAGNOSTIC_POP
2130 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2131 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2132 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2133 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2134 JSON_HEDLEY_DIAGNOSTIC_POP
2135 # else
2136 # define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2137 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2138 # endif
2139 #else
2140 # define JSON_HEDLEY_REQUIRE(expr)
2141 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2142 #endif
2143
2144 #if defined(JSON_HEDLEY_FLAGS)
2145 #undef JSON_HEDLEY_FLAGS
2146 #endif
2147 #if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2148 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2149 #else
2150 #define JSON_HEDLEY_FLAGS
2151 #endif
2152
2153 #if defined(JSON_HEDLEY_FLAGS_CAST)
2154 #undef JSON_HEDLEY_FLAGS_CAST
2155 #endif
2156 #if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2157 # define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2158 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2159 _Pragma("warning(disable:188)") \
2160 ((T) (expr)); \
2161 JSON_HEDLEY_DIAGNOSTIC_POP \
2162 }))
2163 #else
2164 # define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2165 #endif
2166
2167 #if defined(JSON_HEDLEY_EMPTY_BASES)
2168 #undef JSON_HEDLEY_EMPTY_BASES
2169 #endif
2170 #if \
2171 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2172 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2173 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2174 #else
2175 #define JSON_HEDLEY_EMPTY_BASES
2176 #endif
2177
2178 /* Remaining macros are deprecated. */
2179
2180 #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2181 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2182 #endif
2183 #if defined(__clang__)
2184 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2185 #else
2186 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2187 #endif
2188
2189 #if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2190 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2191 #endif
2192 #define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2193
2194 #if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2195 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2196 #endif
2197 #define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2198
2199 #if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2200 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2201 #endif
2202 #define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2203
2204 #if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2205 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2206 #endif
2207 #define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2208
2209 #if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2210 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2211 #endif
2212 #define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2213
2214 #if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2215 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2216 #endif
2217 #define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2218
2219 #if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2220 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2221 #endif
2222 #define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2223
2224 #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2225
2226 // #include <nlohmann/detail/meta/detected.hpp>
2227
2228
2229 #include <type_traits>
2230
2231 // #include <nlohmann/detail/meta/void_t.hpp>
2232
2233
2234 namespace nlohmann
2235 {
2236 namespace detail
2237 {
2238 template<typename ...Ts> struct make_void
2239 {
2240 using type = void;
2241 };
2242 template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
2243 } // namespace detail
2244 } // namespace nlohmann
2245
2246
2247 // https://en.cppreference.com/w/cpp/experimental/is_detected
2248 namespace nlohmann
2249 {
2250 namespace detail
2251 {
2252 struct nonesuch
2253 {
2254 nonesuch() = delete;
2255 ~nonesuch() = delete;
2256 nonesuch(nonesuch const&) = delete;
2257 nonesuch(nonesuch const&&) = delete;
2258 void operator=(nonesuch const&) = delete;
2259 void operator=(nonesuch&&) = delete;
2260 };
2261
2262 template<class Default,
2263 class AlwaysVoid,
2264 template<class...> class Op,
2265 class... Args>
2266 struct detector
2267 {
2268 using value_t = std::false_type;
2269 using type = Default;
2270 };
2271
2272 template<class Default, template<class...> class Op, class... Args>
2273 struct detector<Default, void_t<Op<Args...>>, Op, Args...>
2274 {
2275 using value_t = std::true_type;
2276 using type = Op<Args...>;
2277 };
2278
2279 template<template<class...> class Op, class... Args>
2280 using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
2281
2282 template<template<class...> class Op, class... Args>
2283 struct is_detected_lazy : is_detected<Op, Args...> { };
2284
2285 template<template<class...> class Op, class... Args>
2286 using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
2287
2288 template<class Default, template<class...> class Op, class... Args>
2289 using detected_or = detector<Default, void, Op, Args...>;
2290
2291 template<class Default, template<class...> class Op, class... Args>
2292 using detected_or_t = typename detected_or<Default, Op, Args...>::type;
2293
2294 template<class Expected, template<class...> class Op, class... Args>
2295 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
2296
2297 template<class To, template<class...> class Op, class... Args>
2298 using is_detected_convertible =
2299 std::is_convertible<detected_t<Op, Args...>, To>;
2300 } // namespace detail
2301 } // namespace nlohmann
2302
2303
2304 // This file contains all internal macro definitions
2305 // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2306
2307 // exclude unsupported compilers
2308 #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2309 #if defined(__clang__)
2310 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2311 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2312 #endif
2313 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2314 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2315 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2316 #endif
2317 #endif
2318 #endif
2319
2320 // C++ language standard detection
2321 // if the user manually specified the used c++ version this is skipped
2322 #if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2323 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2324 #define JSON_HAS_CPP_20
2325 #define JSON_HAS_CPP_17
2326 #define JSON_HAS_CPP_14
2327 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2328 #define JSON_HAS_CPP_17
2329 #define JSON_HAS_CPP_14
2330 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2331 #define JSON_HAS_CPP_14
2332 #endif
2333 // the cpp 11 flag is always specified because it is the minimal required version
2334 #define JSON_HAS_CPP_11
2335 #endif
2336
2337 #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2338 #ifdef JSON_HAS_CPP_17
2339 #if defined(__cpp_lib_filesystem)
2340 #define JSON_HAS_FILESYSTEM 1
2341 #elif defined(__cpp_lib_experimental_filesystem)
2342 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2343 #elif !defined(__has_include)
2344 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2345 #elif __has_include(<filesystem>)
2346 #define JSON_HAS_FILESYSTEM 1
2347 #elif __has_include(<experimental/filesystem>)
2348 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2349 #endif
2350
2351 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2352 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2353 #undef JSON_HAS_FILESYSTEM
2354 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2355 #endif
2356
2357 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2358 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2359 #undef JSON_HAS_FILESYSTEM
2360 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2361 #endif
2362
2363 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2364 #if defined(__clang_major__) && __clang_major__ < 7
2365 #undef JSON_HAS_FILESYSTEM
2366 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2367 #endif
2368
2369 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2370 #if defined(_MSC_VER) && _MSC_VER < 1940
2371 #undef JSON_HAS_FILESYSTEM
2372 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2373 #endif
2374
2375 // no filesystem support before iOS 13
2376 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2377 #undef JSON_HAS_FILESYSTEM
2378 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2379 #endif
2380
2381 // no filesystem support before macOS Catalina
2382 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2383 #undef JSON_HAS_FILESYSTEM
2384 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2385 #endif
2386 #endif
2387 #endif
2388
2389 #ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2390 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2391 #endif
2392
2393 #ifndef JSON_HAS_FILESYSTEM
2394 #define JSON_HAS_FILESYSTEM 0
2395 #endif
2396
2397 // disable documentation warnings on clang
2398 #if defined(__clang__)
2399 #pragma clang diagnostic push
2400 #pragma clang diagnostic ignored "-Wdocumentation"
2401 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2402 #endif
2403
2404 // allow disabling exceptions
2405 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2406 #define JSON_THROW(exception) throw exception
2407 #define JSON_TRY try
2408 #define JSON_CATCH(exception) catch(exception)
2409 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2410 #else
2411 #include <cstdlib>
2412 #define JSON_THROW(exception) std::abort()
2413 #define JSON_TRY if(true)
2414 #define JSON_CATCH(exception) if(false)
2415 #define JSON_INTERNAL_CATCH(exception) if(false)
2416 #endif
2417
2418 // override exception macros
2419 #if defined(JSON_THROW_USER)
2420 #undef JSON_THROW
2421 #define JSON_THROW JSON_THROW_USER
2422 #endif
2423 #if defined(JSON_TRY_USER)
2424 #undef JSON_TRY
2425 #define JSON_TRY JSON_TRY_USER
2426 #endif
2427 #if defined(JSON_CATCH_USER)
2428 #undef JSON_CATCH
2429 #define JSON_CATCH JSON_CATCH_USER
2430 #undef JSON_INTERNAL_CATCH
2431 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2432 #endif
2433 #if defined(JSON_INTERNAL_CATCH_USER)
2434 #undef JSON_INTERNAL_CATCH
2435 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2436 #endif
2437
2438 // allow overriding assert
2439 #if !defined(JSON_ASSERT)
2440 #include <cassert> // assert
2441 #define JSON_ASSERT(x) assert(x)
2442 #endif
2443
2444 // allow to access some private functions (needed by the test suite)
2445 #if defined(JSON_TESTS_PRIVATE)
2446 #define JSON_PRIVATE_UNLESS_TESTED public
2447 #else
2448 #define JSON_PRIVATE_UNLESS_TESTED private
2449 #endif
2450
2451 /*!
2452 @brief macro to briefly define a mapping between an enum and JSON
2453 @def NLOHMANN_JSON_SERIALIZE_ENUM
2454 @since version 3.4.0
2455 */
2456 #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2457 template<typename BasicJsonType> \
2458 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2459 { \
2460 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2461 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2462 auto it = std::find_if(std::begin(m), std::end(m), \
2463 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2464 { \
2465 return ej_pair.first == e; \
2466 }); \
2467 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2468 } \
2469 template<typename BasicJsonType> \
2470 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2471 { \
2472 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2473 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2474 auto it = std::find_if(std::begin(m), std::end(m), \
2475 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2476 { \
2477 return ej_pair.second == j; \
2478 }); \
2479 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2480 }
2481
2482 // Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2483 // may be removed in the future once the class is split.
2484
2485 #define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2486 template<template<typename, typename, typename...> class ObjectType, \
2487 template<typename, typename...> class ArrayType, \
2488 class StringType, class BooleanType, class NumberIntegerType, \
2489 class NumberUnsignedType, class NumberFloatType, \
2490 template<typename> class AllocatorType, \
2491 template<typename, typename = void> class JSONSerializer, \
2492 class BinaryType>
2493
2494 #define NLOHMANN_BASIC_JSON_TPL \
2495 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2496 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2497 AllocatorType, JSONSerializer, BinaryType>
2498
2499 // Macros to simplify conversion from/to types
2500
2501 #define NLOHMANN_JSON_EXPAND( x ) x
2502 #define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
2503 #define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2504 NLOHMANN_JSON_PASTE64, \
2505 NLOHMANN_JSON_PASTE63, \
2506 NLOHMANN_JSON_PASTE62, \
2507 NLOHMANN_JSON_PASTE61, \
2508 NLOHMANN_JSON_PASTE60, \
2509 NLOHMANN_JSON_PASTE59, \
2510 NLOHMANN_JSON_PASTE58, \
2511 NLOHMANN_JSON_PASTE57, \
2512 NLOHMANN_JSON_PASTE56, \
2513 NLOHMANN_JSON_PASTE55, \
2514 NLOHMANN_JSON_PASTE54, \
2515 NLOHMANN_JSON_PASTE53, \
2516 NLOHMANN_JSON_PASTE52, \
2517 NLOHMANN_JSON_PASTE51, \
2518 NLOHMANN_JSON_PASTE50, \
2519 NLOHMANN_JSON_PASTE49, \
2520 NLOHMANN_JSON_PASTE48, \
2521 NLOHMANN_JSON_PASTE47, \
2522 NLOHMANN_JSON_PASTE46, \
2523 NLOHMANN_JSON_PASTE45, \
2524 NLOHMANN_JSON_PASTE44, \
2525 NLOHMANN_JSON_PASTE43, \
2526 NLOHMANN_JSON_PASTE42, \
2527 NLOHMANN_JSON_PASTE41, \
2528 NLOHMANN_JSON_PASTE40, \
2529 NLOHMANN_JSON_PASTE39, \
2530 NLOHMANN_JSON_PASTE38, \
2531 NLOHMANN_JSON_PASTE37, \
2532 NLOHMANN_JSON_PASTE36, \
2533 NLOHMANN_JSON_PASTE35, \
2534 NLOHMANN_JSON_PASTE34, \
2535 NLOHMANN_JSON_PASTE33, \
2536 NLOHMANN_JSON_PASTE32, \
2537 NLOHMANN_JSON_PASTE31, \
2538 NLOHMANN_JSON_PASTE30, \
2539 NLOHMANN_JSON_PASTE29, \
2540 NLOHMANN_JSON_PASTE28, \
2541 NLOHMANN_JSON_PASTE27, \
2542 NLOHMANN_JSON_PASTE26, \
2543 NLOHMANN_JSON_PASTE25, \
2544 NLOHMANN_JSON_PASTE24, \
2545 NLOHMANN_JSON_PASTE23, \
2546 NLOHMANN_JSON_PASTE22, \
2547 NLOHMANN_JSON_PASTE21, \
2548 NLOHMANN_JSON_PASTE20, \
2549 NLOHMANN_JSON_PASTE19, \
2550 NLOHMANN_JSON_PASTE18, \
2551 NLOHMANN_JSON_PASTE17, \
2552 NLOHMANN_JSON_PASTE16, \
2553 NLOHMANN_JSON_PASTE15, \
2554 NLOHMANN_JSON_PASTE14, \
2555 NLOHMANN_JSON_PASTE13, \
2556 NLOHMANN_JSON_PASTE12, \
2557 NLOHMANN_JSON_PASTE11, \
2558 NLOHMANN_JSON_PASTE10, \
2559 NLOHMANN_JSON_PASTE9, \
2560 NLOHMANN_JSON_PASTE8, \
2561 NLOHMANN_JSON_PASTE7, \
2562 NLOHMANN_JSON_PASTE6, \
2563 NLOHMANN_JSON_PASTE5, \
2564 NLOHMANN_JSON_PASTE4, \
2565 NLOHMANN_JSON_PASTE3, \
2566 NLOHMANN_JSON_PASTE2, \
2567 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2568 #define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2569 #define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2570 #define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2571 #define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2572 #define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2573 #define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2574 #define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2575 #define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2576 #define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2577 #define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2578 #define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2579 #define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2580 #define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2581 #define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2582 #define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2583 #define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2584 #define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
2585 #define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
2586 #define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
2587 #define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
2588 #define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
2589 #define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
2590 #define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
2591 #define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
2592 #define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
2593 #define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
2594 #define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
2595 #define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
2596 #define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
2597 #define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2598 #define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
2599 #define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
2600 #define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
2601 #define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
2602 #define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
2603 #define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
2604 #define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
2605 #define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
2606 #define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
2607 #define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
2608 #define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
2609 #define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
2610 #define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
2611 #define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
2612 #define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
2613 #define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
2614 #define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
2615 #define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
2616 #define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
2617 #define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
2618 #define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
2619 #define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
2620 #define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
2621 #define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2622 #define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2623 #define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2624 #define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
2625 #define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
2626 #define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
2627 #define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
2628 #define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
2629 #define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
2630 #define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
2631
2632 #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2633 #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2634
2635 /*!
2636 @brief macro
2637 @def NLOHMANN_DEFINE_TYPE_INTRUSIVE
2638 @since version 3.9.0
2639 */
2640 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2641 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2642 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2643
2644 /*!
2645 @brief macro
2646 @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
2647 @since version 3.9.0
2648 */
2649 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2650 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2651 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2652
2653
2654 // inspired from https://stackoverflow.com/a/26745591
2655 // allows to call any std function as if (e.g. with begin):
2656 // using std::begin; begin(x);
2657 //
2658 // it allows using the detected idiom to retrieve the return type
2659 // of such an expression
2660 #define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2661 namespace detail { \
2662 using std::std_name; \
2663 \
2664 template<typename... T> \
2665 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2666 } \
2667 \
2668 namespace detail2 { \
2669 struct std_name##_tag \
2670 { \
2671 }; \
2672 \
2673 template<typename... T> \
2674 std_name##_tag std_name(T&&...); \
2675 \
2676 template<typename... T> \
2677 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2678 \
2679 template<typename... T> \
2680 struct would_call_std_##std_name \
2681 { \
2682 static constexpr auto const value = ::nlohmann::detail:: \
2683 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2684 }; \
2685 } /* namespace detail2 */ \
2686 \
2687 template<typename... T> \
2688 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2689 { \
2690 }
2691
2692 #ifndef JSON_USE_IMPLICIT_CONVERSIONS
2693 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2694 #endif
2695
2696 #if JSON_USE_IMPLICIT_CONVERSIONS
2697 #define JSON_EXPLICIT
2698 #else
2699 #define JSON_EXPLICIT explicit
2700 #endif
2701
2702 #ifndef JSON_DIAGNOSTICS
2703 #define JSON_DIAGNOSTICS 0
2704 #endif
2705
2706
2707 namespace nlohmann
2708 {
2709 namespace detail
2710 {
2711
2712 /*!
2713 @brief replace all occurrences of a substring by another string
2714
2715 @param[in,out] s the string to manipulate; changed so that all
2716 occurrences of @a f are replaced with @a t
2717 @param[in] f the substring to replace with @a t
2718 @param[in] t the string to replace @a f
2719
2720 @pre The search string @a f must not be empty. **This precondition is
2721 enforced with an assertion.**
2722
2723 @since version 2.0.0
2724 */
2725 inline void replace_substring(std::string& s, const std::string& f,
2726 const std::string& t)
2727 {
2728 JSON_ASSERT(!f.empty());
2729 for (auto pos = s.find(f); // find first occurrence of f
2730 pos != std::string::npos; // make sure f was found
2731 s.replace(pos, f.size(), t), // replace with t, and
2732 pos = s.find(f, pos + t.size())) // find next occurrence of f
2733 {}
2734 }
2735
2736 /*!
2737 * @brief string escaping as described in RFC 6901 (Sect. 4)
2738 * @param[in] s string to escape
2739 * @return escaped string
2740 *
2741 * Note the order of escaping "~" to "~0" and "/" to "~1" is important.
2742 */
2743 inline std::string escape(std::string s)
2744 {
2745 replace_substring(s, "~", "~0");
2746 replace_substring(s, "/", "~1");
2747 return s;
2748 }
2749
2750 /*!
2751 * @brief string unescaping as described in RFC 6901 (Sect. 4)
2752 * @param[in] s string to unescape
2753 * @return unescaped string
2754 *
2755 * Note the order of escaping "~1" to "/" and "~0" to "~" is important.
2756 */
2757 static void unescape(std::string& s)
2758 {
2759 replace_substring(s, "~1", "/");
2760 replace_substring(s, "~0", "~");
2761 }
2762
2763 } // namespace detail
2764 } // namespace nlohmann
2765
2766 // #include <nlohmann/detail/input/position_t.hpp>
2767
2768
2769 #include <cstddef> // size_t
2770
2771 namespace nlohmann
2772 {
2773 namespace detail
2774 {
2775 /// struct to capture the start position of the current token
2776 struct position_t
2777 {
2778 /// the total number of characters read
2779 std::size_t chars_read_total = 0;
2780 /// the number of characters read in the current line
2781 std::size_t chars_read_current_line = 0;
2782 /// the number of lines read
2783 std::size_t lines_read = 0;
2784
2785 /// conversion to size_t to preserve SAX interface
2786 constexpr operator size_t() const
2787 {
2788 return chars_read_total;
2789 }
2790 };
2791
2792 } // namespace detail
2793 } // namespace nlohmann
2794
2795 // #include <nlohmann/detail/macro_scope.hpp>
2796
2797
2798 namespace nlohmann
2799 {
2800 namespace detail
2801 {
2802 ////////////////
2803 // exceptions //
2804 ////////////////
2805
2806 /// @brief general exception of the @ref basic_json class
2807 /// @sa https://json.nlohmann.me/api/basic_json/exception/
2808 class exception : public std::exception
2809 {
2810 public:
2811 /// returns the explanatory string
2812 const char* what() const noexcept override
2813 {
2814 return m.what();
2815 }
2816
2817 /// the id of the exception
2818 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
2819
2820 protected:
2821 JSON_HEDLEY_NON_NULL(3)
2822 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
2823
2824 static std::string name(const std::string& ename, int id_)
2825 {
2826 return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
2827 }
2828
2829 template<typename BasicJsonType>
2830 static std::string diagnostics(const BasicJsonType& leaf_element)
2831 {
2832 #if JSON_DIAGNOSTICS
2833 std::vector<std::string> tokens;
2834 for (const auto* current = &leaf_element; current->m_parent != nullptr; current = current->m_parent)
2835 {
2836 switch (current->m_parent->type())
2837 {
2838 case value_t::array:
2839 {
2840 for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
2841 {
2842 if (&current->m_parent->m_value.array->operator[](i) == current)
2843 {
2844 tokens.emplace_back(std::to_string(i));
2845 break;
2846 }
2847 }
2848 break;
2849 }
2850
2851 case value_t::object:
2852 {
2853 for (const auto& element : *current->m_parent->m_value.object)
2854 {
2855 if (&element.second == current)
2856 {
2857 tokens.emplace_back(element.first.c_str());
2858 break;
2859 }
2860 }
2861 break;
2862 }
2863
2864 case value_t::null: // LCOV_EXCL_LINE
2865 case value_t::string: // LCOV_EXCL_LINE
2866 case value_t::boolean: // LCOV_EXCL_LINE
2867 case value_t::number_integer: // LCOV_EXCL_LINE
2868 case value_t::number_unsigned: // LCOV_EXCL_LINE
2869 case value_t::number_float: // LCOV_EXCL_LINE
2870 case value_t::binary: // LCOV_EXCL_LINE
2871 case value_t::discarded: // LCOV_EXCL_LINE
2872 default: // LCOV_EXCL_LINE
2873 break; // LCOV_EXCL_LINE
2874 }
2875 }
2876
2877 if (tokens.empty())
2878 {
2879 return "";
2880 }
2881
2882 return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
2883 [](const std::string & a, const std::string & b)
2884 {
2885 return a + "/" + detail::escape(b);
2886 }) + ") ";
2887 #else
2888 static_cast<void>(leaf_element);
2889 return "";
2890 #endif
2891 }
2892
2893 private:
2894 /// an exception object as storage for error messages
2895 std::runtime_error m;
2896 };
2897
2898 /// @brief exception indicating a parse error
2899 /// @sa https://json.nlohmann.me/api/basic_json/parse_error/
2900 class parse_error : public exception
2901 {
2902 public:
2903 /*!
2904 @brief create a parse error exception
2905 @param[in] id_ the id of the exception
2906 @param[in] pos the position where the error occurred (or with
2907 chars_read_total=0 if the position cannot be
2908 determined)
2909 @param[in] what_arg the explanatory string
2910 @return parse_error object
2911 */
2912 template<typename BasicJsonType>
2913 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context)
2914 {
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()};
2918 }
2919
2920 template<typename BasicJsonType>
2921 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context)
2922 {
2923 std::string w = exception::name("parse_error", id_) + "parse error" +
2924 (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
2925 ": " + exception::diagnostics(context) + what_arg;
2926 return {id_, byte_, w.c_str()};
2927 }
2928
2929 /*!
2930 @brief byte index of the parse error
2931
2932 The byte index of the last read character in the input file.
2933
2934 @note For an input with n bytes, 1 is the index of the first character and
2935 n+1 is the index of the terminating null byte or the end of file.
2936 This also holds true when reading a byte vector (CBOR or MessagePack).
2937 */
2938 const std::size_t byte;
2939
2940 private:
2941 parse_error(int id_, std::size_t byte_, const char* what_arg)
2942 : exception(id_, what_arg), byte(byte_) {}
2943
2944 static std::string position_string(const position_t& pos)
2945 {
2946 return " at line " + std::to_string(pos.lines_read + 1) +
2947 ", column " + std::to_string(pos.chars_read_current_line);
2948 }
2949 };
2950
2951 /// @brief exception indicating errors with iterators
2952 /// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
2953 class invalid_iterator : public exception
2954 {
2955 public:
2956 template<typename BasicJsonType>
2957 static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context)
2958 {
2959 std::string w = exception::name("invalid_iterator", id_) + exception::diagnostics(context) + what_arg;
2960 return {id_, w.c_str()};
2961 }
2962
2963 private:
2964 JSON_HEDLEY_NON_NULL(3)
2965 invalid_iterator(int id_, const char* what_arg)
2966 : exception(id_, what_arg) {}
2967 };
2968
2969 /// @brief exception indicating executing a member function with a wrong type
2970 /// @sa https://json.nlohmann.me/api/basic_json/type_error/
2971 class type_error : public exception
2972 {
2973 public:
2974 template<typename BasicJsonType>
2975 static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
2976 {
2977 std::string w = exception::name("type_error", id_) + exception::diagnostics(context) + what_arg;
2978 return {id_, w.c_str()};
2979 }
2980
2981 private:
2982 JSON_HEDLEY_NON_NULL(3)
2983 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
2984 };
2985
2986 /// @brief exception indicating access out of the defined range
2987 /// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
2988 class out_of_range : public exception
2989 {
2990 public:
2991 template<typename BasicJsonType>
2992 static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context)
2993 {
2994 std::string w = exception::name("out_of_range", id_) + exception::diagnostics(context) + what_arg;
2995 return {id_, w.c_str()};
2996 }
2997
2998 private:
2999 JSON_HEDLEY_NON_NULL(3)
3000 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
3001 };
3002
3003 /// @brief exception indicating other library errors
3004 /// @sa https://json.nlohmann.me/api/basic_json/other_error/
3005 class other_error : public exception
3006 {
3007 public:
3008 template<typename BasicJsonType>
3009 static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
3010 {
3011 std::string w = exception::name("other_error", id_) + exception::diagnostics(context) + what_arg;
3012 return {id_, w.c_str()};
3013 }
3014
3015 private:
3016 JSON_HEDLEY_NON_NULL(3)
3017 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
3018 };
3019
3020 } // namespace detail
3021 } // namespace nlohmann
3022
3023 // #include <nlohmann/detail/macro_scope.hpp>
3024
3025 // #include <nlohmann/detail/meta/cpp_future.hpp>
3026
3027
3028 #include <cstddef> // size_t
3029 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3030 #include <utility> // index_sequence, make_index_sequence, index_sequence_for
3031
3032 // #include <nlohmann/detail/macro_scope.hpp>
3033
3034
3035 namespace nlohmann
3036 {
3037 namespace detail
3038 {
3039
3040 template<typename T>
3041 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3042
3043 #ifdef JSON_HAS_CPP_14
3044
3045 // the following utilities are natively available in C++14
3046 using std::enable_if_t;
3047 using std::index_sequence;
3048 using std::make_index_sequence;
3049 using std::index_sequence_for;
3050
3051 #else
3052
3053 // alias templates to reduce boilerplate
3054 template<bool B, typename T = void>
3055 using enable_if_t = typename std::enable_if<B, T>::type;
3056
3057 // The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3058 // which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3059
3060 //// START OF CODE FROM GOOGLE ABSEIL
3061
3062 // integer_sequence
3063 //
3064 // Class template representing a compile-time integer sequence. An instantiation
3065 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3066 // type through its template arguments (which is a common need when
3067 // working with C++11 variadic templates). `absl::integer_sequence` is designed
3068 // to be a drop-in replacement for C++14's `std::integer_sequence`.
3069 //
3070 // Example:
3071 //
3072 // template< class T, T... Ints >
3073 // void user_function(integer_sequence<T, Ints...>);
3074 //
3075 // int main()
3076 // {
3077 // // user_function's `T` will be deduced to `int` and `Ints...`
3078 // // will be deduced to `0, 1, 2, 3, 4`.
3079 // user_function(make_integer_sequence<int, 5>());
3080 // }
3081 template <typename T, T... Ints>
3082 struct integer_sequence
3083 {
3084 using value_type = T;
3085 static constexpr std::size_t size() noexcept
3086 {
3087 return sizeof...(Ints);
3088 }
3089 };
3090
3091 // index_sequence
3092 //
3093 // A helper template for an `integer_sequence` of `size_t`,
3094 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3095 // `std::index_sequence`.
3096 template <size_t... Ints>
3097 using index_sequence = integer_sequence<size_t, Ints...>;
3098
3099 namespace utility_internal
3100 {
3101
3102 template <typename Seq, size_t SeqSize, size_t Rem>
3103 struct Extend;
3104
3105 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3106 template <typename T, T... Ints, size_t SeqSize>
3107 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3108 {
3109 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3110 };
3111
3112 template <typename T, T... Ints, size_t SeqSize>
3113 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3114 {
3115 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3116 };
3117
3118 // Recursion helper for 'make_integer_sequence<T, N>'.
3119 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3120 template <typename T, size_t N>
3121 struct Gen
3122 {
3123 using type =
3124 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3125 };
3126
3127 template <typename T>
3128 struct Gen<T, 0>
3129 {
3130 using type = integer_sequence<T>;
3131 };
3132
3133 } // namespace utility_internal
3134
3135 // Compile-time sequences of integers
3136
3137 // make_integer_sequence
3138 //
3139 // This template alias is equivalent to
3140 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3141 // replacement for C++14's `std::make_integer_sequence`.
3142 template <typename T, T N>
3143 using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
3144
3145 // make_index_sequence
3146 //
3147 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3148 // and is designed to be a drop-in replacement for C++14's
3149 // `std::make_index_sequence`.
3150 template <size_t N>
3151 using make_index_sequence = make_integer_sequence<size_t, N>;
3152
3153 // index_sequence_for
3154 //
3155 // Converts a typename pack into an index sequence of the same length, and
3156 // is designed to be a drop-in replacement for C++14's
3157 // `std::index_sequence_for()`
3158 template <typename... Ts>
3159 using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
3160
3161 //// END OF CODE FROM GOOGLE ABSEIL
3162
3163 #endif
3164
3165 // dispatch utility (taken from ranges-v3)
3166 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3167 template<> struct priority_tag<0> {};
3168
3169 // taken from ranges-v3
3170 template<typename T>
3171 struct static_const
3172 {
3173 static constexpr T value{};
3174 };
3175
3176 template<typename T>
3177 constexpr T static_const<T>::value; // NOLINT(readability-redundant-declaration)
3178
3179 } // namespace detail
3180 } // namespace nlohmann
3181
3182 // #include <nlohmann/detail/meta/identity_tag.hpp>
3183
3184
3185 namespace nlohmann
3186 {
3187 namespace detail
3188 {
3189 // dispatching helper struct
3190 template <class T> struct identity_tag {};
3191 } // namespace detail
3192 } // namespace nlohmann
3193
3194 // #include <nlohmann/detail/meta/type_traits.hpp>
3195
3196
3197 #include <limits> // numeric_limits
3198 #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3199 #include <utility> // declval
3200 #include <tuple> // tuple
3201
3202 // #include <nlohmann/detail/macro_scope.hpp>
3203
3204
3205 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
3206
3207
3208 #include <iterator> // random_access_iterator_tag
3209
3210 // #include <nlohmann/detail/meta/void_t.hpp>
3211
3212 // #include <nlohmann/detail/meta/cpp_future.hpp>
3213
3214
3215 namespace nlohmann
3216 {
3217 namespace detail
3218 {
3219 template<typename It, typename = void>
3220 struct iterator_types {};
3221
3222 template<typename It>
3223 struct iterator_types <
3224 It,
3225 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3226 typename It::reference, typename It::iterator_category >>
3227 {
3228 using difference_type = typename It::difference_type;
3229 using value_type = typename It::value_type;
3230 using pointer = typename It::pointer;
3231 using reference = typename It::reference;
3232 using iterator_category = typename It::iterator_category;
3233 };
3234
3235 // This is required as some compilers implement std::iterator_traits in a way that
3236 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3237 template<typename T, typename = void>
3238 struct iterator_traits
3239 {
3240 };
3241
3242 template<typename T>
3243 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3244 : iterator_types<T>
3245 {
3246 };
3247
3248 template<typename T>
3249 struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
3250 {
3251 using iterator_category = std::random_access_iterator_tag;
3252 using value_type = T;
3253 using difference_type = ptrdiff_t;
3254 using pointer = T*;
3255 using reference = T&;
3256 };
3257 } // namespace detail
3258 } // namespace nlohmann
3259
3260 // #include <nlohmann/detail/meta/call_std/begin.hpp>
3261
3262
3263 // #include <nlohmann/detail/macro_scope.hpp>
3264
3265
3266 namespace nlohmann
3267 {
3268 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3269 } // namespace nlohmann
3270
3271 // #include <nlohmann/detail/meta/call_std/end.hpp>
3272
3273
3274 // #include <nlohmann/detail/macro_scope.hpp>
3275
3276
3277 namespace nlohmann
3278 {
3279 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3280 } // namespace nlohmann
3281
3282 // #include <nlohmann/detail/meta/cpp_future.hpp>
3283
3284 // #include <nlohmann/detail/meta/detected.hpp>
3285
3286 // #include <nlohmann/json_fwd.hpp>
3287 #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3288 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3289
3290 #include <cstdint> // int64_t, uint64_t
3291 #include <map> // map
3292 #include <memory> // allocator
3293 #include <string> // string
3294 #include <vector> // vector
3295
3296 /*!
3297 @brief namespace for Niels Lohmann
3298 @see https://github.com/nlohmann
3299 @since version 1.0.0
3300 */
3301 namespace nlohmann
3302 {
3303 /*!
3304 @brief default JSONSerializer template argument
3305
3306 This serializer ignores the template arguments and uses ADL
3307 ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
3308 for serialization.
3309 */
3310 template<typename T = void, typename SFINAE = void>
3311 struct adl_serializer;
3312
3313 /// a class to store JSON values
3314 /// @sa https://json.nlohmann.me/api/basic_json/
3315 template<template<typename U, typename V, typename... Args> class ObjectType =
3316 std::map,
3317 template<typename U, typename... Args> class ArrayType = std::vector,
3318 class StringType = std::string, class BooleanType = bool,
3319 class NumberIntegerType = std::int64_t,
3320 class NumberUnsignedType = std::uint64_t,
3321 class NumberFloatType = double,
3322 template<typename U> class AllocatorType = std::allocator,
3323 template<typename T, typename SFINAE = void> class JSONSerializer =
3324 adl_serializer,
3325 class BinaryType = std::vector<std::uint8_t>>
3326 class basic_json;
3327
3328 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
3329 /// @sa https://json.nlohmann.me/api/json_pointer/
3330 template<typename BasicJsonType>
3331 class json_pointer;
3332
3333 /*!
3334 @brief default specialization
3335 @sa https://json.nlohmann.me/api/json/
3336 */
3337 using json = basic_json<>;
3338
3339 /// @brief a minimal map-like container that preserves insertion order
3340 /// @sa https://json.nlohmann.me/api/ordered_map/
3341 template<class Key, class T, class IgnoredLess, class Allocator>
3342 struct ordered_map;
3343
3344 /// @brief specialization that maintains the insertion order of object keys
3345 /// @sa https://json.nlohmann.me/api/ordered_json/
3346 using ordered_json = basic_json<nlohmann::ordered_map>;
3347
3348 } // namespace nlohmann
3349
3350 #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3351
3352
3353 namespace nlohmann
3354 {
3355 /*!
3356 @brief detail namespace with internal helper functions
3357
3358 This namespace collects functions that should not be exposed,
3359 implementations of some @ref basic_json methods, and meta-programming helpers.
3360
3361 @since version 2.1.0
3362 */
3363 namespace detail
3364 {
3365 /////////////
3366 // helpers //
3367 /////////////
3368
3369 // Note to maintainers:
3370 //
3371 // Every trait in this file expects a non CV-qualified type.
3372 // The only exceptions are in the 'aliases for detected' section
3373 // (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3374 //
3375 // In this case, T has to be properly CV-qualified to constraint the function arguments
3376 // (e.g. to_json(BasicJsonType&, const T&))
3377
3378 template<typename> struct is_basic_json : std::false_type {};
3379
3380 NLOHMANN_BASIC_JSON_TPL_DECLARATION
3381 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3382
3383 //////////////////////
3384 // json_ref helpers //
3385 //////////////////////
3386
3387 template<typename>
3388 class json_ref;
3389
3390 template<typename>
3391 struct is_json_ref : std::false_type {};
3392
3393 template<typename T>
3394 struct is_json_ref<json_ref<T>> : std::true_type {};
3395
3396 //////////////////////////
3397 // aliases for detected //
3398 //////////////////////////
3399
3400 template<typename T>
3401 using mapped_type_t = typename T::mapped_type;
3402
3403 template<typename T>
3404 using key_type_t = typename T::key_type;
3405
3406 template<typename T>
3407 using value_type_t = typename T::value_type;
3408
3409 template<typename T>
3410 using difference_type_t = typename T::difference_type;
3411
3412 template<typename T>
3413 using pointer_t = typename T::pointer;
3414
3415 template<typename T>
3416 using reference_t = typename T::reference;
3417
3418 template<typename T>
3419 using iterator_category_t = typename T::iterator_category;
3420
3421 template<typename T, typename... Args>
3422 using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3423
3424 template<typename T, typename... Args>
3425 using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3426
3427 template<typename T, typename U>
3428 using get_template_function = decltype(std::declval<T>().template get<U>());
3429
3430 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3431 template<typename BasicJsonType, typename T, typename = void>
3432 struct has_from_json : std::false_type {};
3433
3434 // trait checking if j.get<T> is valid
3435 // use this trait instead of std::is_constructible or std::is_convertible,
3436 // both rely on, or make use of implicit conversions, and thus fail when T
3437 // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3438 template <typename BasicJsonType, typename T>
3439 struct is_getable
3440 {
3441 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3442 };
3443
3444 template<typename BasicJsonType, typename T>
3445 struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3446 {
3447 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3448
3449 static constexpr bool value =
3450 is_detected_exact<void, from_json_function, serializer,
3451 const BasicJsonType&, T&>::value;
3452 };
3453
3454 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
3455 // this overload is used for non-default-constructible user-defined-types
3456 template<typename BasicJsonType, typename T, typename = void>
3457 struct has_non_default_from_json : std::false_type {};
3458
3459 template<typename BasicJsonType, typename T>
3460 struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3461 {
3462 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3463
3464 static constexpr bool value =
3465 is_detected_exact<T, from_json_function, serializer,
3466 const BasicJsonType&>::value;
3467 };
3468
3469 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3470 // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3471 template<typename BasicJsonType, typename T, typename = void>
3472 struct has_to_json : std::false_type {};
3473
3474 template<typename BasicJsonType, typename T>
3475 struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3476 {
3477 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3478
3479 static constexpr bool value =
3480 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3481 T>::value;
3482 };
3483
3484
3485 ///////////////////
3486 // is_ functions //
3487 ///////////////////
3488
3489 // https://en.cppreference.com/w/cpp/types/conjunction
3490 template<class...> struct conjunction : std::true_type { };
3491 template<class B1> struct conjunction<B1> : B1 { };
3492 template<class B1, class... Bn>
3493 struct conjunction<B1, Bn...>
3494 : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
3495
3496 // https://en.cppreference.com/w/cpp/types/negation
3497 template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3498
3499 // Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3500 // std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3501 // This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3502 template <typename T>
3503 struct is_default_constructible : std::is_default_constructible<T> {};
3504
3505 template <typename T1, typename T2>
3506 struct is_default_constructible<std::pair<T1, T2>>
3507 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3508
3509 template <typename T1, typename T2>
3510 struct is_default_constructible<const std::pair<T1, T2>>
3511 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3512
3513 template <typename... Ts>
3514 struct is_default_constructible<std::tuple<Ts...>>
3515 : conjunction<is_default_constructible<Ts>...> {};
3516
3517 template <typename... Ts>
3518 struct is_default_constructible<const std::tuple<Ts...>>
3519 : conjunction<is_default_constructible<Ts>...> {};
3520
3521
3522 template <typename T, typename... Args>
3523 struct is_constructible : std::is_constructible<T, Args...> {};
3524
3525 template <typename T1, typename T2>
3526 struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3527
3528 template <typename T1, typename T2>
3529 struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3530
3531 template <typename... Ts>
3532 struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3533
3534 template <typename... Ts>
3535 struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3536
3537
3538 template<typename T, typename = void>
3539 struct is_iterator_traits : std::false_type {};
3540
3541 template<typename T>
3542 struct is_iterator_traits<iterator_traits<T>>
3543 {
3544 private:
3545 using traits = iterator_traits<T>;
3546
3547 public:
3548 static constexpr auto value =
3549 is_detected<value_type_t, traits>::value &&
3550 is_detected<difference_type_t, traits>::value &&
3551 is_detected<pointer_t, traits>::value &&
3552 is_detected<iterator_category_t, traits>::value &&
3553 is_detected<reference_t, traits>::value;
3554 };
3555
3556 template<typename T>
3557 struct is_range
3558 {
3559 private:
3560 using t_ref = typename std::add_lvalue_reference<T>::type;
3561
3562 using iterator = detected_t<result_of_begin, t_ref>;
3563 using sentinel = detected_t<result_of_end, t_ref>;
3564
3565 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3566 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3567 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3568 static constexpr auto is_iterator_begin =
3569 is_iterator_traits<iterator_traits<iterator>>::value;
3570
3571 public:
3572 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3573 };
3574
3575 template<typename R>
3576 using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3577
3578 template<typename T>
3579 using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3580
3581 // The following implementation of is_complete_type is taken from
3582 // https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3583 // and is written by Xiang Fan who agreed to using it in this library.
3584
3585 template<typename T, typename = void>
3586 struct is_complete_type : std::false_type {};
3587
3588 template<typename T>
3589 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3590
3591 template<typename BasicJsonType, typename CompatibleObjectType,
3592 typename = void>
3593 struct is_compatible_object_type_impl : std::false_type {};
3594
3595 template<typename BasicJsonType, typename CompatibleObjectType>
3596 struct is_compatible_object_type_impl <
3597 BasicJsonType, CompatibleObjectType,
3598 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3599 is_detected<key_type_t, CompatibleObjectType>::value >>
3600 {
3601 using object_t = typename BasicJsonType::object_t;
3602
3603 // macOS's is_constructible does not play well with nonesuch...
3604 static constexpr bool value =
3605 is_constructible<typename object_t::key_type,
3606 typename CompatibleObjectType::key_type>::value &&
3607 is_constructible<typename object_t::mapped_type,
3608 typename CompatibleObjectType::mapped_type>::value;
3609 };
3610
3611 template<typename BasicJsonType, typename CompatibleObjectType>
3612 struct is_compatible_object_type
3613 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3614
3615 template<typename BasicJsonType, typename ConstructibleObjectType,
3616 typename = void>
3617 struct is_constructible_object_type_impl : std::false_type {};
3618
3619 template<typename BasicJsonType, typename ConstructibleObjectType>
3620 struct is_constructible_object_type_impl <
3621 BasicJsonType, ConstructibleObjectType,
3622 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3623 is_detected<key_type_t, ConstructibleObjectType>::value >>
3624 {
3625 using object_t = typename BasicJsonType::object_t;
3626
3627 static constexpr bool value =
3628 (is_default_constructible<ConstructibleObjectType>::value &&
3629 (std::is_move_assignable<ConstructibleObjectType>::value ||
3630 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3631 (is_constructible<typename ConstructibleObjectType::key_type,
3632 typename object_t::key_type>::value &&
3633 std::is_same <
3634 typename object_t::mapped_type,
3635 typename ConstructibleObjectType::mapped_type >::value)) ||
3636 (has_from_json<BasicJsonType,
3637 typename ConstructibleObjectType::mapped_type>::value ||
3638 has_non_default_from_json <
3639 BasicJsonType,
3640 typename ConstructibleObjectType::mapped_type >::value);
3641 };
3642
3643 template<typename BasicJsonType, typename ConstructibleObjectType>
3644 struct is_constructible_object_type
3645 : is_constructible_object_type_impl<BasicJsonType,
3646 ConstructibleObjectType> {};
3647
3648 template<typename BasicJsonType, typename CompatibleStringType>
3649 struct is_compatible_string_type
3650 {
3651 static constexpr auto value =
3652 is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
3653 };
3654
3655 template<typename BasicJsonType, typename ConstructibleStringType>
3656 struct is_constructible_string_type
3657 {
3658 static constexpr auto value =
3659 is_constructible<ConstructibleStringType,
3660 typename BasicJsonType::string_t>::value;
3661 };
3662
3663 template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3664 struct is_compatible_array_type_impl : std::false_type {};
3665
3666 template<typename BasicJsonType, typename CompatibleArrayType>
3667 struct is_compatible_array_type_impl <
3668 BasicJsonType, CompatibleArrayType,
3669 enable_if_t <
3670 is_detected<iterator_t, CompatibleArrayType>::value&&
3671 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3672 // special case for types like std::filesystem::path whose iterator's value_type are themselves
3673 // c.f. https://github.com/nlohmann/json/pull/3073
3674 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3675 {
3676 static constexpr bool value =
3677 is_constructible<BasicJsonType,
3678 range_value_t<CompatibleArrayType>>::value;
3679 };
3680
3681 template<typename BasicJsonType, typename CompatibleArrayType>
3682 struct is_compatible_array_type
3683 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3684
3685 template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3686 struct is_constructible_array_type_impl : std::false_type {};
3687
3688 template<typename BasicJsonType, typename ConstructibleArrayType>
3689 struct is_constructible_array_type_impl <
3690 BasicJsonType, ConstructibleArrayType,
3691 enable_if_t<std::is_same<ConstructibleArrayType,
3692 typename BasicJsonType::value_type>::value >>
3693 : std::true_type {};
3694
3695 template<typename BasicJsonType, typename ConstructibleArrayType>
3696 struct is_constructible_array_type_impl <
3697 BasicJsonType, ConstructibleArrayType,
3698 enable_if_t < !std::is_same<ConstructibleArrayType,
3699 typename BasicJsonType::value_type>::value&&
3700 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3701 is_default_constructible<ConstructibleArrayType>::value&&
3702 (std::is_move_assignable<ConstructibleArrayType>::value ||
3703 std::is_copy_assignable<ConstructibleArrayType>::value)&&
3704 is_detected<iterator_t, ConstructibleArrayType>::value&&
3705 is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3706 is_detected<range_value_t, ConstructibleArrayType>::value&&
3707 // special case for types like std::filesystem::path whose iterator's value_type are themselves
3708 // c.f. https://github.com/nlohmann/json/pull/3073
3709 !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3710 is_complete_type <
3711 detected_t<range_value_t, ConstructibleArrayType >>::value >>
3712 {
3713 using value_type = range_value_t<ConstructibleArrayType>;
3714
3715 static constexpr bool value =
3716 std::is_same<value_type,
3717 typename BasicJsonType::array_t::value_type>::value ||
3718 has_from_json<BasicJsonType,
3719 value_type>::value ||
3720 has_non_default_from_json <
3721 BasicJsonType,
3722 value_type >::value;
3723 };
3724
3725 template<typename BasicJsonType, typename ConstructibleArrayType>
3726 struct is_constructible_array_type
3727 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3728
3729 template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3730 typename = void>
3731 struct is_compatible_integer_type_impl : std::false_type {};
3732
3733 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3734 struct is_compatible_integer_type_impl <
3735 RealIntegerType, CompatibleNumberIntegerType,
3736 enable_if_t < std::is_integral<RealIntegerType>::value&&
3737 std::is_integral<CompatibleNumberIntegerType>::value&&
3738 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
3739 {
3740 // is there an assert somewhere on overflows?
3741 using RealLimits = std::numeric_limits<RealIntegerType>;
3742 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3743
3744 static constexpr auto value =
3745 is_constructible<RealIntegerType,
3746 CompatibleNumberIntegerType>::value &&
3747 CompatibleLimits::is_integer &&
3748 RealLimits::is_signed == CompatibleLimits::is_signed;
3749 };
3750
3751 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3752 struct is_compatible_integer_type
3753 : is_compatible_integer_type_impl<RealIntegerType,
3754 CompatibleNumberIntegerType> {};
3755
3756 template<typename BasicJsonType, typename CompatibleType, typename = void>
3757 struct is_compatible_type_impl: std::false_type {};
3758
3759 template<typename BasicJsonType, typename CompatibleType>
3760 struct is_compatible_type_impl <
3761 BasicJsonType, CompatibleType,
3762 enable_if_t<is_complete_type<CompatibleType>::value >>
3763 {
3764 static constexpr bool value =
3765 has_to_json<BasicJsonType, CompatibleType>::value;
3766 };
3767
3768 template<typename BasicJsonType, typename CompatibleType>
3769 struct is_compatible_type
3770 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3771
3772 template<typename T1, typename T2>
3773 struct is_constructible_tuple : std::false_type {};
3774
3775 template<typename T1, typename... Args>
3776 struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3777
3778 // a naive helper to check if a type is an ordered_map (exploits the fact that
3779 // ordered_map inherits capacity() from std::vector)
3780 template <typename T>
3781 struct is_ordered_map
3782 {
3783 using one = char;
3784
3785 struct two
3786 {
3787 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3788 };
3789
3790 template <typename C> static one test( decltype(&C::capacity) ) ;
3791 template <typename C> static two test(...);
3792
3793 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
3794 };
3795
3796 // to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
3797 template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
3798 T conditional_static_cast(U value)
3799 {
3800 return static_cast<T>(value);
3801 }
3802
3803 template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
3804 T conditional_static_cast(U value)
3805 {
3806 return value;
3807 }
3808
3809 } // namespace detail
3810 } // namespace nlohmann
3811
3812 // #include <nlohmann/detail/value_t.hpp>
3813
3814
3815 #if JSON_HAS_EXPERIMENTAL_FILESYSTEM
3816 #include <experimental/filesystem>
3817 namespace nlohmann::detail
3818 {
3819 namespace std_fs = std::experimental::filesystem;
3820 } // namespace nlohmann::detail
3821 #elif JSON_HAS_FILESYSTEM
3822 #include <filesystem>
3823 namespace nlohmann::detail
3824 {
3825 namespace std_fs = std::filesystem;
3826 } // namespace nlohmann::detail
3827 #endif
3828
3829 namespace nlohmann
3830 {
3831 namespace detail
3832 {
3833 template<typename BasicJsonType>
3834 void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
3835 {
3836 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
3837 {
3838 JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j));
3839 }
3840 n = nullptr;
3841 }
3842
3843 // overloads for basic_json template parameters
3844 template < typename BasicJsonType, typename ArithmeticType,
3845 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
3846 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
3847 int > = 0 >
3848 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
3849 {
3850 switch (static_cast<value_t>(j))
3851 {
3852 case value_t::number_unsigned:
3853 {
3854 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
3855 break;
3856 }
3857 case value_t::number_integer:
3858 {
3859 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
3860 break;
3861 }
3862 case value_t::number_float:
3863 {
3864 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
3865 break;
3866 }
3867
3868 case value_t::null:
3869 case value_t::object:
3870 case value_t::array:
3871 case value_t::string:
3872 case value_t::boolean:
3873 case value_t::binary:
3874 case value_t::discarded:
3875 default:
3876 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
3877 }
3878 }
3879
3880 template<typename BasicJsonType>
3881 void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
3882 {
3883 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
3884 {
3885 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j));
3886 }
3887 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
3888 }
3889
3890 template<typename BasicJsonType>
3891 void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
3892 {
3893 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
3894 {
3895 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
3896 }
3897 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
3898 }
3899
3900 template <
3901 typename BasicJsonType, typename ConstructibleStringType,
3902 enable_if_t <
3903 is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value&&
3904 !std::is_same<typename BasicJsonType::string_t,
3905 ConstructibleStringType>::value,
3906 int > = 0 >
3907 void from_json(const BasicJsonType& j, ConstructibleStringType& s)
3908 {
3909 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
3910 {
3911 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
3912 }
3913
3914 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
3915 }
3916
3917 template<typename BasicJsonType>
3918 void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
3919 {
3920 get_arithmetic_value(j, val);
3921 }
3922
3923 template<typename BasicJsonType>
3924 void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
3925 {
3926 get_arithmetic_value(j, val);
3927 }
3928
3929 template<typename BasicJsonType>
3930 void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
3931 {
3932 get_arithmetic_value(j, val);
3933 }
3934
3935 template<typename BasicJsonType, typename EnumType,
3936 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
3937 void from_json(const BasicJsonType& j, EnumType& e)
3938 {
3939 typename std::underlying_type<EnumType>::type val;
3940 get_arithmetic_value(j, val);
3941 e = static_cast<EnumType>(val);
3942 }
3943
3944 // forward_list doesn't have an insert method
3945 template<typename BasicJsonType, typename T, typename Allocator,
3946 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
3947 void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
3948 {
3949 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3950 {
3951 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
3952 }
3953 l.clear();
3954 std::transform(j.rbegin(), j.rend(),
3955 std::front_inserter(l), [](const BasicJsonType & i)
3956 {
3957 return i.template get<T>();
3958 });
3959 }
3960
3961 // valarray doesn't have an insert method
3962 template<typename BasicJsonType, typename T,
3963 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
3964 void from_json(const BasicJsonType& j, std::valarray<T>& l)
3965 {
3966 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3967 {
3968 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
3969 }
3970 l.resize(j.size());
3971 std::transform(j.begin(), j.end(), std::begin(l),
3972 [](const BasicJsonType & elem)
3973 {
3974 return elem.template get<T>();
3975 });
3976 }
3977
3978 template<typename BasicJsonType, typename T, std::size_t N>
3979 auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3980 -> decltype(j.template get<T>(), void())
3981 {
3982 for (std::size_t i = 0; i < N; ++i)
3983 {
3984 arr[i] = j.at(i).template get<T>();
3985 }
3986 }
3987
3988 template<typename BasicJsonType>
3989 void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
3990 {
3991 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
3992 }
3993
3994 template<typename BasicJsonType, typename T, std::size_t N>
3995 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
3996 priority_tag<2> /*unused*/)
3997 -> decltype(j.template get<T>(), void())
3998 {
3999 for (std::size_t i = 0; i < N; ++i)
4000 {
4001 arr[i] = j.at(i).template get<T>();
4002 }
4003 }
4004
4005 template<typename BasicJsonType, typename ConstructibleArrayType,
4006 enable_if_t<
4007 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4008 int> = 0>
4009 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4010 -> decltype(
4011 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4012 j.template get<typename ConstructibleArrayType::value_type>(),
4013 void())
4014 {
4015 using std::end;
4016
4017 ConstructibleArrayType ret;
4018 ret.reserve(j.size());
4019 std::transform(j.begin(), j.end(),
4020 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
4021 {
4022 // get<BasicJsonType>() returns *this, this won't call a from_json
4023 // method when value_type is BasicJsonType
4024 return i.template get<typename ConstructibleArrayType::value_type>();
4025 });
4026 arr = std::move(ret);
4027 }
4028
4029 template<typename BasicJsonType, typename ConstructibleArrayType,
4030 enable_if_t<
4031 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4032 int> = 0>
4033 void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4034 priority_tag<0> /*unused*/)
4035 {
4036 using std::end;
4037
4038 ConstructibleArrayType ret;
4039 std::transform(
4040 j.begin(), j.end(), std::inserter(ret, end(ret)),
4041 [](const BasicJsonType & i)
4042 {
4043 // get<BasicJsonType>() returns *this, this won't call a from_json
4044 // method when value_type is BasicJsonType
4045 return i.template get<typename ConstructibleArrayType::value_type>();
4046 });
4047 arr = std::move(ret);
4048 }
4049
4050 template < typename BasicJsonType, typename ConstructibleArrayType,
4051 enable_if_t <
4052 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4053 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4054 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4055 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4056 !is_basic_json<ConstructibleArrayType>::value,
4057 int > = 0 >
4058 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4059 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4060 j.template get<typename ConstructibleArrayType::value_type>(),
4061 void())
4062 {
4063 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4064 {
4065 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4066 }
4067
4068 from_json_array_impl(j, arr, priority_tag<3> {});
4069 }
4070
4071 template < typename BasicJsonType, typename T, std::size_t... Idx >
4072 std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4073 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4074 {
4075 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4076 }
4077
4078 template < typename BasicJsonType, typename T, std::size_t N >
4079 auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4080 -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4081 {
4082 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4083 {
4084 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4085 }
4086
4087 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4088 }
4089
4090 template<typename BasicJsonType>
4091 void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4092 {
4093 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4094 {
4095 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j));
4096 }
4097
4098 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4099 }
4100
4101 template<typename BasicJsonType, typename ConstructibleObjectType,
4102 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
4103 void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
4104 {
4105 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
4106 {
4107 JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j));
4108 }
4109
4110 ConstructibleObjectType ret;
4111 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4112 using value_type = typename ConstructibleObjectType::value_type;
4113 std::transform(
4114 inner_object->begin(), inner_object->end(),
4115 std::inserter(ret, ret.begin()),
4116 [](typename BasicJsonType::object_t::value_type const & p)
4117 {
4118 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
4119 });
4120 obj = std::move(ret);
4121 }
4122
4123 // overload for arithmetic types, not chosen for basic_json template arguments
4124 // (BooleanType, etc..); note: Is it really necessary to provide explicit
4125 // overloads for boolean_t etc. in case of a custom BooleanType which is not
4126 // an arithmetic type?
4127 template < typename BasicJsonType, typename ArithmeticType,
4128 enable_if_t <
4129 std::is_arithmetic<ArithmeticType>::value&&
4130 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
4131 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
4132 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
4133 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4134 int > = 0 >
4135 void from_json(const BasicJsonType& j, ArithmeticType& val)
4136 {
4137 switch (static_cast<value_t>(j))
4138 {
4139 case value_t::number_unsigned:
4140 {
4141 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4142 break;
4143 }
4144 case value_t::number_integer:
4145 {
4146 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4147 break;
4148 }
4149 case value_t::number_float:
4150 {
4151 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4152 break;
4153 }
4154 case value_t::boolean:
4155 {
4156 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
4157 break;
4158 }
4159
4160 case value_t::null:
4161 case value_t::object:
4162 case value_t::array:
4163 case value_t::string:
4164 case value_t::binary:
4165 case value_t::discarded:
4166 default:
4167 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
4168 }
4169 }
4170
4171 template<typename BasicJsonType, typename... Args, std::size_t... Idx>
4172 std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
4173 {
4174 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
4175 }
4176
4177 template < typename BasicJsonType, class A1, class A2 >
4178 std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
4179 {
4180 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
4181 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
4182 }
4183
4184 template<typename BasicJsonType, typename A1, typename A2>
4185 void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
4186 {
4187 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
4188 }
4189
4190 template<typename BasicJsonType, typename... Args>
4191 std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
4192 {
4193 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4194 }
4195
4196 template<typename BasicJsonType, typename... Args>
4197 void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
4198 {
4199 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4200 }
4201
4202 template<typename BasicJsonType, typename TupleRelated>
4203 auto from_json(BasicJsonType&& j, TupleRelated&& t)
4204 -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
4205 {
4206 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4207 {
4208 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4209 }
4210
4211 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
4212 }
4213
4214 template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
4215 typename = enable_if_t < !std::is_constructible <
4216 typename BasicJsonType::string_t, Key >::value >>
4217 void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
4218 {
4219 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4220 {
4221 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4222 }
4223 m.clear();
4224 for (const auto& p : j)
4225 {
4226 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
4227 {
4228 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
4229 }
4230 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4231 }
4232 }
4233
4234 template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
4235 typename = enable_if_t < !std::is_constructible <
4236 typename BasicJsonType::string_t, Key >::value >>
4237 void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
4238 {
4239 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4240 {
4241 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4242 }
4243 m.clear();
4244 for (const auto& p : j)
4245 {
4246 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
4247 {
4248 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
4249 }
4250 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4251 }
4252 }
4253
4254 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4255 template<typename BasicJsonType>
4256 void from_json(const BasicJsonType& j, std_fs::path& p)
4257 {
4258 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4259 {
4260 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
4261 }
4262 p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4263 }
4264 #endif
4265
4266 struct from_json_fn
4267 {
4268 template<typename BasicJsonType, typename T>
4269 auto operator()(const BasicJsonType& j, T&& val) const
4270 noexcept(noexcept(from_json(j, std::forward<T>(val))))
4271 -> decltype(from_json(j, std::forward<T>(val)))
4272 {
4273 return from_json(j, std::forward<T>(val));
4274 }
4275 };
4276 } // namespace detail
4277
4278 /// namespace to hold default `from_json` function
4279 /// to see why this is required:
4280 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
4281 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
4282 {
4283 constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value; // NOLINT(misc-definitions-in-headers)
4284 } // namespace
4285 } // namespace nlohmann
4286
4287 // #include <nlohmann/detail/conversions/to_json.hpp>
4288
4289
4290 #include <algorithm> // copy
4291 #include <iterator> // begin, end
4292 #include <string> // string
4293 #include <tuple> // tuple, get
4294 #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
4295 #include <utility> // move, forward, declval, pair
4296 #include <valarray> // valarray
4297 #include <vector> // vector
4298
4299 // #include <nlohmann/detail/macro_scope.hpp>
4300
4301 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
4302
4303
4304 #include <cstddef> // size_t
4305 #include <iterator> // input_iterator_tag
4306 #include <string> // string, to_string
4307 #include <tuple> // tuple_size, get, tuple_element
4308 #include <utility> // move
4309
4310 // #include <nlohmann/detail/meta/type_traits.hpp>
4311
4312 // #include <nlohmann/detail/value_t.hpp>
4313
4314
4315 namespace nlohmann
4316 {
4317 namespace detail
4318 {
4319 template<typename string_type>
4320 void int_to_string( string_type& target, std::size_t value )
4321 {
4322 // For ADL
4323 using std::to_string;
4324 target = to_string(value);
4325 }
4326 template<typename IteratorType> class iteration_proxy_value
4327 {
4328 public:
4329 using difference_type = std::ptrdiff_t;
4330 using value_type = iteration_proxy_value;
4331 using pointer = value_type * ;
4332 using reference = value_type & ;
4333 using iterator_category = std::input_iterator_tag;
4334 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
4335
4336 private:
4337 /// the iterator
4338 IteratorType anchor;
4339 /// an index for arrays (used to create key names)
4340 std::size_t array_index = 0;
4341 /// last stringified array index
4342 mutable std::size_t array_index_last = 0;
4343 /// a string representation of the array index
4344 mutable string_type array_index_str = "0";
4345 /// an empty string (to return a reference for primitive values)
4346 const string_type empty_str{};
4347
4348 public:
4349 explicit iteration_proxy_value(IteratorType it) noexcept
4350 : anchor(std::move(it))
4351 {}
4352
4353 /// dereference operator (needed for range-based for)
4354 iteration_proxy_value& operator*()
4355 {
4356 return *this;
4357 }
4358
4359 /// increment operator (needed for range-based for)
4360 iteration_proxy_value& operator++()
4361 {
4362 ++anchor;
4363 ++array_index;
4364
4365 return *this;
4366 }
4367
4368 /// equality operator (needed for InputIterator)
4369 bool operator==(const iteration_proxy_value& o) const
4370 {
4371 return anchor == o.anchor;
4372 }
4373
4374 /// inequality operator (needed for range-based for)
4375 bool operator!=(const iteration_proxy_value& o) const
4376 {
4377 return anchor != o.anchor;
4378 }
4379
4380 /// return key of the iterator
4381 const string_type& key() const
4382 {
4383 JSON_ASSERT(anchor.m_object != nullptr);
4384
4385 switch (anchor.m_object->type())
4386 {
4387 // use integer array index as key
4388 case value_t::array:
4389 {
4390 if (array_index != array_index_last)
4391 {
4392 int_to_string( array_index_str, array_index );
4393 array_index_last = array_index;
4394 }
4395 return array_index_str;
4396 }
4397
4398 // use key from the object
4399 case value_t::object:
4400 return anchor.key();
4401
4402 // use an empty key for all primitive types
4403 case value_t::null:
4404 case value_t::string:
4405 case value_t::boolean:
4406 case value_t::number_integer:
4407 case value_t::number_unsigned:
4408 case value_t::number_float:
4409 case value_t::binary:
4410 case value_t::discarded:
4411 default:
4412 return empty_str;
4413 }
4414 }
4415
4416 /// return value of the iterator
4417 typename IteratorType::reference value() const
4418 {
4419 return anchor.value();
4420 }
4421 };
4422
4423 /// proxy class for the items() function
4424 template<typename IteratorType> class iteration_proxy
4425 {
4426 private:
4427 /// the container to iterate
4428 typename IteratorType::reference container;
4429
4430 public:
4431 /// construct iteration proxy from a container
4432 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
4433 : container(cont) {}
4434
4435 /// return iterator begin (needed for range-based for)
4436 iteration_proxy_value<IteratorType> begin() noexcept
4437 {
4438 return iteration_proxy_value<IteratorType>(container.begin());
4439 }
4440
4441 /// return iterator end (needed for range-based for)
4442 iteration_proxy_value<IteratorType> end() noexcept
4443 {
4444 return iteration_proxy_value<IteratorType>(container.end());
4445 }
4446 };
4447 // Structured Bindings Support
4448 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
4449 // And see https://github.com/nlohmann/json/pull/1391
4450 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
4451 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
4452 {
4453 return i.key();
4454 }
4455 // Structured Bindings Support
4456 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
4457 // And see https://github.com/nlohmann/json/pull/1391
4458 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
4459 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
4460 {
4461 return i.value();
4462 }
4463 } // namespace detail
4464 } // namespace nlohmann
4465
4466 // The Addition to the STD Namespace is required to add
4467 // Structured Bindings Support to the iteration_proxy_value class
4468 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
4469 // And see https://github.com/nlohmann/json/pull/1391
4470 namespace std
4471 {
4472 #if defined(__clang__)
4473 // Fix: https://github.com/nlohmann/json/issues/1401
4474 #pragma clang diagnostic push
4475 #pragma clang diagnostic ignored "-Wmismatched-tags"
4476 #endif
4477 template<typename IteratorType>
4478 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
4479 : public std::integral_constant<std::size_t, 2> {};
4480
4481 template<std::size_t N, typename IteratorType>
4482 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
4483 {
4484 public:
4485 using type = decltype(
4486 get<N>(std::declval <
4487 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
4488 };
4489 #if defined(__clang__)
4490 #pragma clang diagnostic pop
4491 #endif
4492 } // namespace std
4493
4494 // #include <nlohmann/detail/meta/cpp_future.hpp>
4495
4496 // #include <nlohmann/detail/meta/type_traits.hpp>
4497
4498 // #include <nlohmann/detail/value_t.hpp>
4499
4500
4501 #if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4502 #include <experimental/filesystem>
4503 namespace nlohmann::detail
4504 {
4505 namespace std_fs = std::experimental::filesystem;
4506 } // namespace nlohmann::detail
4507 #elif JSON_HAS_FILESYSTEM
4508 #include <filesystem>
4509 namespace nlohmann::detail
4510 {
4511 namespace std_fs = std::filesystem;
4512 } // namespace nlohmann::detail
4513 #endif
4514
4515 namespace nlohmann
4516 {
4517 namespace detail
4518 {
4519 //////////////////
4520 // constructors //
4521 //////////////////
4522
4523 /*
4524 * Note all external_constructor<>::construct functions need to call
4525 * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an
4526 * allocated value (e.g., a string). See bug issue
4527 * https://github.com/nlohmann/json/issues/2865 for more information.
4528 */
4529
4530 template<value_t> struct external_constructor;
4531
4532 template<>
4533 struct external_constructor<value_t::boolean>
4534 {
4535 template<typename BasicJsonType>
4536 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
4537 {
4538 j.m_value.destroy(j.m_type);
4539 j.m_type = value_t::boolean;
4540 j.m_value = b;
4541 j.assert_invariant();
4542 }
4543 };
4544
4545 template<>
4546 struct external_constructor<value_t::string>
4547 {
4548 template<typename BasicJsonType>
4549 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
4550 {
4551 j.m_value.destroy(j.m_type);
4552 j.m_type = value_t::string;
4553 j.m_value = s;
4554 j.assert_invariant();
4555 }
4556
4557 template<typename BasicJsonType>
4558 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
4559 {
4560 j.m_value.destroy(j.m_type);
4561 j.m_type = value_t::string;
4562 j.m_value = std::move(s);
4563 j.assert_invariant();
4564 }
4565
4566 template < typename BasicJsonType, typename CompatibleStringType,
4567 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
4568 int > = 0 >
4569 static void construct(BasicJsonType& j, const CompatibleStringType& str)
4570 {
4571 j.m_value.destroy(j.m_type);
4572 j.m_type = value_t::string;
4573 j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
4574 j.assert_invariant();
4575 }
4576 };
4577
4578 template<>
4579 struct external_constructor<value_t::binary>
4580 {
4581 template<typename BasicJsonType>
4582 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
4583 {
4584 j.m_value.destroy(j.m_type);
4585 j.m_type = value_t::binary;
4586 j.m_value = typename BasicJsonType::binary_t(b);
4587 j.assert_invariant();
4588 }
4589
4590 template<typename BasicJsonType>
4591 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
4592 {
4593 j.m_value.destroy(j.m_type);
4594 j.m_type = value_t::binary;
4595 j.m_value = typename BasicJsonType::binary_t(std::move(b));
4596 j.assert_invariant();
4597 }
4598 };
4599
4600 template<>
4601 struct external_constructor<value_t::number_float>
4602 {
4603 template<typename BasicJsonType>
4604 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
4605 {
4606 j.m_value.destroy(j.m_type);
4607 j.m_type = value_t::number_float;
4608 j.m_value = val;
4609 j.assert_invariant();
4610 }
4611 };
4612
4613 template<>
4614 struct external_constructor<value_t::number_unsigned>
4615 {
4616 template<typename BasicJsonType>
4617 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
4618 {
4619 j.m_value.destroy(j.m_type);
4620 j.m_type = value_t::number_unsigned;
4621 j.m_value = val;
4622 j.assert_invariant();
4623 }
4624 };
4625
4626 template<>
4627 struct external_constructor<value_t::number_integer>
4628 {
4629 template<typename BasicJsonType>
4630 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
4631 {
4632 j.m_value.destroy(j.m_type);
4633 j.m_type = value_t::number_integer;
4634 j.m_value = val;
4635 j.assert_invariant();
4636 }
4637 };
4638
4639 template<>
4640 struct external_constructor<value_t::array>
4641 {
4642 template<typename BasicJsonType>
4643 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
4644 {
4645 j.m_value.destroy(j.m_type);
4646 j.m_type = value_t::array;
4647 j.m_value = arr;
4648 j.set_parents();
4649 j.assert_invariant();
4650 }
4651
4652 template<typename BasicJsonType>
4653 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
4654 {
4655 j.m_value.destroy(j.m_type);
4656 j.m_type = value_t::array;
4657 j.m_value = std::move(arr);
4658 j.set_parents();
4659 j.assert_invariant();
4660 }
4661
4662 template < typename BasicJsonType, typename CompatibleArrayType,
4663 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
4664 int > = 0 >
4665 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
4666 {
4667 using std::begin;
4668 using std::end;
4669
4670 j.m_value.destroy(j.m_type);
4671 j.m_type = value_t::array;
4672 j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
4673 j.set_parents();
4674 j.assert_invariant();
4675 }
4676
4677 template<typename BasicJsonType>
4678 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
4679 {
4680 j.m_value.destroy(j.m_type);
4681 j.m_type = value_t::array;
4682 j.m_value = value_t::array;
4683 j.m_value.array->reserve(arr.size());
4684 for (const bool x : arr)
4685 {
4686 j.m_value.array->push_back(x);
4687 j.set_parent(j.m_value.array->back());
4688 }
4689 j.assert_invariant();
4690 }
4691
4692 template<typename BasicJsonType, typename T,
4693 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
4694 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
4695 {
4696 j.m_value.destroy(j.m_type);
4697 j.m_type = value_t::array;
4698 j.m_value = value_t::array;
4699 j.m_value.array->resize(arr.size());
4700 if (arr.size() > 0)
4701 {
4702 std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
4703 }
4704 j.set_parents();
4705 j.assert_invariant();
4706 }
4707 };
4708
4709 template<>
4710 struct external_constructor<value_t::object>
4711 {
4712 template<typename BasicJsonType>
4713 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
4714 {
4715 j.m_value.destroy(j.m_type);
4716 j.m_type = value_t::object;
4717 j.m_value = obj;
4718 j.set_parents();
4719 j.assert_invariant();
4720 }
4721
4722 template<typename BasicJsonType>
4723 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
4724 {
4725 j.m_value.destroy(j.m_type);
4726 j.m_type = value_t::object;
4727 j.m_value = std::move(obj);
4728 j.set_parents();
4729 j.assert_invariant();
4730 }
4731
4732 template < typename BasicJsonType, typename CompatibleObjectType,
4733 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
4734 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
4735 {
4736 using std::begin;
4737 using std::end;
4738
4739 j.m_value.destroy(j.m_type);
4740 j.m_type = value_t::object;
4741 j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
4742 j.set_parents();
4743 j.assert_invariant();
4744 }
4745 };
4746
4747 /////////////
4748 // to_json //
4749 /////////////
4750
4751 template<typename BasicJsonType, typename T,
4752 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
4753 void to_json(BasicJsonType& j, T b) noexcept
4754 {
4755 external_constructor<value_t::boolean>::construct(j, b);
4756 }
4757
4758 template<typename BasicJsonType, typename CompatibleString,
4759 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
4760 void to_json(BasicJsonType& j, const CompatibleString& s)
4761 {
4762 external_constructor<value_t::string>::construct(j, s);
4763 }
4764
4765 template<typename BasicJsonType>
4766 void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
4767 {
4768 external_constructor<value_t::string>::construct(j, std::move(s));
4769 }
4770
4771 template<typename BasicJsonType, typename FloatType,
4772 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
4773 void to_json(BasicJsonType& j, FloatType val) noexcept
4774 {
4775 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
4776 }
4777
4778 template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
4779 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
4780 void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
4781 {
4782 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
4783 }
4784
4785 template<typename BasicJsonType, typename CompatibleNumberIntegerType,
4786 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
4787 void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
4788 {
4789 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
4790 }
4791
4792 template<typename BasicJsonType, typename EnumType,
4793 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4794 void to_json(BasicJsonType& j, EnumType e) noexcept
4795 {
4796 using underlying_type = typename std::underlying_type<EnumType>::type;
4797 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
4798 }
4799
4800 template<typename BasicJsonType>
4801 void to_json(BasicJsonType& j, const std::vector<bool>& e)
4802 {
4803 external_constructor<value_t::array>::construct(j, e);
4804 }
4805
4806 template < typename BasicJsonType, typename CompatibleArrayType,
4807 enable_if_t < is_compatible_array_type<BasicJsonType,
4808 CompatibleArrayType>::value&&
4809 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
4810 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
4811 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
4812 !is_basic_json<CompatibleArrayType>::value,
4813 int > = 0 >
4814 void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
4815 {
4816 external_constructor<value_t::array>::construct(j, arr);
4817 }
4818
4819 template<typename BasicJsonType>
4820 void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
4821 {
4822 external_constructor<value_t::binary>::construct(j, bin);
4823 }
4824
4825 template<typename BasicJsonType, typename T,
4826 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
4827 void to_json(BasicJsonType& j, const std::valarray<T>& arr)
4828 {
4829 external_constructor<value_t::array>::construct(j, std::move(arr));
4830 }
4831
4832 template<typename BasicJsonType>
4833 void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
4834 {
4835 external_constructor<value_t::array>::construct(j, std::move(arr));
4836 }
4837
4838 template < typename BasicJsonType, typename CompatibleObjectType,
4839 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
4840 void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
4841 {
4842 external_constructor<value_t::object>::construct(j, obj);
4843 }
4844
4845 template<typename BasicJsonType>
4846 void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
4847 {
4848 external_constructor<value_t::object>::construct(j, std::move(obj));
4849 }
4850
4851 template <
4852 typename BasicJsonType, typename T, std::size_t N,
4853 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
4854 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4855 int > = 0 >
4856 void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4857 {
4858 external_constructor<value_t::array>::construct(j, arr);
4859 }
4860
4861 template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
4862 void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
4863 {
4864 j = { p.first, p.second };
4865 }
4866
4867 // for https://github.com/nlohmann/json/pull/1134
4868 template<typename BasicJsonType, typename T,
4869 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
4870 void to_json(BasicJsonType& j, const T& b)
4871 {
4872 j = { {b.key(), b.value()} };
4873 }
4874
4875 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
4876 void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
4877 {
4878 j = { std::get<Idx>(t)... };
4879 }
4880
4881 template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
4882 void to_json(BasicJsonType& j, const T& t)
4883 {
4884 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
4885 }
4886
4887 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4888 template<typename BasicJsonType>
4889 void to_json(BasicJsonType& j, const std_fs::path& p)
4890 {
4891 j = p.string();
4892 }
4893 #endif
4894
4895 struct to_json_fn
4896 {
4897 template<typename BasicJsonType, typename T>
4898 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
4899 -> decltype(to_json(j, std::forward<T>(val)), void())
4900 {
4901 return to_json(j, std::forward<T>(val));
4902 }
4903 };
4904 } // namespace detail
4905
4906 /// namespace to hold default `to_json` function
4907 /// to see why this is required:
4908 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
4909 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
4910 {
4911 constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value; // NOLINT(misc-definitions-in-headers)
4912 } // namespace
4913 } // namespace nlohmann
4914
4915 // #include <nlohmann/detail/meta/identity_tag.hpp>
4916
4917 // #include <nlohmann/detail/meta/type_traits.hpp>
4918
4919
4920 namespace nlohmann
4921 {
4922
4923 /// @sa https://json.nlohmann.me/api/adl_serializer/
4924 template<typename ValueType, typename>
4925 struct adl_serializer
4926 {
4927 /// @brief convert a JSON value to any value type
4928 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
4929 template<typename BasicJsonType, typename TargetType = ValueType>
4930 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
4931 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
4932 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
4933 {
4934 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
4935 }
4936
4937 /// @brief convert a JSON value to any value type
4938 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
4939 template<typename BasicJsonType, typename TargetType = ValueType>
4940 static auto from_json(BasicJsonType && j) noexcept(
4941 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
4942 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
4943 {
4944 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
4945 }
4946
4947 /// @brief convert any value type to a JSON value
4948 /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
4949 template<typename BasicJsonType, typename TargetType = ValueType>
4950 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
4951 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
4952 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
4953 {
4954 ::nlohmann::to_json(j, std::forward<TargetType>(val));
4955 }
4956 };
4957 } // namespace nlohmann
4958
4959 // #include <nlohmann/byte_container_with_subtype.hpp>
4960
4961
4962 #include <cstdint> // uint8_t, uint64_t
4963 #include <tuple> // tie
4964 #include <utility> // move
4965
4966 namespace nlohmann
4967 {
4968
4969 /// @brief an internal type for a backed binary type
4970 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
4971 template<typename BinaryType>
4972 class byte_container_with_subtype : public BinaryType
4973 {
4974 public:
4975 using container_type = BinaryType;
4976 using subtype_type = std::uint64_t;
4977
4978 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4979 byte_container_with_subtype() noexcept(noexcept(container_type()))
4980 : container_type()
4981 {}
4982
4983 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4984 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
4985 : container_type(b)
4986 {}
4987
4988 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4989 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
4990 : container_type(std::move(b))
4991 {}
4992
4993 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4994 byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
4995 : container_type(b)
4996 , m_subtype(subtype_)
4997 , m_has_subtype(true)
4998 {}
4999
5000 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5001 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
5002 : container_type(std::move(b))
5003 , m_subtype(subtype_)
5004 , m_has_subtype(true)
5005 {}
5006
5007 bool operator==(const byte_container_with_subtype& rhs) const
5008 {
5009 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
5010 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5011 }
5012
5013 bool operator!=(const byte_container_with_subtype& rhs) const
5014 {
5015 return !(rhs == *this);
5016 }
5017
5018 /// @brief sets the binary subtype
5019 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/
5020 void set_subtype(subtype_type subtype_) noexcept
5021 {
5022 m_subtype = subtype_;
5023 m_has_subtype = true;
5024 }
5025
5026 /// @brief return the binary subtype
5027 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/
5028 constexpr subtype_type subtype() const noexcept
5029 {
5030 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
5031 }
5032
5033 /// @brief return whether the value has a subtype
5034 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/
5035 constexpr bool has_subtype() const noexcept
5036 {
5037 return m_has_subtype;
5038 }
5039
5040 /// @brief clears the binary subtype
5041 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/
5042 void clear_subtype() noexcept
5043 {
5044 m_subtype = 0;
5045 m_has_subtype = false;
5046 }
5047
5048 private:
5049 subtype_type m_subtype = 0;
5050 bool m_has_subtype = false;
5051 };
5052
5053 } // namespace nlohmann
5054
5055 // #include <nlohmann/detail/conversions/from_json.hpp>
5056
5057 // #include <nlohmann/detail/conversions/to_json.hpp>
5058
5059 // #include <nlohmann/detail/exceptions.hpp>
5060
5061 // #include <nlohmann/detail/hash.hpp>
5062
5063
5064 #include <cstdint> // uint8_t
5065 #include <cstddef> // size_t
5066 #include <functional> // hash
5067
5068 // #include <nlohmann/detail/macro_scope.hpp>
5069
5070 // #include <nlohmann/detail/value_t.hpp>
5071
5072
5073 namespace nlohmann
5074 {
5075 namespace detail
5076 {
5077
5078 // boost::hash_combine
5079 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
5080 {
5081 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
5082 return seed;
5083 }
5084
5085 /*!
5086 @brief hash a JSON value
5087
5088 The hash function tries to rely on std::hash where possible. Furthermore, the
5089 type of the JSON value is taken into account to have different hash values for
5090 null, 0, 0U, and false, etc.
5091
5092 @tparam BasicJsonType basic_json specialization
5093 @param j JSON value to hash
5094 @return hash value of j
5095 */
5096 template<typename BasicJsonType>
5097 std::size_t hash(const BasicJsonType& j)
5098 {
5099 using string_t = typename BasicJsonType::string_t;
5100 using number_integer_t = typename BasicJsonType::number_integer_t;
5101 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5102 using number_float_t = typename BasicJsonType::number_float_t;
5103
5104 const auto type = static_cast<std::size_t>(j.type());
5105 switch (j.type())
5106 {
5107 case BasicJsonType::value_t::null:
5108 case BasicJsonType::value_t::discarded:
5109 {
5110 return combine(type, 0);
5111 }
5112
5113 case BasicJsonType::value_t::object:
5114 {
5115 auto seed = combine(type, j.size());
5116 for (const auto& element : j.items())
5117 {
5118 const auto h = std::hash<string_t> {}(element.key());
5119 seed = combine(seed, h);
5120 seed = combine(seed, hash(element.value()));
5121 }
5122 return seed;
5123 }
5124
5125 case BasicJsonType::value_t::array:
5126 {
5127 auto seed = combine(type, j.size());
5128 for (const auto& element : j)
5129 {
5130 seed = combine(seed, hash(element));
5131 }
5132 return seed;
5133 }
5134
5135 case BasicJsonType::value_t::string:
5136 {
5137 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
5138 return combine(type, h);
5139 }
5140
5141 case BasicJsonType::value_t::boolean:
5142 {
5143 const auto h = std::hash<bool> {}(j.template get<bool>());
5144 return combine(type, h);
5145 }
5146
5147 case BasicJsonType::value_t::number_integer:
5148 {
5149 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
5150 return combine(type, h);
5151 }
5152
5153 case BasicJsonType::value_t::number_unsigned:
5154 {
5155 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
5156 return combine(type, h);
5157 }
5158
5159 case BasicJsonType::value_t::number_float:
5160 {
5161 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
5162 return combine(type, h);
5163 }
5164
5165 case BasicJsonType::value_t::binary:
5166 {
5167 auto seed = combine(type, j.get_binary().size());
5168 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
5169 seed = combine(seed, h);
5170 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
5171 for (const auto byte : j.get_binary())
5172 {
5173 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
5174 }
5175 return seed;
5176 }
5177
5178 default: // LCOV_EXCL_LINE
5179 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
5180 return 0; // LCOV_EXCL_LINE
5181 }
5182 }
5183
5184 } // namespace detail
5185 } // namespace nlohmann
5186
5187 // #include <nlohmann/detail/input/binary_reader.hpp>
5188
5189
5190 #include <algorithm> // generate_n
5191 #include <array> // array
5192 #include <cmath> // ldexp
5193 #include <cstddef> // size_t
5194 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
5195 #include <cstdio> // snprintf
5196 #include <cstring> // memcpy
5197 #include <iterator> // back_inserter
5198 #include <limits> // numeric_limits
5199 #include <string> // char_traits, string
5200 #include <utility> // make_pair, move
5201 #include <vector> // vector
5202
5203 // #include <nlohmann/detail/exceptions.hpp>
5204
5205 // #include <nlohmann/detail/input/input_adapters.hpp>
5206
5207
5208 #include <array> // array
5209 #include <cstddef> // size_t
5210 #include <cstring> // strlen
5211 #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
5212 #include <memory> // shared_ptr, make_shared, addressof
5213 #include <numeric> // accumulate
5214 #include <string> // string, char_traits
5215 #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
5216 #include <utility> // pair, declval
5217
5218 #ifndef JSON_NO_IO
5219 #include <cstdio> // FILE *
5220 #include <istream> // istream
5221 #endif // JSON_NO_IO
5222
5223 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
5224
5225 // #include <nlohmann/detail/macro_scope.hpp>
5226
5227
5228 namespace nlohmann
5229 {
5230 namespace detail
5231 {
5232 /// the supported input formats
5233 enum class input_format_t { json, cbor, msgpack, ubjson, bson };
5234
5235 ////////////////////
5236 // input adapters //
5237 ////////////////////
5238
5239 #ifndef JSON_NO_IO
5240 /*!
5241 Input adapter for stdio file access. This adapter read only 1 byte and do not use any
5242 buffer. This adapter is a very low level adapter.
5243 */
5244 class file_input_adapter
5245 {
5246 public:
5247 using char_type = char;
5248
5249 JSON_HEDLEY_NON_NULL(2)
5250 explicit file_input_adapter(std::FILE* f) noexcept
5251 : m_file(f)
5252 {}
5253
5254 // make class move-only
5255 file_input_adapter(const file_input_adapter&) = delete;
5256 file_input_adapter(file_input_adapter&&) noexcept = default;
5257 file_input_adapter& operator=(const file_input_adapter&) = delete;
5258 file_input_adapter& operator=(file_input_adapter&&) = delete;
5259 ~file_input_adapter() = default;
5260
5261 std::char_traits<char>::int_type get_character() noexcept
5262 {
5263 return std::fgetc(m_file);
5264 }
5265
5266 private:
5267 /// the file pointer to read from
5268 std::FILE* m_file;
5269 };
5270
5271
5272 /*!
5273 Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
5274 beginning of input. Does not support changing the underlying std::streambuf
5275 in mid-input. Maintains underlying std::istream and std::streambuf to support
5276 subsequent use of standard std::istream operations to process any input
5277 characters following those used in parsing the JSON input. Clears the
5278 std::istream flags; any input errors (e.g., EOF) will be detected by the first
5279 subsequent call for input from the std::istream.
5280 */
5281 class input_stream_adapter
5282 {
5283 public:
5284 using char_type = char;
5285
5286 ~input_stream_adapter()
5287 {
5288 // clear stream flags; we use underlying streambuf I/O, do not
5289 // maintain ifstream flags, except eof
5290 if (is != nullptr)
5291 {
5292 is->clear(is->rdstate() & std::ios::eofbit);
5293 }
5294 }
5295
5296 explicit input_stream_adapter(std::istream& i)
5297 : is(&i), sb(i.rdbuf())
5298 {}
5299
5300 // delete because of pointer members
5301 input_stream_adapter(const input_stream_adapter&) = delete;
5302 input_stream_adapter& operator=(input_stream_adapter&) = delete;
5303 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
5304
5305 input_stream_adapter(input_stream_adapter&& rhs) noexcept
5306 : is(rhs.is), sb(rhs.sb)
5307 {
5308 rhs.is = nullptr;
5309 rhs.sb = nullptr;
5310 }
5311
5312 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
5313 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
5314 // end up as the same value, e.g. 0xFFFFFFFF.
5315 std::char_traits<char>::int_type get_character()
5316 {
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()))
5320 {
5321 is->clear(is->rdstate() | std::ios::eofbit);
5322 }
5323 return res;
5324 }
5325
5326 private:
5327 /// the associated input stream
5328 std::istream* is = nullptr;
5329 std::streambuf* sb = nullptr;
5330 };
5331 #endif // JSON_NO_IO
5332
5333 // General-purpose iterator-based adapter. It might not be as fast as
5334 // theoretically possible for some containers, but it is extremely versatile.
5335 template<typename IteratorType>
5336 class iterator_input_adapter
5337 {
5338 public:
5339 using char_type = typename std::iterator_traits<IteratorType>::value_type;
5340
5341 iterator_input_adapter(IteratorType first, IteratorType last)
5342 : current(std::move(first)), end(std::move(last))
5343 {}
5344
5345 typename std::char_traits<char_type>::int_type get_character()
5346 {
5347 if (JSON_HEDLEY_LIKELY(current != end))
5348 {
5349 auto result = std::char_traits<char_type>::to_int_type(*current);
5350 std::advance(current, 1);
5351 return result;
5352 }
5353
5354 return std::char_traits<char_type>::eof();
5355 }
5356
5357 private:
5358 IteratorType current;
5359 IteratorType end;
5360
5361 template<typename BaseInputAdapter, size_t T>
5362 friend struct wide_string_input_helper;
5363
5364 bool empty() const
5365 {
5366 return current == end;
5367 }
5368 };
5369
5370
5371 template<typename BaseInputAdapter, size_t T>
5372 struct wide_string_input_helper;
5373
5374 template<typename BaseInputAdapter>
5375 struct wide_string_input_helper<BaseInputAdapter, 4>
5376 {
5377 // UTF-32
5378 static void fill_buffer(BaseInputAdapter& input,
5379 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
5380 size_t& utf8_bytes_index,
5381 size_t& utf8_bytes_filled)
5382 {
5383 utf8_bytes_index = 0;
5384
5385 if (JSON_HEDLEY_UNLIKELY(input.empty()))
5386 {
5387 utf8_bytes[0] = std::char_traits<char>::eof();
5388 utf8_bytes_filled = 1;
5389 }
5390 else
5391 {
5392 // get the current character
5393 const auto wc = input.get_character();
5394
5395 // UTF-32 to UTF-8 encoding
5396 if (wc < 0x80)
5397 {
5398 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5399 utf8_bytes_filled = 1;
5400 }
5401 else if (wc <= 0x7FF)
5402 {
5403 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
5404 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5405 utf8_bytes_filled = 2;
5406 }
5407 else if (wc <= 0xFFFF)
5408 {
5409 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
5410 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5411 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5412 utf8_bytes_filled = 3;
5413 }
5414 else if (wc <= 0x10FFFF)
5415 {
5416 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
5417 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
5418 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5419 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5420 utf8_bytes_filled = 4;
5421 }
5422 else
5423 {
5424 // unknown character
5425 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5426 utf8_bytes_filled = 1;
5427 }
5428 }
5429 }
5430 };
5431
5432 template<typename BaseInputAdapter>
5433 struct wide_string_input_helper<BaseInputAdapter, 2>
5434 {
5435 // UTF-16
5436 static void fill_buffer(BaseInputAdapter& input,
5437 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
5438 size_t& utf8_bytes_index,
5439 size_t& utf8_bytes_filled)
5440 {
5441 utf8_bytes_index = 0;
5442
5443 if (JSON_HEDLEY_UNLIKELY(input.empty()))
5444 {
5445 utf8_bytes[0] = std::char_traits<char>::eof();
5446 utf8_bytes_filled = 1;
5447 }
5448 else
5449 {
5450 // get the current character
5451 const auto wc = input.get_character();
5452
5453 // UTF-16 to UTF-8 encoding
5454 if (wc < 0x80)
5455 {
5456 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5457 utf8_bytes_filled = 1;
5458 }
5459 else if (wc <= 0x7FF)
5460 {
5461 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
5462 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5463 utf8_bytes_filled = 2;
5464 }
5465 else if (0xD800 > wc || wc >= 0xE000)
5466 {
5467 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
5468 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5469 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5470 utf8_bytes_filled = 3;
5471 }
5472 else
5473 {
5474 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
5475 {
5476 const auto wc2 = static_cast<unsigned int>(input.get_character());
5477 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
5478 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
5479 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
5480 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
5481 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
5482 utf8_bytes_filled = 4;
5483 }
5484 else
5485 {
5486 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5487 utf8_bytes_filled = 1;
5488 }
5489 }
5490 }
5491 }
5492 };
5493
5494 // Wraps another input apdater to convert wide character types into individual bytes.
5495 template<typename BaseInputAdapter, typename WideCharType>
5496 class wide_string_input_adapter
5497 {
5498 public:
5499 using char_type = char;
5500
5501 wide_string_input_adapter(BaseInputAdapter base)
5502 : base_adapter(base) {}
5503
5504 typename std::char_traits<char>::int_type get_character() noexcept
5505 {
5506 // check if buffer needs to be filled
5507 if (utf8_bytes_index == utf8_bytes_filled)
5508 {
5509 fill_buffer<sizeof(WideCharType)>();
5510
5511 JSON_ASSERT(utf8_bytes_filled > 0);
5512 JSON_ASSERT(utf8_bytes_index == 0);
5513 }
5514
5515 // use buffer
5516 JSON_ASSERT(utf8_bytes_filled > 0);
5517 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
5518 return utf8_bytes[utf8_bytes_index++];
5519 }
5520
5521 private:
5522 BaseInputAdapter base_adapter;
5523
5524 template<size_t T>
5525 void fill_buffer()
5526 {
5527 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
5528 }
5529
5530 /// a buffer for UTF-8 bytes
5531 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
5532
5533 /// index to the utf8_codes array for the next valid byte
5534 std::size_t utf8_bytes_index = 0;
5535 /// number of valid bytes in the utf8_codes array
5536 std::size_t utf8_bytes_filled = 0;
5537 };
5538
5539
5540 template<typename IteratorType, typename Enable = void>
5541 struct iterator_input_adapter_factory
5542 {
5543 using iterator_type = IteratorType;
5544 using char_type = typename std::iterator_traits<iterator_type>::value_type;
5545 using adapter_type = iterator_input_adapter<iterator_type>;
5546
5547 static adapter_type create(IteratorType first, IteratorType last)
5548 {
5549 return adapter_type(std::move(first), std::move(last));
5550 }
5551 };
5552
5553 template<typename T>
5554 struct is_iterator_of_multibyte
5555 {
5556 using value_type = typename std::iterator_traits<T>::value_type;
5557 enum
5558 {
5559 value = sizeof(value_type) > 1
5560 };
5561 };
5562
5563 template<typename IteratorType>
5564 struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
5565 {
5566 using iterator_type = IteratorType;
5567 using char_type = typename std::iterator_traits<iterator_type>::value_type;
5568 using base_adapter_type = iterator_input_adapter<iterator_type>;
5569 using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
5570
5571 static adapter_type create(IteratorType first, IteratorType last)
5572 {
5573 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
5574 }
5575 };
5576
5577 // General purpose iterator-based input
5578 template<typename IteratorType>
5579 typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
5580 {
5581 using factory_type = iterator_input_adapter_factory<IteratorType>;
5582 return factory_type::create(first, last);
5583 }
5584
5585 // Convenience shorthand from container to iterator
5586 // Enables ADL on begin(container) and end(container)
5587 // Encloses the using declarations in namespace for not to leak them to outside scope
5588
5589 namespace container_input_adapter_factory_impl
5590 {
5591
5592 using std::begin;
5593 using std::end;
5594
5595 template<typename ContainerType, typename Enable = void>
5596 struct container_input_adapter_factory {};
5597
5598 template<typename ContainerType>
5599 struct container_input_adapter_factory< ContainerType,
5600 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
5601 {
5602 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
5603
5604 static adapter_type create(const ContainerType& container)
5605 {
5606 return input_adapter(begin(container), end(container));
5607 }
5608 };
5609
5610 } // namespace container_input_adapter_factory_impl
5611
5612 template<typename ContainerType>
5613 typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
5614 {
5615 return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
5616 }
5617
5618 #ifndef JSON_NO_IO
5619 // Special cases with fast paths
5620 inline file_input_adapter input_adapter(std::FILE* file)
5621 {
5622 return file_input_adapter(file);
5623 }
5624
5625 inline input_stream_adapter input_adapter(std::istream& stream)
5626 {
5627 return input_stream_adapter(stream);
5628 }
5629
5630 inline input_stream_adapter input_adapter(std::istream&& stream)
5631 {
5632 return input_stream_adapter(stream);
5633 }
5634 #endif // JSON_NO_IO
5635
5636 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
5637
5638 // Null-delimited strings, and the like.
5639 template < typename CharT,
5640 typename std::enable_if <
5641 std::is_pointer<CharT>::value&&
5642 !std::is_array<CharT>::value&&
5643 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
5644 sizeof(typename std::remove_pointer<CharT>::type) == 1,
5645 int >::type = 0 >
5646 contiguous_bytes_input_adapter input_adapter(CharT b)
5647 {
5648 auto length = std::strlen(reinterpret_cast<const char*>(b));
5649 const auto* ptr = reinterpret_cast<const char*>(b);
5650 return input_adapter(ptr, ptr + length);
5651 }
5652
5653 template<typename T, std::size_t N>
5654 auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5655 {
5656 return input_adapter(array, array + N);
5657 }
5658
5659 // This class only handles inputs of input_buffer_adapter type.
5660 // It's required so that expressions like {ptr, len} can be implicitly cast
5661 // to the correct adapter.
5662 class span_input_adapter
5663 {
5664 public:
5665 template < typename CharT,
5666 typename std::enable_if <
5667 std::is_pointer<CharT>::value&&
5668 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
5669 sizeof(typename std::remove_pointer<CharT>::type) == 1,
5670 int >::type = 0 >
5671 span_input_adapter(CharT b, std::size_t l)
5672 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
5673
5674 template<class IteratorType,
5675 typename std::enable_if<
5676 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
5677 int>::type = 0>
5678 span_input_adapter(IteratorType first, IteratorType last)
5679 : ia(input_adapter(first, last)) {}
5680
5681 contiguous_bytes_input_adapter&& get()
5682 {
5683 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
5684 }
5685
5686 private:
5687 contiguous_bytes_input_adapter ia;
5688 };
5689 } // namespace detail
5690 } // namespace nlohmann
5691
5692 // #include <nlohmann/detail/input/json_sax.hpp>
5693
5694
5695 #include <cstddef>
5696 #include <string> // string
5697 #include <utility> // move
5698 #include <vector> // vector
5699
5700 // #include <nlohmann/detail/exceptions.hpp>
5701
5702 // #include <nlohmann/detail/macro_scope.hpp>
5703
5704
5705 namespace nlohmann
5706 {
5707
5708 /*!
5709 @brief SAX interface
5710
5711 This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
5712 Each function is called in different situations while the input is parsed. The
5713 boolean return value informs the parser whether to continue processing the
5714 input.
5715 */
5716 template<typename BasicJsonType>
5717 struct json_sax
5718 {
5719 using number_integer_t = typename BasicJsonType::number_integer_t;
5720 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5721 using number_float_t = typename BasicJsonType::number_float_t;
5722 using string_t = typename BasicJsonType::string_t;
5723 using binary_t = typename BasicJsonType::binary_t;
5724
5725 /*!
5726 @brief a null value was read
5727 @return whether parsing should proceed
5728 */
5729 virtual bool null() = 0;
5730
5731 /*!
5732 @brief a boolean value was read
5733 @param[in] val boolean value
5734 @return whether parsing should proceed
5735 */
5736 virtual bool boolean(bool val) = 0;
5737
5738 /*!
5739 @brief an integer number was read
5740 @param[in] val integer value
5741 @return whether parsing should proceed
5742 */
5743 virtual bool number_integer(number_integer_t val) = 0;
5744
5745 /*!
5746 @brief an unsigned integer number was read
5747 @param[in] val unsigned integer value
5748 @return whether parsing should proceed
5749 */
5750 virtual bool number_unsigned(number_unsigned_t val) = 0;
5751
5752 /*!
5753 @brief a floating-point number was read
5754 @param[in] val floating-point value
5755 @param[in] s raw token value
5756 @return whether parsing should proceed
5757 */
5758 virtual bool number_float(number_float_t val, const string_t& s) = 0;
5759
5760 /*!
5761 @brief a string value was read
5762 @param[in] val string value
5763 @return whether parsing should proceed
5764 @note It is safe to move the passed string value.
5765 */
5766 virtual bool string(string_t& val) = 0;
5767
5768 /*!
5769 @brief a binary value was read
5770 @param[in] val binary value
5771 @return whether parsing should proceed
5772 @note It is safe to move the passed binary value.
5773 */
5774 virtual bool binary(binary_t& val) = 0;
5775
5776 /*!
5777 @brief the beginning of an object was read
5778 @param[in] elements number of object elements or -1 if unknown
5779 @return whether parsing should proceed
5780 @note binary formats may report the number of elements
5781 */
5782 virtual bool start_object(std::size_t elements) = 0;
5783
5784 /*!
5785 @brief an object key was read
5786 @param[in] val object key
5787 @return whether parsing should proceed
5788 @note It is safe to move the passed string.
5789 */
5790 virtual bool key(string_t& val) = 0;
5791
5792 /*!
5793 @brief the end of an object was read
5794 @return whether parsing should proceed
5795 */
5796 virtual bool end_object() = 0;
5797
5798 /*!
5799 @brief the beginning of an array was read
5800 @param[in] elements number of array elements or -1 if unknown
5801 @return whether parsing should proceed
5802 @note binary formats may report the number of elements
5803 */
5804 virtual bool start_array(std::size_t elements) = 0;
5805
5806 /*!
5807 @brief the end of an array was read
5808 @return whether parsing should proceed
5809 */
5810 virtual bool end_array() = 0;
5811
5812 /*!
5813 @brief a parse error occurred
5814 @param[in] position the position in the input where the error occurs
5815 @param[in] last_token the last read token
5816 @param[in] ex an exception object describing the error
5817 @return whether parsing should proceed (must return false)
5818 */
5819 virtual bool parse_error(std::size_t position,
5820 const std::string& last_token,
5821 const detail::exception& ex) = 0;
5822
5823 json_sax() = default;
5824 json_sax(const json_sax&) = default;
5825 json_sax(json_sax&&) noexcept = default;
5826 json_sax& operator=(const json_sax&) = default;
5827 json_sax& operator=(json_sax&&) noexcept = default;
5828 virtual ~json_sax() = default;
5829 };
5830
5831
5832 namespace detail
5833 {
5834 /*!
5835 @brief SAX implementation to create a JSON value from SAX events
5836
5837 This class implements the @ref json_sax interface and processes the SAX events
5838 to create a JSON value which makes it basically a DOM parser. The structure or
5839 hierarchy of the JSON value is managed by the stack `ref_stack` which contains
5840 a pointer to the respective array or object for each recursion depth.
5841
5842 After successful parsing, the value that is passed by reference to the
5843 constructor contains the parsed value.
5844
5845 @tparam BasicJsonType the JSON type
5846 */
5847 template<typename BasicJsonType>
5848 class json_sax_dom_parser
5849 {
5850 public:
5851 using number_integer_t = typename BasicJsonType::number_integer_t;
5852 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5853 using number_float_t = typename BasicJsonType::number_float_t;
5854 using string_t = typename BasicJsonType::string_t;
5855 using binary_t = typename BasicJsonType::binary_t;
5856
5857 /*!
5858 @param[in,out] r reference to a JSON value that is manipulated while
5859 parsing
5860 @param[in] allow_exceptions_ whether parse errors yield exceptions
5861 */
5862 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
5863 : root(r), allow_exceptions(allow_exceptions_)
5864 {}
5865
5866 // make class move-only
5867 json_sax_dom_parser(const json_sax_dom_parser&) = delete;
5868 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
5869 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
5870 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
5871 ~json_sax_dom_parser() = default;
5872
5873 bool null()
5874 {
5875 handle_value(nullptr);
5876 return true;
5877 }
5878
5879 bool boolean(bool val)
5880 {
5881 handle_value(val);
5882 return true;
5883 }
5884
5885 bool number_integer(number_integer_t val)
5886 {
5887 handle_value(val);
5888 return true;
5889 }
5890
5891 bool number_unsigned(number_unsigned_t val)
5892 {
5893 handle_value(val);
5894 return true;
5895 }
5896
5897 bool number_float(number_float_t val, const string_t& /*unused*/)
5898 {
5899 handle_value(val);
5900 return true;
5901 }
5902
5903 bool string(string_t& val)
5904 {
5905 handle_value(val);
5906 return true;
5907 }
5908
5909 bool binary(binary_t& val)
5910 {
5911 handle_value(std::move(val));
5912 return true;
5913 }
5914
5915 bool start_object(std::size_t len)
5916 {
5917 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
5918
5919 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
5920 {
5921 JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
5922 }
5923
5924 return true;
5925 }
5926
5927 bool key(string_t& val)
5928 {
5929 // add null at given key and store the reference for later
5930 object_element = &(ref_stack.back()->m_value.object->operator[](val));
5931 return true;
5932 }
5933
5934 bool end_object()
5935 {
5936 ref_stack.back()->set_parents();
5937 ref_stack.pop_back();
5938 return true;
5939 }
5940
5941 bool start_array(std::size_t len)
5942 {
5943 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
5944
5945 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
5946 {
5947 JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
5948 }
5949
5950 return true;
5951 }
5952
5953 bool end_array()
5954 {
5955 ref_stack.back()->set_parents();
5956 ref_stack.pop_back();
5957 return true;
5958 }
5959
5960 template<class Exception>
5961 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
5962 const Exception& ex)
5963 {
5964 errored = true;
5965 static_cast<void>(ex);
5966 if (allow_exceptions)
5967 {
5968 JSON_THROW(ex);
5969 }
5970 return false;
5971 }
5972
5973 constexpr bool is_errored() const
5974 {
5975 return errored;
5976 }
5977
5978 private:
5979 /*!
5980 @invariant If the ref stack is empty, then the passed value will be the new
5981 root.
5982 @invariant If the ref stack contains a value, then it is an array or an
5983 object to which we can add elements
5984 */
5985 template<typename Value>
5986 JSON_HEDLEY_RETURNS_NON_NULL
5987 BasicJsonType* handle_value(Value&& v)
5988 {
5989 if (ref_stack.empty())
5990 {
5991 root = BasicJsonType(std::forward<Value>(v));
5992 return &root;
5993 }
5994
5995 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
5996
5997 if (ref_stack.back()->is_array())
5998 {
5999 ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
6000 return &(ref_stack.back()->m_value.array->back());
6001 }
6002
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;
6007 }
6008
6009 /// the parsed JSON value
6010 BasicJsonType& root;
6011 /// stack to model hierarchy of values
6012 std::vector<BasicJsonType*> ref_stack {};
6013 /// helper to hold the reference for the next object element
6014 BasicJsonType* object_element = nullptr;
6015 /// whether a syntax error occurred
6016 bool errored = false;
6017 /// whether to throw exceptions in case of errors
6018 const bool allow_exceptions = true;
6019 };
6020
6021 template<typename BasicJsonType>
6022 class json_sax_dom_callback_parser
6023 {
6024 public:
6025 using number_integer_t = typename BasicJsonType::number_integer_t;
6026 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6027 using number_float_t = typename BasicJsonType::number_float_t;
6028 using string_t = typename BasicJsonType::string_t;
6029 using binary_t = typename BasicJsonType::binary_t;
6030 using parser_callback_t = typename BasicJsonType::parser_callback_t;
6031 using parse_event_t = typename BasicJsonType::parse_event_t;
6032
6033 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_)
6037 {
6038 keep_stack.push_back(true);
6039 }
6040
6041 // make class move-only
6042 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
6043 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6044 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
6045 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6046 ~json_sax_dom_callback_parser() = default;
6047
6048 bool null()
6049 {
6050 handle_value(nullptr);
6051 return true;
6052 }
6053
6054 bool boolean(bool val)
6055 {
6056 handle_value(val);
6057 return true;
6058 }
6059
6060 bool number_integer(number_integer_t val)
6061 {
6062 handle_value(val);
6063 return true;
6064 }
6065
6066 bool number_unsigned(number_unsigned_t val)
6067 {
6068 handle_value(val);
6069 return true;
6070 }
6071
6072 bool number_float(number_float_t val, const string_t& /*unused*/)
6073 {
6074 handle_value(val);
6075 return true;
6076 }
6077
6078 bool string(string_t& val)
6079 {
6080 handle_value(val);
6081 return true;
6082 }
6083
6084 bool binary(binary_t& val)
6085 {
6086 handle_value(std::move(val));
6087 return true;
6088 }
6089
6090 bool start_object(std::size_t len)
6091 {
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);
6095
6096 auto val = handle_value(BasicJsonType::value_t::object, true);
6097 ref_stack.push_back(val.second);
6098
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()))
6101 {
6102 JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
6103 }
6104
6105 return true;
6106 }
6107
6108 bool key(string_t& val)
6109 {
6110 BasicJsonType k = BasicJsonType(val);
6111
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);
6115
6116 // add discarded value at given key and store the reference for later
6117 if (keep && ref_stack.back())
6118 {
6119 object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
6120 }
6121
6122 return true;
6123 }
6124
6125 bool end_object()
6126 {
6127 if (ref_stack.back())
6128 {
6129 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
6130 {
6131 // discard object
6132 *ref_stack.back() = discarded;
6133 }
6134 else
6135 {
6136 ref_stack.back()->set_parents();
6137 }
6138 }
6139
6140 JSON_ASSERT(!ref_stack.empty());
6141 JSON_ASSERT(!keep_stack.empty());
6142 ref_stack.pop_back();
6143 keep_stack.pop_back();
6144
6145 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
6146 {
6147 // remove discarded value
6148 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
6149 {
6150 if (it->is_discarded())
6151 {
6152 ref_stack.back()->erase(it);
6153 break;
6154 }
6155 }
6156 }
6157
6158 return true;
6159 }
6160
6161 bool start_array(std::size_t len)
6162 {
6163 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
6164 keep_stack.push_back(keep);
6165
6166 auto val = handle_value(BasicJsonType::value_t::array, true);
6167 ref_stack.push_back(val.second);
6168
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()))
6171 {
6172 JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
6173 }
6174
6175 return true;
6176 }
6177
6178 bool end_array()
6179 {
6180 bool keep = true;
6181
6182 if (ref_stack.back())
6183 {
6184 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
6185 if (keep)
6186 {
6187 ref_stack.back()->set_parents();
6188 }
6189 else
6190 {
6191 // discard array
6192 *ref_stack.back() = discarded;
6193 }
6194 }
6195
6196 JSON_ASSERT(!ref_stack.empty());
6197 JSON_ASSERT(!keep_stack.empty());
6198 ref_stack.pop_back();
6199 keep_stack.pop_back();
6200
6201 // remove discarded value
6202 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
6203 {
6204 ref_stack.back()->m_value.array->pop_back();
6205 }
6206
6207 return true;
6208 }
6209
6210 template<class Exception>
6211 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
6212 const Exception& ex)
6213 {
6214 errored = true;
6215 static_cast<void>(ex);
6216 if (allow_exceptions)
6217 {
6218 JSON_THROW(ex);
6219 }
6220 return false;
6221 }
6222
6223 constexpr bool is_errored() const
6224 {
6225 return errored;
6226 }
6227
6228 private:
6229 /*!
6230 @param[in] v value to add to the JSON value we build during parsing
6231 @param[in] skip_callback whether we should skip calling the callback
6232 function; this is required after start_array() and
6233 start_object() SAX events, because otherwise we would call the
6234 callback function with an empty array or object, respectively.
6235
6236 @invariant If the ref stack is empty, then the passed value will be the new
6237 root.
6238 @invariant If the ref stack contains a value, then it is an array or an
6239 object to which we can add elements
6240
6241 @return pair of boolean (whether value should be kept) and pointer (to the
6242 passed value in the ref_stack hierarchy; nullptr if not kept)
6243 */
6244 template<typename Value>
6245 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
6246 {
6247 JSON_ASSERT(!keep_stack.empty());
6248
6249 // do not handle this value if we know it would be added to a discarded
6250 // container
6251 if (!keep_stack.back())
6252 {
6253 return {false, nullptr};
6254 }
6255
6256 // create value
6257 auto value = BasicJsonType(std::forward<Value>(v));
6258
6259 // check callback
6260 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
6261
6262 // do not handle this value if we just learnt it shall be discarded
6263 if (!keep)
6264 {
6265 return {false, nullptr};
6266 }
6267
6268 if (ref_stack.empty())
6269 {
6270 root = std::move(value);
6271 return {true, &root};
6272 }
6273
6274 // skip this value if we already decided to skip the parent
6275 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
6276 if (!ref_stack.back())
6277 {
6278 return {false, nullptr};
6279 }
6280
6281 // we now only expect arrays and objects
6282 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6283
6284 // array
6285 if (ref_stack.back()->is_array())
6286 {
6287 ref_stack.back()->m_value.array->emplace_back(std::move(value));
6288 return {true, &(ref_stack.back()->m_value.array->back())};
6289 }
6290
6291 // object
6292 JSON_ASSERT(ref_stack.back()->is_object());
6293 // check if we should store an element for the current key
6294 JSON_ASSERT(!key_keep_stack.empty());
6295 const bool store_element = key_keep_stack.back();
6296 key_keep_stack.pop_back();
6297
6298 if (!store_element)
6299 {
6300 return {false, nullptr};
6301 }
6302
6303 JSON_ASSERT(object_element);
6304 *object_element = std::move(value);
6305 return {true, object_element};
6306 }
6307
6308 /// the parsed JSON value
6309 BasicJsonType& root;
6310 /// stack to model hierarchy of values
6311 std::vector<BasicJsonType*> ref_stack {};
6312 /// stack to manage which values to keep
6313 std::vector<bool> keep_stack {};
6314 /// stack to manage which object keys to keep
6315 std::vector<bool> key_keep_stack {};
6316 /// helper to hold the reference for the next object element
6317 BasicJsonType* object_element = nullptr;
6318 /// whether a syntax error occurred
6319 bool errored = false;
6320 /// callback function
6321 const parser_callback_t callback = nullptr;
6322 /// whether to throw exceptions in case of errors
6323 const bool allow_exceptions = true;
6324 /// a discarded value for the callback
6325 BasicJsonType discarded = BasicJsonType::value_t::discarded;
6326 };
6327
6328 template<typename BasicJsonType>
6329 class json_sax_acceptor
6330 {
6331 public:
6332 using number_integer_t = typename BasicJsonType::number_integer_t;
6333 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6334 using number_float_t = typename BasicJsonType::number_float_t;
6335 using string_t = typename BasicJsonType::string_t;
6336 using binary_t = typename BasicJsonType::binary_t;
6337
6338 bool null()
6339 {
6340 return true;
6341 }
6342
6343 bool boolean(bool /*unused*/)
6344 {
6345 return true;
6346 }
6347
6348 bool number_integer(number_integer_t /*unused*/)
6349 {
6350 return true;
6351 }
6352
6353 bool number_unsigned(number_unsigned_t /*unused*/)
6354 {
6355 return true;
6356 }
6357
6358 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
6359 {
6360 return true;
6361 }
6362
6363 bool string(string_t& /*unused*/)
6364 {
6365 return true;
6366 }
6367
6368 bool binary(binary_t& /*unused*/)
6369 {
6370 return true;
6371 }
6372
6373 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
6374 {
6375 return true;
6376 }
6377
6378 bool key(string_t& /*unused*/)
6379 {
6380 return true;
6381 }
6382
6383 bool end_object()
6384 {
6385 return true;
6386 }
6387
6388 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
6389 {
6390 return true;
6391 }
6392
6393 bool end_array()
6394 {
6395 return true;
6396 }
6397
6398 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
6399 {
6400 return false;
6401 }
6402 };
6403 } // namespace detail
6404
6405 } // namespace nlohmann
6406
6407 // #include <nlohmann/detail/input/lexer.hpp>
6408
6409
6410 #include <array> // array
6411 #include <clocale> // localeconv
6412 #include <cstddef> // size_t
6413 #include <cstdio> // snprintf
6414 #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
6415 #include <initializer_list> // initializer_list
6416 #include <string> // char_traits, string
6417 #include <utility> // move
6418 #include <vector> // vector
6419
6420 // #include <nlohmann/detail/input/input_adapters.hpp>
6421
6422 // #include <nlohmann/detail/input/position_t.hpp>
6423
6424 // #include <nlohmann/detail/macro_scope.hpp>
6425
6426
6427 namespace nlohmann
6428 {
6429 namespace detail
6430 {
6431 ///////////
6432 // lexer //
6433 ///////////
6434
6435 template<typename BasicJsonType>
6436 class lexer_base
6437 {
6438 public:
6439 /// token types for the parser
6440 enum class token_type
6441 {
6442 uninitialized, ///< indicating the scanner is uninitialized
6443 literal_true, ///< the `true` literal
6444 literal_false, ///< the `false` literal
6445 literal_null, ///< the `null` literal
6446 value_string, ///< a string -- use get_string() for actual value
6447 value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
6448 value_integer, ///< a signed integer -- use get_number_integer() for actual value
6449 value_float, ///< an floating point number -- use get_number_float() for actual value
6450 begin_array, ///< the character for array begin `[`
6451 begin_object, ///< the character for object begin `{`
6452 end_array, ///< the character for array end `]`
6453 end_object, ///< the character for object end `}`
6454 name_separator, ///< the name separator `:`
6455 value_separator, ///< the value separator `,`
6456 parse_error, ///< indicating a parse error
6457 end_of_input, ///< indicating the end of the input buffer
6458 literal_or_value ///< a literal or the begin of a value (only for diagnostics)
6459 };
6460
6461 /// return name of values of type token_type (only used for errors)
6462 JSON_HEDLEY_RETURNS_NON_NULL
6463 JSON_HEDLEY_CONST
6464 static const char* token_type_name(const token_type t) noexcept
6465 {
6466 switch (t)
6467 {
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:
6483 return "'['";
6484 case token_type::begin_object:
6485 return "'{'";
6486 case token_type::end_array:
6487 return "']'";
6488 case token_type::end_object:
6489 return "'}'";
6490 case token_type::name_separator:
6491 return "':'";
6492 case token_type::value_separator:
6493 return "','";
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";
6500 // LCOV_EXCL_START
6501 default: // catch non-enum values
6502 return "unknown token";
6503 // LCOV_EXCL_STOP
6504 }
6505 }
6506 };
6507 /*!
6508 @brief lexical analysis
6509
6510 This class organizes the lexical analysis during JSON deserialization.
6511 */
6512 template<typename BasicJsonType, typename InputAdapterType>
6513 class lexer : public lexer_base<BasicJsonType>
6514 {
6515 using number_integer_t = typename BasicJsonType::number_integer_t;
6516 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6517 using number_float_t = typename BasicJsonType::number_float_t;
6518 using string_t = typename BasicJsonType::string_t;
6519 using char_type = typename InputAdapterType::char_type;
6520 using char_int_type = typename std::char_traits<char_type>::int_type;
6521
6522 public:
6523 using token_type = typename lexer_base<BasicJsonType>::token_type;
6524
6525 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()))
6529 {}
6530
6531 // delete because of pointer members
6532 lexer(const lexer&) = delete;
6533 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6534 lexer& operator=(lexer&) = delete;
6535 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6536 ~lexer() = default;
6537
6538 private:
6539 /////////////////////
6540 // locales
6541 /////////////////////
6542
6543 /// return the locale-dependent decimal point
6544 JSON_HEDLEY_PURE
6545 static char get_decimal_point() noexcept
6546 {
6547 const auto* loc = localeconv();
6548 JSON_ASSERT(loc != nullptr);
6549 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
6550 }
6551
6552 /////////////////////
6553 // scan functions
6554 /////////////////////
6555
6556 /*!
6557 @brief get codepoint from 4 hex characters following `\u`
6558
6559 For input "\u c1 c2 c3 c4" the codepoint is:
6560 (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
6561 = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
6562
6563 Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
6564 must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
6565 conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
6566 between the ASCII value of the character and the desired integer value.
6567
6568 @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
6569 non-hex character)
6570 */
6571 int get_codepoint()
6572 {
6573 // this function only makes sense after reading `\u`
6574 JSON_ASSERT(current == 'u');
6575 int codepoint = 0;
6576
6577 const auto factors = { 12u, 8u, 4u, 0u };
6578 for (const auto factor : factors)
6579 {
6580 get();
6581
6582 if (current >= '0' && current <= '9')
6583 {
6584 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
6585 }
6586 else if (current >= 'A' && current <= 'F')
6587 {
6588 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
6589 }
6590 else if (current >= 'a' && current <= 'f')
6591 {
6592 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
6593 }
6594 else
6595 {
6596 return -1;
6597 }
6598 }
6599
6600 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
6601 return codepoint;
6602 }
6603
6604 /*!
6605 @brief check if the next byte(s) are inside a given range
6606
6607 Adds the current byte and, for each passed range, reads a new byte and
6608 checks if it is inside the range. If a violation was detected, set up an
6609 error message and return false. Otherwise, return true.
6610
6611 @param[in] ranges list of integers; interpreted as list of pairs of
6612 inclusive lower and upper bound, respectively
6613
6614 @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
6615 1, 2, or 3 pairs. This precondition is enforced by an assertion.
6616
6617 @return true if and only if no range violation was detected
6618 */
6619 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
6620 {
6621 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
6622 add(current);
6623
6624 for (auto range = ranges.begin(); range != ranges.end(); ++range)
6625 {
6626 get();
6627 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
6628 {
6629 add(current);
6630 }
6631 else
6632 {
6633 error_message = "invalid string: ill-formed UTF-8 byte";
6634 return false;
6635 }
6636 }
6637
6638 return true;
6639 }
6640
6641 /*!
6642 @brief scan a string literal
6643
6644 This function scans a string according to Sect. 7 of RFC 8259. While
6645 scanning, bytes are escaped and copied into buffer token_buffer. Then the
6646 function returns successfully, token_buffer is *not* null-terminated (as it
6647 may contain \0 bytes), and token_buffer.size() is the number of bytes in the
6648 string.
6649
6650 @return token_type::value_string if string could be successfully scanned,
6651 token_type::parse_error otherwise
6652
6653 @note In case of errors, variable error_message contains a textual
6654 description.
6655 */
6656 token_type scan_string()
6657 {
6658 // reset token_buffer (ignore opening quote)
6659 reset();
6660
6661 // we entered the function by reading an open quote
6662 JSON_ASSERT(current == '\"');
6663
6664 while (true)
6665 {
6666 // get next character
6667 switch (get())
6668 {
6669 // end of file while parsing string
6670 case std::char_traits<char_type>::eof():
6671 {
6672 error_message = "invalid string: missing closing quote";
6673 return token_type::parse_error;
6674 }
6675
6676 // closing quote
6677 case '\"':
6678 {
6679 return token_type::value_string;
6680 }
6681
6682 // escapes
6683 case '\\':
6684 {
6685 switch (get())
6686 {
6687 // quotation mark
6688 case '\"':
6689 add('\"');
6690 break;
6691 // reverse solidus
6692 case '\\':
6693 add('\\');
6694 break;
6695 // solidus
6696 case '/':
6697 add('/');
6698 break;
6699 // backspace
6700 case 'b':
6701 add('\b');
6702 break;
6703 // form feed
6704 case 'f':
6705 add('\f');
6706 break;
6707 // line feed
6708 case 'n':
6709 add('\n');
6710 break;
6711 // carriage return
6712 case 'r':
6713 add('\r');
6714 break;
6715 // tab
6716 case 't':
6717 add('\t');
6718 break;
6719
6720 // unicode escapes
6721 case 'u':
6722 {
6723 const int codepoint1 = get_codepoint();
6724 int codepoint = codepoint1; // start with codepoint1
6725
6726 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
6727 {
6728 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
6729 return token_type::parse_error;
6730 }
6731
6732 // check if code point is a high surrogate
6733 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
6734 {
6735 // expect next \uxxxx entry
6736 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
6737 {
6738 const int codepoint2 = get_codepoint();
6739
6740 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
6741 {
6742 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
6743 return token_type::parse_error;
6744 }
6745
6746 // check if codepoint2 is a low surrogate
6747 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
6748 {
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
6758 - 0x35FDC00u);
6759 }
6760 else
6761 {
6762 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
6763 return token_type::parse_error;
6764 }
6765 }
6766 else
6767 {
6768 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
6769 return token_type::parse_error;
6770 }
6771 }
6772 else
6773 {
6774 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
6775 {
6776 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
6777 return token_type::parse_error;
6778 }
6779 }
6780
6781 // result of the above calculation yields a proper codepoint
6782 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
6783
6784 // translate codepoint into bytes
6785 if (codepoint < 0x80)
6786 {
6787 // 1-byte characters: 0xxxxxxx (ASCII)
6788 add(static_cast<char_int_type>(codepoint));
6789 }
6790 else if (codepoint <= 0x7FF)
6791 {
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)));
6795 }
6796 else if (codepoint <= 0xFFFF)
6797 {
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)));
6802 }
6803 else
6804 {
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)));
6810 }
6811
6812 break;
6813 }
6814
6815 // other characters after escape
6816 default:
6817 error_message = "invalid string: forbidden character after backslash";
6818 return token_type::parse_error;
6819 }
6820
6821 break;
6822 }
6823
6824 // invalid control characters
6825 case 0x00:
6826 {
6827 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
6828 return token_type::parse_error;
6829 }
6830
6831 case 0x01:
6832 {
6833 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
6834 return token_type::parse_error;
6835 }
6836
6837 case 0x02:
6838 {
6839 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
6840 return token_type::parse_error;
6841 }
6842
6843 case 0x03:
6844 {
6845 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
6846 return token_type::parse_error;
6847 }
6848
6849 case 0x04:
6850 {
6851 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
6852 return token_type::parse_error;
6853 }
6854
6855 case 0x05:
6856 {
6857 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
6858 return token_type::parse_error;
6859 }
6860
6861 case 0x06:
6862 {
6863 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
6864 return token_type::parse_error;
6865 }
6866
6867 case 0x07:
6868 {
6869 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
6870 return token_type::parse_error;
6871 }
6872
6873 case 0x08:
6874 {
6875 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
6876 return token_type::parse_error;
6877 }
6878
6879 case 0x09:
6880 {
6881 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
6882 return token_type::parse_error;
6883 }
6884
6885 case 0x0A:
6886 {
6887 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
6888 return token_type::parse_error;
6889 }
6890
6891 case 0x0B:
6892 {
6893 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
6894 return token_type::parse_error;
6895 }
6896
6897 case 0x0C:
6898 {
6899 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
6900 return token_type::parse_error;
6901 }
6902
6903 case 0x0D:
6904 {
6905 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
6906 return token_type::parse_error;
6907 }
6908
6909 case 0x0E:
6910 {
6911 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
6912 return token_type::parse_error;
6913 }
6914
6915 case 0x0F:
6916 {
6917 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
6918 return token_type::parse_error;
6919 }
6920
6921 case 0x10:
6922 {
6923 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
6924 return token_type::parse_error;
6925 }
6926
6927 case 0x11:
6928 {
6929 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
6930 return token_type::parse_error;
6931 }
6932
6933 case 0x12:
6934 {
6935 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
6936 return token_type::parse_error;
6937 }
6938
6939 case 0x13:
6940 {
6941 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
6942 return token_type::parse_error;
6943 }
6944
6945 case 0x14:
6946 {
6947 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
6948 return token_type::parse_error;
6949 }
6950
6951 case 0x15:
6952 {
6953 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
6954 return token_type::parse_error;
6955 }
6956
6957 case 0x16:
6958 {
6959 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
6960 return token_type::parse_error;
6961 }
6962
6963 case 0x17:
6964 {
6965 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
6966 return token_type::parse_error;
6967 }
6968
6969 case 0x18:
6970 {
6971 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
6972 return token_type::parse_error;
6973 }
6974
6975 case 0x19:
6976 {
6977 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
6978 return token_type::parse_error;
6979 }
6980
6981 case 0x1A:
6982 {
6983 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
6984 return token_type::parse_error;
6985 }
6986
6987 case 0x1B:
6988 {
6989 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
6990 return token_type::parse_error;
6991 }
6992
6993 case 0x1C:
6994 {
6995 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
6996 return token_type::parse_error;
6997 }
6998
6999 case 0x1D:
7000 {
7001 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7002 return token_type::parse_error;
7003 }
7004
7005 case 0x1E:
7006 {
7007 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7008 return token_type::parse_error;
7009 }
7010
7011 case 0x1F:
7012 {
7013 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7014 return token_type::parse_error;
7015 }
7016
7017 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7018 case 0x20:
7019 case 0x21:
7020 case 0x23:
7021 case 0x24:
7022 case 0x25:
7023 case 0x26:
7024 case 0x27:
7025 case 0x28:
7026 case 0x29:
7027 case 0x2A:
7028 case 0x2B:
7029 case 0x2C:
7030 case 0x2D:
7031 case 0x2E:
7032 case 0x2F:
7033 case 0x30:
7034 case 0x31:
7035 case 0x32:
7036 case 0x33:
7037 case 0x34:
7038 case 0x35:
7039 case 0x36:
7040 case 0x37:
7041 case 0x38:
7042 case 0x39:
7043 case 0x3A:
7044 case 0x3B:
7045 case 0x3C:
7046 case 0x3D:
7047 case 0x3E:
7048 case 0x3F:
7049 case 0x40:
7050 case 0x41:
7051 case 0x42:
7052 case 0x43:
7053 case 0x44:
7054 case 0x45:
7055 case 0x46:
7056 case 0x47:
7057 case 0x48:
7058 case 0x49:
7059 case 0x4A:
7060 case 0x4B:
7061 case 0x4C:
7062 case 0x4D:
7063 case 0x4E:
7064 case 0x4F:
7065 case 0x50:
7066 case 0x51:
7067 case 0x52:
7068 case 0x53:
7069 case 0x54:
7070 case 0x55:
7071 case 0x56:
7072 case 0x57:
7073 case 0x58:
7074 case 0x59:
7075 case 0x5A:
7076 case 0x5B:
7077 case 0x5D:
7078 case 0x5E:
7079 case 0x5F:
7080 case 0x60:
7081 case 0x61:
7082 case 0x62:
7083 case 0x63:
7084 case 0x64:
7085 case 0x65:
7086 case 0x66:
7087 case 0x67:
7088 case 0x68:
7089 case 0x69:
7090 case 0x6A:
7091 case 0x6B:
7092 case 0x6C:
7093 case 0x6D:
7094 case 0x6E:
7095 case 0x6F:
7096 case 0x70:
7097 case 0x71:
7098 case 0x72:
7099 case 0x73:
7100 case 0x74:
7101 case 0x75:
7102 case 0x76:
7103 case 0x77:
7104 case 0x78:
7105 case 0x79:
7106 case 0x7A:
7107 case 0x7B:
7108 case 0x7C:
7109 case 0x7D:
7110 case 0x7E:
7111 case 0x7F:
7112 {
7113 add(current);
7114 break;
7115 }
7116
7117 // U+0080..U+07FF: bytes C2..DF 80..BF
7118 case 0xC2:
7119 case 0xC3:
7120 case 0xC4:
7121 case 0xC5:
7122 case 0xC6:
7123 case 0xC7:
7124 case 0xC8:
7125 case 0xC9:
7126 case 0xCA:
7127 case 0xCB:
7128 case 0xCC:
7129 case 0xCD:
7130 case 0xCE:
7131 case 0xCF:
7132 case 0xD0:
7133 case 0xD1:
7134 case 0xD2:
7135 case 0xD3:
7136 case 0xD4:
7137 case 0xD5:
7138 case 0xD6:
7139 case 0xD7:
7140 case 0xD8:
7141 case 0xD9:
7142 case 0xDA:
7143 case 0xDB:
7144 case 0xDC:
7145 case 0xDD:
7146 case 0xDE:
7147 case 0xDF:
7148 {
7149 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
7150 {
7151 return token_type::parse_error;
7152 }
7153 break;
7154 }
7155
7156 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7157 case 0xE0:
7158 {
7159 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7160 {
7161 return token_type::parse_error;
7162 }
7163 break;
7164 }
7165
7166 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7167 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7168 case 0xE1:
7169 case 0xE2:
7170 case 0xE3:
7171 case 0xE4:
7172 case 0xE5:
7173 case 0xE6:
7174 case 0xE7:
7175 case 0xE8:
7176 case 0xE9:
7177 case 0xEA:
7178 case 0xEB:
7179 case 0xEC:
7180 case 0xEE:
7181 case 0xEF:
7182 {
7183 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7184 {
7185 return token_type::parse_error;
7186 }
7187 break;
7188 }
7189
7190 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7191 case 0xED:
7192 {
7193 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7194 {
7195 return token_type::parse_error;
7196 }
7197 break;
7198 }
7199
7200 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7201 case 0xF0:
7202 {
7203 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7204 {
7205 return token_type::parse_error;
7206 }
7207 break;
7208 }
7209
7210 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7211 case 0xF1:
7212 case 0xF2:
7213 case 0xF3:
7214 {
7215 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7216 {
7217 return token_type::parse_error;
7218 }
7219 break;
7220 }
7221
7222 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7223 case 0xF4:
7224 {
7225 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
7226 {
7227 return token_type::parse_error;
7228 }
7229 break;
7230 }
7231
7232 // remaining bytes (80..C1 and F5..FF) are ill-formed
7233 default:
7234 {
7235 error_message = "invalid string: ill-formed UTF-8 byte";
7236 return token_type::parse_error;
7237 }
7238 }
7239 }
7240 }
7241
7242 /*!
7243 * @brief scan a comment
7244 * @return whether comment could be scanned successfully
7245 */
7246 bool scan_comment()
7247 {
7248 switch (get())
7249 {
7250 // single-line comments skip input until a newline or EOF is read
7251 case '/':
7252 {
7253 while (true)
7254 {
7255 switch (get())
7256 {
7257 case '\n':
7258 case '\r':
7259 case std::char_traits<char_type>::eof():
7260 case '\0':
7261 return true;
7262
7263 default:
7264 break;
7265 }
7266 }
7267 }
7268
7269 // multi-line comments skip input until */ is read
7270 case '*':
7271 {
7272 while (true)
7273 {
7274 switch (get())
7275 {
7276 case std::char_traits<char_type>::eof():
7277 case '\0':
7278 {
7279 error_message = "invalid comment; missing closing '*/'";
7280 return false;
7281 }
7282
7283 case '*':
7284 {
7285 switch (get())
7286 {
7287 case '/':
7288 return true;
7289
7290 default:
7291 {
7292 unget();
7293 continue;
7294 }
7295 }
7296 }
7297
7298 default:
7299 continue;
7300 }
7301 }
7302 }
7303
7304 // unexpected character after reading '/'
7305 default:
7306 {
7307 error_message = "invalid comment; expecting '/' or '*' after '/'";
7308 return false;
7309 }
7310 }
7311 }
7312
7313 JSON_HEDLEY_NON_NULL(2)
7314 static void strtof(float& f, const char* str, char** endptr) noexcept
7315 {
7316 f = std::strtof(str, endptr);
7317 }
7318
7319 JSON_HEDLEY_NON_NULL(2)
7320 static void strtof(double& f, const char* str, char** endptr) noexcept
7321 {
7322 f = std::strtod(str, endptr);
7323 }
7324
7325 JSON_HEDLEY_NON_NULL(2)
7326 static void strtof(long double& f, const char* str, char** endptr) noexcept
7327 {
7328 f = std::strtold(str, endptr);
7329 }
7330
7331 /*!
7332 @brief scan a number literal
7333
7334 This function scans a string according to Sect. 6 of RFC 8259.
7335
7336 The function is realized with a deterministic finite state machine derived
7337 from the grammar described in RFC 8259. Starting in state "init", the
7338 input is read and used to determined the next state. Only state "done"
7339 accepts the number. State "error" is a trap state to model errors. In the
7340 table below, "anything" means any character but the ones listed before.
7341
7342 state | 0 | 1-9 | e E | + | - | . | anything
7343 ---------|----------|----------|----------|---------|---------|----------|-----------
7344 init | zero | any1 | [error] | [error] | minus | [error] | [error]
7345 minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
7346 zero | done | done | exponent | done | done | decimal1 | done
7347 any1 | any1 | any1 | exponent | done | done | decimal1 | done
7348 decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error]
7349 decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
7350 exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
7351 sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
7352 any2 | any2 | any2 | done | done | done | done | done
7353
7354 The state machine is realized with one label per state (prefixed with
7355 "scan_number_") and `goto` statements between them. The state machine
7356 contains cycles, but any cycle can be left when EOF is read. Therefore,
7357 the function is guaranteed to terminate.
7358
7359 During scanning, the read bytes are stored in token_buffer. This string is
7360 then converted to a signed integer, an unsigned integer, or a
7361 floating-point number.
7362
7363 @return token_type::value_unsigned, token_type::value_integer, or
7364 token_type::value_float if number could be successfully scanned,
7365 token_type::parse_error otherwise
7366
7367 @note The scanner is independent of the current locale. Internally, the
7368 locale's decimal point is used instead of `.` to work with the
7369 locale-dependent converters.
7370 */
7371 token_type scan_number() // lgtm [cpp/use-of-goto]
7372 {
7373 // reset token_buffer to store the number's bytes
7374 reset();
7375
7376 // the type of the parsed number; initially set to unsigned; will be
7377 // changed if minus sign, decimal point or exponent is read
7378 token_type number_type = token_type::value_unsigned;
7379
7380 // state (init): we just found out we need to scan a number
7381 switch (current)
7382 {
7383 case '-':
7384 {
7385 add(current);
7386 goto scan_number_minus;
7387 }
7388
7389 case '0':
7390 {
7391 add(current);
7392 goto scan_number_zero;
7393 }
7394
7395 case '1':
7396 case '2':
7397 case '3':
7398 case '4':
7399 case '5':
7400 case '6':
7401 case '7':
7402 case '8':
7403 case '9':
7404 {
7405 add(current);
7406 goto scan_number_any1;
7407 }
7408
7409 // all other characters are rejected outside scan_number()
7410 default: // LCOV_EXCL_LINE
7411 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
7412 }
7413
7414 scan_number_minus:
7415 // state: we just parsed a leading minus sign
7416 number_type = token_type::value_integer;
7417 switch (get())
7418 {
7419 case '0':
7420 {
7421 add(current);
7422 goto scan_number_zero;
7423 }
7424
7425 case '1':
7426 case '2':
7427 case '3':
7428 case '4':
7429 case '5':
7430 case '6':
7431 case '7':
7432 case '8':
7433 case '9':
7434 {
7435 add(current);
7436 goto scan_number_any1;
7437 }
7438
7439 default:
7440 {
7441 error_message = "invalid number; expected digit after '-'";
7442 return token_type::parse_error;
7443 }
7444 }
7445
7446 scan_number_zero:
7447 // state: we just parse a zero (maybe with a leading minus sign)
7448 switch (get())
7449 {
7450 case '.':
7451 {
7452 add(decimal_point_char);
7453 goto scan_number_decimal1;
7454 }
7455
7456 case 'e':
7457 case 'E':
7458 {
7459 add(current);
7460 goto scan_number_exponent;
7461 }
7462
7463 default:
7464 goto scan_number_done;
7465 }
7466
7467 scan_number_any1:
7468 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
7469 switch (get())
7470 {
7471 case '0':
7472 case '1':
7473 case '2':
7474 case '3':
7475 case '4':
7476 case '5':
7477 case '6':
7478 case '7':
7479 case '8':
7480 case '9':
7481 {
7482 add(current);
7483 goto scan_number_any1;
7484 }
7485
7486 case '.':
7487 {
7488 add(decimal_point_char);
7489 goto scan_number_decimal1;
7490 }
7491
7492 case 'e':
7493 case 'E':
7494 {
7495 add(current);
7496 goto scan_number_exponent;
7497 }
7498
7499 default:
7500 goto scan_number_done;
7501 }
7502
7503 scan_number_decimal1:
7504 // state: we just parsed a decimal point
7505 number_type = token_type::value_float;
7506 switch (get())
7507 {
7508 case '0':
7509 case '1':
7510 case '2':
7511 case '3':
7512 case '4':
7513 case '5':
7514 case '6':
7515 case '7':
7516 case '8':
7517 case '9':
7518 {
7519 add(current);
7520 goto scan_number_decimal2;
7521 }
7522
7523 default:
7524 {
7525 error_message = "invalid number; expected digit after '.'";
7526 return token_type::parse_error;
7527 }
7528 }
7529
7530 scan_number_decimal2:
7531 // we just parsed at least one number after a decimal point
7532 switch (get())
7533 {
7534 case '0':
7535 case '1':
7536 case '2':
7537 case '3':
7538 case '4':
7539 case '5':
7540 case '6':
7541 case '7':
7542 case '8':
7543 case '9':
7544 {
7545 add(current);
7546 goto scan_number_decimal2;
7547 }
7548
7549 case 'e':
7550 case 'E':
7551 {
7552 add(current);
7553 goto scan_number_exponent;
7554 }
7555
7556 default:
7557 goto scan_number_done;
7558 }
7559
7560 scan_number_exponent:
7561 // we just parsed an exponent
7562 number_type = token_type::value_float;
7563 switch (get())
7564 {
7565 case '+':
7566 case '-':
7567 {
7568 add(current);
7569 goto scan_number_sign;
7570 }
7571
7572 case '0':
7573 case '1':
7574 case '2':
7575 case '3':
7576 case '4':
7577 case '5':
7578 case '6':
7579 case '7':
7580 case '8':
7581 case '9':
7582 {
7583 add(current);
7584 goto scan_number_any2;
7585 }
7586
7587 default:
7588 {
7589 error_message =
7590 "invalid number; expected '+', '-', or digit after exponent";
7591 return token_type::parse_error;
7592 }
7593 }
7594
7595 scan_number_sign:
7596 // we just parsed an exponent sign
7597 switch (get())
7598 {
7599 case '0':
7600 case '1':
7601 case '2':
7602 case '3':
7603 case '4':
7604 case '5':
7605 case '6':
7606 case '7':
7607 case '8':
7608 case '9':
7609 {
7610 add(current);
7611 goto scan_number_any2;
7612 }
7613
7614 default:
7615 {
7616 error_message = "invalid number; expected digit after exponent sign";
7617 return token_type::parse_error;
7618 }
7619 }
7620
7621 scan_number_any2:
7622 // we just parsed a number after the exponent or exponent sign
7623 switch (get())
7624 {
7625 case '0':
7626 case '1':
7627 case '2':
7628 case '3':
7629 case '4':
7630 case '5':
7631 case '6':
7632 case '7':
7633 case '8':
7634 case '9':
7635 {
7636 add(current);
7637 goto scan_number_any2;
7638 }
7639
7640 default:
7641 goto scan_number_done;
7642 }
7643
7644 scan_number_done:
7645 // unget the character after the number (we only read it to know that
7646 // we are done scanning a number)
7647 unget();
7648
7649 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
7650 errno = 0;
7651
7652 // try to parse integers first and fall back to floats
7653 if (number_type == token_type::value_unsigned)
7654 {
7655 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
7656
7657 // we checked the number format before
7658 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7659
7660 if (errno == 0)
7661 {
7662 value_unsigned = static_cast<number_unsigned_t>(x);
7663 if (value_unsigned == x)
7664 {
7665 return token_type::value_unsigned;
7666 }
7667 }
7668 }
7669 else if (number_type == token_type::value_integer)
7670 {
7671 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
7672
7673 // we checked the number format before
7674 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7675
7676 if (errno == 0)
7677 {
7678 value_integer = static_cast<number_integer_t>(x);
7679 if (value_integer == x)
7680 {
7681 return token_type::value_integer;
7682 }
7683 }
7684 }
7685
7686 // this code is reached if we parse a floating-point number or if an
7687 // integer conversion above failed
7688 strtof(value_float, token_buffer.data(), &endptr);
7689
7690 // we checked the number format before
7691 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7692
7693 return token_type::value_float;
7694 }
7695
7696 /*!
7697 @param[in] literal_text the literal text to expect
7698 @param[in] length the length of the passed literal text
7699 @param[in] return_type the token type to return on success
7700 */
7701 JSON_HEDLEY_NON_NULL(2)
7702 token_type scan_literal(const char_type* literal_text, const std::size_t length,
7703 token_type return_type)
7704 {
7705 JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
7706 for (std::size_t i = 1; i < length; ++i)
7707 {
7708 if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
7709 {
7710 error_message = "invalid literal";
7711 return token_type::parse_error;
7712 }
7713 }
7714 return return_type;
7715 }
7716
7717 /////////////////////
7718 // input management
7719 /////////////////////
7720
7721 /// reset token_buffer; current character is beginning of token
7722 void reset() noexcept
7723 {
7724 token_buffer.clear();
7725 token_string.clear();
7726 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
7727 }
7728
7729 /*
7730 @brief get next character from the input
7731
7732 This function provides the interface to the used input adapter. It does
7733 not throw in case the input reached EOF, but returns a
7734 `std::char_traits<char>::eof()` in that case. Stores the scanned characters
7735 for use in error messages.
7736
7737 @return character read from the input
7738 */
7739 char_int_type get()
7740 {
7741 ++position.chars_read_total;
7742 ++position.chars_read_current_line;
7743
7744 if (next_unget)
7745 {
7746 // just reset the next_unget variable and work with current
7747 next_unget = false;
7748 }
7749 else
7750 {
7751 current = ia.get_character();
7752 }
7753
7754 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
7755 {
7756 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
7757 }
7758
7759 if (current == '\n')
7760 {
7761 ++position.lines_read;
7762 position.chars_read_current_line = 0;
7763 }
7764
7765 return current;
7766 }
7767
7768 /*!
7769 @brief unget current character (read it again on next get)
7770
7771 We implement unget by setting variable next_unget to true. The input is not
7772 changed - we just simulate ungetting by modifying chars_read_total,
7773 chars_read_current_line, and token_string. The next call to get() will
7774 behave as if the unget character is read again.
7775 */
7776 void unget()
7777 {
7778 next_unget = true;
7779
7780 --position.chars_read_total;
7781
7782 // in case we "unget" a newline, we have to also decrement the lines_read
7783 if (position.chars_read_current_line == 0)
7784 {
7785 if (position.lines_read > 0)
7786 {
7787 --position.lines_read;
7788 }
7789 }
7790 else
7791 {
7792 --position.chars_read_current_line;
7793 }
7794
7795 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
7796 {
7797 JSON_ASSERT(!token_string.empty());
7798 token_string.pop_back();
7799 }
7800 }
7801
7802 /// add a character to token_buffer
7803 void add(char_int_type c)
7804 {
7805 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
7806 }
7807
7808 public:
7809 /////////////////////
7810 // value getters
7811 /////////////////////
7812
7813 /// return integer value
7814 constexpr number_integer_t get_number_integer() const noexcept
7815 {
7816 return value_integer;
7817 }
7818
7819 /// return unsigned integer value
7820 constexpr number_unsigned_t get_number_unsigned() const noexcept
7821 {
7822 return value_unsigned;
7823 }
7824
7825 /// return floating-point value
7826 constexpr number_float_t get_number_float() const noexcept
7827 {
7828 return value_float;
7829 }
7830
7831 /// return current string value (implicitly resets the token; useful only once)
7832 string_t& get_string()
7833 {
7834 return token_buffer;
7835 }
7836
7837 /////////////////////
7838 // diagnostics
7839 /////////////////////
7840
7841 /// return position of last read token
7842 constexpr position_t get_position() const noexcept
7843 {
7844 return position;
7845 }
7846
7847 /// return the last read token (for errors only). Will never contain EOF
7848 /// (an arbitrary value that is not a valid char value, often -1), because
7849 /// 255 may legitimately occur. May contain NUL, which should be escaped.
7850 std::string get_token_string() const
7851 {
7852 // escape control characters
7853 std::string result;
7854 for (const auto c : token_string)
7855 {
7856 if (static_cast<unsigned char>(c) <= '\x1F')
7857 {
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();
7862 }
7863 else
7864 {
7865 // add character as is
7866 result.push_back(static_cast<std::string::value_type>(c));
7867 }
7868 }
7869
7870 return result;
7871 }
7872
7873 /// return syntax error message
7874 JSON_HEDLEY_RETURNS_NON_NULL
7875 constexpr const char* get_error_message() const noexcept
7876 {
7877 return error_message;
7878 }
7879
7880 /////////////////////
7881 // actual scanner
7882 /////////////////////
7883
7884 /*!
7885 @brief skip the UTF-8 byte order mark
7886 @return true iff there is no BOM or the correct BOM has been skipped
7887 */
7888 bool skip_bom()
7889 {
7890 if (get() == 0xEF)
7891 {
7892 // check if we completely parse the BOM
7893 return get() == 0xBB && get() == 0xBF;
7894 }
7895
7896 // the first character is not the beginning of the BOM; unget it to
7897 // process is later
7898 unget();
7899 return true;
7900 }
7901
7902 void skip_whitespace()
7903 {
7904 do
7905 {
7906 get();
7907 }
7908 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
7909 }
7910
7911 token_type scan()
7912 {
7913 // initially, skip the BOM
7914 if (position.chars_read_total == 0 && !skip_bom())
7915 {
7916 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
7917 return token_type::parse_error;
7918 }
7919
7920 // read next character and ignore whitespace
7921 skip_whitespace();
7922
7923 // ignore comments
7924 while (ignore_comments && current == '/')
7925 {
7926 if (!scan_comment())
7927 {
7928 return token_type::parse_error;
7929 }
7930
7931 // skip following whitespace
7932 skip_whitespace();
7933 }
7934
7935 switch (current)
7936 {
7937 // structural characters
7938 case '[':
7939 return token_type::begin_array;
7940 case ']':
7941 return token_type::end_array;
7942 case '{':
7943 return token_type::begin_object;
7944 case '}':
7945 return token_type::end_object;
7946 case ':':
7947 return token_type::name_separator;
7948 case ',':
7949 return token_type::value_separator;
7950
7951 // literals
7952 case 't':
7953 {
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);
7956 }
7957 case 'f':
7958 {
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);
7961 }
7962 case 'n':
7963 {
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);
7966 }
7967
7968 // string
7969 case '\"':
7970 return scan_string();
7971
7972 // number
7973 case '-':
7974 case '0':
7975 case '1':
7976 case '2':
7977 case '3':
7978 case '4':
7979 case '5':
7980 case '6':
7981 case '7':
7982 case '8':
7983 case '9':
7984 return scan_number();
7985
7986 // end of input (the null byte is needed when parsing from
7987 // string literals)
7988 case '\0':
7989 case std::char_traits<char_type>::eof():
7990 return token_type::end_of_input;
7991
7992 // error
7993 default:
7994 error_message = "invalid literal";
7995 return token_type::parse_error;
7996 }
7997 }
7998
7999 private:
8000 /// input adapter
8001 InputAdapterType ia;
8002
8003 /// whether comments should be ignored (true) or signaled as errors (false)
8004 const bool ignore_comments = false;
8005
8006 /// the current character
8007 char_int_type current = std::char_traits<char_type>::eof();
8008
8009 /// whether the next get() call should just return current
8010 bool next_unget = false;
8011
8012 /// the start position of the current token
8013 position_t position {};
8014
8015 /// raw input token string (for error messages)
8016 std::vector<char_type> token_string {};
8017
8018 /// buffer for variable-length tokens (numbers, strings)
8019 string_t token_buffer {};
8020
8021 /// a description of occurred lexer errors
8022 const char* error_message = "";
8023
8024 // number values
8025 number_integer_t value_integer = 0;
8026 number_unsigned_t value_unsigned = 0;
8027 number_float_t value_float = 0;
8028
8029 /// the decimal point
8030 const char_int_type decimal_point_char = '.';
8031 };
8032 } // namespace detail
8033 } // namespace nlohmann
8034
8035 // #include <nlohmann/detail/macro_scope.hpp>
8036
8037 // #include <nlohmann/detail/meta/is_sax.hpp>
8038
8039
8040 #include <cstdint> // size_t
8041 #include <utility> // declval
8042 #include <string> // string
8043
8044 // #include <nlohmann/detail/meta/detected.hpp>
8045
8046 // #include <nlohmann/detail/meta/type_traits.hpp>
8047
8048
8049 namespace nlohmann
8050 {
8051 namespace detail
8052 {
8053 template<typename T>
8054 using null_function_t = decltype(std::declval<T&>().null());
8055
8056 template<typename T>
8057 using boolean_function_t =
8058 decltype(std::declval<T&>().boolean(std::declval<bool>()));
8059
8060 template<typename T, typename Integer>
8061 using number_integer_function_t =
8062 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
8063
8064 template<typename T, typename Unsigned>
8065 using number_unsigned_function_t =
8066 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
8067
8068 template<typename T, typename Float, typename String>
8069 using number_float_function_t = decltype(std::declval<T&>().number_float(
8070 std::declval<Float>(), std::declval<const String&>()));
8071
8072 template<typename T, typename String>
8073 using string_function_t =
8074 decltype(std::declval<T&>().string(std::declval<String&>()));
8075
8076 template<typename T, typename Binary>
8077 using binary_function_t =
8078 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
8079
8080 template<typename T>
8081 using start_object_function_t =
8082 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
8083
8084 template<typename T, typename String>
8085 using key_function_t =
8086 decltype(std::declval<T&>().key(std::declval<String&>()));
8087
8088 template<typename T>
8089 using end_object_function_t = decltype(std::declval<T&>().end_object());
8090
8091 template<typename T>
8092 using start_array_function_t =
8093 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
8094
8095 template<typename T>
8096 using end_array_function_t = decltype(std::declval<T&>().end_array());
8097
8098 template<typename T, typename Exception>
8099 using parse_error_function_t = decltype(std::declval<T&>().parse_error(
8100 std::declval<std::size_t>(), std::declval<const std::string&>(),
8101 std::declval<const Exception&>()));
8102
8103 template<typename SAX, typename BasicJsonType>
8104 struct is_sax
8105 {
8106 private:
8107 static_assert(is_basic_json<BasicJsonType>::value,
8108 "BasicJsonType must be of type basic_json<...>");
8109
8110 using number_integer_t = typename BasicJsonType::number_integer_t;
8111 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8112 using number_float_t = typename BasicJsonType::number_float_t;
8113 using string_t = typename BasicJsonType::string_t;
8114 using binary_t = typename BasicJsonType::binary_t;
8115 using exception_t = typename BasicJsonType::exception;
8116
8117 public:
8118 static constexpr bool value =
8119 is_detected_exact<bool, null_function_t, SAX>::value &&
8120 is_detected_exact<bool, boolean_function_t, SAX>::value &&
8121 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
8122 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
8123 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
8124 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
8125 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
8126 is_detected_exact<bool, start_object_function_t, SAX>::value &&
8127 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
8128 is_detected_exact<bool, end_object_function_t, SAX>::value &&
8129 is_detected_exact<bool, start_array_function_t, SAX>::value &&
8130 is_detected_exact<bool, end_array_function_t, SAX>::value &&
8131 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
8132 };
8133
8134 template<typename SAX, typename BasicJsonType>
8135 struct is_sax_static_asserts
8136 {
8137 private:
8138 static_assert(is_basic_json<BasicJsonType>::value,
8139 "BasicJsonType must be of type basic_json<...>");
8140
8141 using number_integer_t = typename BasicJsonType::number_integer_t;
8142 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8143 using number_float_t = typename BasicJsonType::number_float_t;
8144 using string_t = typename BasicJsonType::string_t;
8145 using binary_t = typename BasicJsonType::binary_t;
8146 using exception_t = typename BasicJsonType::exception;
8147
8148 public:
8149 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
8150 "Missing/invalid function: bool null()");
8151 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
8152 "Missing/invalid function: bool boolean(bool)");
8153 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
8154 "Missing/invalid function: bool boolean(bool)");
8155 static_assert(
8156 is_detected_exact<bool, number_integer_function_t, SAX,
8157 number_integer_t>::value,
8158 "Missing/invalid function: bool number_integer(number_integer_t)");
8159 static_assert(
8160 is_detected_exact<bool, number_unsigned_function_t, SAX,
8161 number_unsigned_t>::value,
8162 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
8163 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
8164 number_float_t, string_t>::value,
8165 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
8166 static_assert(
8167 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
8168 "Missing/invalid function: bool string(string_t&)");
8169 static_assert(
8170 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
8171 "Missing/invalid function: bool binary(binary_t&)");
8172 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
8173 "Missing/invalid function: bool start_object(std::size_t)");
8174 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
8175 "Missing/invalid function: bool key(string_t&)");
8176 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
8177 "Missing/invalid function: bool end_object()");
8178 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
8179 "Missing/invalid function: bool start_array(std::size_t)");
8180 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
8181 "Missing/invalid function: bool end_array()");
8182 static_assert(
8183 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
8184 "Missing/invalid function: bool parse_error(std::size_t, const "
8185 "std::string&, const exception&)");
8186 };
8187 } // namespace detail
8188 } // namespace nlohmann
8189
8190 // #include <nlohmann/detail/meta/type_traits.hpp>
8191
8192 // #include <nlohmann/detail/value_t.hpp>
8193
8194
8195 namespace nlohmann
8196 {
8197 namespace detail
8198 {
8199
8200 /// how to treat CBOR tags
8201 enum class cbor_tag_handler_t
8202 {
8203 error, ///< throw a parse_error exception in case of a tag
8204 ignore, ///< ignore tags
8205 store ///< store tags as binary type
8206 };
8207
8208 /*!
8209 @brief determine system byte order
8210
8211 @return true if and only if system's byte order is little endian
8212
8213 @note from https://stackoverflow.com/a/1001328/266378
8214 */
8215 static inline bool little_endianness(int num = 1) noexcept
8216 {
8217 return *reinterpret_cast<char*>(&num) == 1;
8218 }
8219
8220
8221 ///////////////////
8222 // binary reader //
8223 ///////////////////
8224
8225 /*!
8226 @brief deserialization of CBOR, MessagePack, and UBJSON values
8227 */
8228 template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
8229 class binary_reader
8230 {
8231 using number_integer_t = typename BasicJsonType::number_integer_t;
8232 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8233 using number_float_t = typename BasicJsonType::number_float_t;
8234 using string_t = typename BasicJsonType::string_t;
8235 using binary_t = typename BasicJsonType::binary_t;
8236 using json_sax_t = SAX;
8237 using char_type = typename InputAdapterType::char_type;
8238 using char_int_type = typename std::char_traits<char_type>::int_type;
8239
8240 public:
8241 /*!
8242 @brief create a binary reader
8243
8244 @param[in] adapter input adapter to read from
8245 */
8246 explicit binary_reader(InputAdapterType&& adapter) noexcept : ia(std::move(adapter))
8247 {
8248 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
8249 }
8250
8251 // make class move-only
8252 binary_reader(const binary_reader&) = delete;
8253 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8254 binary_reader& operator=(const binary_reader&) = delete;
8255 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8256 ~binary_reader() = default;
8257
8258 /*!
8259 @param[in] format the binary format to parse
8260 @param[in] sax_ a SAX event processor
8261 @param[in] strict whether to expect the input to be consumed completed
8262 @param[in] tag_handler how to treat CBOR tags
8263
8264 @return whether parsing was successful
8265 */
8266 JSON_HEDLEY_NON_NULL(3)
8267 bool sax_parse(const input_format_t format,
8268 json_sax_t* sax_,
8269 const bool strict = true,
8270 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
8271 {
8272 sax = sax_;
8273 bool result = false;
8274
8275 switch (format)
8276 {
8277 case input_format_t::bson:
8278 result = parse_bson_internal();
8279 break;
8280
8281 case input_format_t::cbor:
8282 result = parse_cbor_internal(true, tag_handler);
8283 break;
8284
8285 case input_format_t::msgpack:
8286 result = parse_msgpack_internal();
8287 break;
8288
8289 case input_format_t::ubjson:
8290 result = parse_ubjson_internal();
8291 break;
8292
8293 case input_format_t::json: // LCOV_EXCL_LINE
8294 default: // LCOV_EXCL_LINE
8295 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8296 }
8297
8298 // strict mode: next byte must be EOF
8299 if (result && strict)
8300 {
8301 if (format == input_format_t::ubjson)
8302 {
8303 get_ignore_noop();
8304 }
8305 else
8306 {
8307 get();
8308 }
8309
8310 if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
8311 {
8312 return sax->parse_error(chars_read, get_token_string(),
8313 parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"), BasicJsonType()));
8314 }
8315 }
8316
8317 return result;
8318 }
8319
8320 private:
8321 //////////
8322 // BSON //
8323 //////////
8324
8325 /*!
8326 @brief Reads in a BSON-object and passes it to the SAX-parser.
8327 @return whether a valid BSON-value was passed to the SAX parser
8328 */
8329 bool parse_bson_internal()
8330 {
8331 std::int32_t document_size{};
8332 get_number<std::int32_t, true>(input_format_t::bson, document_size);
8333
8334 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
8335 {
8336 return false;
8337 }
8338
8339 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
8340 {
8341 return false;
8342 }
8343
8344 return sax->end_object();
8345 }
8346
8347 /*!
8348 @brief Parses a C-style string from the BSON input.
8349 @param[in,out] result A reference to the string variable where the read
8350 string is to be stored.
8351 @return `true` if the \x00-byte indicating the end of the string was
8352 encountered before the EOF; false` indicates an unexpected EOF.
8353 */
8354 bool get_bson_cstr(string_t& result)
8355 {
8356 auto out = std::back_inserter(result);
8357 while (true)
8358 {
8359 get();
8360 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
8361 {
8362 return false;
8363 }
8364 if (current == 0x00)
8365 {
8366 return true;
8367 }
8368 *out++ = static_cast<typename string_t::value_type>(current);
8369 }
8370 }
8371
8372 /*!
8373 @brief Parses a zero-terminated string of length @a len from the BSON
8374 input.
8375 @param[in] len The length (including the zero-byte at the end) of the
8376 string to be read.
8377 @param[in,out] result A reference to the string variable where the read
8378 string is to be stored.
8379 @tparam NumberType The type of the length @a len
8380 @pre len >= 1
8381 @return `true` if the string was successfully parsed
8382 */
8383 template<typename NumberType>
8384 bool get_bson_string(const NumberType len, string_t& result)
8385 {
8386 if (JSON_HEDLEY_UNLIKELY(len < 1))
8387 {
8388 auto last_token = get_token_string();
8389 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"), BasicJsonType()));
8390 }
8391
8392 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
8393 }
8394
8395 /*!
8396 @brief Parses a byte array input of length @a len from the BSON input.
8397 @param[in] len The length of the byte array to be read.
8398 @param[in,out] result A reference to the binary variable where the read
8399 array is to be stored.
8400 @tparam NumberType The type of the length @a len
8401 @pre len >= 0
8402 @return `true` if the byte array was successfully parsed
8403 */
8404 template<typename NumberType>
8405 bool get_bson_binary(const NumberType len, binary_t& result)
8406 {
8407 if (JSON_HEDLEY_UNLIKELY(len < 0))
8408 {
8409 auto last_token = get_token_string();
8410 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"), BasicJsonType()));
8411 }
8412
8413 // All BSON binary values have a subtype
8414 std::uint8_t subtype{};
8415 get_number<std::uint8_t>(input_format_t::bson, subtype);
8416 result.set_subtype(subtype);
8417
8418 return get_binary(input_format_t::bson, len, result);
8419 }
8420
8421 /*!
8422 @brief Read a BSON document element of the given @a element_type.
8423 @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
8424 @param[in] element_type_parse_position The position in the input stream,
8425 where the `element_type` was read.
8426 @warning Not all BSON element types are supported yet. An unsupported
8427 @a element_type will give rise to a parse_error.114:
8428 Unsupported BSON record type 0x...
8429 @return whether a valid BSON-object/array was passed to the SAX parser
8430 */
8431 bool parse_bson_element_internal(const char_int_type element_type,
8432 const std::size_t element_type_parse_position)
8433 {
8434 switch (element_type)
8435 {
8436 case 0x01: // double
8437 {
8438 double number{};
8439 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
8440 }
8441
8442 case 0x02: // string
8443 {
8444 std::int32_t len{};
8445 string_t value;
8446 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
8447 }
8448
8449 case 0x03: // object
8450 {
8451 return parse_bson_internal();
8452 }
8453
8454 case 0x04: // array
8455 {
8456 return parse_bson_array();
8457 }
8458
8459 case 0x05: // binary
8460 {
8461 std::int32_t len{};
8462 binary_t value;
8463 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
8464 }
8465
8466 case 0x08: // boolean
8467 {
8468 return sax->boolean(get() != 0);
8469 }
8470
8471 case 0x0A: // null
8472 {
8473 return sax->null();
8474 }
8475
8476 case 0x10: // int32
8477 {
8478 std::int32_t value{};
8479 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
8480 }
8481
8482 case 0x12: // int64
8483 {
8484 std::int64_t value{};
8485 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
8486 }
8487
8488 default: // anything else not supported (yet)
8489 {
8490 std::array<char, 3> cr{{}};
8491 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8492 return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()), BasicJsonType()));
8493 }
8494 }
8495 }
8496
8497 /*!
8498 @brief Read a BSON element list (as specified in the BSON-spec)
8499
8500 The same binary layout is used for objects and arrays, hence it must be
8501 indicated with the argument @a is_array which one is expected
8502 (true --> array, false --> object).
8503
8504 @param[in] is_array Determines if the element list being read is to be
8505 treated as an object (@a is_array == false), or as an
8506 array (@a is_array == true).
8507 @return whether a valid BSON-object/array was passed to the SAX parser
8508 */
8509 bool parse_bson_element_list(const bool is_array)
8510 {
8511 string_t key;
8512
8513 while (auto element_type = get())
8514 {
8515 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
8516 {
8517 return false;
8518 }
8519
8520 const std::size_t element_type_parse_position = chars_read;
8521 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
8522 {
8523 return false;
8524 }
8525
8526 if (!is_array && !sax->key(key))
8527 {
8528 return false;
8529 }
8530
8531 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
8532 {
8533 return false;
8534 }
8535
8536 // get_bson_cstr only appends
8537 key.clear();
8538 }
8539
8540 return true;
8541 }
8542
8543 /*!
8544 @brief Reads an array from the BSON input and passes it to the SAX-parser.
8545 @return whether a valid BSON-array was passed to the SAX parser
8546 */
8547 bool parse_bson_array()
8548 {
8549 std::int32_t document_size{};
8550 get_number<std::int32_t, true>(input_format_t::bson, document_size);
8551
8552 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
8553 {
8554 return false;
8555 }
8556
8557 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
8558 {
8559 return false;
8560 }
8561
8562 return sax->end_array();
8563 }
8564
8565 //////////
8566 // CBOR //
8567 //////////
8568
8569 /*!
8570 @param[in] get_char whether a new character should be retrieved from the
8571 input (true) or whether the last read character should
8572 be considered instead (false)
8573 @param[in] tag_handler how CBOR tags should be treated
8574
8575 @return whether a valid CBOR value was passed to the SAX parser
8576 */
8577 bool parse_cbor_internal(const bool get_char,
8578 const cbor_tag_handler_t tag_handler)
8579 {
8580 switch (get_char ? get() : current)
8581 {
8582 // EOF
8583 case std::char_traits<char_type>::eof():
8584 return unexpect_eof(input_format_t::cbor, "value");
8585
8586 // Integer 0x00..0x17 (0..23)
8587 case 0x00:
8588 case 0x01:
8589 case 0x02:
8590 case 0x03:
8591 case 0x04:
8592 case 0x05:
8593 case 0x06:
8594 case 0x07:
8595 case 0x08:
8596 case 0x09:
8597 case 0x0A:
8598 case 0x0B:
8599 case 0x0C:
8600 case 0x0D:
8601 case 0x0E:
8602 case 0x0F:
8603 case 0x10:
8604 case 0x11:
8605 case 0x12:
8606 case 0x13:
8607 case 0x14:
8608 case 0x15:
8609 case 0x16:
8610 case 0x17:
8611 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
8612
8613 case 0x18: // Unsigned integer (one-byte uint8_t follows)
8614 {
8615 std::uint8_t number{};
8616 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8617 }
8618
8619 case 0x19: // Unsigned integer (two-byte uint16_t follows)
8620 {
8621 std::uint16_t number{};
8622 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8623 }
8624
8625 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
8626 {
8627 std::uint32_t number{};
8628 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8629 }
8630
8631 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
8632 {
8633 std::uint64_t number{};
8634 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8635 }
8636
8637 // Negative integer -1-0x00..-1-0x17 (-1..-24)
8638 case 0x20:
8639 case 0x21:
8640 case 0x22:
8641 case 0x23:
8642 case 0x24:
8643 case 0x25:
8644 case 0x26:
8645 case 0x27:
8646 case 0x28:
8647 case 0x29:
8648 case 0x2A:
8649 case 0x2B:
8650 case 0x2C:
8651 case 0x2D:
8652 case 0x2E:
8653 case 0x2F:
8654 case 0x30:
8655 case 0x31:
8656 case 0x32:
8657 case 0x33:
8658 case 0x34:
8659 case 0x35:
8660 case 0x36:
8661 case 0x37:
8662 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
8663
8664 case 0x38: // Negative integer (one-byte uint8_t follows)
8665 {
8666 std::uint8_t number{};
8667 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8668 }
8669
8670 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
8671 {
8672 std::uint16_t number{};
8673 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8674 }
8675
8676 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
8677 {
8678 std::uint32_t number{};
8679 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8680 }
8681
8682 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
8683 {
8684 std::uint64_t number{};
8685 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
8686 - static_cast<number_integer_t>(number));
8687 }
8688
8689 // Binary data (0x00..0x17 bytes follow)
8690 case 0x40:
8691 case 0x41:
8692 case 0x42:
8693 case 0x43:
8694 case 0x44:
8695 case 0x45:
8696 case 0x46:
8697 case 0x47:
8698 case 0x48:
8699 case 0x49:
8700 case 0x4A:
8701 case 0x4B:
8702 case 0x4C:
8703 case 0x4D:
8704 case 0x4E:
8705 case 0x4F:
8706 case 0x50:
8707 case 0x51:
8708 case 0x52:
8709 case 0x53:
8710 case 0x54:
8711 case 0x55:
8712 case 0x56:
8713 case 0x57:
8714 case 0x58: // Binary data (one-byte uint8_t for n follows)
8715 case 0x59: // Binary data (two-byte uint16_t for n follow)
8716 case 0x5A: // Binary data (four-byte uint32_t for n follow)
8717 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
8718 case 0x5F: // Binary data (indefinite length)
8719 {
8720 binary_t b;
8721 return get_cbor_binary(b) && sax->binary(b);
8722 }
8723
8724 // UTF-8 string (0x00..0x17 bytes follow)
8725 case 0x60:
8726 case 0x61:
8727 case 0x62:
8728 case 0x63:
8729 case 0x64:
8730 case 0x65:
8731 case 0x66:
8732 case 0x67:
8733 case 0x68:
8734 case 0x69:
8735 case 0x6A:
8736 case 0x6B:
8737 case 0x6C:
8738 case 0x6D:
8739 case 0x6E:
8740 case 0x6F:
8741 case 0x70:
8742 case 0x71:
8743 case 0x72:
8744 case 0x73:
8745 case 0x74:
8746 case 0x75:
8747 case 0x76:
8748 case 0x77:
8749 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
8750 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
8751 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
8752 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
8753 case 0x7F: // UTF-8 string (indefinite length)
8754 {
8755 string_t s;
8756 return get_cbor_string(s) && sax->string(s);
8757 }
8758
8759 // array (0x00..0x17 data items follow)
8760 case 0x80:
8761 case 0x81:
8762 case 0x82:
8763 case 0x83:
8764 case 0x84:
8765 case 0x85:
8766 case 0x86:
8767 case 0x87:
8768 case 0x88:
8769 case 0x89:
8770 case 0x8A:
8771 case 0x8B:
8772 case 0x8C:
8773 case 0x8D:
8774 case 0x8E:
8775 case 0x8F:
8776 case 0x90:
8777 case 0x91:
8778 case 0x92:
8779 case 0x93:
8780 case 0x94:
8781 case 0x95:
8782 case 0x96:
8783 case 0x97:
8784 return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
8785
8786 case 0x98: // array (one-byte uint8_t for n follows)
8787 {
8788 std::uint8_t len{};
8789 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8790 }
8791
8792 case 0x99: // array (two-byte uint16_t for n follow)
8793 {
8794 std::uint16_t len{};
8795 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8796 }
8797
8798 case 0x9A: // array (four-byte uint32_t for n follow)
8799 {
8800 std::uint32_t len{};
8801 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8802 }
8803
8804 case 0x9B: // array (eight-byte uint64_t for n follow)
8805 {
8806 std::uint64_t len{};
8807 return get_number(input_format_t::cbor, len) && get_cbor_array(detail::conditional_static_cast<std::size_t>(len), tag_handler);
8808 }
8809
8810 case 0x9F: // array (indefinite length)
8811 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
8812
8813 // map (0x00..0x17 pairs of data items follow)
8814 case 0xA0:
8815 case 0xA1:
8816 case 0xA2:
8817 case 0xA3:
8818 case 0xA4:
8819 case 0xA5:
8820 case 0xA6:
8821 case 0xA7:
8822 case 0xA8:
8823 case 0xA9:
8824 case 0xAA:
8825 case 0xAB:
8826 case 0xAC:
8827 case 0xAD:
8828 case 0xAE:
8829 case 0xAF:
8830 case 0xB0:
8831 case 0xB1:
8832 case 0xB2:
8833 case 0xB3:
8834 case 0xB4:
8835 case 0xB5:
8836 case 0xB6:
8837 case 0xB7:
8838 return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
8839
8840 case 0xB8: // map (one-byte uint8_t for n follows)
8841 {
8842 std::uint8_t len{};
8843 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8844 }
8845
8846 case 0xB9: // map (two-byte uint16_t for n follow)
8847 {
8848 std::uint16_t len{};
8849 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8850 }
8851
8852 case 0xBA: // map (four-byte uint32_t for n follow)
8853 {
8854 std::uint32_t len{};
8855 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8856 }
8857
8858 case 0xBB: // map (eight-byte uint64_t for n follow)
8859 {
8860 std::uint64_t len{};
8861 return get_number(input_format_t::cbor, len) && get_cbor_object(detail::conditional_static_cast<std::size_t>(len), tag_handler);
8862 }
8863
8864 case 0xBF: // map (indefinite length)
8865 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
8866
8867 case 0xC6: // tagged item
8868 case 0xC7:
8869 case 0xC8:
8870 case 0xC9:
8871 case 0xCA:
8872 case 0xCB:
8873 case 0xCC:
8874 case 0xCD:
8875 case 0xCE:
8876 case 0xCF:
8877 case 0xD0:
8878 case 0xD1:
8879 case 0xD2:
8880 case 0xD3:
8881 case 0xD4:
8882 case 0xD8: // tagged item (1 bytes follow)
8883 case 0xD9: // tagged item (2 bytes follow)
8884 case 0xDA: // tagged item (4 bytes follow)
8885 case 0xDB: // tagged item (8 bytes follow)
8886 {
8887 switch (tag_handler)
8888 {
8889 case cbor_tag_handler_t::error:
8890 {
8891 auto last_token = get_token_string();
8892 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
8893 }
8894
8895 case cbor_tag_handler_t::ignore:
8896 {
8897 // ignore binary subtype
8898 switch (current)
8899 {
8900 case 0xD8:
8901 {
8902 std::uint8_t subtype_to_ignore{};
8903 get_number(input_format_t::cbor, subtype_to_ignore);
8904 break;
8905 }
8906 case 0xD9:
8907 {
8908 std::uint16_t subtype_to_ignore{};
8909 get_number(input_format_t::cbor, subtype_to_ignore);
8910 break;
8911 }
8912 case 0xDA:
8913 {
8914 std::uint32_t subtype_to_ignore{};
8915 get_number(input_format_t::cbor, subtype_to_ignore);
8916 break;
8917 }
8918 case 0xDB:
8919 {
8920 std::uint64_t subtype_to_ignore{};
8921 get_number(input_format_t::cbor, subtype_to_ignore);
8922 break;
8923 }
8924 default:
8925 break;
8926 }
8927 return parse_cbor_internal(true, tag_handler);
8928 }
8929
8930 case cbor_tag_handler_t::store:
8931 {
8932 binary_t b;
8933 // use binary subtype and store in binary container
8934 switch (current)
8935 {
8936 case 0xD8:
8937 {
8938 std::uint8_t subtype{};
8939 get_number(input_format_t::cbor, subtype);
8940 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
8941 break;
8942 }
8943 case 0xD9:
8944 {
8945 std::uint16_t subtype{};
8946 get_number(input_format_t::cbor, subtype);
8947 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
8948 break;
8949 }
8950 case 0xDA:
8951 {
8952 std::uint32_t subtype{};
8953 get_number(input_format_t::cbor, subtype);
8954 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
8955 break;
8956 }
8957 case 0xDB:
8958 {
8959 std::uint64_t subtype{};
8960 get_number(input_format_t::cbor, subtype);
8961 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
8962 break;
8963 }
8964 default:
8965 return parse_cbor_internal(true, tag_handler);
8966 }
8967 get();
8968 return get_cbor_binary(b) && sax->binary(b);
8969 }
8970
8971 default: // LCOV_EXCL_LINE
8972 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8973 return false; // LCOV_EXCL_LINE
8974 }
8975 }
8976
8977 case 0xF4: // false
8978 return sax->boolean(false);
8979
8980 case 0xF5: // true
8981 return sax->boolean(true);
8982
8983 case 0xF6: // null
8984 return sax->null();
8985
8986 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
8987 {
8988 const auto byte1_raw = get();
8989 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
8990 {
8991 return false;
8992 }
8993 const auto byte2_raw = get();
8994 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
8995 {
8996 return false;
8997 }
8998
8999 const auto byte1 = static_cast<unsigned char>(byte1_raw);
9000 const auto byte2 = static_cast<unsigned char>(byte2_raw);
9001
9002 // code from RFC 7049, Appendix D, Figure 3:
9003 // As half-precision floating-point numbers were only added
9004 // to IEEE 754 in 2008, today's programming platforms often
9005 // still only have limited support for them. It is very
9006 // easy to include at least decoding support for them even
9007 // without such support. An example of a small decoder for
9008 // half-precision floating-point numbers in the C language
9009 // is shown in Fig. 3.
9010 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
9011 const double val = [&half]
9012 {
9013 const int exp = (half >> 10u) & 0x1Fu;
9014 const unsigned int mant = half & 0x3FFu;
9015 JSON_ASSERT(0 <= exp&& exp <= 32);
9016 JSON_ASSERT(mant <= 1024);
9017 switch (exp)
9018 {
9019 case 0:
9020 return std::ldexp(mant, -24);
9021 case 31:
9022 return (mant == 0)
9023 ? std::numeric_limits<double>::infinity()
9024 : std::numeric_limits<double>::quiet_NaN();
9025 default:
9026 return std::ldexp(mant + 1024, exp - 25);
9027 }
9028 }();
9029 return sax->number_float((half & 0x8000u) != 0
9030 ? static_cast<number_float_t>(-val)
9031 : static_cast<number_float_t>(val), "");
9032 }
9033
9034 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
9035 {
9036 float number{};
9037 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9038 }
9039
9040 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
9041 {
9042 double number{};
9043 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9044 }
9045
9046 default: // anything else (0xFF is handled inside the other types)
9047 {
9048 auto last_token = get_token_string();
9049 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
9050 }
9051 }
9052 }
9053
9054 /*!
9055 @brief reads a CBOR string
9056
9057 This function first reads starting bytes to determine the expected
9058 string length and then copies this number of bytes into a string.
9059 Additionally, CBOR's strings with indefinite lengths are supported.
9060
9061 @param[out] result created string
9062
9063 @return whether string creation completed
9064 */
9065 bool get_cbor_string(string_t& result)
9066 {
9067 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
9068 {
9069 return false;
9070 }
9071
9072 switch (current)
9073 {
9074 // UTF-8 string (0x00..0x17 bytes follow)
9075 case 0x60:
9076 case 0x61:
9077 case 0x62:
9078 case 0x63:
9079 case 0x64:
9080 case 0x65:
9081 case 0x66:
9082 case 0x67:
9083 case 0x68:
9084 case 0x69:
9085 case 0x6A:
9086 case 0x6B:
9087 case 0x6C:
9088 case 0x6D:
9089 case 0x6E:
9090 case 0x6F:
9091 case 0x70:
9092 case 0x71:
9093 case 0x72:
9094 case 0x73:
9095 case 0x74:
9096 case 0x75:
9097 case 0x76:
9098 case 0x77:
9099 {
9100 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
9101 }
9102
9103 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9104 {
9105 std::uint8_t len{};
9106 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9107 }
9108
9109 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9110 {
9111 std::uint16_t len{};
9112 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9113 }
9114
9115 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9116 {
9117 std::uint32_t len{};
9118 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9119 }
9120
9121 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9122 {
9123 std::uint64_t len{};
9124 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9125 }
9126
9127 case 0x7F: // UTF-8 string (indefinite length)
9128 {
9129 while (get() != 0xFF)
9130 {
9131 string_t chunk;
9132 if (!get_cbor_string(chunk))
9133 {
9134 return false;
9135 }
9136 result.append(chunk);
9137 }
9138 return true;
9139 }
9140
9141 default:
9142 {
9143 auto last_token = get_token_string();
9144 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"), BasicJsonType()));
9145 }
9146 }
9147 }
9148
9149 /*!
9150 @brief reads a CBOR byte array
9151
9152 This function first reads starting bytes to determine the expected
9153 byte array length and then copies this number of bytes into the byte array.
9154 Additionally, CBOR's byte arrays with indefinite lengths are supported.
9155
9156 @param[out] result created byte array
9157
9158 @return whether byte array creation completed
9159 */
9160 bool get_cbor_binary(binary_t& result)
9161 {
9162 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
9163 {
9164 return false;
9165 }
9166
9167 switch (current)
9168 {
9169 // Binary data (0x00..0x17 bytes follow)
9170 case 0x40:
9171 case 0x41:
9172 case 0x42:
9173 case 0x43:
9174 case 0x44:
9175 case 0x45:
9176 case 0x46:
9177 case 0x47:
9178 case 0x48:
9179 case 0x49:
9180 case 0x4A:
9181 case 0x4B:
9182 case 0x4C:
9183 case 0x4D:
9184 case 0x4E:
9185 case 0x4F:
9186 case 0x50:
9187 case 0x51:
9188 case 0x52:
9189 case 0x53:
9190 case 0x54:
9191 case 0x55:
9192 case 0x56:
9193 case 0x57:
9194 {
9195 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
9196 }
9197
9198 case 0x58: // Binary data (one-byte uint8_t for n follows)
9199 {
9200 std::uint8_t len{};
9201 return get_number(input_format_t::cbor, len) &&
9202 get_binary(input_format_t::cbor, len, result);
9203 }
9204
9205 case 0x59: // Binary data (two-byte uint16_t for n follow)
9206 {
9207 std::uint16_t len{};
9208 return get_number(input_format_t::cbor, len) &&
9209 get_binary(input_format_t::cbor, len, result);
9210 }
9211
9212 case 0x5A: // Binary data (four-byte uint32_t for n follow)
9213 {
9214 std::uint32_t len{};
9215 return get_number(input_format_t::cbor, len) &&
9216 get_binary(input_format_t::cbor, len, result);
9217 }
9218
9219 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9220 {
9221 std::uint64_t len{};
9222 return get_number(input_format_t::cbor, len) &&
9223 get_binary(input_format_t::cbor, len, result);
9224 }
9225
9226 case 0x5F: // Binary data (indefinite length)
9227 {
9228 while (get() != 0xFF)
9229 {
9230 binary_t chunk;
9231 if (!get_cbor_binary(chunk))
9232 {
9233 return false;
9234 }
9235 result.insert(result.end(), chunk.begin(), chunk.end());
9236 }
9237 return true;
9238 }
9239
9240 default:
9241 {
9242 auto last_token = get_token_string();
9243 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"), BasicJsonType()));
9244 }
9245 }
9246 }
9247
9248 /*!
9249 @param[in] len the length of the array or static_cast<std::size_t>(-1) for an
9250 array of indefinite size
9251 @param[in] tag_handler how CBOR tags should be treated
9252 @return whether array creation completed
9253 */
9254 bool get_cbor_array(const std::size_t len,
9255 const cbor_tag_handler_t tag_handler)
9256 {
9257 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
9258 {
9259 return false;
9260 }
9261
9262 if (len != static_cast<std::size_t>(-1))
9263 {
9264 for (std::size_t i = 0; i < len; ++i)
9265 {
9266 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
9267 {
9268 return false;
9269 }
9270 }
9271 }
9272 else
9273 {
9274 while (get() != 0xFF)
9275 {
9276 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
9277 {
9278 return false;
9279 }
9280 }
9281 }
9282
9283 return sax->end_array();
9284 }
9285
9286 /*!
9287 @param[in] len the length of the object or static_cast<std::size_t>(-1) for an
9288 object of indefinite size
9289 @param[in] tag_handler how CBOR tags should be treated
9290 @return whether object creation completed
9291 */
9292 bool get_cbor_object(const std::size_t len,
9293 const cbor_tag_handler_t tag_handler)
9294 {
9295 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
9296 {
9297 return false;
9298 }
9299
9300 if (len != 0)
9301 {
9302 string_t key;
9303 if (len != static_cast<std::size_t>(-1))
9304 {
9305 for (std::size_t i = 0; i < len; ++i)
9306 {
9307 get();
9308 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
9309 {
9310 return false;
9311 }
9312
9313 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
9314 {
9315 return false;
9316 }
9317 key.clear();
9318 }
9319 }
9320 else
9321 {
9322 while (get() != 0xFF)
9323 {
9324 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
9325 {
9326 return false;
9327 }
9328
9329 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
9330 {
9331 return false;
9332 }
9333 key.clear();
9334 }
9335 }
9336 }
9337
9338 return sax->end_object();
9339 }
9340
9341 /////////////
9342 // MsgPack //
9343 /////////////
9344
9345 /*!
9346 @return whether a valid MessagePack value was passed to the SAX parser
9347 */
9348 bool parse_msgpack_internal()
9349 {
9350 switch (get())
9351 {
9352 // EOF
9353 case std::char_traits<char_type>::eof():
9354 return unexpect_eof(input_format_t::msgpack, "value");
9355
9356 // positive fixint
9357 case 0x00:
9358 case 0x01:
9359 case 0x02:
9360 case 0x03:
9361 case 0x04:
9362 case 0x05:
9363 case 0x06:
9364 case 0x07:
9365 case 0x08:
9366 case 0x09:
9367 case 0x0A:
9368 case 0x0B:
9369 case 0x0C:
9370 case 0x0D:
9371 case 0x0E:
9372 case 0x0F:
9373 case 0x10:
9374 case 0x11:
9375 case 0x12:
9376 case 0x13:
9377 case 0x14:
9378 case 0x15:
9379 case 0x16:
9380 case 0x17:
9381 case 0x18:
9382 case 0x19:
9383 case 0x1A:
9384 case 0x1B:
9385 case 0x1C:
9386 case 0x1D:
9387 case 0x1E:
9388 case 0x1F:
9389 case 0x20:
9390 case 0x21:
9391 case 0x22:
9392 case 0x23:
9393 case 0x24:
9394 case 0x25:
9395 case 0x26:
9396 case 0x27:
9397 case 0x28:
9398 case 0x29:
9399 case 0x2A:
9400 case 0x2B:
9401 case 0x2C:
9402 case 0x2D:
9403 case 0x2E:
9404 case 0x2F:
9405 case 0x30:
9406 case 0x31:
9407 case 0x32:
9408 case 0x33:
9409 case 0x34:
9410 case 0x35:
9411 case 0x36:
9412 case 0x37:
9413 case 0x38:
9414 case 0x39:
9415 case 0x3A:
9416 case 0x3B:
9417 case 0x3C:
9418 case 0x3D:
9419 case 0x3E:
9420 case 0x3F:
9421 case 0x40:
9422 case 0x41:
9423 case 0x42:
9424 case 0x43:
9425 case 0x44:
9426 case 0x45:
9427 case 0x46:
9428 case 0x47:
9429 case 0x48:
9430 case 0x49:
9431 case 0x4A:
9432 case 0x4B:
9433 case 0x4C:
9434 case 0x4D:
9435 case 0x4E:
9436 case 0x4F:
9437 case 0x50:
9438 case 0x51:
9439 case 0x52:
9440 case 0x53:
9441 case 0x54:
9442 case 0x55:
9443 case 0x56:
9444 case 0x57:
9445 case 0x58:
9446 case 0x59:
9447 case 0x5A:
9448 case 0x5B:
9449 case 0x5C:
9450 case 0x5D:
9451 case 0x5E:
9452 case 0x5F:
9453 case 0x60:
9454 case 0x61:
9455 case 0x62:
9456 case 0x63:
9457 case 0x64:
9458 case 0x65:
9459 case 0x66:
9460 case 0x67:
9461 case 0x68:
9462 case 0x69:
9463 case 0x6A:
9464 case 0x6B:
9465 case 0x6C:
9466 case 0x6D:
9467 case 0x6E:
9468 case 0x6F:
9469 case 0x70:
9470 case 0x71:
9471 case 0x72:
9472 case 0x73:
9473 case 0x74:
9474 case 0x75:
9475 case 0x76:
9476 case 0x77:
9477 case 0x78:
9478 case 0x79:
9479 case 0x7A:
9480 case 0x7B:
9481 case 0x7C:
9482 case 0x7D:
9483 case 0x7E:
9484 case 0x7F:
9485 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9486
9487 // fixmap
9488 case 0x80:
9489 case 0x81:
9490 case 0x82:
9491 case 0x83:
9492 case 0x84:
9493 case 0x85:
9494 case 0x86:
9495 case 0x87:
9496 case 0x88:
9497 case 0x89:
9498 case 0x8A:
9499 case 0x8B:
9500 case 0x8C:
9501 case 0x8D:
9502 case 0x8E:
9503 case 0x8F:
9504 return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
9505
9506 // fixarray
9507 case 0x90:
9508 case 0x91:
9509 case 0x92:
9510 case 0x93:
9511 case 0x94:
9512 case 0x95:
9513 case 0x96:
9514 case 0x97:
9515 case 0x98:
9516 case 0x99:
9517 case 0x9A:
9518 case 0x9B:
9519 case 0x9C:
9520 case 0x9D:
9521 case 0x9E:
9522 case 0x9F:
9523 return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
9524
9525 // fixstr
9526 case 0xA0:
9527 case 0xA1:
9528 case 0xA2:
9529 case 0xA3:
9530 case 0xA4:
9531 case 0xA5:
9532 case 0xA6:
9533 case 0xA7:
9534 case 0xA8:
9535 case 0xA9:
9536 case 0xAA:
9537 case 0xAB:
9538 case 0xAC:
9539 case 0xAD:
9540 case 0xAE:
9541 case 0xAF:
9542 case 0xB0:
9543 case 0xB1:
9544 case 0xB2:
9545 case 0xB3:
9546 case 0xB4:
9547 case 0xB5:
9548 case 0xB6:
9549 case 0xB7:
9550 case 0xB8:
9551 case 0xB9:
9552 case 0xBA:
9553 case 0xBB:
9554 case 0xBC:
9555 case 0xBD:
9556 case 0xBE:
9557 case 0xBF:
9558 case 0xD9: // str 8
9559 case 0xDA: // str 16
9560 case 0xDB: // str 32
9561 {
9562 string_t s;
9563 return get_msgpack_string(s) && sax->string(s);
9564 }
9565
9566 case 0xC0: // nil
9567 return sax->null();
9568
9569 case 0xC2: // false
9570 return sax->boolean(false);
9571
9572 case 0xC3: // true
9573 return sax->boolean(true);
9574
9575 case 0xC4: // bin 8
9576 case 0xC5: // bin 16
9577 case 0xC6: // bin 32
9578 case 0xC7: // ext 8
9579 case 0xC8: // ext 16
9580 case 0xC9: // ext 32
9581 case 0xD4: // fixext 1
9582 case 0xD5: // fixext 2
9583 case 0xD6: // fixext 4
9584 case 0xD7: // fixext 8
9585 case 0xD8: // fixext 16
9586 {
9587 binary_t b;
9588 return get_msgpack_binary(b) && sax->binary(b);
9589 }
9590
9591 case 0xCA: // float 32
9592 {
9593 float number{};
9594 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
9595 }
9596
9597 case 0xCB: // float 64
9598 {
9599 double number{};
9600 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
9601 }
9602
9603 case 0xCC: // uint 8
9604 {
9605 std::uint8_t number{};
9606 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9607 }
9608
9609 case 0xCD: // uint 16
9610 {
9611 std::uint16_t number{};
9612 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9613 }
9614
9615 case 0xCE: // uint 32
9616 {
9617 std::uint32_t number{};
9618 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9619 }
9620
9621 case 0xCF: // uint 64
9622 {
9623 std::uint64_t number{};
9624 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9625 }
9626
9627 case 0xD0: // int 8
9628 {
9629 std::int8_t number{};
9630 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9631 }
9632
9633 case 0xD1: // int 16
9634 {
9635 std::int16_t number{};
9636 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9637 }
9638
9639 case 0xD2: // int 32
9640 {
9641 std::int32_t number{};
9642 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9643 }
9644
9645 case 0xD3: // int 64
9646 {
9647 std::int64_t number{};
9648 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9649 }
9650
9651 case 0xDC: // array 16
9652 {
9653 std::uint16_t len{};
9654 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
9655 }
9656
9657 case 0xDD: // array 32
9658 {
9659 std::uint32_t len{};
9660 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
9661 }
9662
9663 case 0xDE: // map 16
9664 {
9665 std::uint16_t len{};
9666 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
9667 }
9668
9669 case 0xDF: // map 32
9670 {
9671 std::uint32_t len{};
9672 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
9673 }
9674
9675 // negative fixint
9676 case 0xE0:
9677 case 0xE1:
9678 case 0xE2:
9679 case 0xE3:
9680 case 0xE4:
9681 case 0xE5:
9682 case 0xE6:
9683 case 0xE7:
9684 case 0xE8:
9685 case 0xE9:
9686 case 0xEA:
9687 case 0xEB:
9688 case 0xEC:
9689 case 0xED:
9690 case 0xEE:
9691 case 0xEF:
9692 case 0xF0:
9693 case 0xF1:
9694 case 0xF2:
9695 case 0xF3:
9696 case 0xF4:
9697 case 0xF5:
9698 case 0xF6:
9699 case 0xF7:
9700 case 0xF8:
9701 case 0xF9:
9702 case 0xFA:
9703 case 0xFB:
9704 case 0xFC:
9705 case 0xFD:
9706 case 0xFE:
9707 case 0xFF:
9708 return sax->number_integer(static_cast<std::int8_t>(current));
9709
9710 default: // anything else
9711 {
9712 auto last_token = get_token_string();
9713 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
9714 }
9715 }
9716 }
9717
9718 /*!
9719 @brief reads a MessagePack string
9720
9721 This function first reads starting bytes to determine the expected
9722 string length and then copies this number of bytes into a string.
9723
9724 @param[out] result created string
9725
9726 @return whether string creation completed
9727 */
9728 bool get_msgpack_string(string_t& result)
9729 {
9730 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
9731 {
9732 return false;
9733 }
9734
9735 switch (current)
9736 {
9737 // fixstr
9738 case 0xA0:
9739 case 0xA1:
9740 case 0xA2:
9741 case 0xA3:
9742 case 0xA4:
9743 case 0xA5:
9744 case 0xA6:
9745 case 0xA7:
9746 case 0xA8:
9747 case 0xA9:
9748 case 0xAA:
9749 case 0xAB:
9750 case 0xAC:
9751 case 0xAD:
9752 case 0xAE:
9753 case 0xAF:
9754 case 0xB0:
9755 case 0xB1:
9756 case 0xB2:
9757 case 0xB3:
9758 case 0xB4:
9759 case 0xB5:
9760 case 0xB6:
9761 case 0xB7:
9762 case 0xB8:
9763 case 0xB9:
9764 case 0xBA:
9765 case 0xBB:
9766 case 0xBC:
9767 case 0xBD:
9768 case 0xBE:
9769 case 0xBF:
9770 {
9771 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
9772 }
9773
9774 case 0xD9: // str 8
9775 {
9776 std::uint8_t len{};
9777 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9778 }
9779
9780 case 0xDA: // str 16
9781 {
9782 std::uint16_t len{};
9783 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9784 }
9785
9786 case 0xDB: // str 32
9787 {
9788 std::uint32_t len{};
9789 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9790 }
9791
9792 default:
9793 {
9794 auto last_token = get_token_string();
9795 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"), BasicJsonType()));
9796 }
9797 }
9798 }
9799
9800 /*!
9801 @brief reads a MessagePack byte array
9802
9803 This function first reads starting bytes to determine the expected
9804 byte array length and then copies this number of bytes into a byte array.
9805
9806 @param[out] result created byte array
9807
9808 @return whether byte array creation completed
9809 */
9810 bool get_msgpack_binary(binary_t& result)
9811 {
9812 // helper function to set the subtype
9813 auto assign_and_return_true = [&result](std::int8_t subtype)
9814 {
9815 result.set_subtype(static_cast<std::uint8_t>(subtype));
9816 return true;
9817 };
9818
9819 switch (current)
9820 {
9821 case 0xC4: // bin 8
9822 {
9823 std::uint8_t len{};
9824 return get_number(input_format_t::msgpack, len) &&
9825 get_binary(input_format_t::msgpack, len, result);
9826 }
9827
9828 case 0xC5: // bin 16
9829 {
9830 std::uint16_t len{};
9831 return get_number(input_format_t::msgpack, len) &&
9832 get_binary(input_format_t::msgpack, len, result);
9833 }
9834
9835 case 0xC6: // bin 32
9836 {
9837 std::uint32_t len{};
9838 return get_number(input_format_t::msgpack, len) &&
9839 get_binary(input_format_t::msgpack, len, result);
9840 }
9841
9842 case 0xC7: // ext 8
9843 {
9844 std::uint8_t len{};
9845 std::int8_t subtype{};
9846 return get_number(input_format_t::msgpack, len) &&
9847 get_number(input_format_t::msgpack, subtype) &&
9848 get_binary(input_format_t::msgpack, len, result) &&
9849 assign_and_return_true(subtype);
9850 }
9851
9852 case 0xC8: // ext 16
9853 {
9854 std::uint16_t len{};
9855 std::int8_t subtype{};
9856 return get_number(input_format_t::msgpack, len) &&
9857 get_number(input_format_t::msgpack, subtype) &&
9858 get_binary(input_format_t::msgpack, len, result) &&
9859 assign_and_return_true(subtype);
9860 }
9861
9862 case 0xC9: // ext 32
9863 {
9864 std::uint32_t len{};
9865 std::int8_t subtype{};
9866 return get_number(input_format_t::msgpack, len) &&
9867 get_number(input_format_t::msgpack, subtype) &&
9868 get_binary(input_format_t::msgpack, len, result) &&
9869 assign_and_return_true(subtype);
9870 }
9871
9872 case 0xD4: // fixext 1
9873 {
9874 std::int8_t subtype{};
9875 return get_number(input_format_t::msgpack, subtype) &&
9876 get_binary(input_format_t::msgpack, 1, result) &&
9877 assign_and_return_true(subtype);
9878 }
9879
9880 case 0xD5: // fixext 2
9881 {
9882 std::int8_t subtype{};
9883 return get_number(input_format_t::msgpack, subtype) &&
9884 get_binary(input_format_t::msgpack, 2, result) &&
9885 assign_and_return_true(subtype);
9886 }
9887
9888 case 0xD6: // fixext 4
9889 {
9890 std::int8_t subtype{};
9891 return get_number(input_format_t::msgpack, subtype) &&
9892 get_binary(input_format_t::msgpack, 4, result) &&
9893 assign_and_return_true(subtype);
9894 }
9895
9896 case 0xD7: // fixext 8
9897 {
9898 std::int8_t subtype{};
9899 return get_number(input_format_t::msgpack, subtype) &&
9900 get_binary(input_format_t::msgpack, 8, result) &&
9901 assign_and_return_true(subtype);
9902 }
9903
9904 case 0xD8: // fixext 16
9905 {
9906 std::int8_t subtype{};
9907 return get_number(input_format_t::msgpack, subtype) &&
9908 get_binary(input_format_t::msgpack, 16, result) &&
9909 assign_and_return_true(subtype);
9910 }
9911
9912 default: // LCOV_EXCL_LINE
9913 return false; // LCOV_EXCL_LINE
9914 }
9915 }
9916
9917 /*!
9918 @param[in] len the length of the array
9919 @return whether array creation completed
9920 */
9921 bool get_msgpack_array(const std::size_t len)
9922 {
9923 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
9924 {
9925 return false;
9926 }
9927
9928 for (std::size_t i = 0; i < len; ++i)
9929 {
9930 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
9931 {
9932 return false;
9933 }
9934 }
9935
9936 return sax->end_array();
9937 }
9938
9939 /*!
9940 @param[in] len the length of the object
9941 @return whether object creation completed
9942 */
9943 bool get_msgpack_object(const std::size_t len)
9944 {
9945 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
9946 {
9947 return false;
9948 }
9949
9950 string_t key;
9951 for (std::size_t i = 0; i < len; ++i)
9952 {
9953 get();
9954 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
9955 {
9956 return false;
9957 }
9958
9959 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
9960 {
9961 return false;
9962 }
9963 key.clear();
9964 }
9965
9966 return sax->end_object();
9967 }
9968
9969 ////////////
9970 // UBJSON //
9971 ////////////
9972
9973 /*!
9974 @param[in] get_char whether a new character should be retrieved from the
9975 input (true, default) or whether the last read
9976 character should be considered instead
9977
9978 @return whether a valid UBJSON value was passed to the SAX parser
9979 */
9980 bool parse_ubjson_internal(const bool get_char = true)
9981 {
9982 return get_ubjson_value(get_char ? get_ignore_noop() : current);
9983 }
9984
9985 /*!
9986 @brief reads a UBJSON string
9987
9988 This function is either called after reading the 'S' byte explicitly
9989 indicating a string, or in case of an object key where the 'S' byte can be
9990 left out.
9991
9992 @param[out] result created string
9993 @param[in] get_char whether a new character should be retrieved from the
9994 input (true, default) or whether the last read
9995 character should be considered instead
9996
9997 @return whether string creation completed
9998 */
9999 bool get_ubjson_string(string_t& result, const bool get_char = true)
10000 {
10001 if (get_char)
10002 {
10003 get(); // TODO(niels): may we ignore N here?
10004 }
10005
10006 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
10007 {
10008 return false;
10009 }
10010
10011 switch (current)
10012 {
10013 case 'U':
10014 {
10015 std::uint8_t len{};
10016 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10017 }
10018
10019 case 'i':
10020 {
10021 std::int8_t len{};
10022 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10023 }
10024
10025 case 'I':
10026 {
10027 std::int16_t len{};
10028 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10029 }
10030
10031 case 'l':
10032 {
10033 std::int32_t len{};
10034 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10035 }
10036
10037 case 'L':
10038 {
10039 std::int64_t len{};
10040 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10041 }
10042
10043 default:
10044 auto last_token = get_token_string();
10045 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"), BasicJsonType()));
10046 }
10047 }
10048
10049 /*!
10050 @param[out] result determined size
10051 @return whether size determination completed
10052 */
10053 bool get_ubjson_size_value(std::size_t& result)
10054 {
10055 switch (get_ignore_noop())
10056 {
10057 case 'U':
10058 {
10059 std::uint8_t number{};
10060 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10061 {
10062 return false;
10063 }
10064 result = static_cast<std::size_t>(number);
10065 return true;
10066 }
10067
10068 case 'i':
10069 {
10070 std::int8_t number{};
10071 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10072 {
10073 return false;
10074 }
10075 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
10076 return true;
10077 }
10078
10079 case 'I':
10080 {
10081 std::int16_t number{};
10082 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10083 {
10084 return false;
10085 }
10086 result = static_cast<std::size_t>(number);
10087 return true;
10088 }
10089
10090 case 'l':
10091 {
10092 std::int32_t number{};
10093 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10094 {
10095 return false;
10096 }
10097 result = static_cast<std::size_t>(number);
10098 return true;
10099 }
10100
10101 case 'L':
10102 {
10103 std::int64_t number{};
10104 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10105 {
10106 return false;
10107 }
10108 result = static_cast<std::size_t>(number);
10109 return true;
10110 }
10111
10112 default:
10113 {
10114 auto last_token = get_token_string();
10115 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"), BasicJsonType()));
10116 }
10117 }
10118 }
10119
10120 /*!
10121 @brief determine the type and size for a container
10122
10123 In the optimized UBJSON format, a type and a size can be provided to allow
10124 for a more compact representation.
10125
10126 @param[out] result pair of the size and the type
10127
10128 @return whether pair creation completed
10129 */
10130 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result)
10131 {
10132 result.first = string_t::npos; // size
10133 result.second = 0; // type
10134
10135 get_ignore_noop();
10136
10137 if (current == '$')
10138 {
10139 result.second = get(); // must not ignore 'N', because 'N' maybe the type
10140 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type")))
10141 {
10142 return false;
10143 }
10144
10145 get_ignore_noop();
10146 if (JSON_HEDLEY_UNLIKELY(current != '#'))
10147 {
10148 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
10149 {
10150 return false;
10151 }
10152 auto last_token = get_token_string();
10153 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"), BasicJsonType()));
10154 }
10155
10156 return get_ubjson_size_value(result.first);
10157 }
10158
10159 if (current == '#')
10160 {
10161 return get_ubjson_size_value(result.first);
10162 }
10163
10164 return true;
10165 }
10166
10167 /*!
10168 @param prefix the previously read or set type prefix
10169 @return whether value creation completed
10170 */
10171 bool get_ubjson_value(const char_int_type prefix)
10172 {
10173 switch (prefix)
10174 {
10175 case std::char_traits<char_type>::eof(): // EOF
10176 return unexpect_eof(input_format_t::ubjson, "value");
10177
10178 case 'T': // true
10179 return sax->boolean(true);
10180 case 'F': // false
10181 return sax->boolean(false);
10182
10183 case 'Z': // null
10184 return sax->null();
10185
10186 case 'U':
10187 {
10188 std::uint8_t number{};
10189 return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number);
10190 }
10191
10192 case 'i':
10193 {
10194 std::int8_t number{};
10195 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
10196 }
10197
10198 case 'I':
10199 {
10200 std::int16_t number{};
10201 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
10202 }
10203
10204 case 'l':
10205 {
10206 std::int32_t number{};
10207 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
10208 }
10209
10210 case 'L':
10211 {
10212 std::int64_t number{};
10213 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
10214 }
10215
10216 case 'd':
10217 {
10218 float number{};
10219 return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10220 }
10221
10222 case 'D':
10223 {
10224 double number{};
10225 return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10226 }
10227
10228 case 'H':
10229 {
10230 return get_ubjson_high_precision_number();
10231 }
10232
10233 case 'C': // char
10234 {
10235 get();
10236 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char")))
10237 {
10238 return false;
10239 }
10240 if (JSON_HEDLEY_UNLIKELY(current > 127))
10241 {
10242 auto last_token = get_token_string();
10243 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"), BasicJsonType()));
10244 }
10245 string_t s(1, static_cast<typename string_t::value_type>(current));
10246 return sax->string(s);
10247 }
10248
10249 case 'S': // string
10250 {
10251 string_t s;
10252 return get_ubjson_string(s) && sax->string(s);
10253 }
10254
10255 case '[': // array
10256 return get_ubjson_array();
10257
10258 case '{': // object
10259 return get_ubjson_object();
10260
10261 default: // anything else
10262 {
10263 auto last_token = get_token_string();
10264 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
10265 }
10266 }
10267 }
10268
10269 /*!
10270 @return whether array creation completed
10271 */
10272 bool get_ubjson_array()
10273 {
10274 std::pair<std::size_t, char_int_type> size_and_type;
10275 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
10276 {
10277 return false;
10278 }
10279
10280 if (size_and_type.first != string_t::npos)
10281 {
10282 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
10283 {
10284 return false;
10285 }
10286
10287 if (size_and_type.second != 0)
10288 {
10289 if (size_and_type.second != 'N')
10290 {
10291 for (std::size_t i = 0; i < size_and_type.first; ++i)
10292 {
10293 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
10294 {
10295 return false;
10296 }
10297 }
10298 }
10299 }
10300 else
10301 {
10302 for (std::size_t i = 0; i < size_and_type.first; ++i)
10303 {
10304 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
10305 {
10306 return false;
10307 }
10308 }
10309 }
10310 }
10311 else
10312 {
10313 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
10314 {
10315 return false;
10316 }
10317
10318 while (current != ']')
10319 {
10320 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
10321 {
10322 return false;
10323 }
10324 get_ignore_noop();
10325 }
10326 }
10327
10328 return sax->end_array();
10329 }
10330
10331 /*!
10332 @return whether object creation completed
10333 */
10334 bool get_ubjson_object()
10335 {
10336 std::pair<std::size_t, char_int_type> size_and_type;
10337 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
10338 {
10339 return false;
10340 }
10341
10342 string_t key;
10343 if (size_and_type.first != string_t::npos)
10344 {
10345 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
10346 {
10347 return false;
10348 }
10349
10350 if (size_and_type.second != 0)
10351 {
10352 for (std::size_t i = 0; i < size_and_type.first; ++i)
10353 {
10354 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
10355 {
10356 return false;
10357 }
10358 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
10359 {
10360 return false;
10361 }
10362 key.clear();
10363 }
10364 }
10365 else
10366 {
10367 for (std::size_t i = 0; i < size_and_type.first; ++i)
10368 {
10369 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
10370 {
10371 return false;
10372 }
10373 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
10374 {
10375 return false;
10376 }
10377 key.clear();
10378 }
10379 }
10380 }
10381 else
10382 {
10383 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
10384 {
10385 return false;
10386 }
10387
10388 while (current != '}')
10389 {
10390 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
10391 {
10392 return false;
10393 }
10394 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
10395 {
10396 return false;
10397 }
10398 get_ignore_noop();
10399 key.clear();
10400 }
10401 }
10402
10403 return sax->end_object();
10404 }
10405
10406 // Note, no reader for UBJSON binary types is implemented because they do
10407 // not exist
10408
10409 bool get_ubjson_high_precision_number()
10410 {
10411 // get size of following number string
10412 std::size_t size{};
10413 auto res = get_ubjson_size_value(size);
10414 if (JSON_HEDLEY_UNLIKELY(!res))
10415 {
10416 return res;
10417 }
10418
10419 // get number string
10420 std::vector<char> number_vector;
10421 for (std::size_t i = 0; i < size; ++i)
10422 {
10423 get();
10424 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number")))
10425 {
10426 return false;
10427 }
10428 number_vector.push_back(static_cast<char>(current));
10429 }
10430
10431 // parse number string
10432 using ia_type = decltype(detail::input_adapter(number_vector));
10433 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
10434 const auto result_number = number_lexer.scan();
10435 const auto number_string = number_lexer.get_token_string();
10436 const auto result_remainder = number_lexer.scan();
10437
10438 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
10439
10440 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
10441 {
10442 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType()));
10443 }
10444
10445 switch (result_number)
10446 {
10447 case token_type::value_integer:
10448 return sax->number_integer(number_lexer.get_number_integer());
10449 case token_type::value_unsigned:
10450 return sax->number_unsigned(number_lexer.get_number_unsigned());
10451 case token_type::value_float:
10452 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
10453 case token_type::uninitialized:
10454 case token_type::literal_true:
10455 case token_type::literal_false:
10456 case token_type::literal_null:
10457 case token_type::value_string:
10458 case token_type::begin_array:
10459 case token_type::begin_object:
10460 case token_type::end_array:
10461 case token_type::end_object:
10462 case token_type::name_separator:
10463 case token_type::value_separator:
10464 case token_type::parse_error:
10465 case token_type::end_of_input:
10466 case token_type::literal_or_value:
10467 default:
10468 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType()));
10469 }
10470 }
10471
10472 ///////////////////////
10473 // Utility functions //
10474 ///////////////////////
10475
10476 /*!
10477 @brief get next character from the input
10478
10479 This function provides the interface to the used input adapter. It does
10480 not throw in case the input reached EOF, but returns a -'ve valued
10481 `std::char_traits<char_type>::eof()` in that case.
10482
10483 @return character read from the input
10484 */
10485 char_int_type get()
10486 {
10487 ++chars_read;
10488 return current = ia.get_character();
10489 }
10490
10491 /*!
10492 @return character read from the input after ignoring all 'N' entries
10493 */
10494 char_int_type get_ignore_noop()
10495 {
10496 do
10497 {
10498 get();
10499 }
10500 while (current == 'N');
10501
10502 return current;
10503 }
10504
10505 /*
10506 @brief read a number from the input
10507
10508 @tparam NumberType the type of the number
10509 @param[in] format the current format (for diagnostics)
10510 @param[out] result number of type @a NumberType
10511
10512 @return whether conversion completed
10513
10514 @note This function needs to respect the system's endianness, because
10515 bytes in CBOR, MessagePack, and UBJSON are stored in network order
10516 (big endian) and therefore need reordering on little endian systems.
10517 */
10518 template<typename NumberType, bool InputIsLittleEndian = false>
10519 bool get_number(const input_format_t format, NumberType& result)
10520 {
10521 // step 1: read input into array with system's byte order
10522 std::array<std::uint8_t, sizeof(NumberType)> vec{};
10523 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
10524 {
10525 get();
10526 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
10527 {
10528 return false;
10529 }
10530
10531 // reverse byte order prior to conversion if necessary
10532 if (is_little_endian != InputIsLittleEndian)
10533 {
10534 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
10535 }
10536 else
10537 {
10538 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
10539 }
10540 }
10541
10542 // step 2: convert array into number of type T and return
10543 std::memcpy(&result, vec.data(), sizeof(NumberType));
10544 return true;
10545 }
10546
10547 /*!
10548 @brief create a string by reading characters from the input
10549
10550 @tparam NumberType the type of the number
10551 @param[in] format the current format (for diagnostics)
10552 @param[in] len number of characters to read
10553 @param[out] result string created by reading @a len bytes
10554
10555 @return whether string creation completed
10556
10557 @note We can not reserve @a len bytes for the result, because @a len
10558 may be too large. Usually, @ref unexpect_eof() detects the end of
10559 the input before we run out of string memory.
10560 */
10561 template<typename NumberType>
10562 bool get_string(const input_format_t format,
10563 const NumberType len,
10564 string_t& result)
10565 {
10566 bool success = true;
10567 for (NumberType i = 0; i < len; i++)
10568 {
10569 get();
10570 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
10571 {
10572 success = false;
10573 break;
10574 }
10575 result.push_back(static_cast<typename string_t::value_type>(current));
10576 }
10577 return success;
10578 }
10579
10580 /*!
10581 @brief create a byte array by reading bytes from the input
10582
10583 @tparam NumberType the type of the number
10584 @param[in] format the current format (for diagnostics)
10585 @param[in] len number of bytes to read
10586 @param[out] result byte array created by reading @a len bytes
10587
10588 @return whether byte array creation completed
10589
10590 @note We can not reserve @a len bytes for the result, because @a len
10591 may be too large. Usually, @ref unexpect_eof() detects the end of
10592 the input before we run out of memory.
10593 */
10594 template<typename NumberType>
10595 bool get_binary(const input_format_t format,
10596 const NumberType len,
10597 binary_t& result)
10598 {
10599 bool success = true;
10600 for (NumberType i = 0; i < len; i++)
10601 {
10602 get();
10603 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
10604 {
10605 success = false;
10606 break;
10607 }
10608 result.push_back(static_cast<std::uint8_t>(current));
10609 }
10610 return success;
10611 }
10612
10613 /*!
10614 @param[in] format the current format (for diagnostics)
10615 @param[in] context further context information (for diagnostics)
10616 @return whether the last read character is not EOF
10617 */
10618 JSON_HEDLEY_NON_NULL(3)
10619 bool unexpect_eof(const input_format_t format, const char* context) const
10620 {
10621 if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
10622 {
10623 return sax->parse_error(chars_read, "<end of file>",
10624 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), BasicJsonType()));
10625 }
10626 return true;
10627 }
10628
10629 /*!
10630 @return a string representation of the last read byte
10631 */
10632 std::string get_token_string() const
10633 {
10634 std::array<char, 3> cr{{}};
10635 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
10636 return std::string{cr.data()};
10637 }
10638
10639 /*!
10640 @param[in] format the current format
10641 @param[in] detail a detailed error message
10642 @param[in] context further context information
10643 @return a message string to use in the parse_error exceptions
10644 */
10645 std::string exception_message(const input_format_t format,
10646 const std::string& detail,
10647 const std::string& context) const
10648 {
10649 std::string error_msg = "syntax error while parsing ";
10650
10651 switch (format)
10652 {
10653 case input_format_t::cbor:
10654 error_msg += "CBOR";
10655 break;
10656
10657 case input_format_t::msgpack:
10658 error_msg += "MessagePack";
10659 break;
10660
10661 case input_format_t::ubjson:
10662 error_msg += "UBJSON";
10663 break;
10664
10665 case input_format_t::bson:
10666 error_msg += "BSON";
10667 break;
10668
10669 case input_format_t::json: // LCOV_EXCL_LINE
10670 default: // LCOV_EXCL_LINE
10671 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10672 }
10673
10674 return error_msg + " " + context + ": " + detail;
10675 }
10676
10677 private:
10678 /// input adapter
10679 InputAdapterType ia;
10680
10681 /// the current character
10682 char_int_type current = std::char_traits<char_type>::eof();
10683
10684 /// the number of characters read
10685 std::size_t chars_read = 0;
10686
10687 /// whether we can assume little endianness
10688 const bool is_little_endian = little_endianness();
10689
10690 /// the SAX parser
10691 json_sax_t* sax = nullptr;
10692 };
10693 } // namespace detail
10694 } // namespace nlohmann
10695
10696 // #include <nlohmann/detail/input/input_adapters.hpp>
10697
10698 // #include <nlohmann/detail/input/lexer.hpp>
10699
10700 // #include <nlohmann/detail/input/parser.hpp>
10701
10702
10703 #include <cmath> // isfinite
10704 #include <cstdint> // uint8_t
10705 #include <functional> // function
10706 #include <string> // string
10707 #include <utility> // move
10708 #include <vector> // vector
10709
10710 // #include <nlohmann/detail/exceptions.hpp>
10711
10712 // #include <nlohmann/detail/input/input_adapters.hpp>
10713
10714 // #include <nlohmann/detail/input/json_sax.hpp>
10715
10716 // #include <nlohmann/detail/input/lexer.hpp>
10717
10718 // #include <nlohmann/detail/macro_scope.hpp>
10719
10720 // #include <nlohmann/detail/meta/is_sax.hpp>
10721
10722 // #include <nlohmann/detail/value_t.hpp>
10723
10724
10725 namespace nlohmann
10726 {
10727 namespace detail
10728 {
10729 ////////////
10730 // parser //
10731 ////////////
10732
10733 enum class parse_event_t : std::uint8_t
10734 {
10735 /// the parser read `{` and started to process a JSON object
10736 object_start,
10737 /// the parser read `}` and finished processing a JSON object
10738 object_end,
10739 /// the parser read `[` and started to process a JSON array
10740 array_start,
10741 /// the parser read `]` and finished processing a JSON array
10742 array_end,
10743 /// the parser read a key of a value in an object
10744 key,
10745 /// the parser finished reading a JSON value
10746 value
10747 };
10748
10749 template<typename BasicJsonType>
10750 using parser_callback_t =
10751 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
10752
10753 /*!
10754 @brief syntax analysis
10755
10756 This class implements a recursive descent parser.
10757 */
10758 template<typename BasicJsonType, typename InputAdapterType>
10759 class parser
10760 {
10761 using number_integer_t = typename BasicJsonType::number_integer_t;
10762 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
10763 using number_float_t = typename BasicJsonType::number_float_t;
10764 using string_t = typename BasicJsonType::string_t;
10765 using lexer_t = lexer<BasicJsonType, InputAdapterType>;
10766 using token_type = typename lexer_t::token_type;
10767
10768 public:
10769 /// a parser reading from an input adapter
10770 explicit parser(InputAdapterType&& adapter,
10771 const parser_callback_t<BasicJsonType> cb = nullptr,
10772 const bool allow_exceptions_ = true,
10773 const bool skip_comments = false)
10774 : callback(cb)
10775 , m_lexer(std::move(adapter), skip_comments)
10776 , allow_exceptions(allow_exceptions_)
10777 {
10778 // read first token
10779 get_token();
10780 }
10781
10782 /*!
10783 @brief public parser interface
10784
10785 @param[in] strict whether to expect the last token to be EOF
10786 @param[in,out] result parsed JSON value
10787
10788 @throw parse_error.101 in case of an unexpected token
10789 @throw parse_error.102 if to_unicode fails or surrogate error
10790 @throw parse_error.103 if to_unicode fails
10791 */
10792 void parse(const bool strict, BasicJsonType& result)
10793 {
10794 if (callback)
10795 {
10796 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
10797 sax_parse_internal(&sdp);
10798
10799 // in strict mode, input must be completely read
10800 if (strict && (get_token() != token_type::end_of_input))
10801 {
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()));
10806 }
10807
10808 // in case of an error, return discarded value
10809 if (sdp.is_errored())
10810 {
10811 result = value_t::discarded;
10812 return;
10813 }
10814
10815 // set top-level value to null if it was discarded by the callback
10816 // function
10817 if (result.is_discarded())
10818 {
10819 result = nullptr;
10820 }
10821 }
10822 else
10823 {
10824 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
10825 sax_parse_internal(&sdp);
10826
10827 // in strict mode, input must be completely read
10828 if (strict && (get_token() != token_type::end_of_input))
10829 {
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()));
10833 }
10834
10835 // in case of an error, return discarded value
10836 if (sdp.is_errored())
10837 {
10838 result = value_t::discarded;
10839 return;
10840 }
10841 }
10842
10843 result.assert_invariant();
10844 }
10845
10846 /*!
10847 @brief public accept interface
10848
10849 @param[in] strict whether to expect the last token to be EOF
10850 @return whether the input is a proper JSON text
10851 */
10852 bool accept(const bool strict = true)
10853 {
10854 json_sax_acceptor<BasicJsonType> sax_acceptor;
10855 return sax_parse(&sax_acceptor, strict);
10856 }
10857
10858 template<typename SAX>
10859 JSON_HEDLEY_NON_NULL(2)
10860 bool sax_parse(SAX* sax, const bool strict = true)
10861 {
10862 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
10863 const bool result = sax_parse_internal(sax);
10864
10865 // strict mode: next byte must be EOF
10866 if (result && strict && (get_token() != token_type::end_of_input))
10867 {
10868 return sax->parse_error(m_lexer.get_position(),
10869 m_lexer.get_token_string(),
10870 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
10871 }
10872
10873 return result;
10874 }
10875
10876 private:
10877 template<typename SAX>
10878 JSON_HEDLEY_NON_NULL(2)
10879 bool sax_parse_internal(SAX* sax)
10880 {
10881 // stack to remember the hierarchy of structured values we are parsing
10882 // true = array; false = object
10883 std::vector<bool> states;
10884 // value to avoid a goto (see comment where set to true)
10885 bool skip_to_state_evaluation = false;
10886
10887 while (true)
10888 {
10889 if (!skip_to_state_evaluation)
10890 {
10891 // invariant: get_token() was called before each iteration
10892 switch (last_token)
10893 {
10894 case token_type::begin_object:
10895 {
10896 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
10897 {
10898 return false;
10899 }
10900
10901 // closing } -> we are done
10902 if (get_token() == token_type::end_object)
10903 {
10904 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
10905 {
10906 return false;
10907 }
10908 break;
10909 }
10910
10911 // parse key
10912 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
10913 {
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()));
10917 }
10918 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
10919 {
10920 return false;
10921 }
10922
10923 // parse separator (:)
10924 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
10925 {
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()));
10929 }
10930
10931 // remember we are now inside an object
10932 states.push_back(false);
10933
10934 // parse values
10935 get_token();
10936 continue;
10937 }
10938
10939 case token_type::begin_array:
10940 {
10941 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
10942 {
10943 return false;
10944 }
10945
10946 // closing ] -> we are done
10947 if (get_token() == token_type::end_array)
10948 {
10949 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
10950 {
10951 return false;
10952 }
10953 break;
10954 }
10955
10956 // remember we are now inside an array
10957 states.push_back(true);
10958
10959 // parse values (no need to call get_token)
10960 continue;
10961 }
10962
10963 case token_type::value_float:
10964 {
10965 const auto res = m_lexer.get_number_float();
10966
10967 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
10968 {
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()));
10972 }
10973
10974 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
10975 {
10976 return false;
10977 }
10978
10979 break;
10980 }
10981
10982 case token_type::literal_false:
10983 {
10984 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
10985 {
10986 return false;
10987 }
10988 break;
10989 }
10990
10991 case token_type::literal_null:
10992 {
10993 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
10994 {
10995 return false;
10996 }
10997 break;
10998 }
10999
11000 case token_type::literal_true:
11001 {
11002 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
11003 {
11004 return false;
11005 }
11006 break;
11007 }
11008
11009 case token_type::value_integer:
11010 {
11011 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
11012 {
11013 return false;
11014 }
11015 break;
11016 }
11017
11018 case token_type::value_string:
11019 {
11020 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
11021 {
11022 return false;
11023 }
11024 break;
11025 }
11026
11027 case token_type::value_unsigned:
11028 {
11029 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
11030 {
11031 return false;
11032 }
11033 break;
11034 }
11035
11036 case token_type::parse_error:
11037 {
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()));
11042 }
11043
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
11052 {
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()));
11056 }
11057 }
11058 }
11059 else
11060 {
11061 skip_to_state_evaluation = false;
11062 }
11063
11064 // we reached this line after we successfully parsed a value
11065 if (states.empty())
11066 {
11067 // empty stack: we reached the end of the hierarchy: done
11068 return true;
11069 }
11070
11071 if (states.back()) // array
11072 {
11073 // comma -> next value
11074 if (get_token() == token_type::value_separator)
11075 {
11076 // parse a new value
11077 get_token();
11078 continue;
11079 }
11080
11081 // closing ]
11082 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
11083 {
11084 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
11085 {
11086 return false;
11087 }
11088
11089 // We are done with this array. Before we can parse a
11090 // new value, we need to evaluate the new state first.
11091 // By setting skip_to_state_evaluation to false, we
11092 // are effectively jumping to the beginning of this if.
11093 JSON_ASSERT(!states.empty());
11094 states.pop_back();
11095 skip_to_state_evaluation = true;
11096 continue;
11097 }
11098
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()));
11102 }
11103
11104 // states.back() is false -> object
11105
11106 // comma -> next value
11107 if (get_token() == token_type::value_separator)
11108 {
11109 // parse key
11110 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
11111 {
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()));
11115 }
11116
11117 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
11118 {
11119 return false;
11120 }
11121
11122 // parse separator (:)
11123 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
11124 {
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()));
11128 }
11129
11130 // parse values
11131 get_token();
11132 continue;
11133 }
11134
11135 // closing }
11136 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
11137 {
11138 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
11139 {
11140 return false;
11141 }
11142
11143 // We are done with this object. Before we can parse a
11144 // new value, we need to evaluate the new state first.
11145 // By setting skip_to_state_evaluation to false, we
11146 // are effectively jumping to the beginning of this if.
11147 JSON_ASSERT(!states.empty());
11148 states.pop_back();
11149 skip_to_state_evaluation = true;
11150 continue;
11151 }
11152
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()));
11156 }
11157 }
11158
11159 /// get next token from lexer
11160 token_type get_token()
11161 {
11162 return last_token = m_lexer.scan();
11163 }
11164
11165 std::string exception_message(const token_type expected, const std::string& context)
11166 {
11167 std::string error_msg = "syntax error ";
11168
11169 if (!context.empty())
11170 {
11171 error_msg += "while parsing " + context + " ";
11172 }
11173
11174 error_msg += "- ";
11175
11176 if (last_token == token_type::parse_error)
11177 {
11178 error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
11179 m_lexer.get_token_string() + "'";
11180 }
11181 else
11182 {
11183 error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
11184 }
11185
11186 if (expected != token_type::uninitialized)
11187 {
11188 error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
11189 }
11190
11191 return error_msg;
11192 }
11193
11194 private:
11195 /// callback function
11196 const parser_callback_t<BasicJsonType> callback = nullptr;
11197 /// the type of the last read token
11198 token_type last_token = token_type::uninitialized;
11199 /// the lexer
11200 lexer_t m_lexer;
11201 /// whether to throw exceptions in case of errors
11202 const bool allow_exceptions = true;
11203 };
11204
11205 } // namespace detail
11206 } // namespace nlohmann
11207
11208 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
11209
11210
11211 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
11212
11213
11214 #include <cstddef> // ptrdiff_t
11215 #include <limits> // numeric_limits
11216
11217 // #include <nlohmann/detail/macro_scope.hpp>
11218
11219
11220 namespace nlohmann
11221 {
11222 namespace detail
11223 {
11224 /*
11225 @brief an iterator for primitive JSON types
11226
11227 This class models an iterator for primitive JSON types (boolean, number,
11228 string). It's only purpose is to allow the iterator/const_iterator classes
11229 to "iterate" over primitive values. Internally, the iterator is modeled by
11230 a `difference_type` variable. Value begin_value (`0`) models the begin,
11231 end_value (`1`) models past the end.
11232 */
11233 class primitive_iterator_t
11234 {
11235 private:
11236 using difference_type = std::ptrdiff_t;
11237 static constexpr difference_type begin_value = 0;
11238 static constexpr difference_type end_value = begin_value + 1;
11239
11240 JSON_PRIVATE_UNLESS_TESTED:
11241 /// iterator as signed integer type
11242 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
11243
11244 public:
11245 constexpr difference_type get_value() const noexcept
11246 {
11247 return m_it;
11248 }
11249
11250 /// set iterator to a defined beginning
11251 void set_begin() noexcept
11252 {
11253 m_it = begin_value;
11254 }
11255
11256 /// set iterator to a defined past the end
11257 void set_end() noexcept
11258 {
11259 m_it = end_value;
11260 }
11261
11262 /// return whether the iterator can be dereferenced
11263 constexpr bool is_begin() const noexcept
11264 {
11265 return m_it == begin_value;
11266 }
11267
11268 /// return whether the iterator is at end
11269 constexpr bool is_end() const noexcept
11270 {
11271 return m_it == end_value;
11272 }
11273
11274 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
11275 {
11276 return lhs.m_it == rhs.m_it;
11277 }
11278
11279 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
11280 {
11281 return lhs.m_it < rhs.m_it;
11282 }
11283
11284 primitive_iterator_t operator+(difference_type n) noexcept
11285 {
11286 auto result = *this;
11287 result += n;
11288 return result;
11289 }
11290
11291 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
11292 {
11293 return lhs.m_it - rhs.m_it;
11294 }
11295
11296 primitive_iterator_t& operator++() noexcept
11297 {
11298 ++m_it;
11299 return *this;
11300 }
11301
11302 primitive_iterator_t const operator++(int) noexcept // NOLINT(readability-const-return-type)
11303 {
11304 auto result = *this;
11305 ++m_it;
11306 return result;
11307 }
11308
11309 primitive_iterator_t& operator--() noexcept
11310 {
11311 --m_it;
11312 return *this;
11313 }
11314
11315 primitive_iterator_t const operator--(int) noexcept // NOLINT(readability-const-return-type)
11316 {
11317 auto result = *this;
11318 --m_it;
11319 return result;
11320 }
11321
11322 primitive_iterator_t& operator+=(difference_type n) noexcept
11323 {
11324 m_it += n;
11325 return *this;
11326 }
11327
11328 primitive_iterator_t& operator-=(difference_type n) noexcept
11329 {
11330 m_it -= n;
11331 return *this;
11332 }
11333 };
11334 } // namespace detail
11335 } // namespace nlohmann
11336
11337
11338 namespace nlohmann
11339 {
11340 namespace detail
11341 {
11342 /*!
11343 @brief an iterator value
11344
11345 @note This structure could easily be a union, but MSVC currently does not allow
11346 unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
11347 */
11348 template<typename BasicJsonType> struct internal_iterator
11349 {
11350 /// iterator for JSON objects
11351 typename BasicJsonType::object_t::iterator object_iterator {};
11352 /// iterator for JSON arrays
11353 typename BasicJsonType::array_t::iterator array_iterator {};
11354 /// generic iterator for all other types
11355 primitive_iterator_t primitive_iterator {};
11356 };
11357 } // namespace detail
11358 } // namespace nlohmann
11359
11360 // #include <nlohmann/detail/iterators/iter_impl.hpp>
11361
11362
11363 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
11364 #include <type_traits> // conditional, is_const, remove_const
11365
11366 // #include <nlohmann/detail/exceptions.hpp>
11367
11368 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
11369
11370 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
11371
11372 // #include <nlohmann/detail/macro_scope.hpp>
11373
11374 // #include <nlohmann/detail/meta/cpp_future.hpp>
11375
11376 // #include <nlohmann/detail/meta/type_traits.hpp>
11377
11378 // #include <nlohmann/detail/value_t.hpp>
11379
11380
11381 namespace nlohmann
11382 {
11383 namespace detail
11384 {
11385 // forward declare, to be able to friend it later on
11386 template<typename IteratorType> class iteration_proxy;
11387 template<typename IteratorType> class iteration_proxy_value;
11388
11389 /*!
11390 @brief a template for a bidirectional iterator for the @ref basic_json class
11391 This class implements a both iterators (iterator and const_iterator) for the
11392 @ref basic_json class.
11393 @note An iterator is called *initialized* when a pointer to a JSON value has
11394 been set (e.g., by a constructor or a copy assignment). If the iterator is
11395 default-constructed, it is *uninitialized* and most methods are undefined.
11396 **The library uses assertions to detect calls on uninitialized iterators.**
11397 @requirement The class satisfies the following concept requirements:
11398 -
11399 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
11400 The iterator that can be moved can be moved in both directions (i.e.
11401 incremented and decremented).
11402 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional
11403 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
11404 */
11405 template<typename BasicJsonType>
11406 class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
11407 {
11408 /// the iterator with BasicJsonType of different const-ness
11409 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
11410 /// allow basic_json to access private members
11411 friend other_iter_impl;
11412 friend BasicJsonType;
11413 friend iteration_proxy<iter_impl>;
11414 friend iteration_proxy_value<iter_impl>;
11415
11416 using object_t = typename BasicJsonType::object_t;
11417 using array_t = typename BasicJsonType::array_t;
11418 // make sure BasicJsonType is basic_json or const basic_json
11419 static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
11420 "iter_impl only accepts (const) basic_json");
11421
11422 public:
11423
11424 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
11425 /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
11426 /// A user-defined iterator should provide publicly accessible typedefs named
11427 /// iterator_category, value_type, difference_type, pointer, and reference.
11428 /// Note that value_type is required to be non-const, even for constant iterators.
11429 using iterator_category = std::bidirectional_iterator_tag;
11430
11431 /// the type of the values when the iterator is dereferenced
11432 using value_type = typename BasicJsonType::value_type;
11433 /// a type to represent differences between iterators
11434 using difference_type = typename BasicJsonType::difference_type;
11435 /// defines a pointer to the type iterated over (value_type)
11436 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
11437 typename BasicJsonType::const_pointer,
11438 typename BasicJsonType::pointer>::type;
11439 /// defines a reference to the type iterated over (value_type)
11440 using reference =
11441 typename std::conditional<std::is_const<BasicJsonType>::value,
11442 typename BasicJsonType::const_reference,
11443 typename BasicJsonType::reference>::type;
11444
11445 iter_impl() = default;
11446 ~iter_impl() = default;
11447 iter_impl(iter_impl&&) noexcept = default;
11448 iter_impl& operator=(iter_impl&&) noexcept = default;
11449
11450 /*!
11451 @brief constructor for a given JSON instance
11452 @param[in] object pointer to a JSON object for this iterator
11453 @pre object != nullptr
11454 @post The iterator is initialized; i.e. `m_object != nullptr`.
11455 */
11456 explicit iter_impl(pointer object) noexcept : m_object(object)
11457 {
11458 JSON_ASSERT(m_object != nullptr);
11459
11460 switch (m_object->m_type)
11461 {
11462 case value_t::object:
11463 {
11464 m_it.object_iterator = typename object_t::iterator();
11465 break;
11466 }
11467
11468 case value_t::array:
11469 {
11470 m_it.array_iterator = typename array_t::iterator();
11471 break;
11472 }
11473
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:
11482 default:
11483 {
11484 m_it.primitive_iterator = primitive_iterator_t();
11485 break;
11486 }
11487 }
11488 }
11489
11490 /*!
11491 @note The conventional copy constructor and copy assignment are implicitly
11492 defined. Combined with the following converting constructor and
11493 assignment, they support: (1) copy from iterator to iterator, (2)
11494 copy from const iterator to const iterator, and (3) conversion from
11495 iterator to const iterator. However conversion from const iterator
11496 to iterator is not defined.
11497 */
11498
11499 /*!
11500 @brief const copy constructor
11501 @param[in] other const iterator to copy from
11502 @note This copy constructor had to be defined explicitly to circumvent a bug
11503 occurring on msvc v19.0 compiler (VS 2015) debug build. For more
11504 information refer to: https://github.com/nlohmann/json/issues/1608
11505 */
11506 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
11507 : m_object(other.m_object), m_it(other.m_it)
11508 {}
11509
11510 /*!
11511 @brief converting assignment
11512 @param[in] other const iterator to copy from
11513 @return const/non-const iterator
11514 @note It is not checked whether @a other is initialized.
11515 */
11516 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
11517 {
11518 if (&other != this)
11519 {
11520 m_object = other.m_object;
11521 m_it = other.m_it;
11522 }
11523 return *this;
11524 }
11525
11526 /*!
11527 @brief converting constructor
11528 @param[in] other non-const iterator to copy from
11529 @note It is not checked whether @a other is initialized.
11530 */
11531 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
11532 : m_object(other.m_object), m_it(other.m_it)
11533 {}
11534
11535 /*!
11536 @brief converting assignment
11537 @param[in] other non-const iterator to copy from
11538 @return const/non-const iterator
11539 @note It is not checked whether @a other is initialized.
11540 */
11541 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
11542 {
11543 m_object = other.m_object;
11544 m_it = other.m_it;
11545 return *this;
11546 }
11547
11548 JSON_PRIVATE_UNLESS_TESTED:
11549 /*!
11550 @brief set the iterator to the first value
11551 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11552 */
11553 void set_begin() noexcept
11554 {
11555 JSON_ASSERT(m_object != nullptr);
11556
11557 switch (m_object->m_type)
11558 {
11559 case value_t::object:
11560 {
11561 m_it.object_iterator = m_object->m_value.object->begin();
11562 break;
11563 }
11564
11565 case value_t::array:
11566 {
11567 m_it.array_iterator = m_object->m_value.array->begin();
11568 break;
11569 }
11570
11571 case value_t::null:
11572 {
11573 // set to end so begin()==end() is true: null is empty
11574 m_it.primitive_iterator.set_end();
11575 break;
11576 }
11577
11578 case value_t::string:
11579 case value_t::boolean:
11580 case value_t::number_integer:
11581 case value_t::number_unsigned:
11582 case value_t::number_float:
11583 case value_t::binary:
11584 case value_t::discarded:
11585 default:
11586 {
11587 m_it.primitive_iterator.set_begin();
11588 break;
11589 }
11590 }
11591 }
11592
11593 /*!
11594 @brief set the iterator past the last value
11595 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11596 */
11597 void set_end() noexcept
11598 {
11599 JSON_ASSERT(m_object != nullptr);
11600
11601 switch (m_object->m_type)
11602 {
11603 case value_t::object:
11604 {
11605 m_it.object_iterator = m_object->m_value.object->end();
11606 break;
11607 }
11608
11609 case value_t::array:
11610 {
11611 m_it.array_iterator = m_object->m_value.array->end();
11612 break;
11613 }
11614
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:
11623 default:
11624 {
11625 m_it.primitive_iterator.set_end();
11626 break;
11627 }
11628 }
11629 }
11630
11631 public:
11632 /*!
11633 @brief return a reference to the value pointed to by the iterator
11634 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11635 */
11636 reference operator*() const
11637 {
11638 JSON_ASSERT(m_object != nullptr);
11639
11640 switch (m_object->m_type)
11641 {
11642 case value_t::object:
11643 {
11644 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
11645 return m_it.object_iterator->second;
11646 }
11647
11648 case value_t::array:
11649 {
11650 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
11651 return *m_it.array_iterator;
11652 }
11653
11654 case value_t::null:
11655 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11656
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:
11664 default:
11665 {
11666 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
11667 {
11668 return *m_object;
11669 }
11670
11671 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11672 }
11673 }
11674 }
11675
11676 /*!
11677 @brief dereference the iterator
11678 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11679 */
11680 pointer operator->() const
11681 {
11682 JSON_ASSERT(m_object != nullptr);
11683
11684 switch (m_object->m_type)
11685 {
11686 case value_t::object:
11687 {
11688 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
11689 return &(m_it.object_iterator->second);
11690 }
11691
11692 case value_t::array:
11693 {
11694 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
11695 return &*m_it.array_iterator;
11696 }
11697
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:
11706 default:
11707 {
11708 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
11709 {
11710 return m_object;
11711 }
11712
11713 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11714 }
11715 }
11716 }
11717
11718 /*!
11719 @brief post-increment (it++)
11720 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11721 */
11722 iter_impl const operator++(int) // NOLINT(readability-const-return-type)
11723 {
11724 auto result = *this;
11725 ++(*this);
11726 return result;
11727 }
11728
11729 /*!
11730 @brief pre-increment (++it)
11731 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11732 */
11733 iter_impl& operator++()
11734 {
11735 JSON_ASSERT(m_object != nullptr);
11736
11737 switch (m_object->m_type)
11738 {
11739 case value_t::object:
11740 {
11741 std::advance(m_it.object_iterator, 1);
11742 break;
11743 }
11744
11745 case value_t::array:
11746 {
11747 std::advance(m_it.array_iterator, 1);
11748 break;
11749 }
11750
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:
11759 default:
11760 {
11761 ++m_it.primitive_iterator;
11762 break;
11763 }
11764 }
11765
11766 return *this;
11767 }
11768
11769 /*!
11770 @brief post-decrement (it--)
11771 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11772 */
11773 iter_impl const operator--(int) // NOLINT(readability-const-return-type)
11774 {
11775 auto result = *this;
11776 --(*this);
11777 return result;
11778 }
11779
11780 /*!
11781 @brief pre-decrement (--it)
11782 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11783 */
11784 iter_impl& operator--()
11785 {
11786 JSON_ASSERT(m_object != nullptr);
11787
11788 switch (m_object->m_type)
11789 {
11790 case value_t::object:
11791 {
11792 std::advance(m_it.object_iterator, -1);
11793 break;
11794 }
11795
11796 case value_t::array:
11797 {
11798 std::advance(m_it.array_iterator, -1);
11799 break;
11800 }
11801
11802 case value_t::null:
11803 case value_t::string:
11804 case value_t::boolean:
11805 case value_t::number_integer:
11806 case value_t::number_unsigned:
11807 case value_t::number_float:
11808 case value_t::binary:
11809 case value_t::discarded:
11810 default:
11811 {
11812 --m_it.primitive_iterator;
11813 break;
11814 }
11815 }
11816
11817 return *this;
11818 }
11819
11820 /*!
11821 @brief comparison: equal
11822 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11823 */
11824 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
11825 bool operator==(const IterImpl& other) const
11826 {
11827 // if objects are not the same, the comparison is undefined
11828 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
11829 {
11830 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
11831 }
11832
11833 JSON_ASSERT(m_object != nullptr);
11834
11835 switch (m_object->m_type)
11836 {
11837 case value_t::object:
11838 return (m_it.object_iterator == other.m_it.object_iterator);
11839
11840 case value_t::array:
11841 return (m_it.array_iterator == other.m_it.array_iterator);
11842
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:
11851 default:
11852 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
11853 }
11854 }
11855
11856 /*!
11857 @brief comparison: not equal
11858 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11859 */
11860 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
11861 bool operator!=(const IterImpl& other) const
11862 {
11863 return !operator==(other);
11864 }
11865
11866 /*!
11867 @brief comparison: smaller
11868 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11869 */
11870 bool operator<(const iter_impl& other) const
11871 {
11872 // if objects are not the same, the comparison is undefined
11873 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
11874 {
11875 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
11876 }
11877
11878 JSON_ASSERT(m_object != nullptr);
11879
11880 switch (m_object->m_type)
11881 {
11882 case value_t::object:
11883 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object));
11884
11885 case value_t::array:
11886 return (m_it.array_iterator < other.m_it.array_iterator);
11887
11888 case value_t::null:
11889 case value_t::string:
11890 case value_t::boolean:
11891 case value_t::number_integer:
11892 case value_t::number_unsigned:
11893 case value_t::number_float:
11894 case value_t::binary:
11895 case value_t::discarded:
11896 default:
11897 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
11898 }
11899 }
11900
11901 /*!
11902 @brief comparison: less than or equal
11903 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11904 */
11905 bool operator<=(const iter_impl& other) const
11906 {
11907 return !other.operator < (*this);
11908 }
11909
11910 /*!
11911 @brief comparison: greater than
11912 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11913 */
11914 bool operator>(const iter_impl& other) const
11915 {
11916 return !operator<=(other);
11917 }
11918
11919 /*!
11920 @brief comparison: greater than or equal
11921 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11922 */
11923 bool operator>=(const iter_impl& other) const
11924 {
11925 return !operator<(other);
11926 }
11927
11928 /*!
11929 @brief add to iterator
11930 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11931 */
11932 iter_impl& operator+=(difference_type i)
11933 {
11934 JSON_ASSERT(m_object != nullptr);
11935
11936 switch (m_object->m_type)
11937 {
11938 case value_t::object:
11939 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
11940
11941 case value_t::array:
11942 {
11943 std::advance(m_it.array_iterator, i);
11944 break;
11945 }
11946
11947 case value_t::null:
11948 case value_t::string:
11949 case value_t::boolean:
11950 case value_t::number_integer:
11951 case value_t::number_unsigned:
11952 case value_t::number_float:
11953 case value_t::binary:
11954 case value_t::discarded:
11955 default:
11956 {
11957 m_it.primitive_iterator += i;
11958 break;
11959 }
11960 }
11961
11962 return *this;
11963 }
11964
11965 /*!
11966 @brief subtract from iterator
11967 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11968 */
11969 iter_impl& operator-=(difference_type i)
11970 {
11971 return operator+=(-i);
11972 }
11973
11974 /*!
11975 @brief add to iterator
11976 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11977 */
11978 iter_impl operator+(difference_type i) const
11979 {
11980 auto result = *this;
11981 result += i;
11982 return result;
11983 }
11984
11985 /*!
11986 @brief addition of distance and iterator
11987 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11988 */
11989 friend iter_impl operator+(difference_type i, const iter_impl& it)
11990 {
11991 auto result = it;
11992 result += i;
11993 return result;
11994 }
11995
11996 /*!
11997 @brief subtract from iterator
11998 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11999 */
12000 iter_impl operator-(difference_type i) const
12001 {
12002 auto result = *this;
12003 result -= i;
12004 return result;
12005 }
12006
12007 /*!
12008 @brief return difference
12009 @pre The iterator is initialized; i.e. `m_object != nullptr`.
12010 */
12011 difference_type operator-(const iter_impl& other) const
12012 {
12013 JSON_ASSERT(m_object != nullptr);
12014
12015 switch (m_object->m_type)
12016 {
12017 case value_t::object:
12018 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
12019
12020 case value_t::array:
12021 return m_it.array_iterator - other.m_it.array_iterator;
12022
12023 case value_t::null:
12024 case value_t::string:
12025 case value_t::boolean:
12026 case value_t::number_integer:
12027 case value_t::number_unsigned:
12028 case value_t::number_float:
12029 case value_t::binary:
12030 case value_t::discarded:
12031 default:
12032 return m_it.primitive_iterator - other.m_it.primitive_iterator;
12033 }
12034 }
12035
12036 /*!
12037 @brief access to successor
12038 @pre The iterator is initialized; i.e. `m_object != nullptr`.
12039 */
12040 reference operator[](difference_type n) const
12041 {
12042 JSON_ASSERT(m_object != nullptr);
12043
12044 switch (m_object->m_type)
12045 {
12046 case value_t::object:
12047 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object));
12048
12049 case value_t::array:
12050 return *std::next(m_it.array_iterator, n);
12051
12052 case value_t::null:
12053 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
12054
12055 case value_t::string:
12056 case value_t::boolean:
12057 case value_t::number_integer:
12058 case value_t::number_unsigned:
12059 case value_t::number_float:
12060 case value_t::binary:
12061 case value_t::discarded:
12062 default:
12063 {
12064 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
12065 {
12066 return *m_object;
12067 }
12068
12069 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
12070 }
12071 }
12072 }
12073
12074 /*!
12075 @brief return the key of an object iterator
12076 @pre The iterator is initialized; i.e. `m_object != nullptr`.
12077 */
12078 const typename object_t::key_type& key() const
12079 {
12080 JSON_ASSERT(m_object != nullptr);
12081
12082 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
12083 {
12084 return m_it.object_iterator->first;
12085 }
12086
12087 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object));
12088 }
12089
12090 /*!
12091 @brief return the value of an iterator
12092 @pre The iterator is initialized; i.e. `m_object != nullptr`.
12093 */
12094 reference value() const
12095 {
12096 return operator*();
12097 }
12098
12099 JSON_PRIVATE_UNLESS_TESTED:
12100 /// associated JSON instance
12101 pointer m_object = nullptr;
12102 /// the actual iterator of the associated instance
12103 internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
12104 };
12105 } // namespace detail
12106 } // namespace nlohmann
12107
12108 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
12109
12110 // #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
12111
12112
12113 #include <cstddef> // ptrdiff_t
12114 #include <iterator> // reverse_iterator
12115 #include <utility> // declval
12116
12117 namespace nlohmann
12118 {
12119 namespace detail
12120 {
12121 //////////////////////
12122 // reverse_iterator //
12123 //////////////////////
12124
12125 /*!
12126 @brief a template for a reverse iterator class
12127
12128 @tparam Base the base iterator type to reverse. Valid types are @ref
12129 iterator (to create @ref reverse_iterator) and @ref const_iterator (to
12130 create @ref const_reverse_iterator).
12131
12132 @requirement The class satisfies the following concept requirements:
12133 -
12134 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
12135 The iterator that can be moved can be moved in both directions (i.e.
12136 incremented and decremented).
12137 - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
12138 It is possible to write to the pointed-to element (only if @a Base is
12139 @ref iterator).
12140
12141 @since version 1.0.0
12142 */
12143 template<typename Base>
12144 class json_reverse_iterator : public std::reverse_iterator<Base>
12145 {
12146 public:
12147 using difference_type = std::ptrdiff_t;
12148 /// shortcut to the reverse iterator adapter
12149 using base_iterator = std::reverse_iterator<Base>;
12150 /// the reference type for the pointed-to element
12151 using reference = typename Base::reference;
12152
12153 /// create reverse iterator from iterator
12154 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
12155 : base_iterator(it) {}
12156
12157 /// create reverse iterator from base class
12158 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
12159
12160 /// post-increment (it++)
12161 json_reverse_iterator const operator++(int) // NOLINT(readability-const-return-type)
12162 {
12163 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
12164 }
12165
12166 /// pre-increment (++it)
12167 json_reverse_iterator& operator++()
12168 {
12169 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
12170 }
12171
12172 /// post-decrement (it--)
12173 json_reverse_iterator const operator--(int) // NOLINT(readability-const-return-type)
12174 {
12175 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
12176 }
12177
12178 /// pre-decrement (--it)
12179 json_reverse_iterator& operator--()
12180 {
12181 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
12182 }
12183
12184 /// add to iterator
12185 json_reverse_iterator& operator+=(difference_type i)
12186 {
12187 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
12188 }
12189
12190 /// add to iterator
12191 json_reverse_iterator operator+(difference_type i) const
12192 {
12193 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
12194 }
12195
12196 /// subtract from iterator
12197 json_reverse_iterator operator-(difference_type i) const
12198 {
12199 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
12200 }
12201
12202 /// return difference
12203 difference_type operator-(const json_reverse_iterator& other) const
12204 {
12205 return base_iterator(*this) - base_iterator(other);
12206 }
12207
12208 /// access to successor
12209 reference operator[](difference_type n) const
12210 {
12211 return *(this->operator+(n));
12212 }
12213
12214 /// return the key of an object iterator
12215 auto key() const -> decltype(std::declval<Base>().key())
12216 {
12217 auto it = --this->base();
12218 return it.key();
12219 }
12220
12221 /// return the value of an iterator
12222 reference value() const
12223 {
12224 auto it = --this->base();
12225 return it.operator * ();
12226 }
12227 };
12228 } // namespace detail
12229 } // namespace nlohmann
12230
12231 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12232
12233 // #include <nlohmann/detail/json_pointer.hpp>
12234
12235
12236 #include <algorithm> // all_of
12237 #include <cctype> // isdigit
12238 #include <limits> // max
12239 #include <numeric> // accumulate
12240 #include <string> // string
12241 #include <utility> // move
12242 #include <vector> // vector
12243
12244 // #include <nlohmann/detail/exceptions.hpp>
12245
12246 // #include <nlohmann/detail/macro_scope.hpp>
12247
12248 // #include <nlohmann/detail/string_escape.hpp>
12249
12250 // #include <nlohmann/detail/value_t.hpp>
12251
12252
12253 namespace nlohmann
12254 {
12255
12256 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
12257 /// @sa https://json.nlohmann.me/api/json_pointer/
12258 template<typename BasicJsonType>
12259 class json_pointer
12260 {
12261 // allow basic_json to access private members
12262 NLOHMANN_BASIC_JSON_TPL_DECLARATION
12263 friend class basic_json;
12264
12265 public:
12266 /// @brief create JSON pointer
12267 /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
12268 explicit json_pointer(const std::string& s = "")
12269 : reference_tokens(split(s))
12270 {}
12271
12272 /// @brief return a string representation of the JSON pointer
12273 /// @sa https://json.nlohmann.me/api/json_pointer/to_string/
12274 std::string to_string() const
12275 {
12276 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
12277 std::string{},
12278 [](const std::string & a, const std::string & b)
12279 {
12280 return a + "/" + detail::escape(b);
12281 });
12282 }
12283
12284 /// @brief return a string representation of the JSON pointer
12285 /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
12286 operator std::string() const
12287 {
12288 return to_string();
12289 }
12290
12291 /// @brief append another JSON pointer at the end of this JSON pointer
12292 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
12293 json_pointer& operator/=(const json_pointer& ptr)
12294 {
12295 reference_tokens.insert(reference_tokens.end(),
12296 ptr.reference_tokens.begin(),
12297 ptr.reference_tokens.end());
12298 return *this;
12299 }
12300
12301 /// @brief append an unescaped reference token at the end of this JSON pointer
12302 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
12303 json_pointer& operator/=(std::string token)
12304 {
12305 push_back(std::move(token));
12306 return *this;
12307 }
12308
12309 /// @brief append an array index at the end of this JSON pointer
12310 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
12311 json_pointer& operator/=(std::size_t array_idx)
12312 {
12313 return *this /= std::to_string(array_idx);
12314 }
12315
12316 /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
12317 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
12318 friend json_pointer operator/(const json_pointer& lhs,
12319 const json_pointer& rhs)
12320 {
12321 return json_pointer(lhs) /= rhs;
12322 }
12323
12324 /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
12325 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
12326 friend json_pointer operator/(const json_pointer& lhs, std::string token) // NOLINT(performance-unnecessary-value-param)
12327 {
12328 return json_pointer(lhs) /= std::move(token);
12329 }
12330
12331 /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
12332 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
12333 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
12334 {
12335 return json_pointer(lhs) /= array_idx;
12336 }
12337
12338 /// @brief returns the parent of this JSON pointer
12339 /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
12340 json_pointer parent_pointer() const
12341 {
12342 if (empty())
12343 {
12344 return *this;
12345 }
12346
12347 json_pointer res = *this;
12348 res.pop_back();
12349 return res;
12350 }
12351
12352 /// @brief remove last reference token
12353 /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
12354 void pop_back()
12355 {
12356 if (JSON_HEDLEY_UNLIKELY(empty()))
12357 {
12358 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
12359 }
12360
12361 reference_tokens.pop_back();
12362 }
12363
12364 /// @brief return last reference token
12365 /// @sa https://json.nlohmann.me/api/json_pointer/back/
12366 const std::string& back() const
12367 {
12368 if (JSON_HEDLEY_UNLIKELY(empty()))
12369 {
12370 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
12371 }
12372
12373 return reference_tokens.back();
12374 }
12375
12376 /// @brief append an unescaped token at the end of the reference pointer
12377 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
12378 void push_back(const std::string& token)
12379 {
12380 reference_tokens.push_back(token);
12381 }
12382
12383 /// @brief append an unescaped token at the end of the reference pointer
12384 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
12385 void push_back(std::string&& token)
12386 {
12387 reference_tokens.push_back(std::move(token));
12388 }
12389
12390 /// @brief return whether pointer points to the root document
12391 /// @sa https://json.nlohmann.me/api/json_pointer/empty/
12392 bool empty() const noexcept
12393 {
12394 return reference_tokens.empty();
12395 }
12396
12397 private:
12398 /*!
12399 @param[in] s reference token to be converted into an array index
12400
12401 @return integer representation of @a s
12402
12403 @throw parse_error.106 if an array index begins with '0'
12404 @throw parse_error.109 if an array index begins not with a digit
12405 @throw out_of_range.404 if string @a s could not be converted to an integer
12406 @throw out_of_range.410 if an array index exceeds size_type
12407 */
12408 static typename BasicJsonType::size_type array_index(const std::string& s)
12409 {
12410 using size_type = typename BasicJsonType::size_type;
12411
12412 // error condition (cf. RFC 6901, Sect. 4)
12413 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
12414 {
12415 JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", BasicJsonType()));
12416 }
12417
12418 // error condition (cf. RFC 6901, Sect. 4)
12419 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
12420 {
12421 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType()));
12422 }
12423
12424 std::size_t processed_chars = 0;
12425 unsigned long long res = 0; // NOLINT(runtime/int)
12426 JSON_TRY
12427 {
12428 res = std::stoull(s, &processed_chars);
12429 }
12430 JSON_CATCH(std::out_of_range&)
12431 {
12432 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
12433 }
12434
12435 // check if the string was completely read
12436 if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
12437 {
12438 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
12439 }
12440
12441 // only triggered on special platforms (like 32bit), see also
12442 // https://github.com/nlohmann/json/pull/2203
12443 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
12444 {
12445 JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", BasicJsonType())); // LCOV_EXCL_LINE
12446 }
12447
12448 return static_cast<size_type>(res);
12449 }
12450
12451 JSON_PRIVATE_UNLESS_TESTED:
12452 json_pointer top() const
12453 {
12454 if (JSON_HEDLEY_UNLIKELY(empty()))
12455 {
12456 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
12457 }
12458
12459 json_pointer result = *this;
12460 result.reference_tokens = {reference_tokens[0]};
12461 return result;
12462 }
12463
12464 private:
12465 /*!
12466 @brief create and return a reference to the pointed to value
12467
12468 @complexity Linear in the number of reference tokens.
12469
12470 @throw parse_error.109 if array index is not a number
12471 @throw type_error.313 if value cannot be unflattened
12472 */
12473 BasicJsonType& get_and_create(BasicJsonType& j) const
12474 {
12475 auto* result = &j;
12476
12477 // in case no reference tokens exist, return a reference to the JSON value
12478 // j which will be overwritten by a primitive value
12479 for (const auto& reference_token : reference_tokens)
12480 {
12481 switch (result->type())
12482 {
12483 case detail::value_t::null:
12484 {
12485 if (reference_token == "0")
12486 {
12487 // start a new array if reference token is 0
12488 result = &result->operator[](0);
12489 }
12490 else
12491 {
12492 // start a new object otherwise
12493 result = &result->operator[](reference_token);
12494 }
12495 break;
12496 }
12497
12498 case detail::value_t::object:
12499 {
12500 // create an entry in the object
12501 result = &result->operator[](reference_token);
12502 break;
12503 }
12504
12505 case detail::value_t::array:
12506 {
12507 // create an entry in the array
12508 result = &result->operator[](array_index(reference_token));
12509 break;
12510 }
12511
12512 /*
12513 The following code is only reached if there exists a reference
12514 token _and_ the current value is primitive. In this case, we have
12515 an error situation, because primitive values may only occur as
12516 single value; that is, with an empty list of reference tokens.
12517 */
12518 case detail::value_t::string:
12519 case detail::value_t::boolean:
12520 case detail::value_t::number_integer:
12521 case detail::value_t::number_unsigned:
12522 case detail::value_t::number_float:
12523 case detail::value_t::binary:
12524 case detail::value_t::discarded:
12525 default:
12526 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j));
12527 }
12528 }
12529
12530 return *result;
12531 }
12532
12533 /*!
12534 @brief return a reference to the pointed to value
12535
12536 @note This version does not throw if a value is not present, but tries to
12537 create nested values instead. For instance, calling this function
12538 with pointer `"/this/that"` on a null value is equivalent to calling
12539 `operator[]("this").operator[]("that")` on that value, effectively
12540 changing the null value to an object.
12541
12542 @param[in] ptr a JSON value
12543
12544 @return reference to the JSON value pointed to by the JSON pointer
12545
12546 @complexity Linear in the length of the JSON pointer.
12547
12548 @throw parse_error.106 if an array index begins with '0'
12549 @throw parse_error.109 if an array index was not a number
12550 @throw out_of_range.404 if the JSON pointer can not be resolved
12551 */
12552 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
12553 {
12554 for (const auto& reference_token : reference_tokens)
12555 {
12556 // convert null values to arrays or objects before continuing
12557 if (ptr->is_null())
12558 {
12559 // check if reference token is a number
12560 const bool nums =
12561 std::all_of(reference_token.begin(), reference_token.end(),
12562 [](const unsigned char x)
12563 {
12564 return std::isdigit(x);
12565 });
12566
12567 // change value to array for numbers or "-" or to object otherwise
12568 *ptr = (nums || reference_token == "-")
12569 ? detail::value_t::array
12570 : detail::value_t::object;
12571 }
12572
12573 switch (ptr->type())
12574 {
12575 case detail::value_t::object:
12576 {
12577 // use unchecked object access
12578 ptr = &ptr->operator[](reference_token);
12579 break;
12580 }
12581
12582 case detail::value_t::array:
12583 {
12584 if (reference_token == "-")
12585 {
12586 // explicitly treat "-" as index beyond the end
12587 ptr = &ptr->operator[](ptr->m_value.array->size());
12588 }
12589 else
12590 {
12591 // convert array index to number; unchecked access
12592 ptr = &ptr->operator[](array_index(reference_token));
12593 }
12594 break;
12595 }
12596
12597 case detail::value_t::null:
12598 case detail::value_t::string:
12599 case detail::value_t::boolean:
12600 case detail::value_t::number_integer:
12601 case detail::value_t::number_unsigned:
12602 case detail::value_t::number_float:
12603 case detail::value_t::binary:
12604 case detail::value_t::discarded:
12605 default:
12606 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
12607 }
12608 }
12609
12610 return *ptr;
12611 }
12612
12613 /*!
12614 @throw parse_error.106 if an array index begins with '0'
12615 @throw parse_error.109 if an array index was not a number
12616 @throw out_of_range.402 if the array index '-' is used
12617 @throw out_of_range.404 if the JSON pointer can not be resolved
12618 */
12619 BasicJsonType& get_checked(BasicJsonType* ptr) const
12620 {
12621 for (const auto& reference_token : reference_tokens)
12622 {
12623 switch (ptr->type())
12624 {
12625 case detail::value_t::object:
12626 {
12627 // note: at performs range check
12628 ptr = &ptr->at(reference_token);
12629 break;
12630 }
12631
12632 case detail::value_t::array:
12633 {
12634 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12635 {
12636 // "-" always fails the range check
12637 JSON_THROW(detail::out_of_range::create(402,
12638 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12639 ") is out of range", *ptr));
12640 }
12641
12642 // note: at performs range check
12643 ptr = &ptr->at(array_index(reference_token));
12644 break;
12645 }
12646
12647 case detail::value_t::null:
12648 case detail::value_t::string:
12649 case detail::value_t::boolean:
12650 case detail::value_t::number_integer:
12651 case detail::value_t::number_unsigned:
12652 case detail::value_t::number_float:
12653 case detail::value_t::binary:
12654 case detail::value_t::discarded:
12655 default:
12656 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
12657 }
12658 }
12659
12660 return *ptr;
12661 }
12662
12663 /*!
12664 @brief return a const reference to the pointed to value
12665
12666 @param[in] ptr a JSON value
12667
12668 @return const reference to the JSON value pointed to by the JSON
12669 pointer
12670
12671 @throw parse_error.106 if an array index begins with '0'
12672 @throw parse_error.109 if an array index was not a number
12673 @throw out_of_range.402 if the array index '-' is used
12674 @throw out_of_range.404 if the JSON pointer can not be resolved
12675 */
12676 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
12677 {
12678 for (const auto& reference_token : reference_tokens)
12679 {
12680 switch (ptr->type())
12681 {
12682 case detail::value_t::object:
12683 {
12684 // use unchecked object access
12685 ptr = &ptr->operator[](reference_token);
12686 break;
12687 }
12688
12689 case detail::value_t::array:
12690 {
12691 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12692 {
12693 // "-" cannot be used for const access
12694 JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range", *ptr));
12695 }
12696
12697 // use unchecked array access
12698 ptr = &ptr->operator[](array_index(reference_token));
12699 break;
12700 }
12701
12702 case detail::value_t::null:
12703 case detail::value_t::string:
12704 case detail::value_t::boolean:
12705 case detail::value_t::number_integer:
12706 case detail::value_t::number_unsigned:
12707 case detail::value_t::number_float:
12708 case detail::value_t::binary:
12709 case detail::value_t::discarded:
12710 default:
12711 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
12712 }
12713 }
12714
12715 return *ptr;
12716 }
12717
12718 /*!
12719 @throw parse_error.106 if an array index begins with '0'
12720 @throw parse_error.109 if an array index was not a number
12721 @throw out_of_range.402 if the array index '-' is used
12722 @throw out_of_range.404 if the JSON pointer can not be resolved
12723 */
12724 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
12725 {
12726 for (const auto& reference_token : reference_tokens)
12727 {
12728 switch (ptr->type())
12729 {
12730 case detail::value_t::object:
12731 {
12732 // note: at performs range check
12733 ptr = &ptr->at(reference_token);
12734 break;
12735 }
12736
12737 case detail::value_t::array:
12738 {
12739 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12740 {
12741 // "-" always fails the range check
12742 JSON_THROW(detail::out_of_range::create(402,
12743 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12744 ") is out of range", *ptr));
12745 }
12746
12747 // note: at performs range check
12748 ptr = &ptr->at(array_index(reference_token));
12749 break;
12750 }
12751
12752 case detail::value_t::null:
12753 case detail::value_t::string:
12754 case detail::value_t::boolean:
12755 case detail::value_t::number_integer:
12756 case detail::value_t::number_unsigned:
12757 case detail::value_t::number_float:
12758 case detail::value_t::binary:
12759 case detail::value_t::discarded:
12760 default:
12761 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
12762 }
12763 }
12764
12765 return *ptr;
12766 }
12767
12768 /*!
12769 @throw parse_error.106 if an array index begins with '0'
12770 @throw parse_error.109 if an array index was not a number
12771 */
12772 bool contains(const BasicJsonType* ptr) const
12773 {
12774 for (const auto& reference_token : reference_tokens)
12775 {
12776 switch (ptr->type())
12777 {
12778 case detail::value_t::object:
12779 {
12780 if (!ptr->contains(reference_token))
12781 {
12782 // we did not find the key in the object
12783 return false;
12784 }
12785
12786 ptr = &ptr->operator[](reference_token);
12787 break;
12788 }
12789
12790 case detail::value_t::array:
12791 {
12792 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12793 {
12794 // "-" always fails the range check
12795 return false;
12796 }
12797 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
12798 {
12799 // invalid char
12800 return false;
12801 }
12802 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
12803 {
12804 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
12805 {
12806 // first char should be between '1' and '9'
12807 return false;
12808 }
12809 for (std::size_t i = 1; i < reference_token.size(); i++)
12810 {
12811 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
12812 {
12813 // other char should be between '0' and '9'
12814 return false;
12815 }
12816 }
12817 }
12818
12819 const auto idx = array_index(reference_token);
12820 if (idx >= ptr->size())
12821 {
12822 // index out of range
12823 return false;
12824 }
12825
12826 ptr = &ptr->operator[](idx);
12827 break;
12828 }
12829
12830 case detail::value_t::null:
12831 case detail::value_t::string:
12832 case detail::value_t::boolean:
12833 case detail::value_t::number_integer:
12834 case detail::value_t::number_unsigned:
12835 case detail::value_t::number_float:
12836 case detail::value_t::binary:
12837 case detail::value_t::discarded:
12838 default:
12839 {
12840 // we do not expect primitive values if there is still a
12841 // reference token to process
12842 return false;
12843 }
12844 }
12845 }
12846
12847 // no reference token left means we found a primitive value
12848 return true;
12849 }
12850
12851 /*!
12852 @brief split the string input to reference tokens
12853
12854 @note This function is only called by the json_pointer constructor.
12855 All exceptions below are documented there.
12856
12857 @throw parse_error.107 if the pointer is not empty or begins with '/'
12858 @throw parse_error.108 if character '~' is not followed by '0' or '1'
12859 */
12860 static std::vector<std::string> split(const std::string& reference_string)
12861 {
12862 std::vector<std::string> result;
12863
12864 // special case: empty reference string -> no reference tokens
12865 if (reference_string.empty())
12866 {
12867 return result;
12868 }
12869
12870 // check if nonempty reference string begins with slash
12871 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
12872 {
12873 JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", BasicJsonType()));
12874 }
12875
12876 // extract the reference tokens:
12877 // - slash: position of the last read slash (or end of string)
12878 // - start: position after the previous slash
12879 for (
12880 // search for the first slash after the first character
12881 std::size_t slash = reference_string.find_first_of('/', 1),
12882 // set the beginning of the first reference token
12883 start = 1;
12884 // we can stop if start == 0 (if slash == std::string::npos)
12885 start != 0;
12886 // set the beginning of the next reference token
12887 // (will eventually be 0 if slash == std::string::npos)
12888 start = (slash == std::string::npos) ? 0 : slash + 1,
12889 // find next slash
12890 slash = reference_string.find_first_of('/', start))
12891 {
12892 // use the text between the beginning of the reference token
12893 // (start) and the last slash (slash).
12894 auto reference_token = reference_string.substr(start, slash - start);
12895
12896 // check reference tokens are properly escaped
12897 for (std::size_t pos = reference_token.find_first_of('~');
12898 pos != std::string::npos;
12899 pos = reference_token.find_first_of('~', pos + 1))
12900 {
12901 JSON_ASSERT(reference_token[pos] == '~');
12902
12903 // ~ must be followed by 0 or 1
12904 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
12905 (reference_token[pos + 1] != '0' &&
12906 reference_token[pos + 1] != '1')))
12907 {
12908 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType()));
12909 }
12910 }
12911
12912 // finally, store the reference token
12913 detail::unescape(reference_token);
12914 result.push_back(reference_token);
12915 }
12916
12917 return result;
12918 }
12919
12920 private:
12921 /*!
12922 @param[in] reference_string the reference string to the current value
12923 @param[in] value the value to consider
12924 @param[in,out] result the result object to insert values to
12925
12926 @note Empty objects or arrays are flattened to `null`.
12927 */
12928 static void flatten(const std::string& reference_string,
12929 const BasicJsonType& value,
12930 BasicJsonType& result)
12931 {
12932 switch (value.type())
12933 {
12934 case detail::value_t::array:
12935 {
12936 if (value.m_value.array->empty())
12937 {
12938 // flatten empty array as null
12939 result[reference_string] = nullptr;
12940 }
12941 else
12942 {
12943 // iterate array and use index as reference string
12944 for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
12945 {
12946 flatten(reference_string + "/" + std::to_string(i),
12947 value.m_value.array->operator[](i), result);
12948 }
12949 }
12950 break;
12951 }
12952
12953 case detail::value_t::object:
12954 {
12955 if (value.m_value.object->empty())
12956 {
12957 // flatten empty object as null
12958 result[reference_string] = nullptr;
12959 }
12960 else
12961 {
12962 // iterate object and use keys as reference string
12963 for (const auto& element : *value.m_value.object)
12964 {
12965 flatten(reference_string + "/" + detail::escape(element.first), element.second, result);
12966 }
12967 }
12968 break;
12969 }
12970
12971 case detail::value_t::null:
12972 case detail::value_t::string:
12973 case detail::value_t::boolean:
12974 case detail::value_t::number_integer:
12975 case detail::value_t::number_unsigned:
12976 case detail::value_t::number_float:
12977 case detail::value_t::binary:
12978 case detail::value_t::discarded:
12979 default:
12980 {
12981 // add primitive value with its reference string
12982 result[reference_string] = value;
12983 break;
12984 }
12985 }
12986 }
12987
12988 /*!
12989 @param[in] value flattened JSON
12990
12991 @return unflattened JSON
12992
12993 @throw parse_error.109 if array index is not a number
12994 @throw type_error.314 if value is not an object
12995 @throw type_error.315 if object values are not primitive
12996 @throw type_error.313 if value cannot be unflattened
12997 */
12998 static BasicJsonType
12999 unflatten(const BasicJsonType& value)
13000 {
13001 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
13002 {
13003 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value));
13004 }
13005
13006 BasicJsonType result;
13007
13008 // iterate the JSON object values
13009 for (const auto& element : *value.m_value.object)
13010 {
13011 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
13012 {
13013 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second));
13014 }
13015
13016 // assign value to reference pointed to by JSON pointer; Note that if
13017 // the JSON pointer is "" (i.e., points to the whole value), function
13018 // get_and_create returns a reference to result itself. An assignment
13019 // will then create a primitive value.
13020 json_pointer(element.first).get_and_create(result) = element.second;
13021 }
13022
13023 return result;
13024 }
13025
13026 /*!
13027 @brief compares two JSON pointers for equality
13028
13029 @param[in] lhs JSON pointer to compare
13030 @param[in] rhs JSON pointer to compare
13031 @return whether @a lhs is equal to @a rhs
13032
13033 @complexity Linear in the length of the JSON pointer
13034
13035 @exceptionsafety No-throw guarantee: this function never throws exceptions.
13036 */
13037 friend bool operator==(json_pointer const& lhs,
13038 json_pointer const& rhs) noexcept
13039 {
13040 return lhs.reference_tokens == rhs.reference_tokens;
13041 }
13042
13043 /*!
13044 @brief compares two JSON pointers for inequality
13045
13046 @param[in] lhs JSON pointer to compare
13047 @param[in] rhs JSON pointer to compare
13048 @return whether @a lhs is not equal @a rhs
13049
13050 @complexity Linear in the length of the JSON pointer
13051
13052 @exceptionsafety No-throw guarantee: this function never throws exceptions.
13053 */
13054 friend bool operator!=(json_pointer const& lhs,
13055 json_pointer const& rhs) noexcept
13056 {
13057 return !(lhs == rhs);
13058 }
13059
13060 /// the reference tokens
13061 std::vector<std::string> reference_tokens;
13062 };
13063 } // namespace nlohmann
13064
13065 // #include <nlohmann/detail/json_ref.hpp>
13066
13067
13068 #include <initializer_list>
13069 #include <utility>
13070
13071 // #include <nlohmann/detail/meta/type_traits.hpp>
13072
13073
13074 namespace nlohmann
13075 {
13076 namespace detail
13077 {
13078 template<typename BasicJsonType>
13079 class json_ref
13080 {
13081 public:
13082 using value_type = BasicJsonType;
13083
13084 json_ref(value_type&& value)
13085 : owned_value(std::move(value))
13086 {}
13087
13088 json_ref(const value_type& value)
13089 : value_ref(&value)
13090 {}
13091
13092 json_ref(std::initializer_list<json_ref> init)
13093 : owned_value(init)
13094 {}
13095
13096 template <
13097 class... Args,
13098 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
13099 json_ref(Args && ... args)
13100 : owned_value(std::forward<Args>(args)...)
13101 {}
13102
13103 // class should be movable only
13104 json_ref(json_ref&&) noexcept = default;
13105 json_ref(const json_ref&) = delete;
13106 json_ref& operator=(const json_ref&) = delete;
13107 json_ref& operator=(json_ref&&) = delete;
13108 ~json_ref() = default;
13109
13110 value_type moved_or_copied() const
13111 {
13112 if (value_ref == nullptr)
13113 {
13114 return std::move(owned_value);
13115 }
13116 return *value_ref;
13117 }
13118
13119 value_type const& operator*() const
13120 {
13121 return value_ref ? *value_ref : owned_value;
13122 }
13123
13124 value_type const* operator->() const
13125 {
13126 return &** this;
13127 }
13128
13129 private:
13130 mutable value_type owned_value = nullptr;
13131 value_type const* value_ref = nullptr;
13132 };
13133 } // namespace detail
13134 } // namespace nlohmann
13135
13136 // #include <nlohmann/detail/macro_scope.hpp>
13137
13138 // #include <nlohmann/detail/string_escape.hpp>
13139
13140 // #include <nlohmann/detail/meta/cpp_future.hpp>
13141
13142 // #include <nlohmann/detail/meta/type_traits.hpp>
13143
13144 // #include <nlohmann/detail/output/binary_writer.hpp>
13145
13146
13147 #include <algorithm> // reverse
13148 #include <array> // array
13149 #include <cmath> // isnan, isinf
13150 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
13151 #include <cstring> // memcpy
13152 #include <limits> // numeric_limits
13153 #include <string> // string
13154 #include <utility> // move
13155
13156 // #include <nlohmann/detail/input/binary_reader.hpp>
13157
13158 // #include <nlohmann/detail/macro_scope.hpp>
13159
13160 // #include <nlohmann/detail/output/output_adapters.hpp>
13161
13162
13163 #include <algorithm> // copy
13164 #include <cstddef> // size_t
13165 #include <iterator> // back_inserter
13166 #include <memory> // shared_ptr, make_shared
13167 #include <string> // basic_string
13168 #include <vector> // vector
13169
13170 #ifndef JSON_NO_IO
13171 #include <ios> // streamsize
13172 #include <ostream> // basic_ostream
13173 #endif // JSON_NO_IO
13174
13175 // #include <nlohmann/detail/macro_scope.hpp>
13176
13177
13178 namespace nlohmann
13179 {
13180 namespace detail
13181 {
13182 /// abstract output adapter interface
13183 template<typename CharType> struct output_adapter_protocol
13184 {
13185 virtual void write_character(CharType c) = 0;
13186 virtual void write_characters(const CharType* s, std::size_t length) = 0;
13187 virtual ~output_adapter_protocol() = default;
13188
13189 output_adapter_protocol() = default;
13190 output_adapter_protocol(const output_adapter_protocol&) = default;
13191 output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
13192 output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
13193 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
13194 };
13195
13196 /// a type to simplify interfaces
13197 template<typename CharType>
13198 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
13199
13200 /// output adapter for byte vectors
13201 template<typename CharType, typename AllocatorType = std::allocator<CharType>>
13202 class output_vector_adapter : public output_adapter_protocol<CharType>
13203 {
13204 public:
13205 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
13206 : v(vec)
13207 {}
13208
13209 void write_character(CharType c) override
13210 {
13211 v.push_back(c);
13212 }
13213
13214 JSON_HEDLEY_NON_NULL(2)
13215 void write_characters(const CharType* s, std::size_t length) override
13216 {
13217 std::copy(s, s + length, std::back_inserter(v));
13218 }
13219
13220 private:
13221 std::vector<CharType, AllocatorType>& v;
13222 };
13223
13224 #ifndef JSON_NO_IO
13225 /// output adapter for output streams
13226 template<typename CharType>
13227 class output_stream_adapter : public output_adapter_protocol<CharType>
13228 {
13229 public:
13230 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
13231 : stream(s)
13232 {}
13233
13234 void write_character(CharType c) override
13235 {
13236 stream.put(c);
13237 }
13238
13239 JSON_HEDLEY_NON_NULL(2)
13240 void write_characters(const CharType* s, std::size_t length) override
13241 {
13242 stream.write(s, static_cast<std::streamsize>(length));
13243 }
13244
13245 private:
13246 std::basic_ostream<CharType>& stream;
13247 };
13248 #endif // JSON_NO_IO
13249
13250 /// output adapter for basic_string
13251 template<typename CharType, typename StringType = std::basic_string<CharType>>
13252 class output_string_adapter : public output_adapter_protocol<CharType>
13253 {
13254 public:
13255 explicit output_string_adapter(StringType& s) noexcept
13256 : str(s)
13257 {}
13258
13259 void write_character(CharType c) override
13260 {
13261 str.push_back(c);
13262 }
13263
13264 JSON_HEDLEY_NON_NULL(2)
13265 void write_characters(const CharType* s, std::size_t length) override
13266 {
13267 str.append(s, length);
13268 }
13269
13270 private:
13271 StringType& str;
13272 };
13273
13274 template<typename CharType, typename StringType = std::basic_string<CharType>>
13275 class output_adapter
13276 {
13277 public:
13278 template<typename AllocatorType = std::allocator<CharType>>
13279 output_adapter(std::vector<CharType, AllocatorType>& vec)
13280 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
13281
13282 #ifndef JSON_NO_IO
13283 output_adapter(std::basic_ostream<CharType>& s)
13284 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
13285 #endif // JSON_NO_IO
13286
13287 output_adapter(StringType& s)
13288 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
13289
13290 operator output_adapter_t<CharType>()
13291 {
13292 return oa;
13293 }
13294
13295 private:
13296 output_adapter_t<CharType> oa = nullptr;
13297 };
13298 } // namespace detail
13299 } // namespace nlohmann
13300
13301
13302 namespace nlohmann
13303 {
13304 namespace detail
13305 {
13306 ///////////////////
13307 // binary writer //
13308 ///////////////////
13309
13310 /*!
13311 @brief serialization to CBOR and MessagePack values
13312 */
13313 template<typename BasicJsonType, typename CharType>
13314 class binary_writer
13315 {
13316 using string_t = typename BasicJsonType::string_t;
13317 using binary_t = typename BasicJsonType::binary_t;
13318 using number_float_t = typename BasicJsonType::number_float_t;
13319
13320 public:
13321 /*!
13322 @brief create a binary writer
13323
13324 @param[in] adapter output adapter to write to
13325 */
13326 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
13327 {
13328 JSON_ASSERT(oa);
13329 }
13330
13331 /*!
13332 @param[in] j JSON value to serialize
13333 @pre j.type() == value_t::object
13334 */
13335 void write_bson(const BasicJsonType& j)
13336 {
13337 switch (j.type())
13338 {
13339 case value_t::object:
13340 {
13341 write_bson_object(*j.m_value.object);
13342 break;
13343 }
13344
13345 case value_t::null:
13346 case value_t::array:
13347 case value_t::string:
13348 case value_t::boolean:
13349 case value_t::number_integer:
13350 case value_t::number_unsigned:
13351 case value_t::number_float:
13352 case value_t::binary:
13353 case value_t::discarded:
13354 default:
13355 {
13356 JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j));
13357 }
13358 }
13359 }
13360
13361 /*!
13362 @param[in] j JSON value to serialize
13363 */
13364 void write_cbor(const BasicJsonType& j)
13365 {
13366 switch (j.type())
13367 {
13368 case value_t::null:
13369 {
13370 oa->write_character(to_char_type(0xF6));
13371 break;
13372 }
13373
13374 case value_t::boolean:
13375 {
13376 oa->write_character(j.m_value.boolean
13377 ? to_char_type(0xF5)
13378 : to_char_type(0xF4));
13379 break;
13380 }
13381
13382 case value_t::number_integer:
13383 {
13384 if (j.m_value.number_integer >= 0)
13385 {
13386 // CBOR does not differentiate between positive signed
13387 // integers and unsigned integers. Therefore, we used the
13388 // code from the value_t::number_unsigned case here.
13389 if (j.m_value.number_integer <= 0x17)
13390 {
13391 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13392 }
13393 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
13394 {
13395 oa->write_character(to_char_type(0x18));
13396 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13397 }
13398 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
13399 {
13400 oa->write_character(to_char_type(0x19));
13401 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13402 }
13403 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
13404 {
13405 oa->write_character(to_char_type(0x1A));
13406 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13407 }
13408 else
13409 {
13410 oa->write_character(to_char_type(0x1B));
13411 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13412 }
13413 }
13414 else
13415 {
13416 // The conversions below encode the sign in the first
13417 // byte, and the value is converted to a positive number.
13418 const auto positive_number = -1 - j.m_value.number_integer;
13419 if (j.m_value.number_integer >= -24)
13420 {
13421 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
13422 }
13423 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
13424 {
13425 oa->write_character(to_char_type(0x38));
13426 write_number(static_cast<std::uint8_t>(positive_number));
13427 }
13428 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
13429 {
13430 oa->write_character(to_char_type(0x39));
13431 write_number(static_cast<std::uint16_t>(positive_number));
13432 }
13433 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
13434 {
13435 oa->write_character(to_char_type(0x3A));
13436 write_number(static_cast<std::uint32_t>(positive_number));
13437 }
13438 else
13439 {
13440 oa->write_character(to_char_type(0x3B));
13441 write_number(static_cast<std::uint64_t>(positive_number));
13442 }
13443 }
13444 break;
13445 }
13446
13447 case value_t::number_unsigned:
13448 {
13449 if (j.m_value.number_unsigned <= 0x17)
13450 {
13451 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
13452 }
13453 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
13454 {
13455 oa->write_character(to_char_type(0x18));
13456 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
13457 }
13458 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
13459 {
13460 oa->write_character(to_char_type(0x19));
13461 write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
13462 }
13463 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
13464 {
13465 oa->write_character(to_char_type(0x1A));
13466 write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
13467 }
13468 else
13469 {
13470 oa->write_character(to_char_type(0x1B));
13471 write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
13472 }
13473 break;
13474 }
13475
13476 case value_t::number_float:
13477 {
13478 if (std::isnan(j.m_value.number_float))
13479 {
13480 // NaN is 0xf97e00 in CBOR
13481 oa->write_character(to_char_type(0xF9));
13482 oa->write_character(to_char_type(0x7E));
13483 oa->write_character(to_char_type(0x00));
13484 }
13485 else if (std::isinf(j.m_value.number_float))
13486 {
13487 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
13488 oa->write_character(to_char_type(0xf9));
13489 oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
13490 oa->write_character(to_char_type(0x00));
13491 }
13492 else
13493 {
13494 write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
13495 }
13496 break;
13497 }
13498
13499 case value_t::string:
13500 {
13501 // step 1: write control byte and the string length
13502 const auto N = j.m_value.string->size();
13503 if (N <= 0x17)
13504 {
13505 write_number(static_cast<std::uint8_t>(0x60 + N));
13506 }
13507 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13508 {
13509 oa->write_character(to_char_type(0x78));
13510 write_number(static_cast<std::uint8_t>(N));
13511 }
13512 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13513 {
13514 oa->write_character(to_char_type(0x79));
13515 write_number(static_cast<std::uint16_t>(N));
13516 }
13517 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13518 {
13519 oa->write_character(to_char_type(0x7A));
13520 write_number(static_cast<std::uint32_t>(N));
13521 }
13522 // LCOV_EXCL_START
13523 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13524 {
13525 oa->write_character(to_char_type(0x7B));
13526 write_number(static_cast<std::uint64_t>(N));
13527 }
13528 // LCOV_EXCL_STOP
13529
13530 // step 2: write the string
13531 oa->write_characters(
13532 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
13533 j.m_value.string->size());
13534 break;
13535 }
13536
13537 case value_t::array:
13538 {
13539 // step 1: write control byte and the array size
13540 const auto N = j.m_value.array->size();
13541 if (N <= 0x17)
13542 {
13543 write_number(static_cast<std::uint8_t>(0x80 + N));
13544 }
13545 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13546 {
13547 oa->write_character(to_char_type(0x98));
13548 write_number(static_cast<std::uint8_t>(N));
13549 }
13550 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13551 {
13552 oa->write_character(to_char_type(0x99));
13553 write_number(static_cast<std::uint16_t>(N));
13554 }
13555 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13556 {
13557 oa->write_character(to_char_type(0x9A));
13558 write_number(static_cast<std::uint32_t>(N));
13559 }
13560 // LCOV_EXCL_START
13561 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13562 {
13563 oa->write_character(to_char_type(0x9B));
13564 write_number(static_cast<std::uint64_t>(N));
13565 }
13566 // LCOV_EXCL_STOP
13567
13568 // step 2: write each element
13569 for (const auto& el : *j.m_value.array)
13570 {
13571 write_cbor(el);
13572 }
13573 break;
13574 }
13575
13576 case value_t::binary:
13577 {
13578 if (j.m_value.binary->has_subtype())
13579 {
13580 if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
13581 {
13582 write_number(static_cast<std::uint8_t>(0xd8));
13583 write_number(static_cast<std::uint8_t>(j.m_value.binary->subtype()));
13584 }
13585 else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
13586 {
13587 write_number(static_cast<std::uint8_t>(0xd9));
13588 write_number(static_cast<std::uint16_t>(j.m_value.binary->subtype()));
13589 }
13590 else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
13591 {
13592 write_number(static_cast<std::uint8_t>(0xda));
13593 write_number(static_cast<std::uint32_t>(j.m_value.binary->subtype()));
13594 }
13595 else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
13596 {
13597 write_number(static_cast<std::uint8_t>(0xdb));
13598 write_number(static_cast<std::uint64_t>(j.m_value.binary->subtype()));
13599 }
13600 }
13601
13602 // step 1: write control byte and the binary array size
13603 const auto N = j.m_value.binary->size();
13604 if (N <= 0x17)
13605 {
13606 write_number(static_cast<std::uint8_t>(0x40 + N));
13607 }
13608 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13609 {
13610 oa->write_character(to_char_type(0x58));
13611 write_number(static_cast<std::uint8_t>(N));
13612 }
13613 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13614 {
13615 oa->write_character(to_char_type(0x59));
13616 write_number(static_cast<std::uint16_t>(N));
13617 }
13618 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13619 {
13620 oa->write_character(to_char_type(0x5A));
13621 write_number(static_cast<std::uint32_t>(N));
13622 }
13623 // LCOV_EXCL_START
13624 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13625 {
13626 oa->write_character(to_char_type(0x5B));
13627 write_number(static_cast<std::uint64_t>(N));
13628 }
13629 // LCOV_EXCL_STOP
13630
13631 // step 2: write each element
13632 oa->write_characters(
13633 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13634 N);
13635
13636 break;
13637 }
13638
13639 case value_t::object:
13640 {
13641 // step 1: write control byte and the object size
13642 const auto N = j.m_value.object->size();
13643 if (N <= 0x17)
13644 {
13645 write_number(static_cast<std::uint8_t>(0xA0 + N));
13646 }
13647 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13648 {
13649 oa->write_character(to_char_type(0xB8));
13650 write_number(static_cast<std::uint8_t>(N));
13651 }
13652 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13653 {
13654 oa->write_character(to_char_type(0xB9));
13655 write_number(static_cast<std::uint16_t>(N));
13656 }
13657 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13658 {
13659 oa->write_character(to_char_type(0xBA));
13660 write_number(static_cast<std::uint32_t>(N));
13661 }
13662 // LCOV_EXCL_START
13663 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13664 {
13665 oa->write_character(to_char_type(0xBB));
13666 write_number(static_cast<std::uint64_t>(N));
13667 }
13668 // LCOV_EXCL_STOP
13669
13670 // step 2: write each element
13671 for (const auto& el : *j.m_value.object)
13672 {
13673 write_cbor(el.first);
13674 write_cbor(el.second);
13675 }
13676 break;
13677 }
13678
13679 case value_t::discarded:
13680 default:
13681 break;
13682 }
13683 }
13684
13685 /*!
13686 @param[in] j JSON value to serialize
13687 */
13688 void write_msgpack(const BasicJsonType& j)
13689 {
13690 switch (j.type())
13691 {
13692 case value_t::null: // nil
13693 {
13694 oa->write_character(to_char_type(0xC0));
13695 break;
13696 }
13697
13698 case value_t::boolean: // true and false
13699 {
13700 oa->write_character(j.m_value.boolean
13701 ? to_char_type(0xC3)
13702 : to_char_type(0xC2));
13703 break;
13704 }
13705
13706 case value_t::number_integer:
13707 {
13708 if (j.m_value.number_integer >= 0)
13709 {
13710 // MessagePack does not differentiate between positive
13711 // signed integers and unsigned integers. Therefore, we used
13712 // the code from the value_t::number_unsigned case here.
13713 if (j.m_value.number_unsigned < 128)
13714 {
13715 // positive fixnum
13716 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13717 }
13718 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
13719 {
13720 // uint 8
13721 oa->write_character(to_char_type(0xCC));
13722 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13723 }
13724 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
13725 {
13726 // uint 16
13727 oa->write_character(to_char_type(0xCD));
13728 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13729 }
13730 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
13731 {
13732 // uint 32
13733 oa->write_character(to_char_type(0xCE));
13734 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13735 }
13736 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
13737 {
13738 // uint 64
13739 oa->write_character(to_char_type(0xCF));
13740 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13741 }
13742 }
13743 else
13744 {
13745 if (j.m_value.number_integer >= -32)
13746 {
13747 // negative fixnum
13748 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
13749 }
13750 else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
13751 j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
13752 {
13753 // int 8
13754 oa->write_character(to_char_type(0xD0));
13755 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
13756 }
13757 else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
13758 j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
13759 {
13760 // int 16
13761 oa->write_character(to_char_type(0xD1));
13762 write_number(static_cast<std::int16_t>(j.m_value.number_integer));
13763 }
13764 else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
13765 j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
13766 {
13767 // int 32
13768 oa->write_character(to_char_type(0xD2));
13769 write_number(static_cast<std::int32_t>(j.m_value.number_integer));
13770 }
13771 else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
13772 j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
13773 {
13774 // int 64
13775 oa->write_character(to_char_type(0xD3));
13776 write_number(static_cast<std::int64_t>(j.m_value.number_integer));
13777 }
13778 }
13779 break;
13780 }
13781
13782 case value_t::number_unsigned:
13783 {
13784 if (j.m_value.number_unsigned < 128)
13785 {
13786 // positive fixnum
13787 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13788 }
13789 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
13790 {
13791 // uint 8
13792 oa->write_character(to_char_type(0xCC));
13793 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13794 }
13795 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
13796 {
13797 // uint 16
13798 oa->write_character(to_char_type(0xCD));
13799 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13800 }
13801 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
13802 {
13803 // uint 32
13804 oa->write_character(to_char_type(0xCE));
13805 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13806 }
13807 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
13808 {
13809 // uint 64
13810 oa->write_character(to_char_type(0xCF));
13811 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13812 }
13813 break;
13814 }
13815
13816 case value_t::number_float:
13817 {
13818 write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
13819 break;
13820 }
13821
13822 case value_t::string:
13823 {
13824 // step 1: write control byte and the string length
13825 const auto N = j.m_value.string->size();
13826 if (N <= 31)
13827 {
13828 // fixstr
13829 write_number(static_cast<std::uint8_t>(0xA0 | N));
13830 }
13831 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13832 {
13833 // str 8
13834 oa->write_character(to_char_type(0xD9));
13835 write_number(static_cast<std::uint8_t>(N));
13836 }
13837 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13838 {
13839 // str 16
13840 oa->write_character(to_char_type(0xDA));
13841 write_number(static_cast<std::uint16_t>(N));
13842 }
13843 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13844 {
13845 // str 32
13846 oa->write_character(to_char_type(0xDB));
13847 write_number(static_cast<std::uint32_t>(N));
13848 }
13849
13850 // step 2: write the string
13851 oa->write_characters(
13852 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
13853 j.m_value.string->size());
13854 break;
13855 }
13856
13857 case value_t::array:
13858 {
13859 // step 1: write control byte and the array size
13860 const auto N = j.m_value.array->size();
13861 if (N <= 15)
13862 {
13863 // fixarray
13864 write_number(static_cast<std::uint8_t>(0x90 | N));
13865 }
13866 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13867 {
13868 // array 16
13869 oa->write_character(to_char_type(0xDC));
13870 write_number(static_cast<std::uint16_t>(N));
13871 }
13872 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13873 {
13874 // array 32
13875 oa->write_character(to_char_type(0xDD));
13876 write_number(static_cast<std::uint32_t>(N));
13877 }
13878
13879 // step 2: write each element
13880 for (const auto& el : *j.m_value.array)
13881 {
13882 write_msgpack(el);
13883 }
13884 break;
13885 }
13886
13887 case value_t::binary:
13888 {
13889 // step 0: determine if the binary type has a set subtype to
13890 // determine whether or not to use the ext or fixext types
13891 const bool use_ext = j.m_value.binary->has_subtype();
13892
13893 // step 1: write control byte and the byte string length
13894 const auto N = j.m_value.binary->size();
13895 if (N <= (std::numeric_limits<std::uint8_t>::max)())
13896 {
13897 std::uint8_t output_type{};
13898 bool fixed = true;
13899 if (use_ext)
13900 {
13901 switch (N)
13902 {
13903 case 1:
13904 output_type = 0xD4; // fixext 1
13905 break;
13906 case 2:
13907 output_type = 0xD5; // fixext 2
13908 break;
13909 case 4:
13910 output_type = 0xD6; // fixext 4
13911 break;
13912 case 8:
13913 output_type = 0xD7; // fixext 8
13914 break;
13915 case 16:
13916 output_type = 0xD8; // fixext 16
13917 break;
13918 default:
13919 output_type = 0xC7; // ext 8
13920 fixed = false;
13921 break;
13922 }
13923
13924 }
13925 else
13926 {
13927 output_type = 0xC4; // bin 8
13928 fixed = false;
13929 }
13930
13931 oa->write_character(to_char_type(output_type));
13932 if (!fixed)
13933 {
13934 write_number(static_cast<std::uint8_t>(N));
13935 }
13936 }
13937 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13938 {
13939 std::uint8_t output_type = use_ext
13940 ? 0xC8 // ext 16
13941 : 0xC5; // bin 16
13942
13943 oa->write_character(to_char_type(output_type));
13944 write_number(static_cast<std::uint16_t>(N));
13945 }
13946 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13947 {
13948 std::uint8_t output_type = use_ext
13949 ? 0xC9 // ext 32
13950 : 0xC6; // bin 32
13951
13952 oa->write_character(to_char_type(output_type));
13953 write_number(static_cast<std::uint32_t>(N));
13954 }
13955
13956 // step 1.5: if this is an ext type, write the subtype
13957 if (use_ext)
13958 {
13959 write_number(static_cast<std::int8_t>(j.m_value.binary->subtype()));
13960 }
13961
13962 // step 2: write the byte string
13963 oa->write_characters(
13964 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13965 N);
13966
13967 break;
13968 }
13969
13970 case value_t::object:
13971 {
13972 // step 1: write control byte and the object size
13973 const auto N = j.m_value.object->size();
13974 if (N <= 15)
13975 {
13976 // fixmap
13977 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
13978 }
13979 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13980 {
13981 // map 16
13982 oa->write_character(to_char_type(0xDE));
13983 write_number(static_cast<std::uint16_t>(N));
13984 }
13985 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13986 {
13987 // map 32
13988 oa->write_character(to_char_type(0xDF));
13989 write_number(static_cast<std::uint32_t>(N));
13990 }
13991
13992 // step 2: write each element
13993 for (const auto& el : *j.m_value.object)
13994 {
13995 write_msgpack(el.first);
13996 write_msgpack(el.second);
13997 }
13998 break;
13999 }
14000
14001 case value_t::discarded:
14002 default:
14003 break;
14004 }
14005 }
14006
14007 /*!
14008 @param[in] j JSON value to serialize
14009 @param[in] use_count whether to use '#' prefixes (optimized format)
14010 @param[in] use_type whether to use '$' prefixes (optimized format)
14011 @param[in] add_prefix whether prefixes need to be used for this value
14012 */
14013 void write_ubjson(const BasicJsonType& j, const bool use_count,
14014 const bool use_type, const bool add_prefix = true)
14015 {
14016 switch (j.type())
14017 {
14018 case value_t::null:
14019 {
14020 if (add_prefix)
14021 {
14022 oa->write_character(to_char_type('Z'));
14023 }
14024 break;
14025 }
14026
14027 case value_t::boolean:
14028 {
14029 if (add_prefix)
14030 {
14031 oa->write_character(j.m_value.boolean
14032 ? to_char_type('T')
14033 : to_char_type('F'));
14034 }
14035 break;
14036 }
14037
14038 case value_t::number_integer:
14039 {
14040 write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
14041 break;
14042 }
14043
14044 case value_t::number_unsigned:
14045 {
14046 write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
14047 break;
14048 }
14049
14050 case value_t::number_float:
14051 {
14052 write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
14053 break;
14054 }
14055
14056 case value_t::string:
14057 {
14058 if (add_prefix)
14059 {
14060 oa->write_character(to_char_type('S'));
14061 }
14062 write_number_with_ubjson_prefix(j.m_value.string->size(), true);
14063 oa->write_characters(
14064 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
14065 j.m_value.string->size());
14066 break;
14067 }
14068
14069 case value_t::array:
14070 {
14071 if (add_prefix)
14072 {
14073 oa->write_character(to_char_type('['));
14074 }
14075
14076 bool prefix_required = true;
14077 if (use_type && !j.m_value.array->empty())
14078 {
14079 JSON_ASSERT(use_count);
14080 const CharType first_prefix = ubjson_prefix(j.front());
14081 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
14082 [this, first_prefix](const BasicJsonType & v)
14083 {
14084 return ubjson_prefix(v) == first_prefix;
14085 });
14086
14087 if (same_prefix)
14088 {
14089 prefix_required = false;
14090 oa->write_character(to_char_type('$'));
14091 oa->write_character(first_prefix);
14092 }
14093 }
14094
14095 if (use_count)
14096 {
14097 oa->write_character(to_char_type('#'));
14098 write_number_with_ubjson_prefix(j.m_value.array->size(), true);
14099 }
14100
14101 for (const auto& el : *j.m_value.array)
14102 {
14103 write_ubjson(el, use_count, use_type, prefix_required);
14104 }
14105
14106 if (!use_count)
14107 {
14108 oa->write_character(to_char_type(']'));
14109 }
14110
14111 break;
14112 }
14113
14114 case value_t::binary:
14115 {
14116 if (add_prefix)
14117 {
14118 oa->write_character(to_char_type('['));
14119 }
14120
14121 if (use_type && !j.m_value.binary->empty())
14122 {
14123 JSON_ASSERT(use_count);
14124 oa->write_character(to_char_type('$'));
14125 oa->write_character('U');
14126 }
14127
14128 if (use_count)
14129 {
14130 oa->write_character(to_char_type('#'));
14131 write_number_with_ubjson_prefix(j.m_value.binary->size(), true);
14132 }
14133
14134 if (use_type)
14135 {
14136 oa->write_characters(
14137 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
14138 j.m_value.binary->size());
14139 }
14140 else
14141 {
14142 for (size_t i = 0; i < j.m_value.binary->size(); ++i)
14143 {
14144 oa->write_character(to_char_type('U'));
14145 oa->write_character(j.m_value.binary->data()[i]);
14146 }
14147 }
14148
14149 if (!use_count)
14150 {
14151 oa->write_character(to_char_type(']'));
14152 }
14153
14154 break;
14155 }
14156
14157 case value_t::object:
14158 {
14159 if (add_prefix)
14160 {
14161 oa->write_character(to_char_type('{'));
14162 }
14163
14164 bool prefix_required = true;
14165 if (use_type && !j.m_value.object->empty())
14166 {
14167 JSON_ASSERT(use_count);
14168 const CharType first_prefix = ubjson_prefix(j.front());
14169 const bool same_prefix = std::all_of(j.begin(), j.end(),
14170 [this, first_prefix](const BasicJsonType & v)
14171 {
14172 return ubjson_prefix(v) == first_prefix;
14173 });
14174
14175 if (same_prefix)
14176 {
14177 prefix_required = false;
14178 oa->write_character(to_char_type('$'));
14179 oa->write_character(first_prefix);
14180 }
14181 }
14182
14183 if (use_count)
14184 {
14185 oa->write_character(to_char_type('#'));
14186 write_number_with_ubjson_prefix(j.m_value.object->size(), true);
14187 }
14188
14189 for (const auto& el : *j.m_value.object)
14190 {
14191 write_number_with_ubjson_prefix(el.first.size(), true);
14192 oa->write_characters(
14193 reinterpret_cast<const CharType*>(el.first.c_str()),
14194 el.first.size());
14195 write_ubjson(el.second, use_count, use_type, prefix_required);
14196 }
14197
14198 if (!use_count)
14199 {
14200 oa->write_character(to_char_type('}'));
14201 }
14202
14203 break;
14204 }
14205
14206 case value_t::discarded:
14207 default:
14208 break;
14209 }
14210 }
14211
14212 private:
14213 //////////
14214 // BSON //
14215 //////////
14216
14217 /*!
14218 @return The size of a BSON document entry header, including the id marker
14219 and the entry name size (and its null-terminator).
14220 */
14221 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
14222 {
14223 const auto it = name.find(static_cast<typename string_t::value_type>(0));
14224 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
14225 {
14226 JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j));
14227 static_cast<void>(j);
14228 }
14229
14230 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
14231 }
14232
14233 /*!
14234 @brief Writes the given @a element_type and @a name to the output adapter
14235 */
14236 void write_bson_entry_header(const string_t& name,
14237 const std::uint8_t element_type)
14238 {
14239 oa->write_character(to_char_type(element_type)); // boolean
14240 oa->write_characters(
14241 reinterpret_cast<const CharType*>(name.c_str()),
14242 name.size() + 1u);
14243 }
14244
14245 /*!
14246 @brief Writes a BSON element with key @a name and boolean value @a value
14247 */
14248 void write_bson_boolean(const string_t& name,
14249 const bool value)
14250 {
14251 write_bson_entry_header(name, 0x08);
14252 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
14253 }
14254
14255 /*!
14256 @brief Writes a BSON element with key @a name and double value @a value
14257 */
14258 void write_bson_double(const string_t& name,
14259 const double value)
14260 {
14261 write_bson_entry_header(name, 0x01);
14262 write_number<double, true>(value);
14263 }
14264
14265 /*!
14266 @return The size of the BSON-encoded string in @a value
14267 */
14268 static std::size_t calc_bson_string_size(const string_t& value)
14269 {
14270 return sizeof(std::int32_t) + value.size() + 1ul;
14271 }
14272
14273 /*!
14274 @brief Writes a BSON element with key @a name and string value @a value
14275 */
14276 void write_bson_string(const string_t& name,
14277 const string_t& value)
14278 {
14279 write_bson_entry_header(name, 0x02);
14280
14281 write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
14282 oa->write_characters(
14283 reinterpret_cast<const CharType*>(value.c_str()),
14284 value.size() + 1);
14285 }
14286
14287 /*!
14288 @brief Writes a BSON element with key @a name and null value
14289 */
14290 void write_bson_null(const string_t& name)
14291 {
14292 write_bson_entry_header(name, 0x0A);
14293 }
14294
14295 /*!
14296 @return The size of the BSON-encoded integer @a value
14297 */
14298 static std::size_t calc_bson_integer_size(const std::int64_t value)
14299 {
14300 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
14301 ? sizeof(std::int32_t)
14302 : sizeof(std::int64_t);
14303 }
14304
14305 /*!
14306 @brief Writes a BSON element with key @a name and integer @a value
14307 */
14308 void write_bson_integer(const string_t& name,
14309 const std::int64_t value)
14310 {
14311 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
14312 {
14313 write_bson_entry_header(name, 0x10); // int32
14314 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
14315 }
14316 else
14317 {
14318 write_bson_entry_header(name, 0x12); // int64
14319 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
14320 }
14321 }
14322
14323 /*!
14324 @return The size of the BSON-encoded unsigned integer in @a j
14325 */
14326 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
14327 {
14328 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14329 ? sizeof(std::int32_t)
14330 : sizeof(std::int64_t);
14331 }
14332
14333 /*!
14334 @brief Writes a BSON element with key @a name and unsigned @a value
14335 */
14336 void write_bson_unsigned(const string_t& name,
14337 const BasicJsonType& j)
14338 {
14339 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14340 {
14341 write_bson_entry_header(name, 0x10 /* int32 */);
14342 write_number<std::int32_t, true>(static_cast<std::int32_t>(j.m_value.number_unsigned));
14343 }
14344 else if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14345 {
14346 write_bson_entry_header(name, 0x12 /* int64 */);
14347 write_number<std::int64_t, true>(static_cast<std::int64_t>(j.m_value.number_unsigned));
14348 }
14349 else
14350 {
14351 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", j));
14352 }
14353 }
14354
14355 /*!
14356 @brief Writes a BSON element with key @a name and object @a value
14357 */
14358 void write_bson_object_entry(const string_t& name,
14359 const typename BasicJsonType::object_t& value)
14360 {
14361 write_bson_entry_header(name, 0x03); // object
14362 write_bson_object(value);
14363 }
14364
14365 /*!
14366 @return The size of the BSON-encoded array @a value
14367 */
14368 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
14369 {
14370 std::size_t array_index = 0ul;
14371
14372 const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
14373 {
14374 return result + calc_bson_element_size(std::to_string(array_index++), el);
14375 });
14376
14377 return sizeof(std::int32_t) + embedded_document_size + 1ul;
14378 }
14379
14380 /*!
14381 @return The size of the BSON-encoded binary array @a value
14382 */
14383 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
14384 {
14385 return sizeof(std::int32_t) + value.size() + 1ul;
14386 }
14387
14388 /*!
14389 @brief Writes a BSON element with key @a name and array @a value
14390 */
14391 void write_bson_array(const string_t& name,
14392 const typename BasicJsonType::array_t& value)
14393 {
14394 write_bson_entry_header(name, 0x04); // array
14395 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
14396
14397 std::size_t array_index = 0ul;
14398
14399 for (const auto& el : value)
14400 {
14401 write_bson_element(std::to_string(array_index++), el);
14402 }
14403
14404 oa->write_character(to_char_type(0x00));
14405 }
14406
14407 /*!
14408 @brief Writes a BSON element with key @a name and binary value @a value
14409 */
14410 void write_bson_binary(const string_t& name,
14411 const binary_t& value)
14412 {
14413 write_bson_entry_header(name, 0x05);
14414
14415 write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
14416 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
14417
14418 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
14419 }
14420
14421 /*!
14422 @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
14423 @return The calculated size for the BSON document entry for @a j with the given @a name.
14424 */
14425 static std::size_t calc_bson_element_size(const string_t& name,
14426 const BasicJsonType& j)
14427 {
14428 const auto header_size = calc_bson_entry_header_size(name, j);
14429 switch (j.type())
14430 {
14431 case value_t::object:
14432 return header_size + calc_bson_object_size(*j.m_value.object);
14433
14434 case value_t::array:
14435 return header_size + calc_bson_array_size(*j.m_value.array);
14436
14437 case value_t::binary:
14438 return header_size + calc_bson_binary_size(*j.m_value.binary);
14439
14440 case value_t::boolean:
14441 return header_size + 1ul;
14442
14443 case value_t::number_float:
14444 return header_size + 8ul;
14445
14446 case value_t::number_integer:
14447 return header_size + calc_bson_integer_size(j.m_value.number_integer);
14448
14449 case value_t::number_unsigned:
14450 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
14451
14452 case value_t::string:
14453 return header_size + calc_bson_string_size(*j.m_value.string);
14454
14455 case value_t::null:
14456 return header_size + 0ul;
14457
14458 // LCOV_EXCL_START
14459 case value_t::discarded:
14460 default:
14461 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
14462 return 0ul;
14463 // LCOV_EXCL_STOP
14464 }
14465 }
14466
14467 /*!
14468 @brief Serializes the JSON value @a j to BSON and associates it with the
14469 key @a name.
14470 @param name The name to associate with the JSON entity @a j within the
14471 current BSON document
14472 */
14473 void write_bson_element(const string_t& name,
14474 const BasicJsonType& j)
14475 {
14476 switch (j.type())
14477 {
14478 case value_t::object:
14479 return write_bson_object_entry(name, *j.m_value.object);
14480
14481 case value_t::array:
14482 return write_bson_array(name, *j.m_value.array);
14483
14484 case value_t::binary:
14485 return write_bson_binary(name, *j.m_value.binary);
14486
14487 case value_t::boolean:
14488 return write_bson_boolean(name, j.m_value.boolean);
14489
14490 case value_t::number_float:
14491 return write_bson_double(name, j.m_value.number_float);
14492
14493 case value_t::number_integer:
14494 return write_bson_integer(name, j.m_value.number_integer);
14495
14496 case value_t::number_unsigned:
14497 return write_bson_unsigned(name, j);
14498
14499 case value_t::string:
14500 return write_bson_string(name, *j.m_value.string);
14501
14502 case value_t::null:
14503 return write_bson_null(name);
14504
14505 // LCOV_EXCL_START
14506 case value_t::discarded:
14507 default:
14508 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
14509 return;
14510 // LCOV_EXCL_STOP
14511 }
14512 }
14513
14514 /*!
14515 @brief Calculates the size of the BSON serialization of the given
14516 JSON-object @a j.
14517 @param[in] value JSON value to serialize
14518 @pre value.type() == value_t::object
14519 */
14520 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
14521 {
14522 std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
14523 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
14524 {
14525 return result += calc_bson_element_size(el.first, el.second);
14526 });
14527
14528 return sizeof(std::int32_t) + document_size + 1ul;
14529 }
14530
14531 /*!
14532 @param[in] value JSON value to serialize
14533 @pre value.type() == value_t::object
14534 */
14535 void write_bson_object(const typename BasicJsonType::object_t& value)
14536 {
14537 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
14538
14539 for (const auto& el : value)
14540 {
14541 write_bson_element(el.first, el.second);
14542 }
14543
14544 oa->write_character(to_char_type(0x00));
14545 }
14546
14547 //////////
14548 // CBOR //
14549 //////////
14550
14551 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
14552 {
14553 return to_char_type(0xFA); // Single-Precision Float
14554 }
14555
14556 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
14557 {
14558 return to_char_type(0xFB); // Double-Precision Float
14559 }
14560
14561 /////////////
14562 // MsgPack //
14563 /////////////
14564
14565 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
14566 {
14567 return to_char_type(0xCA); // float 32
14568 }
14569
14570 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
14571 {
14572 return to_char_type(0xCB); // float 64
14573 }
14574
14575 ////////////
14576 // UBJSON //
14577 ////////////
14578
14579 // UBJSON: write number (floating point)
14580 template<typename NumberType, typename std::enable_if<
14581 std::is_floating_point<NumberType>::value, int>::type = 0>
14582 void write_number_with_ubjson_prefix(const NumberType n,
14583 const bool add_prefix)
14584 {
14585 if (add_prefix)
14586 {
14587 oa->write_character(get_ubjson_float_prefix(n));
14588 }
14589 write_number(n);
14590 }
14591
14592 // UBJSON: write number (unsigned integer)
14593 template<typename NumberType, typename std::enable_if<
14594 std::is_unsigned<NumberType>::value, int>::type = 0>
14595 void write_number_with_ubjson_prefix(const NumberType n,
14596 const bool add_prefix)
14597 {
14598 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
14599 {
14600 if (add_prefix)
14601 {
14602 oa->write_character(to_char_type('i')); // int8
14603 }
14604 write_number(static_cast<std::uint8_t>(n));
14605 }
14606 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
14607 {
14608 if (add_prefix)
14609 {
14610 oa->write_character(to_char_type('U')); // uint8
14611 }
14612 write_number(static_cast<std::uint8_t>(n));
14613 }
14614 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
14615 {
14616 if (add_prefix)
14617 {
14618 oa->write_character(to_char_type('I')); // int16
14619 }
14620 write_number(static_cast<std::int16_t>(n));
14621 }
14622 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14623 {
14624 if (add_prefix)
14625 {
14626 oa->write_character(to_char_type('l')); // int32
14627 }
14628 write_number(static_cast<std::int32_t>(n));
14629 }
14630 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14631 {
14632 if (add_prefix)
14633 {
14634 oa->write_character(to_char_type('L')); // int64
14635 }
14636 write_number(static_cast<std::int64_t>(n));
14637 }
14638 else
14639 {
14640 if (add_prefix)
14641 {
14642 oa->write_character(to_char_type('H')); // high-precision number
14643 }
14644
14645 const auto number = BasicJsonType(n).dump();
14646 write_number_with_ubjson_prefix(number.size(), true);
14647 for (std::size_t i = 0; i < number.size(); ++i)
14648 {
14649 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
14650 }
14651 }
14652 }
14653
14654 // UBJSON: write number (signed integer)
14655 template < typename NumberType, typename std::enable_if <
14656 std::is_signed<NumberType>::value&&
14657 !std::is_floating_point<NumberType>::value, int >::type = 0 >
14658 void write_number_with_ubjson_prefix(const NumberType n,
14659 const bool add_prefix)
14660 {
14661 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
14662 {
14663 if (add_prefix)
14664 {
14665 oa->write_character(to_char_type('i')); // int8
14666 }
14667 write_number(static_cast<std::int8_t>(n));
14668 }
14669 else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
14670 {
14671 if (add_prefix)
14672 {
14673 oa->write_character(to_char_type('U')); // uint8
14674 }
14675 write_number(static_cast<std::uint8_t>(n));
14676 }
14677 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
14678 {
14679 if (add_prefix)
14680 {
14681 oa->write_character(to_char_type('I')); // int16
14682 }
14683 write_number(static_cast<std::int16_t>(n));
14684 }
14685 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
14686 {
14687 if (add_prefix)
14688 {
14689 oa->write_character(to_char_type('l')); // int32
14690 }
14691 write_number(static_cast<std::int32_t>(n));
14692 }
14693 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
14694 {
14695 if (add_prefix)
14696 {
14697 oa->write_character(to_char_type('L')); // int64
14698 }
14699 write_number(static_cast<std::int64_t>(n));
14700 }
14701 // LCOV_EXCL_START
14702 else
14703 {
14704 if (add_prefix)
14705 {
14706 oa->write_character(to_char_type('H')); // high-precision number
14707 }
14708
14709 const auto number = BasicJsonType(n).dump();
14710 write_number_with_ubjson_prefix(number.size(), true);
14711 for (std::size_t i = 0; i < number.size(); ++i)
14712 {
14713 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
14714 }
14715 }
14716 // LCOV_EXCL_STOP
14717 }
14718
14719 /*!
14720 @brief determine the type prefix of container values
14721 */
14722 CharType ubjson_prefix(const BasicJsonType& j) const noexcept
14723 {
14724 switch (j.type())
14725 {
14726 case value_t::null:
14727 return 'Z';
14728
14729 case value_t::boolean:
14730 return j.m_value.boolean ? 'T' : 'F';
14731
14732 case value_t::number_integer:
14733 {
14734 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
14735 {
14736 return 'i';
14737 }
14738 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
14739 {
14740 return 'U';
14741 }
14742 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
14743 {
14744 return 'I';
14745 }
14746 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
14747 {
14748 return 'l';
14749 }
14750 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
14751 {
14752 return 'L';
14753 }
14754 // anything else is treated as high-precision number
14755 return 'H'; // LCOV_EXCL_LINE
14756 }
14757
14758 case value_t::number_unsigned:
14759 {
14760 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
14761 {
14762 return 'i';
14763 }
14764 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
14765 {
14766 return 'U';
14767 }
14768 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
14769 {
14770 return 'I';
14771 }
14772 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14773 {
14774 return 'l';
14775 }
14776 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14777 {
14778 return 'L';
14779 }
14780 // anything else is treated as high-precision number
14781 return 'H'; // LCOV_EXCL_LINE
14782 }
14783
14784 case value_t::number_float:
14785 return get_ubjson_float_prefix(j.m_value.number_float);
14786
14787 case value_t::string:
14788 return 'S';
14789
14790 case value_t::array: // fallthrough
14791 case value_t::binary:
14792 return '[';
14793
14794 case value_t::object:
14795 return '{';
14796
14797 case value_t::discarded:
14798 default: // discarded values
14799 return 'N';
14800 }
14801 }
14802
14803 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
14804 {
14805 return 'd'; // float 32
14806 }
14807
14808 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
14809 {
14810 return 'D'; // float 64
14811 }
14812
14813 ///////////////////////
14814 // Utility functions //
14815 ///////////////////////
14816
14817 /*
14818 @brief write a number to output input
14819 @param[in] n number of type @a NumberType
14820 @tparam NumberType the type of the number
14821 @tparam OutputIsLittleEndian Set to true if output data is
14822 required to be little endian
14823
14824 @note This function needs to respect the system's endianness, because bytes
14825 in CBOR, MessagePack, and UBJSON are stored in network order (big
14826 endian) and therefore need reordering on little endian systems.
14827 */
14828 template<typename NumberType, bool OutputIsLittleEndian = false>
14829 void write_number(const NumberType n)
14830 {
14831 // step 1: write number to array of length NumberType
14832 std::array<CharType, sizeof(NumberType)> vec{};
14833 std::memcpy(vec.data(), &n, sizeof(NumberType));
14834
14835 // step 2: write array to output (with possible reordering)
14836 if (is_little_endian != OutputIsLittleEndian)
14837 {
14838 // reverse byte order prior to conversion if necessary
14839 std::reverse(vec.begin(), vec.end());
14840 }
14841
14842 oa->write_characters(vec.data(), sizeof(NumberType));
14843 }
14844
14845 void write_compact_float(const number_float_t n, detail::input_format_t format)
14846 {
14847 #ifdef __GNUC__
14848 #pragma GCC diagnostic push
14849 #pragma GCC diagnostic ignored "-Wfloat-equal"
14850 #endif
14851 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
14852 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
14853 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
14854 {
14855 oa->write_character(format == detail::input_format_t::cbor
14856 ? get_cbor_float_prefix(static_cast<float>(n))
14857 : get_msgpack_float_prefix(static_cast<float>(n)));
14858 write_number(static_cast<float>(n));
14859 }
14860 else
14861 {
14862 oa->write_character(format == detail::input_format_t::cbor
14863 ? get_cbor_float_prefix(n)
14864 : get_msgpack_float_prefix(n));
14865 write_number(n);
14866 }
14867 #ifdef __GNUC__
14868 #pragma GCC diagnostic pop
14869 #endif
14870 }
14871
14872 public:
14873 // The following to_char_type functions are implement the conversion
14874 // between uint8_t and CharType. In case CharType is not unsigned,
14875 // such a conversion is required to allow values greater than 128.
14876 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
14877 template < typename C = CharType,
14878 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
14879 static constexpr CharType to_char_type(std::uint8_t x) noexcept
14880 {
14881 return *reinterpret_cast<char*>(&x);
14882 }
14883
14884 template < typename C = CharType,
14885 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
14886 static CharType to_char_type(std::uint8_t x) noexcept
14887 {
14888 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
14889 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
14890 CharType result;
14891 std::memcpy(&result, &x, sizeof(x));
14892 return result;
14893 }
14894
14895 template<typename C = CharType,
14896 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
14897 static constexpr CharType to_char_type(std::uint8_t x) noexcept
14898 {
14899 return x;
14900 }
14901
14902 template < typename InputCharType, typename C = CharType,
14903 enable_if_t <
14904 std::is_signed<C>::value &&
14905 std::is_signed<char>::value &&
14906 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
14907 > * = nullptr >
14908 static constexpr CharType to_char_type(InputCharType x) noexcept
14909 {
14910 return x;
14911 }
14912
14913 private:
14914 /// whether we can assume little endianness
14915 const bool is_little_endian = little_endianness();
14916
14917 /// the output
14918 output_adapter_t<CharType> oa = nullptr;
14919 };
14920 } // namespace detail
14921 } // namespace nlohmann
14922
14923 // #include <nlohmann/detail/output/output_adapters.hpp>
14924
14925 // #include <nlohmann/detail/output/serializer.hpp>
14926
14927
14928 #include <algorithm> // reverse, remove, fill, find, none_of
14929 #include <array> // array
14930 #include <clocale> // localeconv, lconv
14931 #include <cmath> // labs, isfinite, isnan, signbit
14932 #include <cstddef> // size_t, ptrdiff_t
14933 #include <cstdint> // uint8_t
14934 #include <cstdio> // snprintf
14935 #include <limits> // numeric_limits
14936 #include <string> // string, char_traits
14937 #include <iomanip> // setfill, setw
14938 #include <sstream> // stringstream
14939 #include <type_traits> // is_same
14940 #include <utility> // move
14941
14942 // #include <nlohmann/detail/conversions/to_chars.hpp>
14943
14944
14945 #include <array> // array
14946 #include <cmath> // signbit, isfinite
14947 #include <cstdint> // intN_t, uintN_t
14948 #include <cstring> // memcpy, memmove
14949 #include <limits> // numeric_limits
14950 #include <type_traits> // conditional
14951
14952 // #include <nlohmann/detail/macro_scope.hpp>
14953
14954
14955 namespace nlohmann
14956 {
14957 namespace detail
14958 {
14959
14960 /*!
14961 @brief implements the Grisu2 algorithm for binary to decimal floating-point
14962 conversion.
14963
14964 This implementation is a slightly modified version of the reference
14965 implementation which may be obtained from
14966 http://florian.loitsch.com/publications (bench.tar.gz).
14967
14968 The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
14969
14970 For a detailed description of the algorithm see:
14971
14972 [1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
14973 Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
14974 Language Design and Implementation, PLDI 2010
14975 [2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
14976 Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
14977 Design and Implementation, PLDI 1996
14978 */
14979 namespace dtoa_impl
14980 {
14981
14982 template<typename Target, typename Source>
14983 Target reinterpret_bits(const Source source)
14984 {
14985 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
14986
14987 Target target;
14988 std::memcpy(&target, &source, sizeof(Source));
14989 return target;
14990 }
14991
14992 struct diyfp // f * 2^e
14993 {
14994 static constexpr int kPrecision = 64; // = q
14995
14996 std::uint64_t f = 0;
14997 int e = 0;
14998
14999 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
15000
15001 /*!
15002 @brief returns x - y
15003 @pre x.e == y.e and x.f >= y.f
15004 */
15005 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
15006 {
15007 JSON_ASSERT(x.e == y.e);
15008 JSON_ASSERT(x.f >= y.f);
15009
15010 return {x.f - y.f, x.e};
15011 }
15012
15013 /*!
15014 @brief returns x * y
15015 @note The result is rounded. (Only the upper q bits are returned.)
15016 */
15017 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
15018 {
15019 static_assert(kPrecision == 64, "internal error");
15020
15021 // Computes:
15022 // f = round((x.f * y.f) / 2^q)
15023 // e = x.e + y.e + q
15024
15025 // Emulate the 64-bit * 64-bit multiplication:
15026 //
15027 // p = u * v
15028 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
15029 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
15030 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
15031 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
15032 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
15033 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
15034 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
15035 //
15036 // (Since Q might be larger than 2^32 - 1)
15037 //
15038 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
15039 //
15040 // (Q_hi + H does not overflow a 64-bit int)
15041 //
15042 // = p_lo + 2^64 p_hi
15043
15044 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
15045 const std::uint64_t u_hi = x.f >> 32u;
15046 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
15047 const std::uint64_t v_hi = y.f >> 32u;
15048
15049 const std::uint64_t p0 = u_lo * v_lo;
15050 const std::uint64_t p1 = u_lo * v_hi;
15051 const std::uint64_t p2 = u_hi * v_lo;
15052 const std::uint64_t p3 = u_hi * v_hi;
15053
15054 const std::uint64_t p0_hi = p0 >> 32u;
15055 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
15056 const std::uint64_t p1_hi = p1 >> 32u;
15057 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
15058 const std::uint64_t p2_hi = p2 >> 32u;
15059
15060 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
15061
15062 // The full product might now be computed as
15063 //
15064 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
15065 // p_lo = p0_lo + (Q << 32)
15066 //
15067 // But in this particular case here, the full p_lo is not required.
15068 // Effectively we only need to add the highest bit in p_lo to p_hi (and
15069 // Q_hi + 1 does not overflow).
15070
15071 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
15072
15073 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
15074
15075 return {h, x.e + y.e + 64};
15076 }
15077
15078 /*!
15079 @brief normalize x such that the significand is >= 2^(q-1)
15080 @pre x.f != 0
15081 */
15082 static diyfp normalize(diyfp x) noexcept
15083 {
15084 JSON_ASSERT(x.f != 0);
15085
15086 while ((x.f >> 63u) == 0)
15087 {
15088 x.f <<= 1u;
15089 x.e--;
15090 }
15091
15092 return x;
15093 }
15094
15095 /*!
15096 @brief normalize x such that the result has the exponent E
15097 @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
15098 */
15099 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
15100 {
15101 const int delta = x.e - target_exponent;
15102
15103 JSON_ASSERT(delta >= 0);
15104 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
15105
15106 return {x.f << delta, target_exponent};
15107 }
15108 };
15109
15110 struct boundaries
15111 {
15112 diyfp w;
15113 diyfp minus;
15114 diyfp plus;
15115 };
15116
15117 /*!
15118 Compute the (normalized) diyfp representing the input number 'value' and its
15119 boundaries.
15120
15121 @pre value must be finite and positive
15122 */
15123 template<typename FloatType>
15124 boundaries compute_boundaries(FloatType value)
15125 {
15126 JSON_ASSERT(std::isfinite(value));
15127 JSON_ASSERT(value > 0);
15128
15129 // Convert the IEEE representation into a diyfp.
15130 //
15131 // If v is denormal:
15132 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
15133 // If v is normalized:
15134 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
15135
15136 static_assert(std::numeric_limits<FloatType>::is_iec559,
15137 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
15138
15139 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
15140 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
15141 constexpr int kMinExp = 1 - kBias;
15142 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
15143
15144 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
15145
15146 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
15147 const std::uint64_t E = bits >> (kPrecision - 1);
15148 const std::uint64_t F = bits & (kHiddenBit - 1);
15149
15150 const bool is_denormal = E == 0;
15151 const diyfp v = is_denormal
15152 ? diyfp(F, kMinExp)
15153 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
15154
15155 // Compute the boundaries m- and m+ of the floating-point value
15156 // v = f * 2^e.
15157 //
15158 // Determine v- and v+, the floating-point predecessor and successor if v,
15159 // respectively.
15160 //
15161 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
15162 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
15163 //
15164 // v+ = v + 2^e
15165 //
15166 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
15167 // between m- and m+ round to v, regardless of how the input rounding
15168 // algorithm breaks ties.
15169 //
15170 // ---+-------------+-------------+-------------+-------------+--- (A)
15171 // v- m- v m+ v+
15172 //
15173 // -----------------+------+------+-------------+-------------+--- (B)
15174 // v- m- v m+ v+
15175
15176 const bool lower_boundary_is_closer = F == 0 && E > 1;
15177 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
15178 const diyfp m_minus = lower_boundary_is_closer
15179 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
15180 : diyfp(2 * v.f - 1, v.e - 1); // (A)
15181
15182 // Determine the normalized w+ = m+.
15183 const diyfp w_plus = diyfp::normalize(m_plus);
15184
15185 // Determine w- = m- such that e_(w-) = e_(w+).
15186 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
15187
15188 return {diyfp::normalize(v), w_minus, w_plus};
15189 }
15190
15191 // Given normalized diyfp w, Grisu needs to find a (normalized) cached
15192 // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
15193 // within a certain range [alpha, gamma] (Definition 3.2 from [1])
15194 //
15195 // alpha <= e = e_c + e_w + q <= gamma
15196 //
15197 // or
15198 //
15199 // f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
15200 // <= f_c * f_w * 2^gamma
15201 //
15202 // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
15203 //
15204 // 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
15205 //
15206 // or
15207 //
15208 // 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
15209 //
15210 // The choice of (alpha,gamma) determines the size of the table and the form of
15211 // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
15212 // in practice:
15213 //
15214 // The idea is to cut the number c * w = f * 2^e into two parts, which can be
15215 // processed independently: An integral part p1, and a fractional part p2:
15216 //
15217 // f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
15218 // = (f div 2^-e) + (f mod 2^-e) * 2^e
15219 // = p1 + p2 * 2^e
15220 //
15221 // The conversion of p1 into decimal form requires a series of divisions and
15222 // modulos by (a power of) 10. These operations are faster for 32-bit than for
15223 // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
15224 // achieved by choosing
15225 //
15226 // -e >= 32 or e <= -32 := gamma
15227 //
15228 // In order to convert the fractional part
15229 //
15230 // p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
15231 //
15232 // into decimal form, the fraction is repeatedly multiplied by 10 and the digits
15233 // d[-i] are extracted in order:
15234 //
15235 // (10 * p2) div 2^-e = d[-1]
15236 // (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
15237 //
15238 // The multiplication by 10 must not overflow. It is sufficient to choose
15239 //
15240 // 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
15241 //
15242 // Since p2 = f mod 2^-e < 2^-e,
15243 //
15244 // -e <= 60 or e >= -60 := alpha
15245
15246 constexpr int kAlpha = -60;
15247 constexpr int kGamma = -32;
15248
15249 struct cached_power // c = f * 2^e ~= 10^k
15250 {
15251 std::uint64_t f;
15252 int e;
15253 int k;
15254 };
15255
15256 /*!
15257 For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
15258 power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
15259 satisfies (Definition 3.2 from [1])
15260
15261 alpha <= e_c + e + q <= gamma.
15262 */
15263 inline cached_power get_cached_power_for_binary_exponent(int e)
15264 {
15265 // Now
15266 //
15267 // alpha <= e_c + e + q <= gamma (1)
15268 // ==> f_c * 2^alpha <= c * 2^e * 2^q
15269 //
15270 // and since the c's are normalized, 2^(q-1) <= f_c,
15271 //
15272 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
15273 // ==> 2^(alpha - e - 1) <= c
15274 //
15275 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
15276 //
15277 // k = ceil( log_10( 2^(alpha - e - 1) ) )
15278 // = ceil( (alpha - e - 1) * log_10(2) )
15279 //
15280 // From the paper:
15281 // "In theory the result of the procedure could be wrong since c is rounded,
15282 // and the computation itself is approximated [...]. In practice, however,
15283 // this simple function is sufficient."
15284 //
15285 // For IEEE double precision floating-point numbers converted into
15286 // normalized diyfp's w = f * 2^e, with q = 64,
15287 //
15288 // e >= -1022 (min IEEE exponent)
15289 // -52 (p - 1)
15290 // -52 (p - 1, possibly normalize denormal IEEE numbers)
15291 // -11 (normalize the diyfp)
15292 // = -1137
15293 //
15294 // and
15295 //
15296 // e <= +1023 (max IEEE exponent)
15297 // -52 (p - 1)
15298 // -11 (normalize the diyfp)
15299 // = 960
15300 //
15301 // This binary exponent range [-1137,960] results in a decimal exponent
15302 // range [-307,324]. One does not need to store a cached power for each
15303 // k in this range. For each such k it suffices to find a cached power
15304 // such that the exponent of the product lies in [alpha,gamma].
15305 // This implies that the difference of the decimal exponents of adjacent
15306 // table entries must be less than or equal to
15307 //
15308 // floor( (gamma - alpha) * log_10(2) ) = 8.
15309 //
15310 // (A smaller distance gamma-alpha would require a larger table.)
15311
15312 // NB:
15313 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
15314
15315 constexpr int kCachedPowersMinDecExp = -300;
15316 constexpr int kCachedPowersDecStep = 8;
15317
15318 static constexpr std::array<cached_power, 79> kCachedPowers =
15319 {
15320 {
15321 { 0xAB70FE17C79AC6CA, -1060, -300 },
15322 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
15323 { 0xBE5691EF416BD60C, -1007, -284 },
15324 { 0x8DD01FAD907FFC3C, -980, -276 },
15325 { 0xD3515C2831559A83, -954, -268 },
15326 { 0x9D71AC8FADA6C9B5, -927, -260 },
15327 { 0xEA9C227723EE8BCB, -901, -252 },
15328 { 0xAECC49914078536D, -874, -244 },
15329 { 0x823C12795DB6CE57, -847, -236 },
15330 { 0xC21094364DFB5637, -821, -228 },
15331 { 0x9096EA6F3848984F, -794, -220 },
15332 { 0xD77485CB25823AC7, -768, -212 },
15333 { 0xA086CFCD97BF97F4, -741, -204 },
15334 { 0xEF340A98172AACE5, -715, -196 },
15335 { 0xB23867FB2A35B28E, -688, -188 },
15336 { 0x84C8D4DFD2C63F3B, -661, -180 },
15337 { 0xC5DD44271AD3CDBA, -635, -172 },
15338 { 0x936B9FCEBB25C996, -608, -164 },
15339 { 0xDBAC6C247D62A584, -582, -156 },
15340 { 0xA3AB66580D5FDAF6, -555, -148 },
15341 { 0xF3E2F893DEC3F126, -529, -140 },
15342 { 0xB5B5ADA8AAFF80B8, -502, -132 },
15343 { 0x87625F056C7C4A8B, -475, -124 },
15344 { 0xC9BCFF6034C13053, -449, -116 },
15345 { 0x964E858C91BA2655, -422, -108 },
15346 { 0xDFF9772470297EBD, -396, -100 },
15347 { 0xA6DFBD9FB8E5B88F, -369, -92 },
15348 { 0xF8A95FCF88747D94, -343, -84 },
15349 { 0xB94470938FA89BCF, -316, -76 },
15350 { 0x8A08F0F8BF0F156B, -289, -68 },
15351 { 0xCDB02555653131B6, -263, -60 },
15352 { 0x993FE2C6D07B7FAC, -236, -52 },
15353 { 0xE45C10C42A2B3B06, -210, -44 },
15354 { 0xAA242499697392D3, -183, -36 },
15355 { 0xFD87B5F28300CA0E, -157, -28 },
15356 { 0xBCE5086492111AEB, -130, -20 },
15357 { 0x8CBCCC096F5088CC, -103, -12 },
15358 { 0xD1B71758E219652C, -77, -4 },
15359 { 0x9C40000000000000, -50, 4 },
15360 { 0xE8D4A51000000000, -24, 12 },
15361 { 0xAD78EBC5AC620000, 3, 20 },
15362 { 0x813F3978F8940984, 30, 28 },
15363 { 0xC097CE7BC90715B3, 56, 36 },
15364 { 0x8F7E32CE7BEA5C70, 83, 44 },
15365 { 0xD5D238A4ABE98068, 109, 52 },
15366 { 0x9F4F2726179A2245, 136, 60 },
15367 { 0xED63A231D4C4FB27, 162, 68 },
15368 { 0xB0DE65388CC8ADA8, 189, 76 },
15369 { 0x83C7088E1AAB65DB, 216, 84 },
15370 { 0xC45D1DF942711D9A, 242, 92 },
15371 { 0x924D692CA61BE758, 269, 100 },
15372 { 0xDA01EE641A708DEA, 295, 108 },
15373 { 0xA26DA3999AEF774A, 322, 116 },
15374 { 0xF209787BB47D6B85, 348, 124 },
15375 { 0xB454E4A179DD1877, 375, 132 },
15376 { 0x865B86925B9BC5C2, 402, 140 },
15377 { 0xC83553C5C8965D3D, 428, 148 },
15378 { 0x952AB45CFA97A0B3, 455, 156 },
15379 { 0xDE469FBD99A05FE3, 481, 164 },
15380 { 0xA59BC234DB398C25, 508, 172 },
15381 { 0xF6C69A72A3989F5C, 534, 180 },
15382 { 0xB7DCBF5354E9BECE, 561, 188 },
15383 { 0x88FCF317F22241E2, 588, 196 },
15384 { 0xCC20CE9BD35C78A5, 614, 204 },
15385 { 0x98165AF37B2153DF, 641, 212 },
15386 { 0xE2A0B5DC971F303A, 667, 220 },
15387 { 0xA8D9D1535CE3B396, 694, 228 },
15388 { 0xFB9B7CD9A4A7443C, 720, 236 },
15389 { 0xBB764C4CA7A44410, 747, 244 },
15390 { 0x8BAB8EEFB6409C1A, 774, 252 },
15391 { 0xD01FEF10A657842C, 800, 260 },
15392 { 0x9B10A4E5E9913129, 827, 268 },
15393 { 0xE7109BFBA19C0C9D, 853, 276 },
15394 { 0xAC2820D9623BF429, 880, 284 },
15395 { 0x80444B5E7AA7CF85, 907, 292 },
15396 { 0xBF21E44003ACDD2D, 933, 300 },
15397 { 0x8E679C2F5E44FF8F, 960, 308 },
15398 { 0xD433179D9C8CB841, 986, 316 },
15399 { 0x9E19DB92B4E31BA9, 1013, 324 },
15400 }
15401 };
15402
15403 // This computation gives exactly the same results for k as
15404 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
15405 // for |e| <= 1500, but doesn't require floating-point operations.
15406 // NB: log_10(2) ~= 78913 / 2^18
15407 JSON_ASSERT(e >= -1500);
15408 JSON_ASSERT(e <= 1500);
15409 const int f = kAlpha - e - 1;
15410 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
15411
15412 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
15413 JSON_ASSERT(index >= 0);
15414 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
15415
15416 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
15417 JSON_ASSERT(kAlpha <= cached.e + e + 64);
15418 JSON_ASSERT(kGamma >= cached.e + e + 64);
15419
15420 return cached;
15421 }
15422
15423 /*!
15424 For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
15425 For n == 0, returns 1 and sets pow10 := 1.
15426 */
15427 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
15428 {
15429 // LCOV_EXCL_START
15430 if (n >= 1000000000)
15431 {
15432 pow10 = 1000000000;
15433 return 10;
15434 }
15435 // LCOV_EXCL_STOP
15436 if (n >= 100000000)
15437 {
15438 pow10 = 100000000;
15439 return 9;
15440 }
15441 if (n >= 10000000)
15442 {
15443 pow10 = 10000000;
15444 return 8;
15445 }
15446 if (n >= 1000000)
15447 {
15448 pow10 = 1000000;
15449 return 7;
15450 }
15451 if (n >= 100000)
15452 {
15453 pow10 = 100000;
15454 return 6;
15455 }
15456 if (n >= 10000)
15457 {
15458 pow10 = 10000;
15459 return 5;
15460 }
15461 if (n >= 1000)
15462 {
15463 pow10 = 1000;
15464 return 4;
15465 }
15466 if (n >= 100)
15467 {
15468 pow10 = 100;
15469 return 3;
15470 }
15471 if (n >= 10)
15472 {
15473 pow10 = 10;
15474 return 2;
15475 }
15476
15477 pow10 = 1;
15478 return 1;
15479 }
15480
15481 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
15482 std::uint64_t rest, std::uint64_t ten_k)
15483 {
15484 JSON_ASSERT(len >= 1);
15485 JSON_ASSERT(dist <= delta);
15486 JSON_ASSERT(rest <= delta);
15487 JSON_ASSERT(ten_k > 0);
15488
15489 // <--------------------------- delta ---->
15490 // <---- dist --------->
15491 // --------------[------------------+-------------------]--------------
15492 // M- w M+
15493 //
15494 // ten_k
15495 // <------>
15496 // <---- rest ---->
15497 // --------------[------------------+----+--------------]--------------
15498 // w V
15499 // = buf * 10^k
15500 //
15501 // ten_k represents a unit-in-the-last-place in the decimal representation
15502 // stored in buf.
15503 // Decrement buf by ten_k while this takes buf closer to w.
15504
15505 // The tests are written in this order to avoid overflow in unsigned
15506 // integer arithmetic.
15507
15508 while (rest < dist
15509 && delta - rest >= ten_k
15510 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
15511 {
15512 JSON_ASSERT(buf[len - 1] != '0');
15513 buf[len - 1]--;
15514 rest += ten_k;
15515 }
15516 }
15517
15518 /*!
15519 Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
15520 M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
15521 */
15522 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
15523 diyfp M_minus, diyfp w, diyfp M_plus)
15524 {
15525 static_assert(kAlpha >= -60, "internal error");
15526 static_assert(kGamma <= -32, "internal error");
15527
15528 // Generates the digits (and the exponent) of a decimal floating-point
15529 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
15530 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
15531 //
15532 // <--------------------------- delta ---->
15533 // <---- dist --------->
15534 // --------------[------------------+-------------------]--------------
15535 // M- w M+
15536 //
15537 // Grisu2 generates the digits of M+ from left to right and stops as soon as
15538 // V is in [M-,M+].
15539
15540 JSON_ASSERT(M_plus.e >= kAlpha);
15541 JSON_ASSERT(M_plus.e <= kGamma);
15542
15543 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
15544 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
15545
15546 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
15547 //
15548 // M+ = f * 2^e
15549 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
15550 // = ((p1 ) * 2^-e + (p2 )) * 2^e
15551 // = p1 + p2 * 2^e
15552
15553 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
15554
15555 auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
15556 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
15557
15558 // 1)
15559 //
15560 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
15561
15562 JSON_ASSERT(p1 > 0);
15563
15564 std::uint32_t pow10{};
15565 const int k = find_largest_pow10(p1, pow10);
15566
15567 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
15568 //
15569 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
15570 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
15571 //
15572 // M+ = p1 + p2 * 2^e
15573 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
15574 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
15575 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
15576 //
15577 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
15578 //
15579 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
15580 //
15581 // but stop as soon as
15582 //
15583 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
15584
15585 int n = k;
15586 while (n > 0)
15587 {
15588 // Invariants:
15589 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
15590 // pow10 = 10^(n-1) <= p1 < 10^n
15591 //
15592 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
15593 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
15594 //
15595 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
15596 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
15597 //
15598 JSON_ASSERT(d <= 9);
15599 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
15600 //
15601 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
15602 //
15603 p1 = r;
15604 n--;
15605 //
15606 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
15607 // pow10 = 10^n
15608 //
15609
15610 // Now check if enough digits have been generated.
15611 // Compute
15612 //
15613 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
15614 //
15615 // Note:
15616 // Since rest and delta share the same exponent e, it suffices to
15617 // compare the significands.
15618 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
15619 if (rest <= delta)
15620 {
15621 // V = buffer * 10^n, with M- <= V <= M+.
15622
15623 decimal_exponent += n;
15624
15625 // We may now just stop. But instead look if the buffer could be
15626 // decremented to bring V closer to w.
15627 //
15628 // pow10 = 10^n is now 1 ulp in the decimal representation V.
15629 // The rounding procedure works with diyfp's with an implicit
15630 // exponent of e.
15631 //
15632 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
15633 //
15634 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
15635 grisu2_round(buffer, length, dist, delta, rest, ten_n);
15636
15637 return;
15638 }
15639
15640 pow10 /= 10;
15641 //
15642 // pow10 = 10^(n-1) <= p1 < 10^n
15643 // Invariants restored.
15644 }
15645
15646 // 2)
15647 //
15648 // The digits of the integral part have been generated:
15649 //
15650 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
15651 // = buffer + p2 * 2^e
15652 //
15653 // Now generate the digits of the fractional part p2 * 2^e.
15654 //
15655 // Note:
15656 // No decimal point is generated: the exponent is adjusted instead.
15657 //
15658 // p2 actually represents the fraction
15659 //
15660 // p2 * 2^e
15661 // = p2 / 2^-e
15662 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
15663 //
15664 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
15665 //
15666 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
15667 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
15668 //
15669 // using
15670 //
15671 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
15672 // = ( d) * 2^-e + ( r)
15673 //
15674 // or
15675 // 10^m * p2 * 2^e = d + r * 2^e
15676 //
15677 // i.e.
15678 //
15679 // M+ = buffer + p2 * 2^e
15680 // = buffer + 10^-m * (d + r * 2^e)
15681 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
15682 //
15683 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
15684
15685 JSON_ASSERT(p2 > delta);
15686
15687 int m = 0;
15688 for (;;)
15689 {
15690 // Invariant:
15691 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
15692 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
15693 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
15694 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
15695 //
15696 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
15697 p2 *= 10;
15698 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
15699 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
15700 //
15701 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
15702 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
15703 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
15704 //
15705 JSON_ASSERT(d <= 9);
15706 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
15707 //
15708 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
15709 //
15710 p2 = r;
15711 m++;
15712 //
15713 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
15714 // Invariant restored.
15715
15716 // Check if enough digits have been generated.
15717 //
15718 // 10^-m * p2 * 2^e <= delta * 2^e
15719 // p2 * 2^e <= 10^m * delta * 2^e
15720 // p2 <= 10^m * delta
15721 delta *= 10;
15722 dist *= 10;
15723 if (p2 <= delta)
15724 {
15725 break;
15726 }
15727 }
15728
15729 // V = buffer * 10^-m, with M- <= V <= M+.
15730
15731 decimal_exponent -= m;
15732
15733 // 1 ulp in the decimal representation is now 10^-m.
15734 // Since delta and dist are now scaled by 10^m, we need to do the
15735 // same with ulp in order to keep the units in sync.
15736 //
15737 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
15738 //
15739 const std::uint64_t ten_m = one.f;
15740 grisu2_round(buffer, length, dist, delta, p2, ten_m);
15741
15742 // By construction this algorithm generates the shortest possible decimal
15743 // number (Loitsch, Theorem 6.2) which rounds back to w.
15744 // For an input number of precision p, at least
15745 //
15746 // N = 1 + ceil(p * log_10(2))
15747 //
15748 // decimal digits are sufficient to identify all binary floating-point
15749 // numbers (Matula, "In-and-Out conversions").
15750 // This implies that the algorithm does not produce more than N decimal
15751 // digits.
15752 //
15753 // N = 17 for p = 53 (IEEE double precision)
15754 // N = 9 for p = 24 (IEEE single precision)
15755 }
15756
15757 /*!
15758 v = buf * 10^decimal_exponent
15759 len is the length of the buffer (number of decimal digits)
15760 The buffer must be large enough, i.e. >= max_digits10.
15761 */
15762 JSON_HEDLEY_NON_NULL(1)
15763 inline void grisu2(char* buf, int& len, int& decimal_exponent,
15764 diyfp m_minus, diyfp v, diyfp m_plus)
15765 {
15766 JSON_ASSERT(m_plus.e == m_minus.e);
15767 JSON_ASSERT(m_plus.e == v.e);
15768
15769 // --------(-----------------------+-----------------------)-------- (A)
15770 // m- v m+
15771 //
15772 // --------------------(-----------+-----------------------)-------- (B)
15773 // m- v m+
15774 //
15775 // First scale v (and m- and m+) such that the exponent is in the range
15776 // [alpha, gamma].
15777
15778 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
15779
15780 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
15781
15782 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
15783 const diyfp w = diyfp::mul(v, c_minus_k);
15784 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
15785 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
15786
15787 // ----(---+---)---------------(---+---)---------------(---+---)----
15788 // w- w w+
15789 // = c*m- = c*v = c*m+
15790 //
15791 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
15792 // w+ are now off by a small amount.
15793 // In fact:
15794 //
15795 // w - v * 10^k < 1 ulp
15796 //
15797 // To account for this inaccuracy, add resp. subtract 1 ulp.
15798 //
15799 // --------+---[---------------(---+---)---------------]---+--------
15800 // w- M- w M+ w+
15801 //
15802 // Now any number in [M-, M+] (bounds included) will round to w when input,
15803 // regardless of how the input rounding algorithm breaks ties.
15804 //
15805 // And digit_gen generates the shortest possible such number in [M-, M+].
15806 // Note that this does not mean that Grisu2 always generates the shortest
15807 // possible number in the interval (m-, m+).
15808 const diyfp M_minus(w_minus.f + 1, w_minus.e);
15809 const diyfp M_plus (w_plus.f - 1, w_plus.e );
15810
15811 decimal_exponent = -cached.k; // = -(-k) = k
15812
15813 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
15814 }
15815
15816 /*!
15817 v = buf * 10^decimal_exponent
15818 len is the length of the buffer (number of decimal digits)
15819 The buffer must be large enough, i.e. >= max_digits10.
15820 */
15821 template<typename FloatType>
15822 JSON_HEDLEY_NON_NULL(1)
15823 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
15824 {
15825 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
15826 "internal error: not enough precision");
15827
15828 JSON_ASSERT(std::isfinite(value));
15829 JSON_ASSERT(value > 0);
15830
15831 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
15832 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
15833 // decimal representations are not exactly "short".
15834 //
15835 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
15836 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
15837 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
15838 // does.
15839 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
15840 // representation using the corresponding std::from_chars function recovers value exactly". That
15841 // indicates that single precision floating-point numbers should be recovered using
15842 // 'std::strtof'.
15843 //
15844 // NB: If the neighbors are computed for single-precision numbers, there is a single float
15845 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
15846 // value is off by 1 ulp.
15847 #if 0
15848 const boundaries w = compute_boundaries(static_cast<double>(value));
15849 #else
15850 const boundaries w = compute_boundaries(value);
15851 #endif
15852
15853 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
15854 }
15855
15856 /*!
15857 @brief appends a decimal representation of e to buf
15858 @return a pointer to the element following the exponent.
15859 @pre -1000 < e < 1000
15860 */
15861 JSON_HEDLEY_NON_NULL(1)
15862 JSON_HEDLEY_RETURNS_NON_NULL
15863 inline char* append_exponent(char* buf, int e)
15864 {
15865 JSON_ASSERT(e > -1000);
15866 JSON_ASSERT(e < 1000);
15867
15868 if (e < 0)
15869 {
15870 e = -e;
15871 *buf++ = '-';
15872 }
15873 else
15874 {
15875 *buf++ = '+';
15876 }
15877
15878 auto k = static_cast<std::uint32_t>(e);
15879 if (k < 10)
15880 {
15881 // Always print at least two digits in the exponent.
15882 // This is for compatibility with printf("%g").
15883 *buf++ = '0';
15884 *buf++ = static_cast<char>('0' + k);
15885 }
15886 else if (k < 100)
15887 {
15888 *buf++ = static_cast<char>('0' + k / 10);
15889 k %= 10;
15890 *buf++ = static_cast<char>('0' + k);
15891 }
15892 else
15893 {
15894 *buf++ = static_cast<char>('0' + k / 100);
15895 k %= 100;
15896 *buf++ = static_cast<char>('0' + k / 10);
15897 k %= 10;
15898 *buf++ = static_cast<char>('0' + k);
15899 }
15900
15901 return buf;
15902 }
15903
15904 /*!
15905 @brief prettify v = buf * 10^decimal_exponent
15906
15907 If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
15908 notation. Otherwise it will be printed in exponential notation.
15909
15910 @pre min_exp < 0
15911 @pre max_exp > 0
15912 */
15913 JSON_HEDLEY_NON_NULL(1)
15914 JSON_HEDLEY_RETURNS_NON_NULL
15915 inline char* format_buffer(char* buf, int len, int decimal_exponent,
15916 int min_exp, int max_exp)
15917 {
15918 JSON_ASSERT(min_exp < 0);
15919 JSON_ASSERT(max_exp > 0);
15920
15921 const int k = len;
15922 const int n = len + decimal_exponent;
15923
15924 // v = buf * 10^(n-k)
15925 // k is the length of the buffer (number of decimal digits)
15926 // n is the position of the decimal point relative to the start of the buffer.
15927
15928 if (k <= n && n <= max_exp)
15929 {
15930 // digits[000]
15931 // len <= max_exp + 2
15932
15933 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
15934 // Make it look like a floating-point number (#362, #378)
15935 buf[n + 0] = '.';
15936 buf[n + 1] = '0';
15937 return buf + (static_cast<size_t>(n) + 2);
15938 }
15939
15940 if (0 < n && n <= max_exp)
15941 {
15942 // dig.its
15943 // len <= max_digits10 + 1
15944
15945 JSON_ASSERT(k > n);
15946
15947 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
15948 buf[n] = '.';
15949 return buf + (static_cast<size_t>(k) + 1U);
15950 }
15951
15952 if (min_exp < n && n <= 0)
15953 {
15954 // 0.[000]digits
15955 // len <= 2 + (-min_exp - 1) + max_digits10
15956
15957 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
15958 buf[0] = '0';
15959 buf[1] = '.';
15960 std::memset(buf + 2, '0', static_cast<size_t>(-n));
15961 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
15962 }
15963
15964 if (k == 1)
15965 {
15966 // dE+123
15967 // len <= 1 + 5
15968
15969 buf += 1;
15970 }
15971 else
15972 {
15973 // d.igitsE+123
15974 // len <= max_digits10 + 1 + 5
15975
15976 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
15977 buf[1] = '.';
15978 buf += 1 + static_cast<size_t>(k);
15979 }
15980
15981 *buf++ = 'e';
15982 return append_exponent(buf, n - 1);
15983 }
15984
15985 } // namespace dtoa_impl
15986
15987 /*!
15988 @brief generates a decimal representation of the floating-point number value in [first, last).
15989
15990 The format of the resulting decimal representation is similar to printf's %g
15991 format. Returns an iterator pointing past-the-end of the decimal representation.
15992
15993 @note The input number must be finite, i.e. NaN's and Inf's are not supported.
15994 @note The buffer must be large enough.
15995 @note The result is NOT null-terminated.
15996 */
15997 template<typename FloatType>
15998 JSON_HEDLEY_NON_NULL(1, 2)
15999 JSON_HEDLEY_RETURNS_NON_NULL
16000 char* to_chars(char* first, const char* last, FloatType value)
16001 {
16002 static_cast<void>(last); // maybe unused - fix warning
16003 JSON_ASSERT(std::isfinite(value));
16004
16005 // Use signbit(value) instead of (value < 0) since signbit works for -0.
16006 if (std::signbit(value))
16007 {
16008 value = -value;
16009 *first++ = '-';
16010 }
16011
16012 #ifdef __GNUC__
16013 #pragma GCC diagnostic push
16014 #pragma GCC diagnostic ignored "-Wfloat-equal"
16015 #endif
16016 if (value == 0) // +-0
16017 {
16018 *first++ = '0';
16019 // Make it look like a floating-point number (#362, #378)
16020 *first++ = '.';
16021 *first++ = '0';
16022 return first;
16023 }
16024 #ifdef __GNUC__
16025 #pragma GCC diagnostic pop
16026 #endif
16027
16028 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
16029
16030 // Compute v = buffer * 10^decimal_exponent.
16031 // The decimal digits are stored in the buffer, which needs to be interpreted
16032 // as an unsigned decimal integer.
16033 // len is the length of the buffer, i.e. the number of decimal digits.
16034 int len = 0;
16035 int decimal_exponent = 0;
16036 dtoa_impl::grisu2(first, len, decimal_exponent, value);
16037
16038 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
16039
16040 // Format the buffer like printf("%.*g", prec, value)
16041 constexpr int kMinExp = -4;
16042 // Use digits10 here to increase compatibility with version 2.
16043 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
16044
16045 JSON_ASSERT(last - first >= kMaxExp + 2);
16046 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
16047 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
16048
16049 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
16050 }
16051
16052 } // namespace detail
16053 } // namespace nlohmann
16054
16055 // #include <nlohmann/detail/exceptions.hpp>
16056
16057 // #include <nlohmann/detail/macro_scope.hpp>
16058
16059 // #include <nlohmann/detail/meta/cpp_future.hpp>
16060
16061 // #include <nlohmann/detail/output/binary_writer.hpp>
16062
16063 // #include <nlohmann/detail/output/output_adapters.hpp>
16064
16065 // #include <nlohmann/detail/value_t.hpp>
16066
16067
16068 namespace nlohmann
16069 {
16070 namespace detail
16071 {
16072 ///////////////////
16073 // serialization //
16074 ///////////////////
16075
16076 /// how to treat decoding errors
16077 enum class error_handler_t
16078 {
16079 strict, ///< throw a type_error exception in case of invalid UTF-8
16080 replace, ///< replace invalid UTF-8 sequences with U+FFFD
16081 ignore ///< ignore invalid UTF-8 sequences
16082 };
16083
16084 template<typename BasicJsonType>
16085 class serializer
16086 {
16087 using string_t = typename BasicJsonType::string_t;
16088 using number_float_t = typename BasicJsonType::number_float_t;
16089 using number_integer_t = typename BasicJsonType::number_integer_t;
16090 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
16091 using binary_char_t = typename BasicJsonType::binary_t::value_type;
16092 static constexpr std::uint8_t UTF8_ACCEPT = 0;
16093 static constexpr std::uint8_t UTF8_REJECT = 1;
16094
16095 public:
16096 /*!
16097 @param[in] s output stream to serialize to
16098 @param[in] ichar indentation character to use
16099 @param[in] error_handler_ how to react on decoding errors
16100 */
16101 serializer(output_adapter_t<char> s, const char ichar,
16102 error_handler_t error_handler_ = error_handler_t::strict)
16103 : o(std::move(s))
16104 , loc(std::localeconv())
16105 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
16106 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
16107 , indent_char(ichar)
16108 , indent_string(512, indent_char)
16109 , error_handler(error_handler_)
16110 {}
16111
16112 // delete because of pointer members
16113 serializer(const serializer&) = delete;
16114 serializer& operator=(const serializer&) = delete;
16115 serializer(serializer&&) = delete;
16116 serializer& operator=(serializer&&) = delete;
16117 ~serializer() = default;
16118
16119 /*!
16120 @brief internal implementation of the serialization function
16121
16122 This function is called by the public member function dump and organizes
16123 the serialization internally. The indentation level is propagated as
16124 additional parameter. In case of arrays and objects, the function is
16125 called recursively.
16126
16127 - strings and object keys are escaped using `escape_string()`
16128 - integer numbers are converted implicitly via `operator<<`
16129 - floating-point numbers are converted to a string using `"%g"` format
16130 - binary values are serialized as objects containing the subtype and the
16131 byte array
16132
16133 @param[in] val value to serialize
16134 @param[in] pretty_print whether the output shall be pretty-printed
16135 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
16136 in the output are escaped with `\uXXXX` sequences, and the result consists
16137 of ASCII characters only.
16138 @param[in] indent_step the indent level
16139 @param[in] current_indent the current indent level (only used internally)
16140 */
16141 void dump(const BasicJsonType& val,
16142 const bool pretty_print,
16143 const bool ensure_ascii,
16144 const unsigned int indent_step,
16145 const unsigned int current_indent = 0)
16146 {
16147 switch (val.m_type)
16148 {
16149 case value_t::object:
16150 {
16151 if (val.m_value.object->empty())
16152 {
16153 o->write_characters("{}", 2);
16154 return;
16155 }
16156
16157 if (pretty_print)
16158 {
16159 o->write_characters("{\n", 2);
16160
16161 // variable to hold indentation for recursive calls
16162 const auto new_indent = current_indent + indent_step;
16163 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
16164 {
16165 indent_string.resize(indent_string.size() * 2, ' ');
16166 }
16167
16168 // first n-1 elements
16169 auto i = val.m_value.object->cbegin();
16170 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
16171 {
16172 o->write_characters(indent_string.c_str(), new_indent);
16173 o->write_character('\"');
16174 dump_escaped(i->first, ensure_ascii);
16175 o->write_characters("\": ", 3);
16176 dump(i->second, true, ensure_ascii, indent_step, new_indent);
16177 o->write_characters(",\n", 2);
16178 }
16179
16180 // last element
16181 JSON_ASSERT(i != val.m_value.object->cend());
16182 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
16183 o->write_characters(indent_string.c_str(), new_indent);
16184 o->write_character('\"');
16185 dump_escaped(i->first, ensure_ascii);
16186 o->write_characters("\": ", 3);
16187 dump(i->second, true, ensure_ascii, indent_step, new_indent);
16188
16189 o->write_character('\n');
16190 o->write_characters(indent_string.c_str(), current_indent);
16191 o->write_character('}');
16192 }
16193 else
16194 {
16195 o->write_character('{');
16196
16197 // first n-1 elements
16198 auto i = val.m_value.object->cbegin();
16199 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
16200 {
16201 o->write_character('\"');
16202 dump_escaped(i->first, ensure_ascii);
16203 o->write_characters("\":", 2);
16204 dump(i->second, false, ensure_ascii, indent_step, current_indent);
16205 o->write_character(',');
16206 }
16207
16208 // last element
16209 JSON_ASSERT(i != val.m_value.object->cend());
16210 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
16211 o->write_character('\"');
16212 dump_escaped(i->first, ensure_ascii);
16213 o->write_characters("\":", 2);
16214 dump(i->second, false, ensure_ascii, indent_step, current_indent);
16215
16216 o->write_character('}');
16217 }
16218
16219 return;
16220 }
16221
16222 case value_t::array:
16223 {
16224 if (val.m_value.array->empty())
16225 {
16226 o->write_characters("[]", 2);
16227 return;
16228 }
16229
16230 if (pretty_print)
16231 {
16232 o->write_characters("[\n", 2);
16233
16234 // variable to hold indentation for recursive calls
16235 const auto new_indent = current_indent + indent_step;
16236 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
16237 {
16238 indent_string.resize(indent_string.size() * 2, ' ');
16239 }
16240
16241 // first n-1 elements
16242 for (auto i = val.m_value.array->cbegin();
16243 i != val.m_value.array->cend() - 1; ++i)
16244 {
16245 o->write_characters(indent_string.c_str(), new_indent);
16246 dump(*i, true, ensure_ascii, indent_step, new_indent);
16247 o->write_characters(",\n", 2);
16248 }
16249
16250 // last element
16251 JSON_ASSERT(!val.m_value.array->empty());
16252 o->write_characters(indent_string.c_str(), new_indent);
16253 dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
16254
16255 o->write_character('\n');
16256 o->write_characters(indent_string.c_str(), current_indent);
16257 o->write_character(']');
16258 }
16259 else
16260 {
16261 o->write_character('[');
16262
16263 // first n-1 elements
16264 for (auto i = val.m_value.array->cbegin();
16265 i != val.m_value.array->cend() - 1; ++i)
16266 {
16267 dump(*i, false, ensure_ascii, indent_step, current_indent);
16268 o->write_character(',');
16269 }
16270
16271 // last element
16272 JSON_ASSERT(!val.m_value.array->empty());
16273 dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
16274
16275 o->write_character(']');
16276 }
16277
16278 return;
16279 }
16280
16281 case value_t::string:
16282 {
16283 o->write_character('\"');
16284 dump_escaped(*val.m_value.string, ensure_ascii);
16285 o->write_character('\"');
16286 return;
16287 }
16288
16289 case value_t::binary:
16290 {
16291 if (pretty_print)
16292 {
16293 o->write_characters("{\n", 2);
16294
16295 // variable to hold indentation for recursive calls
16296 const auto new_indent = current_indent + indent_step;
16297 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
16298 {
16299 indent_string.resize(indent_string.size() * 2, ' ');
16300 }
16301
16302 o->write_characters(indent_string.c_str(), new_indent);
16303
16304 o->write_characters("\"bytes\": [", 10);
16305
16306 if (!val.m_value.binary->empty())
16307 {
16308 for (auto i = val.m_value.binary->cbegin();
16309 i != val.m_value.binary->cend() - 1; ++i)
16310 {
16311 dump_integer(*i);
16312 o->write_characters(", ", 2);
16313 }
16314 dump_integer(val.m_value.binary->back());
16315 }
16316
16317 o->write_characters("],\n", 3);
16318 o->write_characters(indent_string.c_str(), new_indent);
16319
16320 o->write_characters("\"subtype\": ", 11);
16321 if (val.m_value.binary->has_subtype())
16322 {
16323 dump_integer(val.m_value.binary->subtype());
16324 }
16325 else
16326 {
16327 o->write_characters("null", 4);
16328 }
16329 o->write_character('\n');
16330 o->write_characters(indent_string.c_str(), current_indent);
16331 o->write_character('}');
16332 }
16333 else
16334 {
16335 o->write_characters("{\"bytes\":[", 10);
16336
16337 if (!val.m_value.binary->empty())
16338 {
16339 for (auto i = val.m_value.binary->cbegin();
16340 i != val.m_value.binary->cend() - 1; ++i)
16341 {
16342 dump_integer(*i);
16343 o->write_character(',');
16344 }
16345 dump_integer(val.m_value.binary->back());
16346 }
16347
16348 o->write_characters("],\"subtype\":", 12);
16349 if (val.m_value.binary->has_subtype())
16350 {
16351 dump_integer(val.m_value.binary->subtype());
16352 o->write_character('}');
16353 }
16354 else
16355 {
16356 o->write_characters("null}", 5);
16357 }
16358 }
16359 return;
16360 }
16361
16362 case value_t::boolean:
16363 {
16364 if (val.m_value.boolean)
16365 {
16366 o->write_characters("true", 4);
16367 }
16368 else
16369 {
16370 o->write_characters("false", 5);
16371 }
16372 return;
16373 }
16374
16375 case value_t::number_integer:
16376 {
16377 dump_integer(val.m_value.number_integer);
16378 return;
16379 }
16380
16381 case value_t::number_unsigned:
16382 {
16383 dump_integer(val.m_value.number_unsigned);
16384 return;
16385 }
16386
16387 case value_t::number_float:
16388 {
16389 dump_float(val.m_value.number_float);
16390 return;
16391 }
16392
16393 case value_t::discarded:
16394 {
16395 o->write_characters("<discarded>", 11);
16396 return;
16397 }
16398
16399 case value_t::null:
16400 {
16401 o->write_characters("null", 4);
16402 return;
16403 }
16404
16405 default: // LCOV_EXCL_LINE
16406 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16407 }
16408 }
16409
16410 JSON_PRIVATE_UNLESS_TESTED:
16411 /*!
16412 @brief dump escaped string
16413
16414 Escape a string by replacing certain special characters by a sequence of an
16415 escape character (backslash) and another character and other control
16416 characters by a sequence of "\u" followed by a four-digit hex
16417 representation. The escaped string is written to output stream @a o.
16418
16419 @param[in] s the string to escape
16420 @param[in] ensure_ascii whether to escape non-ASCII characters with
16421 \uXXXX sequences
16422
16423 @complexity Linear in the length of string @a s.
16424 */
16425 void dump_escaped(const string_t& s, const bool ensure_ascii)
16426 {
16427 std::uint32_t codepoint{};
16428 std::uint8_t state = UTF8_ACCEPT;
16429 std::size_t bytes = 0; // number of bytes written to string_buffer
16430
16431 // number of bytes written at the point of the last valid byte
16432 std::size_t bytes_after_last_accept = 0;
16433 std::size_t undumped_chars = 0;
16434
16435 for (std::size_t i = 0; i < s.size(); ++i)
16436 {
16437 const auto byte = static_cast<std::uint8_t>(s[i]);
16438
16439 switch (decode(state, codepoint, byte))
16440 {
16441 case UTF8_ACCEPT: // decode found a new code point
16442 {
16443 switch (codepoint)
16444 {
16445 case 0x08: // backspace
16446 {
16447 string_buffer[bytes++] = '\\';
16448 string_buffer[bytes++] = 'b';
16449 break;
16450 }
16451
16452 case 0x09: // horizontal tab
16453 {
16454 string_buffer[bytes++] = '\\';
16455 string_buffer[bytes++] = 't';
16456 break;
16457 }
16458
16459 case 0x0A: // newline
16460 {
16461 string_buffer[bytes++] = '\\';
16462 string_buffer[bytes++] = 'n';
16463 break;
16464 }
16465
16466 case 0x0C: // formfeed
16467 {
16468 string_buffer[bytes++] = '\\';
16469 string_buffer[bytes++] = 'f';
16470 break;
16471 }
16472
16473 case 0x0D: // carriage return
16474 {
16475 string_buffer[bytes++] = '\\';
16476 string_buffer[bytes++] = 'r';
16477 break;
16478 }
16479
16480 case 0x22: // quotation mark
16481 {
16482 string_buffer[bytes++] = '\\';
16483 string_buffer[bytes++] = '\"';
16484 break;
16485 }
16486
16487 case 0x5C: // reverse solidus
16488 {
16489 string_buffer[bytes++] = '\\';
16490 string_buffer[bytes++] = '\\';
16491 break;
16492 }
16493
16494 default:
16495 {
16496 // escape control characters (0x00..0x1F) or, if
16497 // ensure_ascii parameter is used, non-ASCII characters
16498 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
16499 {
16500 if (codepoint <= 0xFFFF)
16501 {
16502 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
16503 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
16504 static_cast<std::uint16_t>(codepoint)));
16505 bytes += 6;
16506 }
16507 else
16508 {
16509 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
16510 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
16511 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
16512 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
16513 bytes += 12;
16514 }
16515 }
16516 else
16517 {
16518 // copy byte to buffer (all previous bytes
16519 // been copied have in default case above)
16520 string_buffer[bytes++] = s[i];
16521 }
16522 break;
16523 }
16524 }
16525
16526 // write buffer and reset index; there must be 13 bytes
16527 // left, as this is the maximal number of bytes to be
16528 // written ("\uxxxx\uxxxx\0") for one code point
16529 if (string_buffer.size() - bytes < 13)
16530 {
16531 o->write_characters(string_buffer.data(), bytes);
16532 bytes = 0;
16533 }
16534
16535 // remember the byte position of this accept
16536 bytes_after_last_accept = bytes;
16537 undumped_chars = 0;
16538 break;
16539 }
16540
16541 case UTF8_REJECT: // decode found invalid UTF-8 byte
16542 {
16543 switch (error_handler)
16544 {
16545 case error_handler_t::strict:
16546 {
16547 std::stringstream ss;
16548 ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (byte | 0);
16549 JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + ss.str(), BasicJsonType()));
16550 }
16551
16552 case error_handler_t::ignore:
16553 case error_handler_t::replace:
16554 {
16555 // in case we saw this character the first time, we
16556 // would like to read it again, because the byte
16557 // may be OK for itself, but just not OK for the
16558 // previous sequence
16559 if (undumped_chars > 0)
16560 {
16561 --i;
16562 }
16563
16564 // reset length buffer to the last accepted index;
16565 // thus removing/ignoring the invalid characters
16566 bytes = bytes_after_last_accept;
16567
16568 if (error_handler == error_handler_t::replace)
16569 {
16570 // add a replacement character
16571 if (ensure_ascii)
16572 {
16573 string_buffer[bytes++] = '\\';
16574 string_buffer[bytes++] = 'u';
16575 string_buffer[bytes++] = 'f';
16576 string_buffer[bytes++] = 'f';
16577 string_buffer[bytes++] = 'f';
16578 string_buffer[bytes++] = 'd';
16579 }
16580 else
16581 {
16582 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
16583 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
16584 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
16585 }
16586
16587 // write buffer and reset index; there must be 13 bytes
16588 // left, as this is the maximal number of bytes to be
16589 // written ("\uxxxx\uxxxx\0") for one code point
16590 if (string_buffer.size() - bytes < 13)
16591 {
16592 o->write_characters(string_buffer.data(), bytes);
16593 bytes = 0;
16594 }
16595
16596 bytes_after_last_accept = bytes;
16597 }
16598
16599 undumped_chars = 0;
16600
16601 // continue processing the string
16602 state = UTF8_ACCEPT;
16603 break;
16604 }
16605
16606 default: // LCOV_EXCL_LINE
16607 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16608 }
16609 break;
16610 }
16611
16612 default: // decode found yet incomplete multi-byte code point
16613 {
16614 if (!ensure_ascii)
16615 {
16616 // code point will not be escaped - copy byte to buffer
16617 string_buffer[bytes++] = s[i];
16618 }
16619 ++undumped_chars;
16620 break;
16621 }
16622 }
16623 }
16624
16625 // we finished processing the string
16626 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
16627 {
16628 // write buffer
16629 if (bytes > 0)
16630 {
16631 o->write_characters(string_buffer.data(), bytes);
16632 }
16633 }
16634 else
16635 {
16636 // we finish reading, but do not accept: string was incomplete
16637 switch (error_handler)
16638 {
16639 case error_handler_t::strict:
16640 {
16641 std::stringstream ss;
16642 ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (static_cast<std::uint8_t>(s.back()) | 0);
16643 JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + ss.str(), BasicJsonType()));
16644 }
16645
16646 case error_handler_t::ignore:
16647 {
16648 // write all accepted bytes
16649 o->write_characters(string_buffer.data(), bytes_after_last_accept);
16650 break;
16651 }
16652
16653 case error_handler_t::replace:
16654 {
16655 // write all accepted bytes
16656 o->write_characters(string_buffer.data(), bytes_after_last_accept);
16657 // add a replacement character
16658 if (ensure_ascii)
16659 {
16660 o->write_characters("\\ufffd", 6);
16661 }
16662 else
16663 {
16664 o->write_characters("\xEF\xBF\xBD", 3);
16665 }
16666 break;
16667 }
16668
16669 default: // LCOV_EXCL_LINE
16670 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16671 }
16672 }
16673 }
16674
16675 private:
16676 /*!
16677 @brief count digits
16678
16679 Count the number of decimal (base 10) digits for an input unsigned integer.
16680
16681 @param[in] x unsigned integer number to count its digits
16682 @return number of decimal digits
16683 */
16684 inline unsigned int count_digits(number_unsigned_t x) noexcept
16685 {
16686 unsigned int n_digits = 1;
16687 for (;;)
16688 {
16689 if (x < 10)
16690 {
16691 return n_digits;
16692 }
16693 if (x < 100)
16694 {
16695 return n_digits + 1;
16696 }
16697 if (x < 1000)
16698 {
16699 return n_digits + 2;
16700 }
16701 if (x < 10000)
16702 {
16703 return n_digits + 3;
16704 }
16705 x = x / 10000u;
16706 n_digits += 4;
16707 }
16708 }
16709
16710 // templates to avoid warnings about useless casts
16711 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
16712 bool is_negative_number(NumberType x)
16713 {
16714 return x < 0;
16715 }
16716
16717 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
16718 bool is_negative_number(NumberType /*unused*/)
16719 {
16720 return false;
16721 }
16722
16723 /*!
16724 @brief dump an integer
16725
16726 Dump a given integer to output stream @a o. Works internally with
16727 @a number_buffer.
16728
16729 @param[in] x integer number (signed or unsigned) to dump
16730 @tparam NumberType either @a number_integer_t or @a number_unsigned_t
16731 */
16732 template < typename NumberType, detail::enable_if_t <
16733 std::is_integral<NumberType>::value ||
16734 std::is_same<NumberType, number_unsigned_t>::value ||
16735 std::is_same<NumberType, number_integer_t>::value ||
16736 std::is_same<NumberType, binary_char_t>::value,
16737 int > = 0 >
16738 void dump_integer(NumberType x)
16739 {
16740 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
16741 {
16742 {
16743 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
16744 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
16745 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
16746 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
16747 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
16748 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
16749 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
16750 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
16751 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
16752 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
16753 }
16754 };
16755
16756 // special case for "0"
16757 if (x == 0)
16758 {
16759 o->write_character('0');
16760 return;
16761 }
16762
16763 // use a pointer to fill the buffer
16764 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
16765
16766 number_unsigned_t abs_value;
16767
16768 unsigned int n_chars{};
16769
16770 if (is_negative_number(x))
16771 {
16772 *buffer_ptr = '-';
16773 abs_value = remove_sign(static_cast<number_integer_t>(x));
16774
16775 // account one more byte for the minus sign
16776 n_chars = 1 + count_digits(abs_value);
16777 }
16778 else
16779 {
16780 abs_value = static_cast<number_unsigned_t>(x);
16781 n_chars = count_digits(abs_value);
16782 }
16783
16784 // spare 1 byte for '\0'
16785 JSON_ASSERT(n_chars < number_buffer.size() - 1);
16786
16787 // jump to the end to generate the string from backward,
16788 // so we later avoid reversing the result
16789 buffer_ptr += n_chars;
16790
16791 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
16792 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
16793 while (abs_value >= 100)
16794 {
16795 const auto digits_index = static_cast<unsigned>((abs_value % 100));
16796 abs_value /= 100;
16797 *(--buffer_ptr) = digits_to_99[digits_index][1];
16798 *(--buffer_ptr) = digits_to_99[digits_index][0];
16799 }
16800
16801 if (abs_value >= 10)
16802 {
16803 const auto digits_index = static_cast<unsigned>(abs_value);
16804 *(--buffer_ptr) = digits_to_99[digits_index][1];
16805 *(--buffer_ptr) = digits_to_99[digits_index][0];
16806 }
16807 else
16808 {
16809 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
16810 }
16811
16812 o->write_characters(number_buffer.data(), n_chars);
16813 }
16814
16815 /*!
16816 @brief dump a floating-point number
16817
16818 Dump a given floating-point number to output stream @a o. Works internally
16819 with @a number_buffer.
16820
16821 @param[in] x floating-point number to dump
16822 */
16823 void dump_float(number_float_t x)
16824 {
16825 // NaN / inf
16826 if (!std::isfinite(x))
16827 {
16828 o->write_characters("null", 4);
16829 return;
16830 }
16831
16832 // If number_float_t is an IEEE-754 single or double precision number,
16833 // use the Grisu2 algorithm to produce short numbers which are
16834 // guaranteed to round-trip, using strtof and strtod, resp.
16835 //
16836 // NB: The test below works if <long double> == <double>.
16837 static constexpr bool is_ieee_single_or_double
16838 = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
16839 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
16840
16841 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
16842 }
16843
16844 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
16845 {
16846 auto* begin = number_buffer.data();
16847 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
16848
16849 o->write_characters(begin, static_cast<size_t>(end - begin));
16850 }
16851
16852 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
16853 {
16854 // get number of digits for a float -> text -> float round-trip
16855 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
16856
16857 // the actual conversion
16858 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
16859 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
16860
16861 // negative value indicates an error
16862 JSON_ASSERT(len > 0);
16863 // check if buffer was large enough
16864 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
16865
16866 // erase thousands separator
16867 if (thousands_sep != '\0')
16868 {
16869 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
16870 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
16871 std::fill(end, number_buffer.end(), '\0');
16872 JSON_ASSERT((end - number_buffer.begin()) <= len);
16873 len = (end - number_buffer.begin());
16874 }
16875
16876 // convert decimal point to '.'
16877 if (decimal_point != '\0' && decimal_point != '.')
16878 {
16879 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
16880 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
16881 if (dec_pos != number_buffer.end())
16882 {
16883 *dec_pos = '.';
16884 }
16885 }
16886
16887 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
16888
16889 // determine if we need to append ".0"
16890 const bool value_is_int_like =
16891 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
16892 [](char c)
16893 {
16894 return c == '.' || c == 'e';
16895 });
16896
16897 if (value_is_int_like)
16898 {
16899 o->write_characters(".0", 2);
16900 }
16901 }
16902
16903 /*!
16904 @brief check whether a string is UTF-8 encoded
16905
16906 The function checks each byte of a string whether it is UTF-8 encoded. The
16907 result of the check is stored in the @a state parameter. The function must
16908 be called initially with state 0 (accept). State 1 means the string must
16909 be rejected, because the current byte is not allowed. If the string is
16910 completely processed, but the state is non-zero, the string ended
16911 prematurely; that is, the last byte indicated more bytes should have
16912 followed.
16913
16914 @param[in,out] state the state of the decoding
16915 @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
16916 @param[in] byte next byte to decode
16917 @return new state
16918
16919 @note The function has been edited: a std::array is used.
16920
16921 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
16922 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
16923 */
16924 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
16925 {
16926 static const std::array<std::uint8_t, 400> utf8d =
16927 {
16928 {
16929 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
16930 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
16931 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
16932 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
16933 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
16934 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
16935 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
16936 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
16937 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
16938 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
16939 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
16940 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
16941 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
16942 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
16943 }
16944 };
16945
16946 JSON_ASSERT(byte < utf8d.size());
16947 const std::uint8_t type = utf8d[byte];
16948
16949 codep = (state != UTF8_ACCEPT)
16950 ? (byte & 0x3fu) | (codep << 6u)
16951 : (0xFFu >> type) & (byte);
16952
16953 std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
16954 JSON_ASSERT(index < 400);
16955 state = utf8d[index];
16956 return state;
16957 }
16958
16959 /*
16960 * Overload to make the compiler happy while it is instantiating
16961 * dump_integer for number_unsigned_t.
16962 * Must never be called.
16963 */
16964 number_unsigned_t remove_sign(number_unsigned_t x)
16965 {
16966 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16967 return x; // LCOV_EXCL_LINE
16968 }
16969
16970 /*
16971 * Helper function for dump_integer
16972 *
16973 * This function takes a negative signed integer and returns its absolute
16974 * value as unsigned integer. The plus/minus shuffling is necessary as we can
16975 * not directly remove the sign of an arbitrary signed integer as the
16976 * absolute values of INT_MIN and INT_MAX are usually not the same. See
16977 * #1708 for details.
16978 */
16979 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
16980 {
16981 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
16982 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
16983 }
16984
16985 private:
16986 /// the output of the serializer
16987 output_adapter_t<char> o = nullptr;
16988
16989 /// a (hopefully) large enough character buffer
16990 std::array<char, 64> number_buffer{{}};
16991
16992 /// the locale
16993 const std::lconv* loc = nullptr;
16994 /// the locale's thousand separator character
16995 const char thousands_sep = '\0';
16996 /// the locale's decimal point character
16997 const char decimal_point = '\0';
16998
16999 /// string buffer
17000 std::array<char, 512> string_buffer{{}};
17001
17002 /// the indentation character
17003 const char indent_char;
17004 /// the indentation string
17005 string_t indent_string;
17006
17007 /// error_handler how to react on decoding errors
17008 const error_handler_t error_handler;
17009 };
17010 } // namespace detail
17011 } // namespace nlohmann
17012
17013 // #include <nlohmann/detail/value_t.hpp>
17014
17015 // #include <nlohmann/json_fwd.hpp>
17016
17017 // #include <nlohmann/ordered_map.hpp>
17018
17019
17020 #include <functional> // less
17021 #include <initializer_list> // initializer_list
17022 #include <iterator> // input_iterator_tag, iterator_traits
17023 #include <memory> // allocator
17024 #include <stdexcept> // for out_of_range
17025 #include <type_traits> // enable_if, is_convertible
17026 #include <utility> // pair
17027 #include <vector> // vector
17028
17029 // #include <nlohmann/detail/macro_scope.hpp>
17030
17031
17032 namespace nlohmann
17033 {
17034
17035 /// ordered_map: a minimal map-like container that preserves insertion order
17036 /// for use within nlohmann::basic_json<ordered_map>
17037 template <class Key, class T, class IgnoredLess = std::less<Key>,
17038 class Allocator = std::allocator<std::pair<const Key, T>>>
17039 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
17040 {
17041 using key_type = Key;
17042 using mapped_type = T;
17043 using Container = std::vector<std::pair<const Key, T>, Allocator>;
17044 using iterator = typename Container::iterator;
17045 using const_iterator = typename Container::const_iterator;
17046 using size_type = typename Container::size_type;
17047 using value_type = typename Container::value_type;
17048
17049 // Explicit constructors instead of `using Container::Container`
17050 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
17051 ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {}
17052 template <class It>
17053 ordered_map(It first, It last, const Allocator& alloc = Allocator())
17054 : Container{first, last, alloc} {}
17055 ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator() )
17056 : Container{init, alloc} {}
17057
17058 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
17059 {
17060 for (auto it = this->begin(); it != this->end(); ++it)
17061 {
17062 if (it->first == key)
17063 {
17064 return {it, false};
17065 }
17066 }
17067 Container::emplace_back(key, t);
17068 return {--this->end(), true};
17069 }
17070
17071 T& operator[](const Key& key)
17072 {
17073 return emplace(key, T{}).first->second;
17074 }
17075
17076 const T& operator[](const Key& key) const
17077 {
17078 return at(key);
17079 }
17080
17081 T& at(const Key& key)
17082 {
17083 for (auto it = this->begin(); it != this->end(); ++it)
17084 {
17085 if (it->first == key)
17086 {
17087 return it->second;
17088 }
17089 }
17090
17091 JSON_THROW(std::out_of_range("key not found"));
17092 }
17093
17094 const T& at(const Key& key) const
17095 {
17096 for (auto it = this->begin(); it != this->end(); ++it)
17097 {
17098 if (it->first == key)
17099 {
17100 return it->second;
17101 }
17102 }
17103
17104 JSON_THROW(std::out_of_range("key not found"));
17105 }
17106
17107 size_type erase(const Key& key)
17108 {
17109 for (auto it = this->begin(); it != this->end(); ++it)
17110 {
17111 if (it->first == key)
17112 {
17113 // Since we cannot move const Keys, re-construct them in place
17114 for (auto next = it; ++next != this->end(); ++it)
17115 {
17116 it->~value_type(); // Destroy but keep allocation
17117 new (&*it) value_type{std::move(*next)};
17118 }
17119 Container::pop_back();
17120 return 1;
17121 }
17122 }
17123 return 0;
17124 }
17125
17126 iterator erase(iterator pos)
17127 {
17128 return erase(pos, std::next(pos));
17129 }
17130
17131 iterator erase(iterator first, iterator last)
17132 {
17133 const auto elements_affected = std::distance(first, last);
17134 const auto offset = std::distance(Container::begin(), first);
17135
17136 // This is the start situation. We need to delete elements_affected
17137 // elements (3 in this example: e, f, g), and need to return an
17138 // iterator past the last deleted element (h in this example).
17139 // Note that offset is the distance from the start of the vector
17140 // to first. We will need this later.
17141
17142 // [ a, b, c, d, e, f, g, h, i, j ]
17143 // ^ ^
17144 // first last
17145
17146 // Since we cannot move const Keys, we re-construct them in place.
17147 // We start at first and re-construct (viz. copy) the elements from
17148 // the back of the vector. Example for first iteration:
17149
17150 // ,--------.
17151 // v | destroy e and re-construct with h
17152 // [ a, b, c, d, e, f, g, h, i, j ]
17153 // ^ ^
17154 // it it + elements_affected
17155
17156 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
17157 {
17158 it->~value_type(); // destroy but keep allocation
17159 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
17160 }
17161
17162 // [ a, b, c, d, h, i, j, h, i, j ]
17163 // ^ ^
17164 // first last
17165
17166 // remove the unneeded elements at the end of the vector
17167 Container::resize(this->size() - static_cast<size_type>(elements_affected));
17168
17169 // [ a, b, c, d, h, i, j ]
17170 // ^ ^
17171 // first last
17172
17173 // first is now pointing past the last deleted element, but we cannot
17174 // use this iterator, because it may have been invalidated by the
17175 // resize call. Instead, we can return begin() + offset.
17176 return Container::begin() + offset;
17177 }
17178
17179 size_type count(const Key& key) const
17180 {
17181 for (auto it = this->begin(); it != this->end(); ++it)
17182 {
17183 if (it->first == key)
17184 {
17185 return 1;
17186 }
17187 }
17188 return 0;
17189 }
17190
17191 iterator find(const Key& key)
17192 {
17193 for (auto it = this->begin(); it != this->end(); ++it)
17194 {
17195 if (it->first == key)
17196 {
17197 return it;
17198 }
17199 }
17200 return Container::end();
17201 }
17202
17203 const_iterator find(const Key& key) const
17204 {
17205 for (auto it = this->begin(); it != this->end(); ++it)
17206 {
17207 if (it->first == key)
17208 {
17209 return it;
17210 }
17211 }
17212 return Container::end();
17213 }
17214
17215 std::pair<iterator, bool> insert( value_type&& value )
17216 {
17217 return emplace(value.first, std::move(value.second));
17218 }
17219
17220 std::pair<iterator, bool> insert( const value_type& value )
17221 {
17222 for (auto it = this->begin(); it != this->end(); ++it)
17223 {
17224 if (it->first == value.first)
17225 {
17226 return {it, false};
17227 }
17228 }
17229 Container::push_back(value);
17230 return {--this->end(), true};
17231 }
17232
17233 template<typename InputIt>
17234 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
17235 std::input_iterator_tag>::value>::type;
17236
17237 template<typename InputIt, typename = require_input_iter<InputIt>>
17238 void insert(InputIt first, InputIt last)
17239 {
17240 for (auto it = first; it != last; ++it)
17241 {
17242 insert(*it);
17243 }
17244 }
17245 };
17246
17247 } // namespace nlohmann
17248
17249
17250 #if defined(JSON_HAS_CPP_17)
17251 #include <string_view>
17252 #endif
17253
17254 /*!
17255 @brief namespace for Niels Lohmann
17256 @see https://github.com/nlohmann
17257 @since version 1.0.0
17258 */
17259 namespace nlohmann
17260 {
17261
17262 /*!
17263 @brief a class to store JSON values
17264
17265 @internal
17266 @invariant The member variables @a m_value and @a m_type have the following
17267 relationship:
17268 - If `m_type == value_t::object`, then `m_value.object != nullptr`.
17269 - If `m_type == value_t::array`, then `m_value.array != nullptr`.
17270 - If `m_type == value_t::string`, then `m_value.string != nullptr`.
17271 The invariants are checked by member function assert_invariant().
17272
17273 @note ObjectType trick from https://stackoverflow.com/a/9860911
17274 @endinternal
17275
17276 @since version 1.0.0
17277
17278 @nosubgrouping
17279 */
17280 NLOHMANN_BASIC_JSON_TPL_DECLARATION
17281 class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
17282 {
17283 private:
17284 template<detail::value_t> friend struct detail::external_constructor;
17285 friend ::nlohmann::json_pointer<basic_json>;
17286
17287 template<typename BasicJsonType, typename InputType>
17288 friend class ::nlohmann::detail::parser;
17289 friend ::nlohmann::detail::serializer<basic_json>;
17290 template<typename BasicJsonType>
17291 friend class ::nlohmann::detail::iter_impl;
17292 template<typename BasicJsonType, typename CharType>
17293 friend class ::nlohmann::detail::binary_writer;
17294 template<typename BasicJsonType, typename InputType, typename SAX>
17295 friend class ::nlohmann::detail::binary_reader;
17296 template<typename BasicJsonType>
17297 friend class ::nlohmann::detail::json_sax_dom_parser;
17298 template<typename BasicJsonType>
17299 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
17300 friend class ::nlohmann::detail::exception;
17301
17302 /// workaround type for MSVC
17303 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
17304
17305 JSON_PRIVATE_UNLESS_TESTED:
17306 // convenience aliases for types residing in namespace detail;
17307 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
17308
17309 template<typename InputAdapterType>
17310 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
17311 InputAdapterType adapter,
17312 detail::parser_callback_t<basic_json>cb = nullptr,
17313 const bool allow_exceptions = true,
17314 const bool ignore_comments = false
17315 )
17316 {
17317 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
17318 std::move(cb), allow_exceptions, ignore_comments);
17319 }
17320
17321 private:
17322 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
17323 template<typename BasicJsonType>
17324 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
17325 template<typename BasicJsonType>
17326 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
17327 template<typename Iterator>
17328 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
17329 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
17330
17331 template<typename CharType>
17332 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
17333
17334 template<typename InputType>
17335 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
17336 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
17337
17338 JSON_PRIVATE_UNLESS_TESTED:
17339 using serializer = ::nlohmann::detail::serializer<basic_json>;
17340
17341 public:
17342 using value_t = detail::value_t;
17343 /// JSON Pointer, see @ref nlohmann::json_pointer
17344 using json_pointer = ::nlohmann::json_pointer<basic_json>;
17345 template<typename T, typename SFINAE>
17346 using json_serializer = JSONSerializer<T, SFINAE>;
17347 /// how to treat decoding errors
17348 using error_handler_t = detail::error_handler_t;
17349 /// how to treat CBOR tags
17350 using cbor_tag_handler_t = detail::cbor_tag_handler_t;
17351 /// helper type for initializer lists of basic_json values
17352 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
17353
17354 using input_format_t = detail::input_format_t;
17355 /// SAX interface type, see @ref nlohmann::json_sax
17356 using json_sax_t = json_sax<basic_json>;
17357
17358 ////////////////
17359 // exceptions //
17360 ////////////////
17361
17362 /// @name exceptions
17363 /// Classes to implement user-defined exceptions.
17364 /// @{
17365
17366 using exception = detail::exception;
17367 using parse_error = detail::parse_error;
17368 using invalid_iterator = detail::invalid_iterator;
17369 using type_error = detail::type_error;
17370 using out_of_range = detail::out_of_range;
17371 using other_error = detail::other_error;
17372
17373 /// @}
17374
17375
17376 /////////////////////
17377 // container types //
17378 /////////////////////
17379
17380 /// @name container types
17381 /// The canonic container types to use @ref basic_json like any other STL
17382 /// container.
17383 /// @{
17384
17385 /// the type of elements in a basic_json container
17386 using value_type = basic_json;
17387
17388 /// the type of an element reference
17389 using reference = value_type&;
17390 /// the type of an element const reference
17391 using const_reference = const value_type&;
17392
17393 /// a type to represent differences between iterators
17394 using difference_type = std::ptrdiff_t;
17395 /// a type to represent container sizes
17396 using size_type = std::size_t;
17397
17398 /// the allocator type
17399 using allocator_type = AllocatorType<basic_json>;
17400
17401 /// the type of an element pointer
17402 using pointer = typename std::allocator_traits<allocator_type>::pointer;
17403 /// the type of an element const pointer
17404 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
17405
17406 /// an iterator for a basic_json container
17407 using iterator = iter_impl<basic_json>;
17408 /// a const iterator for a basic_json container
17409 using const_iterator = iter_impl<const basic_json>;
17410 /// a reverse iterator for a basic_json container
17411 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
17412 /// a const reverse iterator for a basic_json container
17413 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
17414
17415 /// @}
17416
17417
17418 /// @brief returns the allocator associated with the container
17419 /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
17420 static allocator_type get_allocator()
17421 {
17422 return allocator_type();
17423 }
17424
17425 /// @brief returns version information on the library
17426 /// @sa https://json.nlohmann.me/api/basic_json/meta/
17427 JSON_HEDLEY_WARN_UNUSED_RESULT
17428 static basic_json meta()
17429 {
17430 basic_json result;
17431
17432 result["copyright"] = "(C) 2013-2022 Niels Lohmann";
17433 result["name"] = "JSON for Modern C++";
17434 result["url"] = "https://github.com/nlohmann/json";
17435 result["version"]["string"] =
17436 std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
17437 std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
17438 std::to_string(NLOHMANN_JSON_VERSION_PATCH);
17439 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
17440 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
17441 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
17442
17443 #ifdef _WIN32
17444 result["platform"] = "win32";
17445 #elif defined __linux__
17446 result["platform"] = "linux";
17447 #elif defined __APPLE__
17448 result["platform"] = "apple";
17449 #elif defined __unix__
17450 result["platform"] = "unix";
17451 #else
17452 result["platform"] = "unknown";
17453 #endif
17454
17455 #if defined(__ICC) || defined(__INTEL_COMPILER)
17456 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
17457 #elif defined(__clang__)
17458 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
17459 #elif defined(__GNUC__) || defined(__GNUG__)
17460 result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
17461 #elif defined(__HP_cc) || defined(__HP_aCC)
17462 result["compiler"] = "hp"
17463 #elif defined(__IBMCPP__)
17464 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
17465 #elif defined(_MSC_VER)
17466 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
17467 #elif defined(__PGI)
17468 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
17469 #elif defined(__SUNPRO_CC)
17470 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
17471 #else
17472 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
17473 #endif
17474
17475 #ifdef __cplusplus
17476 result["compiler"]["c++"] = std::to_string(__cplusplus);
17477 #else
17478 result["compiler"]["c++"] = "unknown";
17479 #endif
17480 return result;
17481 }
17482
17483
17484 ///////////////////////////
17485 // JSON value data types //
17486 ///////////////////////////
17487
17488 /// @name JSON value data types
17489 /// The data types to store a JSON value. These types are derived from
17490 /// the template arguments passed to class @ref basic_json.
17491 /// @{
17492
17493 /// @brief object key comparator type
17494 /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
17495 #if defined(JSON_HAS_CPP_14)
17496 // Use transparent comparator if possible, combined with perfect forwarding
17497 // on find() and count() calls prevents unnecessary string construction.
17498 using object_comparator_t = std::less<>;
17499 #else
17500 using object_comparator_t = std::less<StringType>;
17501 #endif
17502
17503 /// @brief a type for an object
17504 /// @sa https://json.nlohmann.me/api/basic_json/object_t/
17505 using object_t = ObjectType<StringType,
17506 basic_json,
17507 object_comparator_t,
17508 AllocatorType<std::pair<const StringType,
17509 basic_json>>>;
17510
17511 /// @brief a type for an array
17512 /// @sa https://json.nlohmann.me/api/basic_json/array_t/
17513 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
17514
17515 /// @brief a type for a string
17516 /// @sa https://json.nlohmann.me/api/basic_json/string_t/
17517 using string_t = StringType;
17518
17519 /// @brief a type for a boolean
17520 /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
17521 using boolean_t = BooleanType;
17522
17523 /// @brief a type for a number (integer)
17524 /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
17525 using number_integer_t = NumberIntegerType;
17526
17527 /// @brief a type for a number (unsigned)
17528 /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
17529 using number_unsigned_t = NumberUnsignedType;
17530
17531 /// @brief a type for a number (floating-point)
17532 /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
17533 using number_float_t = NumberFloatType;
17534
17535 /// @brief a type for a packed binary type
17536 /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
17537 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
17538
17539 /// @}
17540
17541 private:
17542
17543 /// helper for exception-safe object creation
17544 template<typename T, typename... Args>
17545 JSON_HEDLEY_RETURNS_NON_NULL
17546 static T* create(Args&& ... args)
17547 {
17548 AllocatorType<T> alloc;
17549 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
17550
17551 auto deleter = [&](T * obj)
17552 {
17553 AllocatorTraits::deallocate(alloc, obj, 1);
17554 };
17555 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
17556 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
17557 JSON_ASSERT(obj != nullptr);
17558 return obj.release();
17559 }
17560
17561 ////////////////////////
17562 // JSON value storage //
17563 ////////////////////////
17564
17565 JSON_PRIVATE_UNLESS_TESTED:
17566 /*!
17567 @brief a JSON value
17568
17569 The actual storage for a JSON value of the @ref basic_json class. This
17570 union combines the different storage types for the JSON value types
17571 defined in @ref value_t.
17572
17573 JSON type | value_t type | used type
17574 --------- | --------------- | ------------------------
17575 object | object | pointer to @ref object_t
17576 array | array | pointer to @ref array_t
17577 string | string | pointer to @ref string_t
17578 boolean | boolean | @ref boolean_t
17579 number | number_integer | @ref number_integer_t
17580 number | number_unsigned | @ref number_unsigned_t
17581 number | number_float | @ref number_float_t
17582 binary | binary | pointer to @ref binary_t
17583 null | null | *no value is stored*
17584
17585 @note Variable-length types (objects, arrays, and strings) are stored as
17586 pointers. The size of the union should not exceed 64 bits if the default
17587 value types are used.
17588
17589 @since version 1.0.0
17590 */
17591 union json_value
17592 {
17593 /// object (stored with pointer to save storage)
17594 object_t* object;
17595 /// array (stored with pointer to save storage)
17596 array_t* array;
17597 /// string (stored with pointer to save storage)
17598 string_t* string;
17599 /// binary (stored with pointer to save storage)
17600 binary_t* binary;
17601 /// boolean
17602 boolean_t boolean;
17603 /// number (integer)
17604 number_integer_t number_integer;
17605 /// number (unsigned integer)
17606 number_unsigned_t number_unsigned;
17607 /// number (floating-point)
17608 number_float_t number_float;
17609
17610 /// default constructor (for null values)
17611 json_value() = default;
17612 /// constructor for booleans
17613 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)
17622 {
17623 switch (t)
17624 {
17625 case value_t::object:
17626 {
17627 object = create<object_t>();
17628 break;
17629 }
17630
17631 case value_t::array:
17632 {
17633 array = create<array_t>();
17634 break;
17635 }
17636
17637 case value_t::string:
17638 {
17639 string = create<string_t>("");
17640 break;
17641 }
17642
17643 case value_t::binary:
17644 {
17645 binary = create<binary_t>();
17646 break;
17647 }
17648
17649 case value_t::boolean:
17650 {
17651 boolean = static_cast<boolean_t>(false);
17652 break;
17653 }
17654
17655 case value_t::number_integer:
17656 {
17657 number_integer = static_cast<number_integer_t>(0);
17658 break;
17659 }
17660
17661 case value_t::number_unsigned:
17662 {
17663 number_unsigned = static_cast<number_unsigned_t>(0);
17664 break;
17665 }
17666
17667 case value_t::number_float:
17668 {
17669 number_float = static_cast<number_float_t>(0.0);
17670 break;
17671 }
17672
17673 case value_t::null:
17674 {
17675 object = nullptr; // silence warning, see #821
17676 break;
17677 }
17678
17679 case value_t::discarded:
17680 default:
17681 {
17682 object = nullptr; // silence warning, see #821
17683 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
17684 {
17685 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5", basic_json())); // LCOV_EXCL_LINE
17686 }
17687 break;
17688 }
17689 }
17690 }
17691
17692 /// constructor for strings
17693 json_value(const string_t& value) : string(create<string_t>(value)) {}
17694
17695 /// constructor for rvalue strings
17696 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
17697
17698 /// constructor for objects
17699 json_value(const object_t& value) : object(create<object_t>(value)) {}
17700
17701 /// constructor for rvalue objects
17702 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
17703
17704 /// constructor for arrays
17705 json_value(const array_t& value) : array(create<array_t>(value)) {}
17706
17707 /// constructor for rvalue arrays
17708 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
17709
17710 /// constructor for binary arrays
17711 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
17712
17713 /// constructor for rvalue binary arrays
17714 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
17715
17716 /// constructor for binary arrays (internal type)
17717 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
17718
17719 /// constructor for rvalue binary arrays (internal type)
17720 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
17721
17722 void destroy(value_t t)
17723 {
17724 if (t == value_t::array || t == value_t::object)
17725 {
17726 // flatten the current json_value to a heap-allocated stack
17727 std::vector<basic_json> stack;
17728
17729 // move the top-level items to stack
17730 if (t == value_t::array)
17731 {
17732 stack.reserve(array->size());
17733 std::move(array->begin(), array->end(), std::back_inserter(stack));
17734 }
17735 else
17736 {
17737 stack.reserve(object->size());
17738 for (auto&& it : *object)
17739 {
17740 stack.push_back(std::move(it.second));
17741 }
17742 }
17743
17744 while (!stack.empty())
17745 {
17746 // move the last item to local variable to be processed
17747 basic_json current_item(std::move(stack.back()));
17748 stack.pop_back();
17749
17750 // if current_item is array/object, move
17751 // its children to the stack to be processed later
17752 if (current_item.is_array())
17753 {
17754 std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack));
17755
17756 current_item.m_value.array->clear();
17757 }
17758 else if (current_item.is_object())
17759 {
17760 for (auto&& it : *current_item.m_value.object)
17761 {
17762 stack.push_back(std::move(it.second));
17763 }
17764
17765 current_item.m_value.object->clear();
17766 }
17767
17768 // it's now safe that current_item get destructed
17769 // since it doesn't have any children
17770 }
17771 }
17772
17773 switch (t)
17774 {
17775 case value_t::object:
17776 {
17777 AllocatorType<object_t> alloc;
17778 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
17779 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
17780 break;
17781 }
17782
17783 case value_t::array:
17784 {
17785 AllocatorType<array_t> alloc;
17786 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
17787 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
17788 break;
17789 }
17790
17791 case value_t::string:
17792 {
17793 AllocatorType<string_t> alloc;
17794 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
17795 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
17796 break;
17797 }
17798
17799 case value_t::binary:
17800 {
17801 AllocatorType<binary_t> alloc;
17802 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
17803 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
17804 break;
17805 }
17806
17807 case value_t::null:
17808 case value_t::boolean:
17809 case value_t::number_integer:
17810 case value_t::number_unsigned:
17811 case value_t::number_float:
17812 case value_t::discarded:
17813 default:
17814 {
17815 break;
17816 }
17817 }
17818 }
17819 };
17820
17821 private:
17822 /*!
17823 @brief checks the class invariants
17824
17825 This function asserts the class invariants. It needs to be called at the
17826 end of every constructor to make sure that created objects respect the
17827 invariant. Furthermore, it has to be called each time the type of a JSON
17828 value is changed, because the invariant expresses a relationship between
17829 @a m_type and @a m_value.
17830
17831 Furthermore, the parent relation is checked for arrays and objects: If
17832 @a check_parents true and the value is an array or object, then the
17833 container's elements must have the current value as parent.
17834
17835 @param[in] check_parents whether the parent relation should be checked.
17836 The value is true by default and should only be set to false
17837 during destruction of objects when the invariant does not
17838 need to hold.
17839 */
17840 void assert_invariant(bool check_parents = true) const noexcept
17841 {
17842 JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
17843 JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
17844 JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
17845 JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
17846
17847 #if JSON_DIAGNOSTICS
17848 JSON_TRY
17849 {
17850 // cppcheck-suppress assertWithSideEffect
17851 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
17852 {
17853 return j.m_parent == this;
17854 }));
17855 }
17856 JSON_CATCH(...) {} // LCOV_EXCL_LINE
17857 #endif
17858 static_cast<void>(check_parents);
17859 }
17860
17861 void set_parents()
17862 {
17863 #if JSON_DIAGNOSTICS
17864 switch (m_type)
17865 {
17866 case value_t::array:
17867 {
17868 for (auto& element : *m_value.array)
17869 {
17870 element.m_parent = this;
17871 }
17872 break;
17873 }
17874
17875 case value_t::object:
17876 {
17877 for (auto& element : *m_value.object)
17878 {
17879 element.second.m_parent = this;
17880 }
17881 break;
17882 }
17883
17884 case value_t::null:
17885 case value_t::string:
17886 case value_t::boolean:
17887 case value_t::number_integer:
17888 case value_t::number_unsigned:
17889 case value_t::number_float:
17890 case value_t::binary:
17891 case value_t::discarded:
17892 default:
17893 break;
17894 }
17895 #endif
17896 }
17897
17898 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
17899 {
17900 #if JSON_DIAGNOSTICS
17901 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
17902 {
17903 (it + i)->m_parent = this;
17904 }
17905 #else
17906 static_cast<void>(count_set_parents);
17907 #endif
17908 return it;
17909 }
17910
17911 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
17912 {
17913 #if JSON_DIAGNOSTICS
17914 if (old_capacity != static_cast<std::size_t>(-1))
17915 {
17916 // see https://github.com/nlohmann/json/issues/2838
17917 JSON_ASSERT(type() == value_t::array);
17918 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
17919 {
17920 // capacity has changed: update all parents
17921 set_parents();
17922 return j;
17923 }
17924 }
17925
17926 // ordered_json uses a vector internally, so pointers could have
17927 // been invalidated; see https://github.com/nlohmann/json/issues/2962
17928 #ifdef JSON_HEDLEY_MSVC_VERSION
17929 #pragma warning(push )
17930 #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
17931 #endif
17932 if (detail::is_ordered_map<object_t>::value)
17933 {
17934 set_parents();
17935 return j;
17936 }
17937 #ifdef JSON_HEDLEY_MSVC_VERSION
17938 #pragma warning( pop )
17939 #endif
17940
17941 j.m_parent = this;
17942 #else
17943 static_cast<void>(j);
17944 static_cast<void>(old_capacity);
17945 #endif
17946 return j;
17947 }
17948
17949 public:
17950 //////////////////////////
17951 // JSON parser callback //
17952 //////////////////////////
17953
17954 /// @brief parser event types
17955 /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
17956 using parse_event_t = detail::parse_event_t;
17957
17958 /// @brief per-element parser callback type
17959 /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
17960 using parser_callback_t = detail::parser_callback_t<basic_json>;
17961
17962 //////////////////
17963 // constructors //
17964 //////////////////
17965
17966 /// @name constructors and destructors
17967 /// Constructors of class @ref basic_json, copy/move constructor, copy
17968 /// assignment, static functions creating objects, and the destructor.
17969 /// @{
17970
17971 /// @brief create an empty value with a given type
17972 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
17973 basic_json(const value_t v)
17974 : m_type(v), m_value(v)
17975 {
17976 assert_invariant();
17977 }
17978
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)
17983 {
17984 assert_invariant();
17985 }
17986
17987 /// @brief create a JSON value from compatible types
17988 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
17989 template < typename CompatibleType,
17990 typename U = detail::uncvref_t<CompatibleType>,
17991 detail::enable_if_t <
17992 !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
17993 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
17994 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
17995 std::forward<CompatibleType>(val))))
17996 {
17997 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
17998 set_parents();
17999 assert_invariant();
18000 }
18001
18002 /// @brief create a JSON value from an existing one
18003 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18004 template < typename BasicJsonType,
18005 detail::enable_if_t <
18006 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
18007 basic_json(const BasicJsonType& val)
18008 {
18009 using other_boolean_t = typename BasicJsonType::boolean_t;
18010 using other_number_float_t = typename BasicJsonType::number_float_t;
18011 using other_number_integer_t = typename BasicJsonType::number_integer_t;
18012 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18013 using other_string_t = typename BasicJsonType::string_t;
18014 using other_object_t = typename BasicJsonType::object_t;
18015 using other_array_t = typename BasicJsonType::array_t;
18016 using other_binary_t = typename BasicJsonType::binary_t;
18017
18018 switch (val.type())
18019 {
18020 case value_t::boolean:
18021 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
18022 break;
18023 case value_t::number_float:
18024 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
18025 break;
18026 case value_t::number_integer:
18027 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
18028 break;
18029 case value_t::number_unsigned:
18030 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
18031 break;
18032 case value_t::string:
18033 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
18034 break;
18035 case value_t::object:
18036 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
18037 break;
18038 case value_t::array:
18039 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
18040 break;
18041 case value_t::binary:
18042 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
18043 break;
18044 case value_t::null:
18045 *this = nullptr;
18046 break;
18047 case value_t::discarded:
18048 m_type = value_t::discarded;
18049 break;
18050 default: // LCOV_EXCL_LINE
18051 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18052 }
18053 set_parents();
18054 assert_invariant();
18055 }
18056
18057 /// @brief create a container (array or object) from an initializer list
18058 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18059 basic_json(initializer_list_t init,
18060 bool type_deduction = true,
18061 value_t manual_type = value_t::array)
18062 {
18063 // check if each element is an array with two elements whose first
18064 // element is a string
18065 bool is_an_object = std::all_of(init.begin(), init.end(),
18066 [](const detail::json_ref<basic_json>& element_ref)
18067 {
18068 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
18069 });
18070
18071 // adjust type if type deduction is not wanted
18072 if (!type_deduction)
18073 {
18074 // if array is wanted, do not create an object though possible
18075 if (manual_type == value_t::array)
18076 {
18077 is_an_object = false;
18078 }
18079
18080 // if object is wanted but impossible, throw an exception
18081 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
18082 {
18083 JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json()));
18084 }
18085 }
18086
18087 if (is_an_object)
18088 {
18089 // the initializer list is a list of pairs -> create object
18090 m_type = value_t::object;
18091 m_value = value_t::object;
18092
18093 for (auto& element_ref : init)
18094 {
18095 auto element = element_ref.moved_or_copied();
18096 m_value.object->emplace(
18097 std::move(*((*element.m_value.array)[0].m_value.string)),
18098 std::move((*element.m_value.array)[1]));
18099 }
18100 }
18101 else
18102 {
18103 // the initializer list describes an array -> create array
18104 m_type = value_t::array;
18105 m_value.array = create<array_t>(init.begin(), init.end());
18106 }
18107
18108 set_parents();
18109 assert_invariant();
18110 }
18111
18112 /// @brief explicitly create a binary array (without subtype)
18113 /// @sa https://json.nlohmann.me/api/basic_json/binary/
18114 JSON_HEDLEY_WARN_UNUSED_RESULT
18115 static basic_json binary(const typename binary_t::container_type& init)
18116 {
18117 auto res = basic_json();
18118 res.m_type = value_t::binary;
18119 res.m_value = init;
18120 return res;
18121 }
18122
18123 /// @brief explicitly create a binary array (with subtype)
18124 /// @sa https://json.nlohmann.me/api/basic_json/binary/
18125 JSON_HEDLEY_WARN_UNUSED_RESULT
18126 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
18127 {
18128 auto res = basic_json();
18129 res.m_type = value_t::binary;
18130 res.m_value = binary_t(init, subtype);
18131 return res;
18132 }
18133
18134 /// @brief explicitly create a binary array
18135 /// @sa https://json.nlohmann.me/api/basic_json/binary/
18136 JSON_HEDLEY_WARN_UNUSED_RESULT
18137 static basic_json binary(typename binary_t::container_type&& init)
18138 {
18139 auto res = basic_json();
18140 res.m_type = value_t::binary;
18141 res.m_value = std::move(init);
18142 return res;
18143 }
18144
18145 /// @brief explicitly create a binary array (with subtype)
18146 /// @sa https://json.nlohmann.me/api/basic_json/binary/
18147 JSON_HEDLEY_WARN_UNUSED_RESULT
18148 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
18149 {
18150 auto res = basic_json();
18151 res.m_type = value_t::binary;
18152 res.m_value = binary_t(std::move(init), subtype);
18153 return res;
18154 }
18155
18156 /// @brief explicitly create an array from an initializer list
18157 /// @sa https://json.nlohmann.me/api/basic_json/array/
18158 JSON_HEDLEY_WARN_UNUSED_RESULT
18159 static basic_json array(initializer_list_t init = {})
18160 {
18161 return basic_json(init, false, value_t::array);
18162 }
18163
18164 /// @brief explicitly create an object from an initializer list
18165 /// @sa https://json.nlohmann.me/api/basic_json/object/
18166 JSON_HEDLEY_WARN_UNUSED_RESULT
18167 static basic_json object(initializer_list_t init = {})
18168 {
18169 return basic_json(init, false, value_t::object);
18170 }
18171
18172 /// @brief construct an array with count copies of given value
18173 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18174 basic_json(size_type cnt, const basic_json& val)
18175 : m_type(value_t::array)
18176 {
18177 m_value.array = create<array_t>(cnt, val);
18178 set_parents();
18179 assert_invariant();
18180 }
18181
18182 /// @brief construct a JSON container given an iterator range
18183 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18184 template < class InputIT, typename std::enable_if <
18185 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
18186 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
18187 basic_json(InputIT first, InputIT last)
18188 {
18189 JSON_ASSERT(first.m_object != nullptr);
18190 JSON_ASSERT(last.m_object != nullptr);
18191
18192 // make sure iterator fits the current value
18193 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
18194 {
18195 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json()));
18196 }
18197
18198 // copy type from first iterator
18199 m_type = first.m_object->m_type;
18200
18201 // check if iterator range is complete for primitive values
18202 switch (m_type)
18203 {
18204 case value_t::boolean:
18205 case value_t::number_float:
18206 case value_t::number_integer:
18207 case value_t::number_unsigned:
18208 case value_t::string:
18209 {
18210 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
18211 || !last.m_it.primitive_iterator.is_end()))
18212 {
18213 JSON_THROW(invalid_iterator::create(204, "iterators out of range", *first.m_object));
18214 }
18215 break;
18216 }
18217
18218 case value_t::null:
18219 case value_t::object:
18220 case value_t::array:
18221 case value_t::binary:
18222 case value_t::discarded:
18223 default:
18224 break;
18225 }
18226
18227 switch (m_type)
18228 {
18229 case value_t::number_integer:
18230 {
18231 m_value.number_integer = first.m_object->m_value.number_integer;
18232 break;
18233 }
18234
18235 case value_t::number_unsigned:
18236 {
18237 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
18238 break;
18239 }
18240
18241 case value_t::number_float:
18242 {
18243 m_value.number_float = first.m_object->m_value.number_float;
18244 break;
18245 }
18246
18247 case value_t::boolean:
18248 {
18249 m_value.boolean = first.m_object->m_value.boolean;
18250 break;
18251 }
18252
18253 case value_t::string:
18254 {
18255 m_value = *first.m_object->m_value.string;
18256 break;
18257 }
18258
18259 case value_t::object:
18260 {
18261 m_value.object = create<object_t>(first.m_it.object_iterator,
18262 last.m_it.object_iterator);
18263 break;
18264 }
18265
18266 case value_t::array:
18267 {
18268 m_value.array = create<array_t>(first.m_it.array_iterator,
18269 last.m_it.array_iterator);
18270 break;
18271 }
18272
18273 case value_t::binary:
18274 {
18275 m_value = *first.m_object->m_value.binary;
18276 break;
18277 }
18278
18279 case value_t::null:
18280 case value_t::discarded:
18281 default:
18282 JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), *first.m_object));
18283 }
18284
18285 set_parents();
18286 assert_invariant();
18287 }
18288
18289
18290 ///////////////////////////////////////
18291 // other constructors and destructor //
18292 ///////////////////////////////////////
18293
18294 template<typename JsonRef,
18295 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
18296 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
18297 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
18298
18299 /// @brief copy constructor
18300 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18301 basic_json(const basic_json& other)
18302 : m_type(other.m_type)
18303 {
18304 // check of passed value is valid
18305 other.assert_invariant();
18306
18307 switch (m_type)
18308 {
18309 case value_t::object:
18310 {
18311 m_value = *other.m_value.object;
18312 break;
18313 }
18314
18315 case value_t::array:
18316 {
18317 m_value = *other.m_value.array;
18318 break;
18319 }
18320
18321 case value_t::string:
18322 {
18323 m_value = *other.m_value.string;
18324 break;
18325 }
18326
18327 case value_t::boolean:
18328 {
18329 m_value = other.m_value.boolean;
18330 break;
18331 }
18332
18333 case value_t::number_integer:
18334 {
18335 m_value = other.m_value.number_integer;
18336 break;
18337 }
18338
18339 case value_t::number_unsigned:
18340 {
18341 m_value = other.m_value.number_unsigned;
18342 break;
18343 }
18344
18345 case value_t::number_float:
18346 {
18347 m_value = other.m_value.number_float;
18348 break;
18349 }
18350
18351 case value_t::binary:
18352 {
18353 m_value = *other.m_value.binary;
18354 break;
18355 }
18356
18357 case value_t::null:
18358 case value_t::discarded:
18359 default:
18360 break;
18361 }
18362
18363 set_parents();
18364 assert_invariant();
18365 }
18366
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))
18372 {
18373 // check that passed value is valid
18374 other.assert_invariant(false);
18375
18376 // invalidate payload
18377 other.m_type = value_t::null;
18378 other.m_value = {};
18379
18380 set_parents();
18381 assert_invariant();
18382 }
18383
18384 /// @brief copy assignment
18385 /// @sa https://json.nlohmann.me/api/basic_json/operator=/
18386 basic_json& operator=(basic_json other) noexcept (
18387 std::is_nothrow_move_constructible<value_t>::value&&
18388 std::is_nothrow_move_assignable<value_t>::value&&
18389 std::is_nothrow_move_constructible<json_value>::value&&
18390 std::is_nothrow_move_assignable<json_value>::value
18391 )
18392 {
18393 // check that passed value is valid
18394 other.assert_invariant();
18395
18396 using std::swap;
18397 swap(m_type, other.m_type);
18398 swap(m_value, other.m_value);
18399
18400 set_parents();
18401 assert_invariant();
18402 return *this;
18403 }
18404
18405 /// @brief destructor
18406 /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
18407 ~basic_json() noexcept
18408 {
18409 assert_invariant(false);
18410 m_value.destroy(m_type);
18411 }
18412
18413 /// @}
18414
18415 public:
18416 ///////////////////////
18417 // object inspection //
18418 ///////////////////////
18419
18420 /// @name object inspection
18421 /// Functions to inspect the type of a JSON value.
18422 /// @{
18423
18424 /// @brief serialization
18425 /// @sa https://json.nlohmann.me/api/basic_json/dump/
18426 string_t dump(const int indent = -1,
18427 const char indent_char = ' ',
18428 const bool ensure_ascii = false,
18429 const error_handler_t error_handler = error_handler_t::strict) const
18430 {
18431 string_t result;
18432 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
18433
18434 if (indent >= 0)
18435 {
18436 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
18437 }
18438 else
18439 {
18440 s.dump(*this, false, ensure_ascii, 0);
18441 }
18442
18443 return result;
18444 }
18445
18446 /// @brief return the type of the JSON value (explicit)
18447 /// @sa https://json.nlohmann.me/api/basic_json/type/
18448 constexpr value_t type() const noexcept
18449 {
18450 return m_type;
18451 }
18452
18453 /// @brief return whether type is primitive
18454 /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
18455 constexpr bool is_primitive() const noexcept
18456 {
18457 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
18458 }
18459
18460 /// @brief return whether type is structured
18461 /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
18462 constexpr bool is_structured() const noexcept
18463 {
18464 return is_array() || is_object();
18465 }
18466
18467 /// @brief return whether value is null
18468 /// @sa https://json.nlohmann.me/api/basic_json/is_null/
18469 constexpr bool is_null() const noexcept
18470 {
18471 return m_type == value_t::null;
18472 }
18473
18474 /// @brief return whether value is a boolean
18475 /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
18476 constexpr bool is_boolean() const noexcept
18477 {
18478 return m_type == value_t::boolean;
18479 }
18480
18481 /// @brief return whether value is a number
18482 /// @sa https://json.nlohmann.me/api/basic_json/is_number/
18483 constexpr bool is_number() const noexcept
18484 {
18485 return is_number_integer() || is_number_float();
18486 }
18487
18488 /// @brief return whether value is an integer number
18489 /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
18490 constexpr bool is_number_integer() const noexcept
18491 {
18492 return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
18493 }
18494
18495 /// @brief return whether value is an unsigned integer number
18496 /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
18497 constexpr bool is_number_unsigned() const noexcept
18498 {
18499 return m_type == value_t::number_unsigned;
18500 }
18501
18502 /// @brief return whether value is a floating-point number
18503 /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
18504 constexpr bool is_number_float() const noexcept
18505 {
18506 return m_type == value_t::number_float;
18507 }
18508
18509 /// @brief return whether value is an object
18510 /// @sa https://json.nlohmann.me/api/basic_json/is_object/
18511 constexpr bool is_object() const noexcept
18512 {
18513 return m_type == value_t::object;
18514 }
18515
18516 /// @brief return whether value is an array
18517 /// @sa https://json.nlohmann.me/api/basic_json/is_array/
18518 constexpr bool is_array() const noexcept
18519 {
18520 return m_type == value_t::array;
18521 }
18522
18523 /// @brief return whether value is a string
18524 /// @sa https://json.nlohmann.me/api/basic_json/is_string/
18525 constexpr bool is_string() const noexcept
18526 {
18527 return m_type == value_t::string;
18528 }
18529
18530 /// @brief return whether value is a binary array
18531 /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
18532 constexpr bool is_binary() const noexcept
18533 {
18534 return m_type == value_t::binary;
18535 }
18536
18537 /// @brief return whether value is discarded
18538 /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
18539 constexpr bool is_discarded() const noexcept
18540 {
18541 return m_type == value_t::discarded;
18542 }
18543
18544 /// @brief return the type of the JSON value (implicit)
18545 /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
18546 constexpr operator value_t() const noexcept
18547 {
18548 return m_type;
18549 }
18550
18551 /// @}
18552
18553 private:
18554 //////////////////
18555 // value access //
18556 //////////////////
18557
18558 /// get a boolean (explicit)
18559 boolean_t get_impl(boolean_t* /*unused*/) const
18560 {
18561 if (JSON_HEDLEY_LIKELY(is_boolean()))
18562 {
18563 return m_value.boolean;
18564 }
18565
18566 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this));
18567 }
18568
18569 /// get a pointer to the value (object)
18570 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
18571 {
18572 return is_object() ? m_value.object : nullptr;
18573 }
18574
18575 /// get a pointer to the value (object)
18576 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
18577 {
18578 return is_object() ? m_value.object : nullptr;
18579 }
18580
18581 /// get a pointer to the value (array)
18582 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
18583 {
18584 return is_array() ? m_value.array : nullptr;
18585 }
18586
18587 /// get a pointer to the value (array)
18588 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
18589 {
18590 return is_array() ? m_value.array : nullptr;
18591 }
18592
18593 /// get a pointer to the value (string)
18594 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
18595 {
18596 return is_string() ? m_value.string : nullptr;
18597 }
18598
18599 /// get a pointer to the value (string)
18600 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
18601 {
18602 return is_string() ? m_value.string : nullptr;
18603 }
18604
18605 /// get a pointer to the value (boolean)
18606 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
18607 {
18608 return is_boolean() ? &m_value.boolean : nullptr;
18609 }
18610
18611 /// get a pointer to the value (boolean)
18612 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
18613 {
18614 return is_boolean() ? &m_value.boolean : nullptr;
18615 }
18616
18617 /// get a pointer to the value (integer number)
18618 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
18619 {
18620 return is_number_integer() ? &m_value.number_integer : nullptr;
18621 }
18622
18623 /// get a pointer to the value (integer number)
18624 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
18625 {
18626 return is_number_integer() ? &m_value.number_integer : nullptr;
18627 }
18628
18629 /// get a pointer to the value (unsigned number)
18630 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
18631 {
18632 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
18633 }
18634
18635 /// get a pointer to the value (unsigned number)
18636 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
18637 {
18638 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
18639 }
18640
18641 /// get a pointer to the value (floating-point number)
18642 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
18643 {
18644 return is_number_float() ? &m_value.number_float : nullptr;
18645 }
18646
18647 /// get a pointer to the value (floating-point number)
18648 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
18649 {
18650 return is_number_float() ? &m_value.number_float : nullptr;
18651 }
18652
18653 /// get a pointer to the value (binary)
18654 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
18655 {
18656 return is_binary() ? m_value.binary : nullptr;
18657 }
18658
18659 /// get a pointer to the value (binary)
18660 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
18661 {
18662 return is_binary() ? m_value.binary : nullptr;
18663 }
18664
18665 /*!
18666 @brief helper function to implement get_ref()
18667
18668 This function helps to implement get_ref() without code duplication for
18669 const and non-const overloads
18670
18671 @tparam ThisType will be deduced as `basic_json` or `const basic_json`
18672
18673 @throw type_error.303 if ReferenceType does not match underlying value
18674 type of the current JSON
18675 */
18676 template<typename ReferenceType, typename ThisType>
18677 static ReferenceType get_ref_impl(ThisType& obj)
18678 {
18679 // delegate the call to get_ptr<>()
18680 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
18681
18682 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
18683 {
18684 return *ptr;
18685 }
18686
18687 JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj));
18688 }
18689
18690 public:
18691 /// @name value access
18692 /// Direct access to the stored value of a JSON value.
18693 /// @{
18694
18695 /// @brief get a pointer value (implicit)
18696 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
18697 template<typename PointerType, typename std::enable_if<
18698 std::is_pointer<PointerType>::value, int>::type = 0>
18699 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
18700 {
18701 // delegate the call to get_impl_ptr<>()
18702 return get_impl_ptr(static_cast<PointerType>(nullptr));
18703 }
18704
18705 /// @brief get a pointer value (implicit)
18706 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
18707 template < typename PointerType, typename std::enable_if <
18708 std::is_pointer<PointerType>::value&&
18709 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
18710 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
18711 {
18712 // delegate the call to get_impl_ptr<>() const
18713 return get_impl_ptr(static_cast<PointerType>(nullptr));
18714 }
18715
18716 private:
18717 /*!
18718 @brief get a value (explicit)
18719
18720 Explicit type conversion between the JSON value and a compatible value
18721 which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
18722 and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
18723 The value is converted by calling the @ref json_serializer<ValueType>
18724 `from_json()` method.
18725
18726 The function is equivalent to executing
18727 @code {.cpp}
18728 ValueType ret;
18729 JSONSerializer<ValueType>::from_json(*this, ret);
18730 return ret;
18731 @endcode
18732
18733 This overloads is chosen if:
18734 - @a ValueType is not @ref basic_json,
18735 - @ref json_serializer<ValueType> has a `from_json()` method of the form
18736 `void from_json(const basic_json&, ValueType&)`, and
18737 - @ref json_serializer<ValueType> does not have a `from_json()` method of
18738 the form `ValueType from_json(const basic_json&)`
18739
18740 @tparam ValueType the returned value type
18741
18742 @return copy of the JSON value, converted to @a ValueType
18743
18744 @throw what @ref json_serializer<ValueType> `from_json()` method throws
18745
18746 @liveexample{The example below shows several conversions from JSON values
18747 to other types. There a few things to note: (1) Floating-point numbers can
18748 be converted to integers\, (2) A JSON array can be converted to a standard
18749 `std::vector<short>`\, (3) A JSON object can be converted to C++
18750 associative containers such as `std::unordered_map<std::string\,
18751 json>`.,get__ValueType_const}
18752
18753 @since version 2.1.0
18754 */
18755 template < typename ValueType,
18756 detail::enable_if_t <
18757 detail::is_default_constructible<ValueType>::value&&
18758 detail::has_from_json<basic_json_t, ValueType>::value,
18759 int > = 0 >
18760 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
18761 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
18762 {
18763 auto ret = ValueType();
18764 JSONSerializer<ValueType>::from_json(*this, ret);
18765 return ret;
18766 }
18767
18768 /*!
18769 @brief get a value (explicit); special case
18770
18771 Explicit type conversion between the JSON value and a compatible value
18772 which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
18773 and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
18774 The value is converted by calling the @ref json_serializer<ValueType>
18775 `from_json()` method.
18776
18777 The function is equivalent to executing
18778 @code {.cpp}
18779 return JSONSerializer<ValueType>::from_json(*this);
18780 @endcode
18781
18782 This overloads is chosen if:
18783 - @a ValueType is not @ref basic_json and
18784 - @ref json_serializer<ValueType> has a `from_json()` method of the form
18785 `ValueType from_json(const basic_json&)`
18786
18787 @note If @ref json_serializer<ValueType> has both overloads of
18788 `from_json()`, this one is chosen.
18789
18790 @tparam ValueType the returned value type
18791
18792 @return copy of the JSON value, converted to @a ValueType
18793
18794 @throw what @ref json_serializer<ValueType> `from_json()` method throws
18795
18796 @since version 2.1.0
18797 */
18798 template < typename ValueType,
18799 detail::enable_if_t <
18800 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
18801 int > = 0 >
18802 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
18803 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
18804 {
18805 return JSONSerializer<ValueType>::from_json(*this);
18806 }
18807
18808 /*!
18809 @brief get special-case overload
18810
18811 This overloads converts the current @ref basic_json in a different
18812 @ref basic_json type
18813
18814 @tparam BasicJsonType == @ref basic_json
18815
18816 @return a copy of *this, converted into @a BasicJsonType
18817
18818 @complexity Depending on the implementation of the called `from_json()`
18819 method.
18820
18821 @since version 3.2.0
18822 */
18823 template < typename BasicJsonType,
18824 detail::enable_if_t <
18825 detail::is_basic_json<BasicJsonType>::value,
18826 int > = 0 >
18827 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
18828 {
18829 return *this;
18830 }
18831
18832 /*!
18833 @brief get special-case overload
18834
18835 This overloads avoids a lot of template boilerplate, it can be seen as the
18836 identity method
18837
18838 @tparam BasicJsonType == @ref basic_json
18839
18840 @return a copy of *this
18841
18842 @complexity Constant.
18843
18844 @since version 2.1.0
18845 */
18846 template<typename BasicJsonType,
18847 detail::enable_if_t<
18848 std::is_same<BasicJsonType, basic_json_t>::value,
18849 int> = 0>
18850 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
18851 {
18852 return *this;
18853 }
18854
18855 /*!
18856 @brief get a pointer value (explicit)
18857 @copydoc get()
18858 */
18859 template<typename PointerType,
18860 detail::enable_if_t<
18861 std::is_pointer<PointerType>::value,
18862 int> = 0>
18863 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
18864 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
18865 {
18866 // delegate the call to get_ptr
18867 return get_ptr<PointerType>();
18868 }
18869
18870 public:
18871 /*!
18872 @brief get a (pointer) value (explicit)
18873
18874 Performs explicit type conversion between the JSON value and a compatible value if required.
18875
18876 - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
18877 No copies are made.
18878
18879 - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
18880 from the current @ref basic_json.
18881
18882 - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
18883 method.
18884
18885 @tparam ValueTypeCV the provided value type
18886 @tparam ValueType the returned value type
18887
18888 @return copy of the JSON value, converted to @tparam ValueType if necessary
18889
18890 @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
18891
18892 @since version 2.1.0
18893 */
18894 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
18895 #if defined(JSON_HAS_CPP_14)
18896 constexpr
18897 #endif
18898 auto get() const noexcept(
18899 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
18900 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
18901 {
18902 // we cannot static_assert on ValueTypeCV being non-const, because
18903 // there is support for get<const basic_json_t>(), which is why we
18904 // still need the uncvref
18905 static_assert(!std::is_reference<ValueTypeCV>::value,
18906 "get() cannot be used with reference types, you might want to use get_ref()");
18907 return get_impl<ValueType>(detail::priority_tag<4> {});
18908 }
18909
18910 /*!
18911 @brief get a pointer value (explicit)
18912
18913 Explicit pointer access to the internally stored JSON value. No copies are
18914 made.
18915
18916 @warning The pointer becomes invalid if the underlying JSON object
18917 changes.
18918
18919 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
18920 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
18921 @ref number_unsigned_t, or @ref number_float_t.
18922
18923 @return pointer to the internally stored JSON value if the requested
18924 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
18925
18926 @complexity Constant.
18927
18928 @liveexample{The example below shows how pointers to internal values of a
18929 JSON value can be requested. Note that no type conversions are made and a
18930 `nullptr` is returned if the value and the requested pointer type does not
18931 match.,get__PointerType}
18932
18933 @sa see @ref get_ptr() for explicit pointer-member access
18934
18935 @since version 1.0.0
18936 */
18937 template<typename PointerType, typename std::enable_if<
18938 std::is_pointer<PointerType>::value, int>::type = 0>
18939 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
18940 {
18941 // delegate the call to get_ptr
18942 return get_ptr<PointerType>();
18943 }
18944
18945 /// @brief get a value (explicit)
18946 /// @sa https://json.nlohmann.me/api/basic_json/get_to/
18947 template < typename ValueType,
18948 detail::enable_if_t <
18949 !detail::is_basic_json<ValueType>::value&&
18950 detail::has_from_json<basic_json_t, ValueType>::value,
18951 int > = 0 >
18952 ValueType & get_to(ValueType& v) const noexcept(noexcept(
18953 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
18954 {
18955 JSONSerializer<ValueType>::from_json(*this, v);
18956 return v;
18957 }
18958
18959 // specialization to allow calling get_to with a basic_json value
18960 // see https://github.com/nlohmann/json/issues/2175
18961 template<typename ValueType,
18962 detail::enable_if_t <
18963 detail::is_basic_json<ValueType>::value,
18964 int> = 0>
18965 ValueType & get_to(ValueType& v) const
18966 {
18967 v = *this;
18968 return v;
18969 }
18970
18971 template <
18972 typename T, std::size_t N,
18973 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
18974 detail::enable_if_t <
18975 detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
18976 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
18977 noexcept(noexcept(JSONSerializer<Array>::from_json(
18978 std::declval<const basic_json_t&>(), v)))
18979 {
18980 JSONSerializer<Array>::from_json(*this, v);
18981 return v;
18982 }
18983
18984 /// @brief get a reference value (implicit)
18985 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
18986 template<typename ReferenceType, typename std::enable_if<
18987 std::is_reference<ReferenceType>::value, int>::type = 0>
18988 ReferenceType get_ref()
18989 {
18990 // delegate call to get_ref_impl
18991 return get_ref_impl<ReferenceType>(*this);
18992 }
18993
18994 /// @brief get a reference value (implicit)
18995 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
18996 template < typename ReferenceType, typename std::enable_if <
18997 std::is_reference<ReferenceType>::value&&
18998 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
18999 ReferenceType get_ref() const
19000 {
19001 // delegate call to get_ref_impl
19002 return get_ref_impl<ReferenceType>(*this);
19003 }
19004
19005 /*!
19006 @brief get a value (implicit)
19007
19008 Implicit type conversion between the JSON value and a compatible value.
19009 The call is realized by calling @ref get() const.
19010
19011 @tparam ValueType non-pointer type compatible to the JSON value, for
19012 instance `int` for JSON integer numbers, `bool` for JSON booleans, or
19013 `std::vector` types for JSON arrays. The character type of @ref string_t
19014 as well as an initializer list of this type is excluded to avoid
19015 ambiguities as these types implicitly convert to `std::string`.
19016
19017 @return copy of the JSON value, converted to type @a ValueType
19018
19019 @throw type_error.302 in case passed type @a ValueType is incompatible
19020 to the JSON value type (e.g., the JSON value is of type boolean, but a
19021 string is requested); see example below
19022
19023 @complexity Linear in the size of the JSON value.
19024
19025 @liveexample{The example below shows several conversions from JSON values
19026 to other types. There a few things to note: (1) Floating-point numbers can
19027 be converted to integers\, (2) A JSON array can be converted to a standard
19028 `std::vector<short>`\, (3) A JSON object can be converted to C++
19029 associative containers such as `std::unordered_map<std::string\,
19030 json>`.,operator__ValueType}
19031
19032 @since version 1.0.0
19033 */
19034 template < typename ValueType, typename std::enable_if <
19035 detail::conjunction <
19036 detail::negation<std::is_pointer<ValueType>>,
19037 detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
19038 detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
19039 detail::negation<detail::is_basic_json<ValueType>>,
19040 detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
19041
19042 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
19043 detail::negation<std::is_same<ValueType, std::string_view>>,
19044 #endif
19045 detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
19046 >::value, int >::type = 0 >
19047 JSON_EXPLICIT operator ValueType() const
19048 {
19049 // delegate the call to get<>() const
19050 return get<ValueType>();
19051 }
19052
19053 /// @brief get a binary value
19054 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
19055 binary_t& get_binary()
19056 {
19057 if (!is_binary())
19058 {
19059 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
19060 }
19061
19062 return *get_ptr<binary_t*>();
19063 }
19064
19065 /// @brief get a binary value
19066 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
19067 const binary_t& get_binary() const
19068 {
19069 if (!is_binary())
19070 {
19071 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
19072 }
19073
19074 return *get_ptr<const binary_t*>();
19075 }
19076
19077 /// @}
19078
19079
19080 ////////////////////
19081 // element access //
19082 ////////////////////
19083
19084 /// @name element access
19085 /// Access to the JSON value.
19086 /// @{
19087
19088 /// @brief access specified array element with bounds checking
19089 /// @sa https://json.nlohmann.me/api/basic_json/at/
19090 reference at(size_type idx)
19091 {
19092 // at only works for arrays
19093 if (JSON_HEDLEY_LIKELY(is_array()))
19094 {
19095 JSON_TRY
19096 {
19097 return set_parent(m_value.array->at(idx));
19098 }
19099 JSON_CATCH (std::out_of_range&)
19100 {
19101 // create better exception explanation
19102 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
19103 }
19104 }
19105 else
19106 {
19107 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
19108 }
19109 }
19110
19111 /// @brief access specified array element with bounds checking
19112 /// @sa https://json.nlohmann.me/api/basic_json/at/
19113 const_reference at(size_type idx) const
19114 {
19115 // at only works for arrays
19116 if (JSON_HEDLEY_LIKELY(is_array()))
19117 {
19118 JSON_TRY
19119 {
19120 return m_value.array->at(idx);
19121 }
19122 JSON_CATCH (std::out_of_range&)
19123 {
19124 // create better exception explanation
19125 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
19126 }
19127 }
19128 else
19129 {
19130 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
19131 }
19132 }
19133
19134 /// @brief access specified object element with bounds checking
19135 /// @sa https://json.nlohmann.me/api/basic_json/at/
19136 reference at(const typename object_t::key_type& key)
19137 {
19138 // at only works for objects
19139 if (JSON_HEDLEY_LIKELY(is_object()))
19140 {
19141 JSON_TRY
19142 {
19143 return set_parent(m_value.object->at(key));
19144 }
19145 JSON_CATCH (std::out_of_range&)
19146 {
19147 // create better exception explanation
19148 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
19149 }
19150 }
19151 else
19152 {
19153 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
19154 }
19155 }
19156
19157 /// @brief access specified object element with bounds checking
19158 /// @sa https://json.nlohmann.me/api/basic_json/at/
19159 const_reference at(const typename object_t::key_type& key) const
19160 {
19161 // at only works for objects
19162 if (JSON_HEDLEY_LIKELY(is_object()))
19163 {
19164 JSON_TRY
19165 {
19166 return m_value.object->at(key);
19167 }
19168 JSON_CATCH (std::out_of_range&)
19169 {
19170 // create better exception explanation
19171 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
19172 }
19173 }
19174 else
19175 {
19176 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
19177 }
19178 }
19179
19180 /// @brief access specified array element
19181 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19182 reference operator[](size_type idx)
19183 {
19184 // implicitly convert null value to an empty array
19185 if (is_null())
19186 {
19187 m_type = value_t::array;
19188 m_value.array = create<array_t>();
19189 assert_invariant();
19190 }
19191
19192 // operator[] only works for arrays
19193 if (JSON_HEDLEY_LIKELY(is_array()))
19194 {
19195 // fill up array with null values if given idx is outside range
19196 if (idx >= m_value.array->size())
19197 {
19198 #if JSON_DIAGNOSTICS
19199 // remember array size & capacity before resizing
19200 const auto old_size = m_value.array->size();
19201 const auto old_capacity = m_value.array->capacity();
19202 #endif
19203 m_value.array->resize(idx + 1);
19204
19205 #if JSON_DIAGNOSTICS
19206 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
19207 {
19208 // capacity has changed: update all parents
19209 set_parents();
19210 }
19211 else
19212 {
19213 // set parent for values added above
19214 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
19215 }
19216 #endif
19217 assert_invariant();
19218 }
19219
19220 return m_value.array->operator[](idx);
19221 }
19222
19223 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
19224 }
19225
19226 /// @brief access specified array element
19227 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19228 const_reference operator[](size_type idx) const
19229 {
19230 // const operator[] only works for arrays
19231 if (JSON_HEDLEY_LIKELY(is_array()))
19232 {
19233 return m_value.array->operator[](idx);
19234 }
19235
19236 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
19237 }
19238
19239 /// @brief access specified object element
19240 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19241 reference operator[](const typename object_t::key_type& key)
19242 {
19243 // implicitly convert null value to an empty object
19244 if (is_null())
19245 {
19246 m_type = value_t::object;
19247 m_value.object = create<object_t>();
19248 assert_invariant();
19249 }
19250
19251 // operator[] only works for objects
19252 if (JSON_HEDLEY_LIKELY(is_object()))
19253 {
19254 return set_parent(m_value.object->operator[](key));
19255 }
19256
19257 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
19258 }
19259
19260 /// @brief access specified object element
19261 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19262 const_reference operator[](const typename object_t::key_type& key) const
19263 {
19264 // const operator[] only works for objects
19265 if (JSON_HEDLEY_LIKELY(is_object()))
19266 {
19267 JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
19268 return m_value.object->find(key)->second;
19269 }
19270
19271 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
19272 }
19273
19274 /// @brief access specified object element
19275 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19276 template<typename T>
19277 JSON_HEDLEY_NON_NULL(2)
19278 reference operator[](T* key)
19279 {
19280 // implicitly convert null to object
19281 if (is_null())
19282 {
19283 m_type = value_t::object;
19284 m_value = value_t::object;
19285 assert_invariant();
19286 }
19287
19288 // at only works for objects
19289 if (JSON_HEDLEY_LIKELY(is_object()))
19290 {
19291 return set_parent(m_value.object->operator[](key));
19292 }
19293
19294 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
19295 }
19296
19297 /// @brief access specified object element
19298 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19299 template<typename T>
19300 JSON_HEDLEY_NON_NULL(2)
19301 const_reference operator[](T* key) const
19302 {
19303 // at only works for objects
19304 if (JSON_HEDLEY_LIKELY(is_object()))
19305 {
19306 JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
19307 return m_value.object->find(key)->second;
19308 }
19309
19310 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
19311 }
19312
19313 /// @brief access specified object element with default value
19314 /// @sa https://json.nlohmann.me/api/basic_json/value/
19315 /// using std::is_convertible in a std::enable_if will fail when using explicit conversions
19316 template < class ValueType, typename std::enable_if <
19317 detail::is_getable<basic_json_t, ValueType>::value
19318 && !std::is_same<value_t, ValueType>::value, int >::type = 0 >
19319 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
19320 {
19321 // at only works for objects
19322 if (JSON_HEDLEY_LIKELY(is_object()))
19323 {
19324 // if key is found, return value and given default value otherwise
19325 const auto it = find(key);
19326 if (it != end())
19327 {
19328 return it->template get<ValueType>();
19329 }
19330
19331 return default_value;
19332 }
19333
19334 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
19335 }
19336
19337 /// @brief access specified object element with default value
19338 /// @sa https://json.nlohmann.me/api/basic_json/value/
19339 /// overload for a default value of type const char*
19340 string_t value(const typename object_t::key_type& key, const char* default_value) const
19341 {
19342 return value(key, string_t(default_value));
19343 }
19344
19345 /// @brief access specified object element via JSON Pointer with default value
19346 /// @sa https://json.nlohmann.me/api/basic_json/value/
19347 template<class ValueType, typename std::enable_if<
19348 detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
19349 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
19350 {
19351 // at only works for objects
19352 if (JSON_HEDLEY_LIKELY(is_object()))
19353 {
19354 // if pointer resolves a value, return it or use default value
19355 JSON_TRY
19356 {
19357 return ptr.get_checked(this).template get<ValueType>();
19358 }
19359 JSON_INTERNAL_CATCH (out_of_range&)
19360 {
19361 return default_value;
19362 }
19363 }
19364
19365 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
19366 }
19367
19368 /// @brief access specified object element via JSON Pointer with default value
19369 /// @sa https://json.nlohmann.me/api/basic_json/value/
19370 /// overload for a default value of type const char*
19371 JSON_HEDLEY_NON_NULL(3)
19372 string_t value(const json_pointer& ptr, const char* default_value) const
19373 {
19374 return value(ptr, string_t(default_value));
19375 }
19376
19377 /// @brief access the first element
19378 /// @sa https://json.nlohmann.me/api/basic_json/front/
19379 reference front()
19380 {
19381 return *begin();
19382 }
19383
19384 /// @brief access the first element
19385 /// @sa https://json.nlohmann.me/api/basic_json/front/
19386 const_reference front() const
19387 {
19388 return *cbegin();
19389 }
19390
19391 /// @brief access the last element
19392 /// @sa https://json.nlohmann.me/api/basic_json/back/
19393 reference back()
19394 {
19395 auto tmp = end();
19396 --tmp;
19397 return *tmp;
19398 }
19399
19400 /// @brief access the last element
19401 /// @sa https://json.nlohmann.me/api/basic_json/back/
19402 const_reference back() const
19403 {
19404 auto tmp = cend();
19405 --tmp;
19406 return *tmp;
19407 }
19408
19409 /// @brief remove element given an iterator
19410 /// @sa https://json.nlohmann.me/api/basic_json/erase/
19411 template < class IteratorType, typename std::enable_if <
19412 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
19413 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
19414 = 0 >
19415 IteratorType erase(IteratorType pos)
19416 {
19417 // make sure iterator fits the current value
19418 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
19419 {
19420 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
19421 }
19422
19423 IteratorType result = end();
19424
19425 switch (m_type)
19426 {
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:
19433 {
19434 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
19435 {
19436 JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this));
19437 }
19438
19439 if (is_string())
19440 {
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;
19445 }
19446 else if (is_binary())
19447 {
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;
19452 }
19453
19454 m_type = value_t::null;
19455 assert_invariant();
19456 break;
19457 }
19458
19459 case value_t::object:
19460 {
19461 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
19462 break;
19463 }
19464
19465 case value_t::array:
19466 {
19467 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
19468 break;
19469 }
19470
19471 case value_t::null:
19472 case value_t::discarded:
19473 default:
19474 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
19475 }
19476
19477 return result;
19478 }
19479
19480 /// @brief remove elements given an iterator range
19481 /// @sa https://json.nlohmann.me/api/basic_json/erase/
19482 template < class IteratorType, typename std::enable_if <
19483 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
19484 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
19485 = 0 >
19486 IteratorType erase(IteratorType first, IteratorType last)
19487 {
19488 // make sure iterator fits the current value
19489 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
19490 {
19491 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this));
19492 }
19493
19494 IteratorType result = end();
19495
19496 switch (m_type)
19497 {
19498 case value_t::boolean:
19499 case value_t::number_float:
19500 case value_t::number_integer:
19501 case value_t::number_unsigned:
19502 case value_t::string:
19503 case value_t::binary:
19504 {
19505 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
19506 || !last.m_it.primitive_iterator.is_end()))
19507 {
19508 JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this));
19509 }
19510
19511 if (is_string())
19512 {
19513 AllocatorType<string_t> alloc;
19514 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
19515 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
19516 m_value.string = nullptr;
19517 }
19518 else if (is_binary())
19519 {
19520 AllocatorType<binary_t> alloc;
19521 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
19522 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
19523 m_value.binary = nullptr;
19524 }
19525
19526 m_type = value_t::null;
19527 assert_invariant();
19528 break;
19529 }
19530
19531 case value_t::object:
19532 {
19533 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
19534 last.m_it.object_iterator);
19535 break;
19536 }
19537
19538 case value_t::array:
19539 {
19540 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
19541 last.m_it.array_iterator);
19542 break;
19543 }
19544
19545 case value_t::null:
19546 case value_t::discarded:
19547 default:
19548 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
19549 }
19550
19551 return result;
19552 }
19553
19554 /// @brief remove element from a JSON object given a key
19555 /// @sa https://json.nlohmann.me/api/basic_json/erase/
19556 size_type erase(const typename object_t::key_type& key)
19557 {
19558 // this erase only works for objects
19559 if (JSON_HEDLEY_LIKELY(is_object()))
19560 {
19561 return m_value.object->erase(key);
19562 }
19563
19564 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
19565 }
19566
19567 /// @brief remove element from a JSON array given an index
19568 /// @sa https://json.nlohmann.me/api/basic_json/erase/
19569 void erase(const size_type idx)
19570 {
19571 // this erase only works for arrays
19572 if (JSON_HEDLEY_LIKELY(is_array()))
19573 {
19574 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
19575 {
19576 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
19577 }
19578
19579 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
19580 }
19581 else
19582 {
19583 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
19584 }
19585 }
19586
19587 /// @}
19588
19589
19590 ////////////
19591 // lookup //
19592 ////////////
19593
19594 /// @name lookup
19595 /// @{
19596
19597 /// @brief find an element in a JSON object
19598 /// @sa https://json.nlohmann.me/api/basic_json/find/
19599 template<typename KeyT>
19600 iterator find(KeyT&& key)
19601 {
19602 auto result = end();
19603
19604 if (is_object())
19605 {
19606 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
19607 }
19608
19609 return result;
19610 }
19611
19612 /// @brief find an element in a JSON object
19613 /// @sa https://json.nlohmann.me/api/basic_json/find/
19614 template<typename KeyT>
19615 const_iterator find(KeyT&& key) const
19616 {
19617 auto result = cend();
19618
19619 if (is_object())
19620 {
19621 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
19622 }
19623
19624 return result;
19625 }
19626
19627 /// @brief returns the number of occurrences of a key in a JSON object
19628 /// @sa https://json.nlohmann.me/api/basic_json/count/
19629 template<typename KeyT>
19630 size_type count(KeyT&& key) const
19631 {
19632 // return 0 for all nonobject types
19633 return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
19634 }
19635
19636 /// @brief check the existence of an element in a JSON object
19637 /// @sa https://json.nlohmann.me/api/basic_json/contains/
19638 template < typename KeyT, typename std::enable_if <
19639 !std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int >::type = 0 >
19640 bool contains(KeyT && key) const
19641 {
19642 return is_object() && m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
19643 }
19644
19645 /// @brief check the existence of an element in a JSON object given a JSON pointer
19646 /// @sa https://json.nlohmann.me/api/basic_json/contains/
19647 bool contains(const json_pointer& ptr) const
19648 {
19649 return ptr.contains(this);
19650 }
19651
19652 /// @}
19653
19654
19655 ///////////////
19656 // iterators //
19657 ///////////////
19658
19659 /// @name iterators
19660 /// @{
19661
19662 /// @brief returns an iterator to the first element
19663 /// @sa https://json.nlohmann.me/api/basic_json/begin/
19664 iterator begin() noexcept
19665 {
19666 iterator result(this);
19667 result.set_begin();
19668 return result;
19669 }
19670
19671 /// @brief returns an iterator to the first element
19672 /// @sa https://json.nlohmann.me/api/basic_json/begin/
19673 const_iterator begin() const noexcept
19674 {
19675 return cbegin();
19676 }
19677
19678 /// @brief returns a const iterator to the first element
19679 /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
19680 const_iterator cbegin() const noexcept
19681 {
19682 const_iterator result(this);
19683 result.set_begin();
19684 return result;
19685 }
19686
19687 /// @brief returns an iterator to one past the last element
19688 /// @sa https://json.nlohmann.me/api/basic_json/end/
19689 iterator end() noexcept
19690 {
19691 iterator result(this);
19692 result.set_end();
19693 return result;
19694 }
19695
19696 /// @brief returns an iterator to one past the last element
19697 /// @sa https://json.nlohmann.me/api/basic_json/end/
19698 const_iterator end() const noexcept
19699 {
19700 return cend();
19701 }
19702
19703 /// @brief returns an iterator to one past the last element
19704 /// @sa https://json.nlohmann.me/api/basic_json/cend/
19705 const_iterator cend() const noexcept
19706 {
19707 const_iterator result(this);
19708 result.set_end();
19709 return result;
19710 }
19711
19712 /// @brief returns an iterator to the reverse-beginning
19713 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
19714 reverse_iterator rbegin() noexcept
19715 {
19716 return reverse_iterator(end());
19717 }
19718
19719 /// @brief returns an iterator to the reverse-beginning
19720 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
19721 const_reverse_iterator rbegin() const noexcept
19722 {
19723 return crbegin();
19724 }
19725
19726 /// @brief returns an iterator to the reverse-end
19727 /// @sa https://json.nlohmann.me/api/basic_json/rend/
19728 reverse_iterator rend() noexcept
19729 {
19730 return reverse_iterator(begin());
19731 }
19732
19733 /// @brief returns an iterator to the reverse-end
19734 /// @sa https://json.nlohmann.me/api/basic_json/rend/
19735 const_reverse_iterator rend() const noexcept
19736 {
19737 return crend();
19738 }
19739
19740 /// @brief returns a const reverse iterator to the last element
19741 /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
19742 const_reverse_iterator crbegin() const noexcept
19743 {
19744 return const_reverse_iterator(cend());
19745 }
19746
19747 /// @brief returns a const reverse iterator to one before the first
19748 /// @sa https://json.nlohmann.me/api/basic_json/crend/
19749 const_reverse_iterator crend() const noexcept
19750 {
19751 return const_reverse_iterator(cbegin());
19752 }
19753
19754 public:
19755 /// @brief wrapper to access iterator member functions in range-based for
19756 /// @sa https://json.nlohmann.me/api/basic_json/items/
19757 /// @deprecated This function is deprecated since 3.1.0 and will be removed in
19758 /// version 4.0.0 of the library. Please use @ref items() instead;
19759 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
19760 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
19761 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
19762 {
19763 return ref.items();
19764 }
19765
19766 /// @brief wrapper to access iterator member functions in range-based for
19767 /// @sa https://json.nlohmann.me/api/basic_json/items/
19768 /// @deprecated This function is deprecated since 3.1.0 and will be removed in
19769 /// version 4.0.0 of the library. Please use @ref items() instead;
19770 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
19771 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
19772 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
19773 {
19774 return ref.items();
19775 }
19776
19777 /// @brief helper to access iterator member functions in range-based for
19778 /// @sa https://json.nlohmann.me/api/basic_json/items/
19779 iteration_proxy<iterator> items() noexcept
19780 {
19781 return iteration_proxy<iterator>(*this);
19782 }
19783
19784 /// @brief helper to access iterator member functions in range-based for
19785 /// @sa https://json.nlohmann.me/api/basic_json/items/
19786 iteration_proxy<const_iterator> items() const noexcept
19787 {
19788 return iteration_proxy<const_iterator>(*this);
19789 }
19790
19791 /// @}
19792
19793
19794 //////////////
19795 // capacity //
19796 //////////////
19797
19798 /// @name capacity
19799 /// @{
19800
19801 /// @brief checks whether the container is empty.
19802 /// @sa https://json.nlohmann.me/api/basic_json/empty/
19803 bool empty() const noexcept
19804 {
19805 switch (m_type)
19806 {
19807 case value_t::null:
19808 {
19809 // null values are empty
19810 return true;
19811 }
19812
19813 case value_t::array:
19814 {
19815 // delegate call to array_t::empty()
19816 return m_value.array->empty();
19817 }
19818
19819 case value_t::object:
19820 {
19821 // delegate call to object_t::empty()
19822 return m_value.object->empty();
19823 }
19824
19825 case value_t::string:
19826 case value_t::boolean:
19827 case value_t::number_integer:
19828 case value_t::number_unsigned:
19829 case value_t::number_float:
19830 case value_t::binary:
19831 case value_t::discarded:
19832 default:
19833 {
19834 // all other types are nonempty
19835 return false;
19836 }
19837 }
19838 }
19839
19840 /// @brief returns the number of elements
19841 /// @sa https://json.nlohmann.me/api/basic_json/size/
19842 size_type size() const noexcept
19843 {
19844 switch (m_type)
19845 {
19846 case value_t::null:
19847 {
19848 // null values are empty
19849 return 0;
19850 }
19851
19852 case value_t::array:
19853 {
19854 // delegate call to array_t::size()
19855 return m_value.array->size();
19856 }
19857
19858 case value_t::object:
19859 {
19860 // delegate call to object_t::size()
19861 return m_value.object->size();
19862 }
19863
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:
19871 default:
19872 {
19873 // all other types have size 1
19874 return 1;
19875 }
19876 }
19877 }
19878
19879 /// @brief returns the maximum possible number of elements
19880 /// @sa https://json.nlohmann.me/api/basic_json/max_size/
19881 size_type max_size() const noexcept
19882 {
19883 switch (m_type)
19884 {
19885 case value_t::array:
19886 {
19887 // delegate call to array_t::max_size()
19888 return m_value.array->max_size();
19889 }
19890
19891 case value_t::object:
19892 {
19893 // delegate call to object_t::max_size()
19894 return m_value.object->max_size();
19895 }
19896
19897 case value_t::null:
19898 case value_t::string:
19899 case value_t::boolean:
19900 case value_t::number_integer:
19901 case value_t::number_unsigned:
19902 case value_t::number_float:
19903 case value_t::binary:
19904 case value_t::discarded:
19905 default:
19906 {
19907 // all other types have max_size() == size()
19908 return size();
19909 }
19910 }
19911 }
19912
19913 /// @}
19914
19915
19916 ///////////////
19917 // modifiers //
19918 ///////////////
19919
19920 /// @name modifiers
19921 /// @{
19922
19923 /// @brief clears the contents
19924 /// @sa https://json.nlohmann.me/api/basic_json/clear/
19925 void clear() noexcept
19926 {
19927 switch (m_type)
19928 {
19929 case value_t::number_integer:
19930 {
19931 m_value.number_integer = 0;
19932 break;
19933 }
19934
19935 case value_t::number_unsigned:
19936 {
19937 m_value.number_unsigned = 0;
19938 break;
19939 }
19940
19941 case value_t::number_float:
19942 {
19943 m_value.number_float = 0.0;
19944 break;
19945 }
19946
19947 case value_t::boolean:
19948 {
19949 m_value.boolean = false;
19950 break;
19951 }
19952
19953 case value_t::string:
19954 {
19955 m_value.string->clear();
19956 break;
19957 }
19958
19959 case value_t::binary:
19960 {
19961 m_value.binary->clear();
19962 break;
19963 }
19964
19965 case value_t::array:
19966 {
19967 m_value.array->clear();
19968 break;
19969 }
19970
19971 case value_t::object:
19972 {
19973 m_value.object->clear();
19974 break;
19975 }
19976
19977 case value_t::null:
19978 case value_t::discarded:
19979 default:
19980 break;
19981 }
19982 }
19983
19984 /// @brief add an object to an array
19985 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
19986 void push_back(basic_json&& val)
19987 {
19988 // push_back only works for null objects or arrays
19989 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
19990 {
19991 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
19992 }
19993
19994 // transform null object into an array
19995 if (is_null())
19996 {
19997 m_type = value_t::array;
19998 m_value = value_t::array;
19999 assert_invariant();
20000 }
20001
20002 // add element to array (move semantics)
20003 const auto old_capacity = m_value.array->capacity();
20004 m_value.array->push_back(std::move(val));
20005 set_parent(m_value.array->back(), old_capacity);
20006 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
20007 }
20008
20009 /// @brief add an object to an array
20010 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
20011 reference operator+=(basic_json&& val)
20012 {
20013 push_back(std::move(val));
20014 return *this;
20015 }
20016
20017 /// @brief add an object to an array
20018 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
20019 void push_back(const basic_json& val)
20020 {
20021 // push_back only works for null objects or arrays
20022 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
20023 {
20024 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
20025 }
20026
20027 // transform null object into an array
20028 if (is_null())
20029 {
20030 m_type = value_t::array;
20031 m_value = value_t::array;
20032 assert_invariant();
20033 }
20034
20035 // add element to array
20036 const auto old_capacity = m_value.array->capacity();
20037 m_value.array->push_back(val);
20038 set_parent(m_value.array->back(), old_capacity);
20039 }
20040
20041 /// @brief add an object to an array
20042 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
20043 reference operator+=(const basic_json& val)
20044 {
20045 push_back(val);
20046 return *this;
20047 }
20048
20049 /// @brief add an object to an object
20050 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
20051 void push_back(const typename object_t::value_type& val)
20052 {
20053 // push_back only works for null objects or objects
20054 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
20055 {
20056 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
20057 }
20058
20059 // transform null object into an object
20060 if (is_null())
20061 {
20062 m_type = value_t::object;
20063 m_value = value_t::object;
20064 assert_invariant();
20065 }
20066
20067 // add element to object
20068 auto res = m_value.object->insert(val);
20069 set_parent(res.first->second);
20070 }
20071
20072 /// @brief add an object to an object
20073 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
20074 reference operator+=(const typename object_t::value_type& val)
20075 {
20076 push_back(val);
20077 return *this;
20078 }
20079
20080 /// @brief add an object to an object
20081 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
20082 void push_back(initializer_list_t init)
20083 {
20084 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
20085 {
20086 basic_json&& key = init.begin()->moved_or_copied();
20087 push_back(typename object_t::value_type(
20088 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
20089 }
20090 else
20091 {
20092 push_back(basic_json(init));
20093 }
20094 }
20095
20096 /// @brief add an object to an object
20097 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
20098 reference operator+=(initializer_list_t init)
20099 {
20100 push_back(init);
20101 return *this;
20102 }
20103
20104 /// @brief add an object to an array
20105 /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
20106 template<class... Args>
20107 reference emplace_back(Args&& ... args)
20108 {
20109 // emplace_back only works for null objects or arrays
20110 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
20111 {
20112 JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this));
20113 }
20114
20115 // transform null object into an array
20116 if (is_null())
20117 {
20118 m_type = value_t::array;
20119 m_value = value_t::array;
20120 assert_invariant();
20121 }
20122
20123 // add element to array (perfect forwarding)
20124 const auto old_capacity = m_value.array->capacity();
20125 m_value.array->emplace_back(std::forward<Args>(args)...);
20126 return set_parent(m_value.array->back(), old_capacity);
20127 }
20128
20129 /// @brief add an object to an object if key does not exist
20130 /// @sa https://json.nlohmann.me/api/basic_json/emplace/
20131 template<class... Args>
20132 std::pair<iterator, bool> emplace(Args&& ... args)
20133 {
20134 // emplace only works for null objects or arrays
20135 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
20136 {
20137 JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this));
20138 }
20139
20140 // transform null object into an object
20141 if (is_null())
20142 {
20143 m_type = value_t::object;
20144 m_value = value_t::object;
20145 assert_invariant();
20146 }
20147
20148 // add element to array (perfect forwarding)
20149 auto res = m_value.object->emplace(std::forward<Args>(args)...);
20150 set_parent(res.first->second);
20151
20152 // create result iterator and set iterator to the result of emplace
20153 auto it = begin();
20154 it.m_it.object_iterator = res.first;
20155
20156 // return pair of iterator and boolean
20157 return {it, res.second};
20158 }
20159
20160 /// Helper for insertion of an iterator
20161 /// @note: This uses std::distance to support GCC 4.8,
20162 /// see https://github.com/nlohmann/json/pull/1257
20163 template<typename... Args>
20164 iterator insert_iterator(const_iterator pos, Args&& ... args)
20165 {
20166 iterator result(this);
20167 JSON_ASSERT(m_value.array != nullptr);
20168
20169 auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
20170 m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
20171 result.m_it.array_iterator = m_value.array->begin() + insert_pos;
20172
20173 // This could have been written as:
20174 // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
20175 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
20176
20177 set_parents();
20178 return result;
20179 }
20180
20181 /// @brief inserts element into array
20182 /// @sa https://json.nlohmann.me/api/basic_json/insert/
20183 iterator insert(const_iterator pos, const basic_json& val)
20184 {
20185 // insert only works for arrays
20186 if (JSON_HEDLEY_LIKELY(is_array()))
20187 {
20188 // check if iterator pos fits to this JSON value
20189 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
20190 {
20191 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
20192 }
20193
20194 // insert to array and return iterator
20195 return insert_iterator(pos, val);
20196 }
20197
20198 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20199 }
20200
20201 /// @brief inserts element into array
20202 /// @sa https://json.nlohmann.me/api/basic_json/insert/
20203 iterator insert(const_iterator pos, basic_json&& val)
20204 {
20205 return insert(pos, val);
20206 }
20207
20208 /// @brief inserts copies of element into array
20209 /// @sa https://json.nlohmann.me/api/basic_json/insert/
20210 iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
20211 {
20212 // insert only works for arrays
20213 if (JSON_HEDLEY_LIKELY(is_array()))
20214 {
20215 // check if iterator pos fits to this JSON value
20216 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
20217 {
20218 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
20219 }
20220
20221 // insert to array and return iterator
20222 return insert_iterator(pos, cnt, val);
20223 }
20224
20225 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20226 }
20227
20228 /// @brief inserts range of elements into array
20229 /// @sa https://json.nlohmann.me/api/basic_json/insert/
20230 iterator insert(const_iterator pos, const_iterator first, const_iterator last)
20231 {
20232 // insert only works for arrays
20233 if (JSON_HEDLEY_UNLIKELY(!is_array()))
20234 {
20235 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20236 }
20237
20238 // check if iterator pos fits to this JSON value
20239 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
20240 {
20241 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
20242 }
20243
20244 // check if range iterators belong to the same JSON object
20245 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20246 {
20247 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
20248 }
20249
20250 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
20251 {
20252 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this));
20253 }
20254
20255 // insert to array and return iterator
20256 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
20257 }
20258
20259 /// @brief inserts elements from initializer list into array
20260 /// @sa https://json.nlohmann.me/api/basic_json/insert/
20261 iterator insert(const_iterator pos, initializer_list_t ilist)
20262 {
20263 // insert only works for arrays
20264 if (JSON_HEDLEY_UNLIKELY(!is_array()))
20265 {
20266 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20267 }
20268
20269 // check if iterator pos fits to this JSON value
20270 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
20271 {
20272 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
20273 }
20274
20275 // insert to array and return iterator
20276 return insert_iterator(pos, ilist.begin(), ilist.end());
20277 }
20278
20279 /// @brief inserts range of elements into object
20280 /// @sa https://json.nlohmann.me/api/basic_json/insert/
20281 void insert(const_iterator first, const_iterator last)
20282 {
20283 // insert only works for objects
20284 if (JSON_HEDLEY_UNLIKELY(!is_object()))
20285 {
20286 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20287 }
20288
20289 // check if range iterators belong to the same JSON object
20290 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20291 {
20292 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
20293 }
20294
20295 // passed iterators must belong to objects
20296 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
20297 {
20298 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this));
20299 }
20300
20301 m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
20302 }
20303
20304 /// @brief updates a JSON object from another object, overwriting existing keys
20305 /// @sa https://json.nlohmann.me/api/basic_json/update/
20306 void update(const_reference j, bool merge_objects = false)
20307 {
20308 update(j.begin(), j.end(), merge_objects);
20309 }
20310
20311 /// @brief updates a JSON object from another object, overwriting existing keys
20312 /// @sa https://json.nlohmann.me/api/basic_json/update/
20313 void update(const_iterator first, const_iterator last, bool merge_objects = false)
20314 {
20315 // implicitly convert null value to an empty object
20316 if (is_null())
20317 {
20318 m_type = value_t::object;
20319 m_value.object = create<object_t>();
20320 assert_invariant();
20321 }
20322
20323 if (JSON_HEDLEY_UNLIKELY(!is_object()))
20324 {
20325 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this));
20326 }
20327
20328 // check if range iterators belong to the same JSON object
20329 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20330 {
20331 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
20332 }
20333
20334 // passed iterators must belong to objects
20335 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
20336 {
20337 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(first.m_object->type_name()), *first.m_object));
20338 }
20339
20340 for (auto it = first; it != last; ++it)
20341 {
20342 if (merge_objects && it.value().is_object())
20343 {
20344 auto it2 = m_value.object->find(it.key());
20345 if (it2 != m_value.object->end())
20346 {
20347 it2->second.update(it.value(), true);
20348 continue;
20349 }
20350 }
20351 m_value.object->operator[](it.key()) = it.value();
20352 #if JSON_DIAGNOSTICS
20353 m_value.object->operator[](it.key()).m_parent = this;
20354 #endif
20355 }
20356 }
20357
20358 /// @brief exchanges the values
20359 /// @sa https://json.nlohmann.me/api/basic_json/swap/
20360 void swap(reference other) noexcept (
20361 std::is_nothrow_move_constructible<value_t>::value&&
20362 std::is_nothrow_move_assignable<value_t>::value&&
20363 std::is_nothrow_move_constructible<json_value>::value&&
20364 std::is_nothrow_move_assignable<json_value>::value
20365 )
20366 {
20367 std::swap(m_type, other.m_type);
20368 std::swap(m_value, other.m_value);
20369
20370 set_parents();
20371 other.set_parents();
20372 assert_invariant();
20373 }
20374
20375 /// @brief exchanges the values
20376 /// @sa https://json.nlohmann.me/api/basic_json/swap/
20377 friend void swap(reference left, reference right) noexcept (
20378 std::is_nothrow_move_constructible<value_t>::value&&
20379 std::is_nothrow_move_assignable<value_t>::value&&
20380 std::is_nothrow_move_constructible<json_value>::value&&
20381 std::is_nothrow_move_assignable<json_value>::value
20382 )
20383 {
20384 left.swap(right);
20385 }
20386
20387 /// @brief exchanges the values
20388 /// @sa https://json.nlohmann.me/api/basic_json/swap/
20389 void swap(array_t& other) // NOLINT(bugprone-exception-escape)
20390 {
20391 // swap only works for arrays
20392 if (JSON_HEDLEY_LIKELY(is_array()))
20393 {
20394 std::swap(*(m_value.array), other);
20395 }
20396 else
20397 {
20398 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20399 }
20400 }
20401
20402 /// @brief exchanges the values
20403 /// @sa https://json.nlohmann.me/api/basic_json/swap/
20404 void swap(object_t& other) // NOLINT(bugprone-exception-escape)
20405 {
20406 // swap only works for objects
20407 if (JSON_HEDLEY_LIKELY(is_object()))
20408 {
20409 std::swap(*(m_value.object), other);
20410 }
20411 else
20412 {
20413 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20414 }
20415 }
20416
20417 /// @brief exchanges the values
20418 /// @sa https://json.nlohmann.me/api/basic_json/swap/
20419 void swap(string_t& other) // NOLINT(bugprone-exception-escape)
20420 {
20421 // swap only works for strings
20422 if (JSON_HEDLEY_LIKELY(is_string()))
20423 {
20424 std::swap(*(m_value.string), other);
20425 }
20426 else
20427 {
20428 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20429 }
20430 }
20431
20432 /// @brief exchanges the values
20433 /// @sa https://json.nlohmann.me/api/basic_json/swap/
20434 void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
20435 {
20436 // swap only works for strings
20437 if (JSON_HEDLEY_LIKELY(is_binary()))
20438 {
20439 std::swap(*(m_value.binary), other);
20440 }
20441 else
20442 {
20443 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20444 }
20445 }
20446
20447 /// @brief exchanges the values
20448 /// @sa https://json.nlohmann.me/api/basic_json/swap/
20449 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
20450 {
20451 // swap only works for strings
20452 if (JSON_HEDLEY_LIKELY(is_binary()))
20453 {
20454 std::swap(*(m_value.binary), other);
20455 }
20456 else
20457 {
20458 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20459 }
20460 }
20461
20462 /// @}
20463
20464 public:
20465 //////////////////////////////////////////
20466 // lexicographical comparison operators //
20467 //////////////////////////////////////////
20468
20469 /// @name lexicographical comparison operators
20470 /// @{
20471
20472 /// @brief comparison: equal
20473 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
20474 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
20475 {
20476 #ifdef __GNUC__
20477 #pragma GCC diagnostic push
20478 #pragma GCC diagnostic ignored "-Wfloat-equal"
20479 #endif
20480 const auto lhs_type = lhs.type();
20481 const auto rhs_type = rhs.type();
20482
20483 if (lhs_type == rhs_type)
20484 {
20485 switch (lhs_type)
20486 {
20487 case value_t::array:
20488 return *lhs.m_value.array == *rhs.m_value.array;
20489
20490 case value_t::object:
20491 return *lhs.m_value.object == *rhs.m_value.object;
20492
20493 case value_t::null:
20494 return true;
20495
20496 case value_t::string:
20497 return *lhs.m_value.string == *rhs.m_value.string;
20498
20499 case value_t::boolean:
20500 return lhs.m_value.boolean == rhs.m_value.boolean;
20501
20502 case value_t::number_integer:
20503 return lhs.m_value.number_integer == rhs.m_value.number_integer;
20504
20505 case value_t::number_unsigned:
20506 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
20507
20508 case value_t::number_float:
20509 return lhs.m_value.number_float == rhs.m_value.number_float;
20510
20511 case value_t::binary:
20512 return *lhs.m_value.binary == *rhs.m_value.binary;
20513
20514 case value_t::discarded:
20515 default:
20516 return false;
20517 }
20518 }
20519 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
20520 {
20521 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
20522 }
20523 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
20524 {
20525 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
20526 }
20527 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
20528 {
20529 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
20530 }
20531 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
20532 {
20533 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
20534 }
20535 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
20536 {
20537 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
20538 }
20539 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
20540 {
20541 return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
20542 }
20543
20544 return false;
20545 #ifdef __GNUC__
20546 #pragma GCC diagnostic pop
20547 #endif
20548 }
20549
20550 /// @brief comparison: equal
20551 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
20552 template<typename ScalarType, typename std::enable_if<
20553 std::is_scalar<ScalarType>::value, int>::type = 0>
20554 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
20555 {
20556 return lhs == basic_json(rhs);
20557 }
20558
20559 /// @brief comparison: equal
20560 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
20561 template<typename ScalarType, typename std::enable_if<
20562 std::is_scalar<ScalarType>::value, int>::type = 0>
20563 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
20564 {
20565 return basic_json(lhs) == rhs;
20566 }
20567
20568 /// @brief comparison: not equal
20569 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
20570 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
20571 {
20572 return !(lhs == rhs);
20573 }
20574
20575 /// @brief comparison: not equal
20576 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
20577 template<typename ScalarType, typename std::enable_if<
20578 std::is_scalar<ScalarType>::value, int>::type = 0>
20579 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
20580 {
20581 return lhs != basic_json(rhs);
20582 }
20583
20584 /// @brief comparison: not equal
20585 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
20586 template<typename ScalarType, typename std::enable_if<
20587 std::is_scalar<ScalarType>::value, int>::type = 0>
20588 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
20589 {
20590 return basic_json(lhs) != rhs;
20591 }
20592
20593 /// @brief comparison: less than
20594 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
20595 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
20596 {
20597 const auto lhs_type = lhs.type();
20598 const auto rhs_type = rhs.type();
20599
20600 if (lhs_type == rhs_type)
20601 {
20602 switch (lhs_type)
20603 {
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);
20608
20609 case value_t::object:
20610 return (*lhs.m_value.object) < (*rhs.m_value.object);
20611
20612 case value_t::null:
20613 return false;
20614
20615 case value_t::string:
20616 return (*lhs.m_value.string) < (*rhs.m_value.string);
20617
20618 case value_t::boolean:
20619 return (lhs.m_value.boolean) < (rhs.m_value.boolean);
20620
20621 case value_t::number_integer:
20622 return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
20623
20624 case value_t::number_unsigned:
20625 return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned);
20626
20627 case value_t::number_float:
20628 return (lhs.m_value.number_float) < (rhs.m_value.number_float);
20629
20630 case value_t::binary:
20631 return (*lhs.m_value.binary) < (*rhs.m_value.binary);
20632
20633 case value_t::discarded:
20634 default:
20635 return false;
20636 }
20637 }
20638 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
20639 {
20640 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
20641 }
20642 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
20643 {
20644 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
20645 }
20646 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
20647 {
20648 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
20649 }
20650 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
20651 {
20652 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
20653 }
20654 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
20655 {
20656 return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
20657 }
20658 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
20659 {
20660 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
20661 }
20662
20663 // We only reach this line if we cannot compare values. In that case,
20664 // we compare types. Note we have to call the operator explicitly,
20665 // because MSVC has problems otherwise.
20666 return operator<(lhs_type, rhs_type);
20667 }
20668
20669 /// @brief comparison: less than
20670 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
20671 template<typename ScalarType, typename std::enable_if<
20672 std::is_scalar<ScalarType>::value, int>::type = 0>
20673 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
20674 {
20675 return lhs < basic_json(rhs);
20676 }
20677
20678 /// @brief comparison: less than
20679 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
20680 template<typename ScalarType, typename std::enable_if<
20681 std::is_scalar<ScalarType>::value, int>::type = 0>
20682 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
20683 {
20684 return basic_json(lhs) < rhs;
20685 }
20686
20687 /// @brief comparison: less than or equal
20688 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
20689 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
20690 {
20691 return !(rhs < lhs);
20692 }
20693
20694 /// @brief comparison: less than or equal
20695 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
20696 template<typename ScalarType, typename std::enable_if<
20697 std::is_scalar<ScalarType>::value, int>::type = 0>
20698 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
20699 {
20700 return lhs <= basic_json(rhs);
20701 }
20702
20703 /// @brief comparison: less than or equal
20704 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
20705 template<typename ScalarType, typename std::enable_if<
20706 std::is_scalar<ScalarType>::value, int>::type = 0>
20707 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
20708 {
20709 return basic_json(lhs) <= rhs;
20710 }
20711
20712 /// @brief comparison: greater than
20713 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
20714 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
20715 {
20716 return !(lhs <= rhs);
20717 }
20718
20719 /// @brief comparison: greater than
20720 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
20721 template<typename ScalarType, typename std::enable_if<
20722 std::is_scalar<ScalarType>::value, int>::type = 0>
20723 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
20724 {
20725 return lhs > basic_json(rhs);
20726 }
20727
20728 /// @brief comparison: greater than
20729 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
20730 template<typename ScalarType, typename std::enable_if<
20731 std::is_scalar<ScalarType>::value, int>::type = 0>
20732 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
20733 {
20734 return basic_json(lhs) > rhs;
20735 }
20736
20737 /// @brief comparison: greater than or equal
20738 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
20739 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
20740 {
20741 return !(lhs < rhs);
20742 }
20743
20744 /// @brief comparison: greater than or equal
20745 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
20746 template<typename ScalarType, typename std::enable_if<
20747 std::is_scalar<ScalarType>::value, int>::type = 0>
20748 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
20749 {
20750 return lhs >= basic_json(rhs);
20751 }
20752
20753 /// @brief comparison: greater than or equal
20754 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
20755 template<typename ScalarType, typename std::enable_if<
20756 std::is_scalar<ScalarType>::value, int>::type = 0>
20757 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
20758 {
20759 return basic_json(lhs) >= rhs;
20760 }
20761
20762 /// @}
20763
20764 ///////////////////
20765 // serialization //
20766 ///////////////////
20767
20768 /// @name serialization
20769 /// @{
20770 #ifndef JSON_NO_IO
20771 /// @brief serialize to stream
20772 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
20773 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
20774 {
20775 // read width member and use it as indentation parameter if nonzero
20776 const bool pretty_print = o.width() > 0;
20777 const auto indentation = pretty_print ? o.width() : 0;
20778
20779 // reset width to 0 for subsequent calls to this stream
20780 o.width(0);
20781
20782 // do the actual serialization
20783 serializer s(detail::output_adapter<char>(o), o.fill());
20784 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
20785 return o;
20786 }
20787
20788 /// @brief serialize to stream
20789 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
20790 /// @deprecated This function is deprecated since 3.0.0 and will be removed in
20791 /// version 4.0.0 of the library. Please use
20792 /// operator<<(std::ostream&, const basic_json&) instead; that is,
20793 /// replace calls like `j >> o;` with `o << j;`.
20794 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
20795 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
20796 {
20797 return o << j;
20798 }
20799 #endif // JSON_NO_IO
20800 /// @}
20801
20802
20803 /////////////////////
20804 // deserialization //
20805 /////////////////////
20806
20807 /// @name deserialization
20808 /// @{
20809
20810 /// @brief deserialize from a compatible input
20811 /// @sa https://json.nlohmann.me/api/basic_json/parse/
20812 template<typename InputType>
20813 JSON_HEDLEY_WARN_UNUSED_RESULT
20814 static basic_json parse(InputType&& i,
20815 const parser_callback_t cb = nullptr,
20816 const bool allow_exceptions = true,
20817 const bool ignore_comments = false)
20818 {
20819 basic_json result;
20820 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
20821 return result;
20822 }
20823
20824 /// @brief deserialize from a pair of character iterators
20825 /// @sa https://json.nlohmann.me/api/basic_json/parse/
20826 template<typename IteratorType>
20827 JSON_HEDLEY_WARN_UNUSED_RESULT
20828 static basic_json parse(IteratorType first,
20829 IteratorType last,
20830 const parser_callback_t cb = nullptr,
20831 const bool allow_exceptions = true,
20832 const bool ignore_comments = false)
20833 {
20834 basic_json result;
20835 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
20836 return result;
20837 }
20838
20839 JSON_HEDLEY_WARN_UNUSED_RESULT
20840 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
20841 static basic_json parse(detail::span_input_adapter&& i,
20842 const parser_callback_t cb = nullptr,
20843 const bool allow_exceptions = true,
20844 const bool ignore_comments = false)
20845 {
20846 basic_json result;
20847 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
20848 return result;
20849 }
20850
20851 /// @brief check if the input is valid JSON
20852 /// @sa https://json.nlohmann.me/api/basic_json/accept/
20853 template<typename InputType>
20854 static bool accept(InputType&& i,
20855 const bool ignore_comments = false)
20856 {
20857 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
20858 }
20859
20860 /// @brief check if the input is valid JSON
20861 /// @sa https://json.nlohmann.me/api/basic_json/accept/
20862 template<typename IteratorType>
20863 static bool accept(IteratorType first, IteratorType last,
20864 const bool ignore_comments = false)
20865 {
20866 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
20867 }
20868
20869 JSON_HEDLEY_WARN_UNUSED_RESULT
20870 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
20871 static bool accept(detail::span_input_adapter&& i,
20872 const bool ignore_comments = false)
20873 {
20874 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
20875 }
20876
20877 /// @brief generate SAX events
20878 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
20879 template <typename InputType, typename SAX>
20880 JSON_HEDLEY_NON_NULL(2)
20881 static bool sax_parse(InputType&& i, SAX* sax,
20882 input_format_t format = input_format_t::json,
20883 const bool strict = true,
20884 const bool ignore_comments = false)
20885 {
20886 auto ia = detail::input_adapter(std::forward<InputType>(i));
20887 return format == input_format_t::json
20888 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
20889 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
20890 }
20891
20892 /// @brief generate SAX events
20893 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
20894 template<class IteratorType, class SAX>
20895 JSON_HEDLEY_NON_NULL(3)
20896 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
20897 input_format_t format = input_format_t::json,
20898 const bool strict = true,
20899 const bool ignore_comments = false)
20900 {
20901 auto ia = detail::input_adapter(std::move(first), std::move(last));
20902 return format == input_format_t::json
20903 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
20904 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
20905 }
20906
20907 /// @brief generate SAX events
20908 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
20909 /// @deprecated This function is deprecated since 3.8.0 and will be removed in
20910 /// version 4.0.0 of the library. Please use
20911 /// sax_parse(ptr, ptr + len) instead.
20912 template <typename SAX>
20913 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
20914 JSON_HEDLEY_NON_NULL(2)
20915 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
20916 input_format_t format = input_format_t::json,
20917 const bool strict = true,
20918 const bool ignore_comments = false)
20919 {
20920 auto ia = i.get();
20921 return format == input_format_t::json
20922 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
20923 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
20924 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
20925 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
20926 }
20927 #ifndef JSON_NO_IO
20928 /// @brief deserialize from stream
20929 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
20930 /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
20931 /// version 4.0.0 of the library. Please use
20932 /// operator>>(std::istream&, basic_json&) instead; that is,
20933 /// replace calls like `j << i;` with `i >> j;`.
20934 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
20935 friend std::istream& operator<<(basic_json& j, std::istream& i)
20936 {
20937 return operator>>(i, j);
20938 }
20939
20940 /// @brief deserialize from stream
20941 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
20942 friend std::istream& operator>>(std::istream& i, basic_json& j)
20943 {
20944 parser(detail::input_adapter(i)).parse(false, j);
20945 return i;
20946 }
20947 #endif // JSON_NO_IO
20948 /// @}
20949
20950 ///////////////////////////
20951 // convenience functions //
20952 ///////////////////////////
20953
20954 /// @brief return the type as string
20955 /// @sa https://json.nlohmann.me/api/basic_json/type_name/
20956 JSON_HEDLEY_RETURNS_NON_NULL
20957 const char* type_name() const noexcept
20958 {
20959 switch (m_type)
20960 {
20961 case value_t::null:
20962 return "null";
20963 case value_t::object:
20964 return "object";
20965 case value_t::array:
20966 return "array";
20967 case value_t::string:
20968 return "string";
20969 case value_t::boolean:
20970 return "boolean";
20971 case value_t::binary:
20972 return "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:
20978 default:
20979 return "number";
20980 }
20981 }
20982
20983
20984 JSON_PRIVATE_UNLESS_TESTED:
20985 //////////////////////
20986 // member variables //
20987 //////////////////////
20988
20989 /// the type of the current element
20990 value_t m_type = value_t::null;
20991
20992 /// the value of the current element
20993 json_value m_value = {};
20994
20995 #if JSON_DIAGNOSTICS
20996 /// a pointer to a parent value (for debugging purposes)
20997 basic_json* m_parent = nullptr;
20998 #endif
20999
21000 //////////////////////////////////////////
21001 // binary serialization/deserialization //
21002 //////////////////////////////////////////
21003
21004 /// @name binary serialization/deserialization support
21005 /// @{
21006
21007 public:
21008 /// @brief create a CBOR serialization of a given JSON value
21009 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
21010 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
21011 {
21012 std::vector<std::uint8_t> result;
21013 to_cbor(j, result);
21014 return result;
21015 }
21016
21017 /// @brief create a CBOR serialization of a given JSON value
21018 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
21019 static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
21020 {
21021 binary_writer<std::uint8_t>(o).write_cbor(j);
21022 }
21023
21024 /// @brief create a CBOR serialization of a given JSON value
21025 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
21026 static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
21027 {
21028 binary_writer<char>(o).write_cbor(j);
21029 }
21030
21031 /// @brief create a MessagePack serialization of a given JSON value
21032 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
21033 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
21034 {
21035 std::vector<std::uint8_t> result;
21036 to_msgpack(j, result);
21037 return result;
21038 }
21039
21040 /// @brief create a MessagePack serialization of a given JSON value
21041 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
21042 static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
21043 {
21044 binary_writer<std::uint8_t>(o).write_msgpack(j);
21045 }
21046
21047 /// @brief create a MessagePack serialization of a given JSON value
21048 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
21049 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
21050 {
21051 binary_writer<char>(o).write_msgpack(j);
21052 }
21053
21054 /// @brief create a UBJSON serialization of a given JSON value
21055 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
21056 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
21057 const bool use_size = false,
21058 const bool use_type = false)
21059 {
21060 std::vector<std::uint8_t> result;
21061 to_ubjson(j, result, use_size, use_type);
21062 return result;
21063 }
21064
21065 /// @brief create a UBJSON serialization of a given JSON value
21066 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
21067 static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
21068 const bool use_size = false, const bool use_type = false)
21069 {
21070 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
21071 }
21072
21073 /// @brief create a UBJSON serialization of a given JSON value
21074 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
21075 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
21076 const bool use_size = false, const bool use_type = false)
21077 {
21078 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
21079 }
21080
21081 /// @brief create a BSON serialization of a given JSON value
21082 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
21083 static std::vector<std::uint8_t> to_bson(const basic_json& j)
21084 {
21085 std::vector<std::uint8_t> result;
21086 to_bson(j, result);
21087 return result;
21088 }
21089
21090 /// @brief create a BSON serialization of a given JSON value
21091 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
21092 static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
21093 {
21094 binary_writer<std::uint8_t>(o).write_bson(j);
21095 }
21096
21097 /// @brief create a BSON serialization of a given JSON value
21098 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
21099 static void to_bson(const basic_json& j, detail::output_adapter<char> o)
21100 {
21101 binary_writer<char>(o).write_bson(j);
21102 }
21103
21104 /// @brief create a JSON value from an input in CBOR format
21105 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
21106 template<typename InputType>
21107 JSON_HEDLEY_WARN_UNUSED_RESULT
21108 static basic_json from_cbor(InputType&& i,
21109 const bool strict = true,
21110 const bool allow_exceptions = true,
21111 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
21112 {
21113 basic_json result;
21114 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21115 auto ia = detail::input_adapter(std::forward<InputType>(i));
21116 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
21117 return res ? result : basic_json(value_t::discarded);
21118 }
21119
21120 /// @brief create a JSON value from an input in CBOR format
21121 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
21122 template<typename IteratorType>
21123 JSON_HEDLEY_WARN_UNUSED_RESULT
21124 static basic_json from_cbor(IteratorType first, IteratorType last,
21125 const bool strict = true,
21126 const bool allow_exceptions = true,
21127 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
21128 {
21129 basic_json result;
21130 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21131 auto ia = detail::input_adapter(std::move(first), std::move(last));
21132 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
21133 return res ? result : basic_json(value_t::discarded);
21134 }
21135
21136 template<typename T>
21137 JSON_HEDLEY_WARN_UNUSED_RESULT
21138 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
21139 static basic_json from_cbor(const T* ptr, std::size_t len,
21140 const bool strict = true,
21141 const bool allow_exceptions = true,
21142 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
21143 {
21144 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
21145 }
21146
21147
21148 JSON_HEDLEY_WARN_UNUSED_RESULT
21149 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
21150 static basic_json from_cbor(detail::span_input_adapter&& i,
21151 const bool strict = true,
21152 const bool allow_exceptions = true,
21153 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
21154 {
21155 basic_json result;
21156 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21157 auto ia = i.get();
21158 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21159 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
21160 return res ? result : basic_json(value_t::discarded);
21161 }
21162
21163 /// @brief create a JSON value from an input in MessagePack format
21164 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
21165 template<typename InputType>
21166 JSON_HEDLEY_WARN_UNUSED_RESULT
21167 static basic_json from_msgpack(InputType&& i,
21168 const bool strict = true,
21169 const bool allow_exceptions = true)
21170 {
21171 basic_json result;
21172 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21173 auto ia = detail::input_adapter(std::forward<InputType>(i));
21174 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
21175 return res ? result : basic_json(value_t::discarded);
21176 }
21177
21178 /// @brief create a JSON value from an input in MessagePack format
21179 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
21180 template<typename IteratorType>
21181 JSON_HEDLEY_WARN_UNUSED_RESULT
21182 static basic_json from_msgpack(IteratorType first, IteratorType last,
21183 const bool strict = true,
21184 const bool allow_exceptions = true)
21185 {
21186 basic_json result;
21187 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21188 auto ia = detail::input_adapter(std::move(first), std::move(last));
21189 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
21190 return res ? result : basic_json(value_t::discarded);
21191 }
21192
21193 template<typename T>
21194 JSON_HEDLEY_WARN_UNUSED_RESULT
21195 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
21196 static basic_json from_msgpack(const T* ptr, std::size_t len,
21197 const bool strict = true,
21198 const bool allow_exceptions = true)
21199 {
21200 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
21201 }
21202
21203 JSON_HEDLEY_WARN_UNUSED_RESULT
21204 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
21205 static basic_json from_msgpack(detail::span_input_adapter&& i,
21206 const bool strict = true,
21207 const bool allow_exceptions = true)
21208 {
21209 basic_json result;
21210 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21211 auto ia = i.get();
21212 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21213 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
21214 return res ? result : basic_json(value_t::discarded);
21215 }
21216
21217 /// @brief create a JSON value from an input in UBJSON format
21218 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
21219 template<typename InputType>
21220 JSON_HEDLEY_WARN_UNUSED_RESULT
21221 static basic_json from_ubjson(InputType&& i,
21222 const bool strict = true,
21223 const bool allow_exceptions = true)
21224 {
21225 basic_json result;
21226 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21227 auto ia = detail::input_adapter(std::forward<InputType>(i));
21228 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
21229 return res ? result : basic_json(value_t::discarded);
21230 }
21231
21232 /// @brief create a JSON value from an input in UBJSON format
21233 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
21234 template<typename IteratorType>
21235 JSON_HEDLEY_WARN_UNUSED_RESULT
21236 static basic_json from_ubjson(IteratorType first, IteratorType last,
21237 const bool strict = true,
21238 const bool allow_exceptions = true)
21239 {
21240 basic_json result;
21241 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21242 auto ia = detail::input_adapter(std::move(first), std::move(last));
21243 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
21244 return res ? result : basic_json(value_t::discarded);
21245 }
21246
21247 template<typename T>
21248 JSON_HEDLEY_WARN_UNUSED_RESULT
21249 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
21250 static basic_json from_ubjson(const T* ptr, std::size_t len,
21251 const bool strict = true,
21252 const bool allow_exceptions = true)
21253 {
21254 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
21255 }
21256
21257 JSON_HEDLEY_WARN_UNUSED_RESULT
21258 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
21259 static basic_json from_ubjson(detail::span_input_adapter&& i,
21260 const bool strict = true,
21261 const bool allow_exceptions = true)
21262 {
21263 basic_json result;
21264 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21265 auto ia = i.get();
21266 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21267 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
21268 return res ? result : basic_json(value_t::discarded);
21269 }
21270
21271 /// @brief create a JSON value from an input in BSON format
21272 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
21273 template<typename InputType>
21274 JSON_HEDLEY_WARN_UNUSED_RESULT
21275 static basic_json from_bson(InputType&& i,
21276 const bool strict = true,
21277 const bool allow_exceptions = true)
21278 {
21279 basic_json result;
21280 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21281 auto ia = detail::input_adapter(std::forward<InputType>(i));
21282 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
21283 return res ? result : basic_json(value_t::discarded);
21284 }
21285
21286 /// @brief create a JSON value from an input in BSON format
21287 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
21288 template<typename IteratorType>
21289 JSON_HEDLEY_WARN_UNUSED_RESULT
21290 static basic_json from_bson(IteratorType first, IteratorType last,
21291 const bool strict = true,
21292 const bool allow_exceptions = true)
21293 {
21294 basic_json result;
21295 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21296 auto ia = detail::input_adapter(std::move(first), std::move(last));
21297 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
21298 return res ? result : basic_json(value_t::discarded);
21299 }
21300
21301 template<typename T>
21302 JSON_HEDLEY_WARN_UNUSED_RESULT
21303 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
21304 static basic_json from_bson(const T* ptr, std::size_t len,
21305 const bool strict = true,
21306 const bool allow_exceptions = true)
21307 {
21308 return from_bson(ptr, ptr + len, strict, allow_exceptions);
21309 }
21310
21311 JSON_HEDLEY_WARN_UNUSED_RESULT
21312 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
21313 static basic_json from_bson(detail::span_input_adapter&& i,
21314 const bool strict = true,
21315 const bool allow_exceptions = true)
21316 {
21317 basic_json result;
21318 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21319 auto ia = i.get();
21320 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21321 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
21322 return res ? result : basic_json(value_t::discarded);
21323 }
21324 /// @}
21325
21326 //////////////////////////
21327 // JSON Pointer support //
21328 //////////////////////////
21329
21330 /// @name JSON Pointer functions
21331 /// @{
21332
21333 /// @brief access specified element via JSON Pointer
21334 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21335 reference operator[](const json_pointer& ptr)
21336 {
21337 return ptr.get_unchecked(this);
21338 }
21339
21340 /// @brief access specified element via JSON Pointer
21341 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21342 const_reference operator[](const json_pointer& ptr) const
21343 {
21344 return ptr.get_unchecked(this);
21345 }
21346
21347 /// @brief access specified element via JSON Pointer
21348 /// @sa https://json.nlohmann.me/api/basic_json/at/
21349 reference at(const json_pointer& ptr)
21350 {
21351 return ptr.get_checked(this);
21352 }
21353
21354 /// @brief access specified element via JSON Pointer
21355 /// @sa https://json.nlohmann.me/api/basic_json/at/
21356 const_reference at(const json_pointer& ptr) const
21357 {
21358 return ptr.get_checked(this);
21359 }
21360
21361 /// @brief return flattened JSON value
21362 /// @sa https://json.nlohmann.me/api/basic_json/flatten/
21363 basic_json flatten() const
21364 {
21365 basic_json result(value_t::object);
21366 json_pointer::flatten("", *this, result);
21367 return result;
21368 }
21369
21370 /// @brief unflatten a previously flattened JSON value
21371 /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
21372 basic_json unflatten() const
21373 {
21374 return json_pointer::unflatten(*this);
21375 }
21376
21377 /// @}
21378
21379 //////////////////////////
21380 // JSON Patch functions //
21381 //////////////////////////
21382
21383 /// @name JSON Patch functions
21384 /// @{
21385
21386 /// @brief applies a JSON patch
21387 /// @sa https://json.nlohmann.me/api/basic_json/patch/
21388 basic_json patch(const basic_json& json_patch) const
21389 {
21390 // make a working copy to apply the patch to
21391 basic_json result = *this;
21392
21393 // the valid JSON Patch operations
21394 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
21395
21396 const auto get_op = [](const std::string & op)
21397 {
21398 if (op == "add")
21399 {
21400 return patch_operations::add;
21401 }
21402 if (op == "remove")
21403 {
21404 return patch_operations::remove;
21405 }
21406 if (op == "replace")
21407 {
21408 return patch_operations::replace;
21409 }
21410 if (op == "move")
21411 {
21412 return patch_operations::move;
21413 }
21414 if (op == "copy")
21415 {
21416 return patch_operations::copy;
21417 }
21418 if (op == "test")
21419 {
21420 return patch_operations::test;
21421 }
21422
21423 return patch_operations::invalid;
21424 };
21425
21426 // wrapper for "add" operation; add value at ptr
21427 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
21428 {
21429 // adding to the root of the target document means replacing it
21430 if (ptr.empty())
21431 {
21432 result = val;
21433 return;
21434 }
21435
21436 // make sure the top element of the pointer exists
21437 json_pointer top_pointer = ptr.top();
21438 if (top_pointer != ptr)
21439 {
21440 result.at(top_pointer);
21441 }
21442
21443 // get reference to parent of JSON pointer ptr
21444 const auto last_path = ptr.back();
21445 ptr.pop_back();
21446 basic_json& parent = result[ptr];
21447
21448 switch (parent.m_type)
21449 {
21450 case value_t::null:
21451 case value_t::object:
21452 {
21453 // use operator[] to add value
21454 parent[last_path] = val;
21455 break;
21456 }
21457
21458 case value_t::array:
21459 {
21460 if (last_path == "-")
21461 {
21462 // special case: append to back
21463 parent.push_back(val);
21464 }
21465 else
21466 {
21467 const auto idx = json_pointer::array_index(last_path);
21468 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
21469 {
21470 // avoid undefined behavior
21471 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", parent));
21472 }
21473
21474 // default case: insert add offset
21475 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
21476 }
21477 break;
21478 }
21479
21480 // if there exists a parent it cannot be primitive
21481 case value_t::string: // LCOV_EXCL_LINE
21482 case value_t::boolean: // LCOV_EXCL_LINE
21483 case value_t::number_integer: // LCOV_EXCL_LINE
21484 case value_t::number_unsigned: // LCOV_EXCL_LINE
21485 case value_t::number_float: // LCOV_EXCL_LINE
21486 case value_t::binary: // LCOV_EXCL_LINE
21487 case value_t::discarded: // LCOV_EXCL_LINE
21488 default: // LCOV_EXCL_LINE
21489 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
21490 }
21491 };
21492
21493 // wrapper for "remove" operation; remove value at ptr
21494 const auto operation_remove = [this, &result](json_pointer & ptr)
21495 {
21496 // get reference to parent of JSON pointer ptr
21497 const auto last_path = ptr.back();
21498 ptr.pop_back();
21499 basic_json& parent = result.at(ptr);
21500
21501 // remove child
21502 if (parent.is_object())
21503 {
21504 // perform range check
21505 auto it = parent.find(last_path);
21506 if (JSON_HEDLEY_LIKELY(it != parent.end()))
21507 {
21508 parent.erase(it);
21509 }
21510 else
21511 {
21512 JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", *this));
21513 }
21514 }
21515 else if (parent.is_array())
21516 {
21517 // note erase performs range check
21518 parent.erase(json_pointer::array_index(last_path));
21519 }
21520 };
21521
21522 // type check: top level value must be an array
21523 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
21524 {
21525 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", json_patch));
21526 }
21527
21528 // iterate and apply the operations
21529 for (const auto& val : json_patch)
21530 {
21531 // wrapper to get a value for an operation
21532 const auto get_value = [&val](const std::string & op,
21533 const std::string & member,
21534 bool string_type) -> basic_json &
21535 {
21536 // find value
21537 auto it = val.m_value.object->find(member);
21538
21539 // context-sensitive error message
21540 const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
21541
21542 // check if desired value is present
21543 if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
21544 {
21545 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
21546 JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", val));
21547 }
21548
21549 // check if result is of type string
21550 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
21551 {
21552 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
21553 JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", val));
21554 }
21555
21556 // no error: return value
21557 return it->second;
21558 };
21559
21560 // type check: every element of the array must be an object
21561 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
21562 {
21563 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", val));
21564 }
21565
21566 // collect mandatory members
21567 const auto op = get_value("op", "op", true).template get<std::string>();
21568 const auto path = get_value(op, "path", true).template get<std::string>();
21569 json_pointer ptr(path);
21570
21571 switch (get_op(op))
21572 {
21573 case patch_operations::add:
21574 {
21575 operation_add(ptr, get_value("add", "value", false));
21576 break;
21577 }
21578
21579 case patch_operations::remove:
21580 {
21581 operation_remove(ptr);
21582 break;
21583 }
21584
21585 case patch_operations::replace:
21586 {
21587 // the "path" location must exist - use at()
21588 result.at(ptr) = get_value("replace", "value", false);
21589 break;
21590 }
21591
21592 case patch_operations::move:
21593 {
21594 const auto from_path = get_value("move", "from", true).template get<std::string>();
21595 json_pointer from_ptr(from_path);
21596
21597 // the "from" location must exist - use at()
21598 basic_json v = result.at(from_ptr);
21599
21600 // The move operation is functionally identical to a
21601 // "remove" operation on the "from" location, followed
21602 // immediately by an "add" operation at the target
21603 // location with the value that was just removed.
21604 operation_remove(from_ptr);
21605 operation_add(ptr, v);
21606 break;
21607 }
21608
21609 case patch_operations::copy:
21610 {
21611 const auto from_path = get_value("copy", "from", true).template get<std::string>();
21612 const json_pointer from_ptr(from_path);
21613
21614 // the "from" location must exist - use at()
21615 basic_json v = result.at(from_ptr);
21616
21617 // The copy is functionally identical to an "add"
21618 // operation at the target location using the value
21619 // specified in the "from" member.
21620 operation_add(ptr, v);
21621 break;
21622 }
21623
21624 case patch_operations::test:
21625 {
21626 bool success = false;
21627 JSON_TRY
21628 {
21629 // check if "value" matches the one at "path"
21630 // the "path" location must exist - use at()
21631 success = (result.at(ptr) == get_value("test", "value", false));
21632 }
21633 JSON_INTERNAL_CATCH (out_of_range&)
21634 {
21635 // ignore out of range errors: success remains false
21636 }
21637
21638 // throw an exception if test fails
21639 if (JSON_HEDLEY_UNLIKELY(!success))
21640 {
21641 JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), val));
21642 }
21643
21644 break;
21645 }
21646
21647 case patch_operations::invalid:
21648 default:
21649 {
21650 // op must be "add", "remove", "replace", "move", "copy", or
21651 // "test"
21652 JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid", val));
21653 }
21654 }
21655 }
21656
21657 return result;
21658 }
21659
21660 /// @brief creates a diff as a JSON patch
21661 /// @sa https://json.nlohmann.me/api/basic_json/diff/
21662 JSON_HEDLEY_WARN_UNUSED_RESULT
21663 static basic_json diff(const basic_json& source, const basic_json& target,
21664 const std::string& path = "")
21665 {
21666 // the patch
21667 basic_json result(value_t::array);
21668
21669 // if the values are the same, return empty patch
21670 if (source == target)
21671 {
21672 return result;
21673 }
21674
21675 if (source.type() != target.type())
21676 {
21677 // different types: replace value
21678 result.push_back(
21679 {
21680 {"op", "replace"}, {"path", path}, {"value", target}
21681 });
21682 return result;
21683 }
21684
21685 switch (source.type())
21686 {
21687 case value_t::array:
21688 {
21689 // first pass: traverse common elements
21690 std::size_t i = 0;
21691 while (i < source.size() && i < target.size())
21692 {
21693 // recursive call to compare array values at index i
21694 auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
21695 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
21696 ++i;
21697 }
21698
21699 // We now reached the end of at least one array
21700 // in a second pass, traverse the remaining elements
21701
21702 // remove my remaining elements
21703 const auto end_index = static_cast<difference_type>(result.size());
21704 while (i < source.size())
21705 {
21706 // add operations in reverse order to avoid invalid
21707 // indices
21708 result.insert(result.begin() + end_index, object(
21709 {
21710 {"op", "remove"},
21711 {"path", path + "/" + std::to_string(i)}
21712 }));
21713 ++i;
21714 }
21715
21716 // add other remaining elements
21717 while (i < target.size())
21718 {
21719 result.push_back(
21720 {
21721 {"op", "add"},
21722 {"path", path + "/-"},
21723 {"value", target[i]}
21724 });
21725 ++i;
21726 }
21727
21728 break;
21729 }
21730
21731 case value_t::object:
21732 {
21733 // first pass: traverse this object's elements
21734 for (auto it = source.cbegin(); it != source.cend(); ++it)
21735 {
21736 // escape the key name to be used in a JSON patch
21737 const auto path_key = path + "/" + detail::escape(it.key());
21738
21739 if (target.find(it.key()) != target.end())
21740 {
21741 // recursive call to compare object values at key it
21742 auto temp_diff = diff(it.value(), target[it.key()], path_key);
21743 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
21744 }
21745 else
21746 {
21747 // found a key that is not in o -> remove it
21748 result.push_back(object(
21749 {
21750 {"op", "remove"}, {"path", path_key}
21751 }));
21752 }
21753 }
21754
21755 // second pass: traverse other object's elements
21756 for (auto it = target.cbegin(); it != target.cend(); ++it)
21757 {
21758 if (source.find(it.key()) == source.end())
21759 {
21760 // found a key that is not in this -> add it
21761 const auto path_key = path + "/" + detail::escape(it.key());
21762 result.push_back(
21763 {
21764 {"op", "add"}, {"path", path_key},
21765 {"value", it.value()}
21766 });
21767 }
21768 }
21769
21770 break;
21771 }
21772
21773 case value_t::null:
21774 case value_t::string:
21775 case value_t::boolean:
21776 case value_t::number_integer:
21777 case value_t::number_unsigned:
21778 case value_t::number_float:
21779 case value_t::binary:
21780 case value_t::discarded:
21781 default:
21782 {
21783 // both primitive type: replace value
21784 result.push_back(
21785 {
21786 {"op", "replace"}, {"path", path}, {"value", target}
21787 });
21788 break;
21789 }
21790 }
21791
21792 return result;
21793 }
21794
21795 /// @}
21796
21797 ////////////////////////////////
21798 // JSON Merge Patch functions //
21799 ////////////////////////////////
21800
21801 /// @name JSON Merge Patch functions
21802 /// @{
21803
21804 /// @brief applies a JSON Merge Patch
21805 /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
21806 void merge_patch(const basic_json& apply_patch)
21807 {
21808 if (apply_patch.is_object())
21809 {
21810 if (!is_object())
21811 {
21812 *this = object();
21813 }
21814 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
21815 {
21816 if (it.value().is_null())
21817 {
21818 erase(it.key());
21819 }
21820 else
21821 {
21822 operator[](it.key()).merge_patch(it.value());
21823 }
21824 }
21825 }
21826 else
21827 {
21828 *this = apply_patch;
21829 }
21830 }
21831
21832 /// @}
21833 };
21834
21835 /// @brief user-defined to_string function for JSON values
21836 /// @sa https://json.nlohmann.me/api/basic_json/to_string/
21837 NLOHMANN_BASIC_JSON_TPL_DECLARATION
21838 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
21839 {
21840 return j.dump();
21841 }
21842
21843 } // namespace nlohmann
21844
21845 ///////////////////////
21846 // nonmember support //
21847 ///////////////////////
21848
21849 namespace std // NOLINT(cert-dcl58-cpp)
21850 {
21851
21852 /// @brief hash value for JSON objects
21853 /// @sa https://json.nlohmann.me/api/basic_json/std_hash/
21854 NLOHMANN_BASIC_JSON_TPL_DECLARATION
21855 struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL>
21856 {
21857 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
21858 {
21859 return nlohmann::detail::hash(j);
21860 }
21861 };
21862
21863 // specialization for std::less<value_t>
21864 template<>
21865 struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
21866 {
21867 /*!
21868 @brief compare two value_t enum values
21869 @since version 3.0.0
21870 */
21871 bool operator()(nlohmann::detail::value_t lhs,
21872 nlohmann::detail::value_t rhs) const noexcept
21873 {
21874 return nlohmann::detail::operator<(lhs, rhs);
21875 }
21876 };
21877
21878 // C++20 prohibit function specialization in the std namespace.
21879 #ifndef JSON_HAS_CPP_20
21880
21881 /// @brief exchanges the values of two JSON objects
21882 /// @sa https://json.nlohmann.me/api/basic_json/std_swap/
21883 NLOHMANN_BASIC_JSON_TPL_DECLARATION
21884 inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name)
21885 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression)
21886 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
21887 {
21888 j1.swap(j2);
21889 }
21890
21891 #endif
21892
21893 } // namespace std
21894
21895 /// @brief user-defined string literal for JSON values
21896 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
21897 JSON_HEDLEY_NON_NULL(1)
21898 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
21899 {
21900 return nlohmann::json::parse(s, s + n);
21901 }
21902
21903 /// @brief user-defined string literal for JSON pointer
21904 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
21905 JSON_HEDLEY_NON_NULL(1)
21906 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
21907 {
21908 return nlohmann::json::json_pointer(std::string(s, n));
21909 }
21910
21911 // #include <nlohmann/detail/macro_unscope.hpp>
21912
21913
21914 // restore clang diagnostic settings
21915 #if defined(__clang__)
21916 #pragma clang diagnostic pop
21917 #endif
21918
21919 // clean up
21920 #undef JSON_ASSERT
21921 #undef JSON_INTERNAL_CATCH
21922 #undef JSON_CATCH
21923 #undef JSON_THROW
21924 #undef JSON_TRY
21925 #undef JSON_PRIVATE_UNLESS_TESTED
21926 #undef JSON_HAS_CPP_11
21927 #undef JSON_HAS_CPP_14
21928 #undef JSON_HAS_CPP_17
21929 #undef JSON_HAS_CPP_20
21930 #undef JSON_HAS_FILESYSTEM
21931 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
21932 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
21933 #undef NLOHMANN_BASIC_JSON_TPL
21934 #undef JSON_EXPLICIT
21935 #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
21936
21937 // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
21938
21939
21940 #undef JSON_HEDLEY_ALWAYS_INLINE
21941 #undef JSON_HEDLEY_ARM_VERSION
21942 #undef JSON_HEDLEY_ARM_VERSION_CHECK
21943 #undef JSON_HEDLEY_ARRAY_PARAM
21944 #undef JSON_HEDLEY_ASSUME
21945 #undef JSON_HEDLEY_BEGIN_C_DECLS
21946 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
21947 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
21948 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
21949 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
21950 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
21951 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
21952 #undef JSON_HEDLEY_CLANG_HAS_WARNING
21953 #undef JSON_HEDLEY_COMPCERT_VERSION
21954 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
21955 #undef JSON_HEDLEY_CONCAT
21956 #undef JSON_HEDLEY_CONCAT3
21957 #undef JSON_HEDLEY_CONCAT3_EX
21958 #undef JSON_HEDLEY_CONCAT_EX
21959 #undef JSON_HEDLEY_CONST
21960 #undef JSON_HEDLEY_CONSTEXPR
21961 #undef JSON_HEDLEY_CONST_CAST
21962 #undef JSON_HEDLEY_CPP_CAST
21963 #undef JSON_HEDLEY_CRAY_VERSION
21964 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
21965 #undef JSON_HEDLEY_C_DECL
21966 #undef JSON_HEDLEY_DEPRECATED
21967 #undef JSON_HEDLEY_DEPRECATED_FOR
21968 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
21969 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
21970 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
21971 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
21972 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
21973 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
21974 #undef JSON_HEDLEY_DIAGNOSTIC_POP
21975 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
21976 #undef JSON_HEDLEY_DMC_VERSION
21977 #undef JSON_HEDLEY_DMC_VERSION_CHECK
21978 #undef JSON_HEDLEY_EMPTY_BASES
21979 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
21980 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
21981 #undef JSON_HEDLEY_END_C_DECLS
21982 #undef JSON_HEDLEY_FLAGS
21983 #undef JSON_HEDLEY_FLAGS_CAST
21984 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
21985 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
21986 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
21987 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
21988 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
21989 #undef JSON_HEDLEY_GCC_HAS_FEATURE
21990 #undef JSON_HEDLEY_GCC_HAS_WARNING
21991 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
21992 #undef JSON_HEDLEY_GCC_VERSION
21993 #undef JSON_HEDLEY_GCC_VERSION_CHECK
21994 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
21995 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
21996 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
21997 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
21998 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
21999 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
22000 #undef JSON_HEDLEY_GNUC_HAS_WARNING
22001 #undef JSON_HEDLEY_GNUC_VERSION
22002 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
22003 #undef JSON_HEDLEY_HAS_ATTRIBUTE
22004 #undef JSON_HEDLEY_HAS_BUILTIN
22005 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
22006 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
22007 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
22008 #undef JSON_HEDLEY_HAS_EXTENSION
22009 #undef JSON_HEDLEY_HAS_FEATURE
22010 #undef JSON_HEDLEY_HAS_WARNING
22011 #undef JSON_HEDLEY_IAR_VERSION
22012 #undef JSON_HEDLEY_IAR_VERSION_CHECK
22013 #undef JSON_HEDLEY_IBM_VERSION
22014 #undef JSON_HEDLEY_IBM_VERSION_CHECK
22015 #undef JSON_HEDLEY_IMPORT
22016 #undef JSON_HEDLEY_INLINE
22017 #undef JSON_HEDLEY_INTEL_CL_VERSION
22018 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
22019 #undef JSON_HEDLEY_INTEL_VERSION
22020 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
22021 #undef JSON_HEDLEY_IS_CONSTANT
22022 #undef JSON_HEDLEY_IS_CONSTEXPR_
22023 #undef JSON_HEDLEY_LIKELY
22024 #undef JSON_HEDLEY_MALLOC
22025 #undef JSON_HEDLEY_MCST_LCC_VERSION
22026 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
22027 #undef JSON_HEDLEY_MESSAGE
22028 #undef JSON_HEDLEY_MSVC_VERSION
22029 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
22030 #undef JSON_HEDLEY_NEVER_INLINE
22031 #undef JSON_HEDLEY_NON_NULL
22032 #undef JSON_HEDLEY_NO_ESCAPE
22033 #undef JSON_HEDLEY_NO_RETURN
22034 #undef JSON_HEDLEY_NO_THROW
22035 #undef JSON_HEDLEY_NULL
22036 #undef JSON_HEDLEY_PELLES_VERSION
22037 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
22038 #undef JSON_HEDLEY_PGI_VERSION
22039 #undef JSON_HEDLEY_PGI_VERSION_CHECK
22040 #undef JSON_HEDLEY_PREDICT
22041 #undef JSON_HEDLEY_PRINTF_FORMAT
22042 #undef JSON_HEDLEY_PRIVATE
22043 #undef JSON_HEDLEY_PUBLIC
22044 #undef JSON_HEDLEY_PURE
22045 #undef JSON_HEDLEY_REINTERPRET_CAST
22046 #undef JSON_HEDLEY_REQUIRE
22047 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
22048 #undef JSON_HEDLEY_REQUIRE_MSG
22049 #undef JSON_HEDLEY_RESTRICT
22050 #undef JSON_HEDLEY_RETURNS_NON_NULL
22051 #undef JSON_HEDLEY_SENTINEL
22052 #undef JSON_HEDLEY_STATIC_ASSERT
22053 #undef JSON_HEDLEY_STATIC_CAST
22054 #undef JSON_HEDLEY_STRINGIFY
22055 #undef JSON_HEDLEY_STRINGIFY_EX
22056 #undef JSON_HEDLEY_SUNPRO_VERSION
22057 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
22058 #undef JSON_HEDLEY_TINYC_VERSION
22059 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
22060 #undef JSON_HEDLEY_TI_ARMCL_VERSION
22061 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
22062 #undef JSON_HEDLEY_TI_CL2000_VERSION
22063 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
22064 #undef JSON_HEDLEY_TI_CL430_VERSION
22065 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
22066 #undef JSON_HEDLEY_TI_CL6X_VERSION
22067 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
22068 #undef JSON_HEDLEY_TI_CL7X_VERSION
22069 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
22070 #undef JSON_HEDLEY_TI_CLPRU_VERSION
22071 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
22072 #undef JSON_HEDLEY_TI_VERSION
22073 #undef JSON_HEDLEY_TI_VERSION_CHECK
22074 #undef JSON_HEDLEY_UNAVAILABLE
22075 #undef JSON_HEDLEY_UNLIKELY
22076 #undef JSON_HEDLEY_UNPREDICTABLE
22077 #undef JSON_HEDLEY_UNREACHABLE
22078 #undef JSON_HEDLEY_UNREACHABLE_RETURN
22079 #undef JSON_HEDLEY_VERSION
22080 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
22081 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
22082 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
22083 #undef JSON_HEDLEY_VERSION_ENCODE
22084 #undef JSON_HEDLEY_WARNING
22085 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
22086 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
22087 #undef JSON_HEDLEY_FALL_THROUGH
22088
22089
22090
22091 #endif // INCLUDE_NLOHMANN_JSON_HPP_
This page took 0.491563 seconds and 4 git commands to generate.