xref: /aosp_15_r20/external/ublksrv/include/nlohmann/json.hpp (revision 94c4a1e103eb1715230460aab379dff275992c20)
1 //     __ _____ _____ _____
2 //  __|  |   __|     |   | |  JSON for Modern C++
3 // |  |  |__   |  |  | | | |  version 3.10.5
4 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5 //
6 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7 // SPDX-License-Identifier: MIT
8 
9 /****************************************************************************\
10  * Note on documentation: The source files contain links to the online      *
11  * documentation of the public API at https://json.nlohmann.me. This URL    *
12  * contains the most recent documentation and should also be applicable to  *
13  * previous versions; documentation for deprecated functions is not         *
14  * removed, but marked deprecated. See "Generate documentation" section in  *
15  * file docs/README.md.                                                     *
16 \****************************************************************************/
17 
18 #ifndef INCLUDE_NLOHMANN_JSON_HPP_
19 #define INCLUDE_NLOHMANN_JSON_HPP_
20 
21 #ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
22     #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
23         #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 10 || NLOHMANN_JSON_VERSION_PATCH != 5
24             #warning "Already included a different version of the library!"
25         #endif
26     #endif
27 #endif
28 
29 #define NLOHMANN_JSON_VERSION_MAJOR 3   // NOLINT(modernize-macro-to-enum)
30 #define NLOHMANN_JSON_VERSION_MINOR 10  // NOLINT(modernize-macro-to-enum)
31 #define NLOHMANN_JSON_VERSION_PATCH 5   // NOLINT(modernize-macro-to-enum)
32 
33 #include <algorithm> // all_of, find, for_each
34 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
35 #include <functional> // hash, less
36 #include <initializer_list> // initializer_list
37 #ifndef JSON_NO_IO
38     #include <iosfwd> // istream, ostream
39 #endif  // JSON_NO_IO
40 #include <iterator> // random_access_iterator_tag
41 #include <memory> // unique_ptr
42 #include <numeric> // accumulate
43 #include <string> // string, stoi, to_string
44 #include <utility> // declval, forward, move, pair, swap
45 #include <vector> // vector
46 
47 // #include <nlohmann/adl_serializer.hpp>
48 //     __ _____ _____ _____
49 //  __|  |   __|     |   | |  JSON for Modern C++
50 // |  |  |__   |  |  | | | |  version 3.10.5
51 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
52 //
53 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
54 // SPDX-License-Identifier: MIT
55 
56 
57 
58 #include <type_traits>
59 #include <utility>
60 
61 // #include <nlohmann/detail/conversions/from_json.hpp>
62 //     __ _____ _____ _____
63 //  __|  |   __|     |   | |  JSON for Modern C++
64 // |  |  |__   |  |  | | | |  version 3.10.5
65 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
66 //
67 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
68 // SPDX-License-Identifier: MIT
69 
70 
71 
72 #include <algorithm> // transform
73 #include <array> // array
74 #include <forward_list> // forward_list
75 #include <iterator> // inserter, front_inserter, end
76 #include <map> // map
77 #include <string> // string
78 #include <tuple> // tuple, make_tuple
79 #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
80 #include <unordered_map> // unordered_map
81 #include <utility> // pair, declval
82 #include <valarray> // valarray
83 
84 // #include <nlohmann/detail/exceptions.hpp>
85 //     __ _____ _____ _____
86 //  __|  |   __|     |   | |  JSON for Modern C++
87 // |  |  |__   |  |  | | | |  version 3.10.5
88 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
89 //
90 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
91 // SPDX-License-Identifier: MIT
92 
93 
94 
95 #include <cstddef> // nullptr_t
96 #include <exception> // exception
97 #include <stdexcept> // runtime_error
98 #include <string> // to_string
99 #include <vector> // vector
100 
101 // #include <nlohmann/detail/value_t.hpp>
102 //     __ _____ _____ _____
103 //  __|  |   __|     |   | |  JSON for Modern C++
104 // |  |  |__   |  |  | | | |  version 3.10.5
105 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
106 //
107 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
108 // SPDX-License-Identifier: MIT
109 
110 
111 
112 #include <array> // array
113 #include <cstddef> // size_t
114 #include <cstdint> // uint8_t
115 #include <string> // string
116 
117 // #include <nlohmann/detail/macro_scope.hpp>
118 //     __ _____ _____ _____
119 //  __|  |   __|     |   | |  JSON for Modern C++
120 // |  |  |__   |  |  | | | |  version 3.10.5
121 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
122 //
123 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
124 // SPDX-License-Identifier: MIT
125 
126 
127 
128 #include <utility> // declval, pair
129 // #include <nlohmann/thirdparty/hedley/hedley.hpp>
130 
131 
132 //     __ _____ _____ _____
133 //  __|  |   __|     |   | |  JSON for Modern C++
134 // |  |  |__   |  |  | | | |  version 3.10.5
135 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
136 //
137 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
138 // SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <[email protected]>
139 // SPDX-License-Identifier: MIT
140 
141 /* Hedley - https://nemequ.github.io/hedley
142  * Created by Evan Nemerson <[email protected]>
143  */
144 
145 #if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
146 #if defined(JSON_HEDLEY_VERSION)
147     #undef JSON_HEDLEY_VERSION
148 #endif
149 #define JSON_HEDLEY_VERSION 15
150 
151 #if defined(JSON_HEDLEY_STRINGIFY_EX)
152     #undef JSON_HEDLEY_STRINGIFY_EX
153 #endif
154 #define JSON_HEDLEY_STRINGIFY_EX(x) #x
155 
156 #if defined(JSON_HEDLEY_STRINGIFY)
157     #undef JSON_HEDLEY_STRINGIFY
158 #endif
159 #define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
160 
161 #if defined(JSON_HEDLEY_CONCAT_EX)
162     #undef JSON_HEDLEY_CONCAT_EX
163 #endif
164 #define JSON_HEDLEY_CONCAT_EX(a,b) a##b
165 
166 #if defined(JSON_HEDLEY_CONCAT)
167     #undef JSON_HEDLEY_CONCAT
168 #endif
169 #define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
170 
171 #if defined(JSON_HEDLEY_CONCAT3_EX)
172     #undef JSON_HEDLEY_CONCAT3_EX
173 #endif
174 #define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
175 
176 #if defined(JSON_HEDLEY_CONCAT3)
177     #undef JSON_HEDLEY_CONCAT3
178 #endif
179 #define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
180 
181 #if defined(JSON_HEDLEY_VERSION_ENCODE)
182     #undef JSON_HEDLEY_VERSION_ENCODE
183 #endif
184 #define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
185 
186 #if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
187     #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
188 #endif
189 #define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
190 
191 #if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
192     #undef JSON_HEDLEY_VERSION_DECODE_MINOR
193 #endif
194 #define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
195 
196 #if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
197     #undef JSON_HEDLEY_VERSION_DECODE_REVISION
198 #endif
199 #define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
200 
201 #if defined(JSON_HEDLEY_GNUC_VERSION)
202     #undef JSON_HEDLEY_GNUC_VERSION
203 #endif
204 #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
205     #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
206 #elif defined(__GNUC__)
207     #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
208 #endif
209 
210 #if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
211     #undef JSON_HEDLEY_GNUC_VERSION_CHECK
212 #endif
213 #if defined(JSON_HEDLEY_GNUC_VERSION)
214     #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
215 #else
216     #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
217 #endif
218 
219 #if defined(JSON_HEDLEY_MSVC_VERSION)
220     #undef JSON_HEDLEY_MSVC_VERSION
221 #endif
222 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
223     #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
224 #elif defined(_MSC_FULL_VER) && !defined(__ICL)
225     #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
226 #elif defined(_MSC_VER) && !defined(__ICL)
227     #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
228 #endif
229 
230 #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
231     #undef JSON_HEDLEY_MSVC_VERSION_CHECK
232 #endif
233 #if !defined(JSON_HEDLEY_MSVC_VERSION)
234     #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
235 #elif defined(_MSC_VER) && (_MSC_VER >= 1400)
236     #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
237 #elif defined(_MSC_VER) && (_MSC_VER >= 1200)
238     #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
239 #else
240     #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
241 #endif
242 
243 #if defined(JSON_HEDLEY_INTEL_VERSION)
244     #undef JSON_HEDLEY_INTEL_VERSION
245 #endif
246 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
247     #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
248 #elif defined(__INTEL_COMPILER) && !defined(__ICL)
249     #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
250 #endif
251 
252 #if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
253     #undef JSON_HEDLEY_INTEL_VERSION_CHECK
254 #endif
255 #if defined(JSON_HEDLEY_INTEL_VERSION)
256     #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
257 #else
258     #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
259 #endif
260 
261 #if defined(JSON_HEDLEY_INTEL_CL_VERSION)
262     #undef JSON_HEDLEY_INTEL_CL_VERSION
263 #endif
264 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
265     #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
266 #endif
267 
268 #if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
269     #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
270 #endif
271 #if defined(JSON_HEDLEY_INTEL_CL_VERSION)
272     #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
273 #else
274     #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
275 #endif
276 
277 #if defined(JSON_HEDLEY_PGI_VERSION)
278     #undef JSON_HEDLEY_PGI_VERSION
279 #endif
280 #if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
281     #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
282 #endif
283 
284 #if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
285     #undef JSON_HEDLEY_PGI_VERSION_CHECK
286 #endif
287 #if defined(JSON_HEDLEY_PGI_VERSION)
288     #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
289 #else
290     #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
291 #endif
292 
293 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
294     #undef JSON_HEDLEY_SUNPRO_VERSION
295 #endif
296 #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
297     #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)
298 #elif defined(__SUNPRO_C)
299     #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
300 #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
301     #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)
302 #elif defined(__SUNPRO_CC)
303     #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
304 #endif
305 
306 #if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
307     #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
308 #endif
309 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
310     #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
311 #else
312     #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
313 #endif
314 
315 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
316     #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
317 #endif
318 #if defined(__EMSCRIPTEN__)
319     #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
320 #endif
321 
322 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
323     #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
324 #endif
325 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
326     #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
327 #else
328     #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
329 #endif
330 
331 #if defined(JSON_HEDLEY_ARM_VERSION)
332     #undef JSON_HEDLEY_ARM_VERSION
333 #endif
334 #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
335     #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
336 #elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
337     #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
338 #endif
339 
340 #if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
341     #undef JSON_HEDLEY_ARM_VERSION_CHECK
342 #endif
343 #if defined(JSON_HEDLEY_ARM_VERSION)
344     #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
345 #else
346     #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
347 #endif
348 
349 #if defined(JSON_HEDLEY_IBM_VERSION)
350     #undef JSON_HEDLEY_IBM_VERSION
351 #endif
352 #if defined(__ibmxl__)
353     #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
354 #elif defined(__xlC__) && defined(__xlC_ver__)
355     #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
356 #elif defined(__xlC__)
357     #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
358 #endif
359 
360 #if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
361     #undef JSON_HEDLEY_IBM_VERSION_CHECK
362 #endif
363 #if defined(JSON_HEDLEY_IBM_VERSION)
364     #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
365 #else
366     #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
367 #endif
368 
369 #if defined(JSON_HEDLEY_TI_VERSION)
370     #undef JSON_HEDLEY_TI_VERSION
371 #endif
372 #if \
373     defined(__TI_COMPILER_VERSION__) && \
374     ( \
375       defined(__TMS470__) || defined(__TI_ARM__) || \
376       defined(__MSP430__) || \
377       defined(__TMS320C2000__) \
378     )
379 #if (__TI_COMPILER_VERSION__ >= 16000000)
380     #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
381 #endif
382 #endif
383 
384 #if defined(JSON_HEDLEY_TI_VERSION_CHECK)
385     #undef JSON_HEDLEY_TI_VERSION_CHECK
386 #endif
387 #if defined(JSON_HEDLEY_TI_VERSION)
388     #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
389 #else
390     #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
391 #endif
392 
393 #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
394     #undef JSON_HEDLEY_TI_CL2000_VERSION
395 #endif
396 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
397     #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
398 #endif
399 
400 #if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
401     #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
402 #endif
403 #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
404     #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
405 #else
406     #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
407 #endif
408 
409 #if defined(JSON_HEDLEY_TI_CL430_VERSION)
410     #undef JSON_HEDLEY_TI_CL430_VERSION
411 #endif
412 #if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
413     #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
414 #endif
415 
416 #if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
417     #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
418 #endif
419 #if defined(JSON_HEDLEY_TI_CL430_VERSION)
420     #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
421 #else
422     #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
423 #endif
424 
425 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
426     #undef JSON_HEDLEY_TI_ARMCL_VERSION
427 #endif
428 #if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
429     #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
430 #endif
431 
432 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
433     #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
434 #endif
435 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
436     #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
437 #else
438     #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
439 #endif
440 
441 #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
442     #undef JSON_HEDLEY_TI_CL6X_VERSION
443 #endif
444 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
445     #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
446 #endif
447 
448 #if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
449     #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
450 #endif
451 #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
452     #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
453 #else
454     #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
455 #endif
456 
457 #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
458     #undef JSON_HEDLEY_TI_CL7X_VERSION
459 #endif
460 #if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
461     #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
462 #endif
463 
464 #if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
465     #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
466 #endif
467 #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
468     #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
469 #else
470     #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
471 #endif
472 
473 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
474     #undef JSON_HEDLEY_TI_CLPRU_VERSION
475 #endif
476 #if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
477     #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
478 #endif
479 
480 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
481     #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
482 #endif
483 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
484     #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
485 #else
486     #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
487 #endif
488 
489 #if defined(JSON_HEDLEY_CRAY_VERSION)
490     #undef JSON_HEDLEY_CRAY_VERSION
491 #endif
492 #if defined(_CRAYC)
493     #if defined(_RELEASE_PATCHLEVEL)
494         #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
495     #else
496         #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
497     #endif
498 #endif
499 
500 #if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
501     #undef JSON_HEDLEY_CRAY_VERSION_CHECK
502 #endif
503 #if defined(JSON_HEDLEY_CRAY_VERSION)
504     #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
505 #else
506     #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
507 #endif
508 
509 #if defined(JSON_HEDLEY_IAR_VERSION)
510     #undef JSON_HEDLEY_IAR_VERSION
511 #endif
512 #if defined(__IAR_SYSTEMS_ICC__)
513     #if __VER__ > 1000
514         #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
515     #else
516         #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
517     #endif
518 #endif
519 
520 #if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
521     #undef JSON_HEDLEY_IAR_VERSION_CHECK
522 #endif
523 #if defined(JSON_HEDLEY_IAR_VERSION)
524     #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
525 #else
526     #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
527 #endif
528 
529 #if defined(JSON_HEDLEY_TINYC_VERSION)
530     #undef JSON_HEDLEY_TINYC_VERSION
531 #endif
532 #if defined(__TINYC__)
533     #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
534 #endif
535 
536 #if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
537     #undef JSON_HEDLEY_TINYC_VERSION_CHECK
538 #endif
539 #if defined(JSON_HEDLEY_TINYC_VERSION)
540     #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
541 #else
542     #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
543 #endif
544 
545 #if defined(JSON_HEDLEY_DMC_VERSION)
546     #undef JSON_HEDLEY_DMC_VERSION
547 #endif
548 #if defined(__DMC__)
549     #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
550 #endif
551 
552 #if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
553     #undef JSON_HEDLEY_DMC_VERSION_CHECK
554 #endif
555 #if defined(JSON_HEDLEY_DMC_VERSION)
556     #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
557 #else
558     #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
559 #endif
560 
561 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
562     #undef JSON_HEDLEY_COMPCERT_VERSION
563 #endif
564 #if defined(__COMPCERT_VERSION__)
565     #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
566 #endif
567 
568 #if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
569     #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
570 #endif
571 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
572     #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
573 #else
574     #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
575 #endif
576 
577 #if defined(JSON_HEDLEY_PELLES_VERSION)
578     #undef JSON_HEDLEY_PELLES_VERSION
579 #endif
580 #if defined(__POCC__)
581     #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
582 #endif
583 
584 #if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
585     #undef JSON_HEDLEY_PELLES_VERSION_CHECK
586 #endif
587 #if defined(JSON_HEDLEY_PELLES_VERSION)
588     #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
589 #else
590     #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
591 #endif
592 
593 #if defined(JSON_HEDLEY_MCST_LCC_VERSION)
594     #undef JSON_HEDLEY_MCST_LCC_VERSION
595 #endif
596 #if defined(__LCC__) && defined(__LCC_MINOR__)
597     #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
598 #endif
599 
600 #if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
601     #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
602 #endif
603 #if defined(JSON_HEDLEY_MCST_LCC_VERSION)
604     #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
605 #else
606     #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
607 #endif
608 
609 #if defined(JSON_HEDLEY_GCC_VERSION)
610     #undef JSON_HEDLEY_GCC_VERSION
611 #endif
612 #if \
613     defined(JSON_HEDLEY_GNUC_VERSION) && \
614     !defined(__clang__) && \
615     !defined(JSON_HEDLEY_INTEL_VERSION) && \
616     !defined(JSON_HEDLEY_PGI_VERSION) && \
617     !defined(JSON_HEDLEY_ARM_VERSION) && \
618     !defined(JSON_HEDLEY_CRAY_VERSION) && \
619     !defined(JSON_HEDLEY_TI_VERSION) && \
620     !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
621     !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
622     !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
623     !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
624     !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
625     !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
626     !defined(__COMPCERT__) && \
627     !defined(JSON_HEDLEY_MCST_LCC_VERSION)
628     #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
629 #endif
630 
631 #if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
632     #undef JSON_HEDLEY_GCC_VERSION_CHECK
633 #endif
634 #if defined(JSON_HEDLEY_GCC_VERSION)
635     #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
636 #else
637     #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
638 #endif
639 
640 #if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
641     #undef JSON_HEDLEY_HAS_ATTRIBUTE
642 #endif
643 #if \
644   defined(__has_attribute) && \
645   ( \
646     (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
647   )
648 #  define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
649 #else
650 #  define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
651 #endif
652 
653 #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
654     #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
655 #endif
656 #if defined(__has_attribute)
657     #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
658 #else
659     #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
660 #endif
661 
662 #if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
663     #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
664 #endif
665 #if defined(__has_attribute)
666     #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
667 #else
668     #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
669 #endif
670 
671 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
672     #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
673 #endif
674 #if \
675     defined(__has_cpp_attribute) && \
676     defined(__cplusplus) && \
677     (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
678     #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
679 #else
680     #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
681 #endif
682 
683 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
684     #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
685 #endif
686 #if !defined(__cplusplus) || !defined(__has_cpp_attribute)
687     #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
688 #elif \
689     !defined(JSON_HEDLEY_PGI_VERSION) && \
690     !defined(JSON_HEDLEY_IAR_VERSION) && \
691     (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
692     (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
693     #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
694 #else
695     #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
696 #endif
697 
698 #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
699     #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
700 #endif
701 #if defined(__has_cpp_attribute) && defined(__cplusplus)
702     #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
703 #else
704     #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
705 #endif
706 
707 #if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
708     #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
709 #endif
710 #if defined(__has_cpp_attribute) && defined(__cplusplus)
711     #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
712 #else
713     #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
714 #endif
715 
716 #if defined(JSON_HEDLEY_HAS_BUILTIN)
717     #undef JSON_HEDLEY_HAS_BUILTIN
718 #endif
719 #if defined(__has_builtin)
720     #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
721 #else
722     #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
723 #endif
724 
725 #if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
726     #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
727 #endif
728 #if defined(__has_builtin)
729     #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
730 #else
731     #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
732 #endif
733 
734 #if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
735     #undef JSON_HEDLEY_GCC_HAS_BUILTIN
736 #endif
737 #if defined(__has_builtin)
738     #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
739 #else
740     #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
741 #endif
742 
743 #if defined(JSON_HEDLEY_HAS_FEATURE)
744     #undef JSON_HEDLEY_HAS_FEATURE
745 #endif
746 #if defined(__has_feature)
747     #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
748 #else
749     #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
750 #endif
751 
752 #if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
753     #undef JSON_HEDLEY_GNUC_HAS_FEATURE
754 #endif
755 #if defined(__has_feature)
756     #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
757 #else
758     #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
759 #endif
760 
761 #if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
762     #undef JSON_HEDLEY_GCC_HAS_FEATURE
763 #endif
764 #if defined(__has_feature)
765     #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
766 #else
767     #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
768 #endif
769 
770 #if defined(JSON_HEDLEY_HAS_EXTENSION)
771     #undef JSON_HEDLEY_HAS_EXTENSION
772 #endif
773 #if defined(__has_extension)
774     #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
775 #else
776     #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
777 #endif
778 
779 #if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
780     #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
781 #endif
782 #if defined(__has_extension)
783     #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
784 #else
785     #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
786 #endif
787 
788 #if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
789     #undef JSON_HEDLEY_GCC_HAS_EXTENSION
790 #endif
791 #if defined(__has_extension)
792     #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
793 #else
794     #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
795 #endif
796 
797 #if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
798     #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
799 #endif
800 #if defined(__has_declspec_attribute)
801     #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
802 #else
803     #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
804 #endif
805 
806 #if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
807     #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
808 #endif
809 #if defined(__has_declspec_attribute)
810     #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
811 #else
812     #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
813 #endif
814 
815 #if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
816     #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
817 #endif
818 #if defined(__has_declspec_attribute)
819     #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
820 #else
821     #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
822 #endif
823 
824 #if defined(JSON_HEDLEY_HAS_WARNING)
825     #undef JSON_HEDLEY_HAS_WARNING
826 #endif
827 #if defined(__has_warning)
828     #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
829 #else
830     #define JSON_HEDLEY_HAS_WARNING(warning) (0)
831 #endif
832 
833 #if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
834     #undef JSON_HEDLEY_GNUC_HAS_WARNING
835 #endif
836 #if defined(__has_warning)
837     #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
838 #else
839     #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
840 #endif
841 
842 #if defined(JSON_HEDLEY_GCC_HAS_WARNING)
843     #undef JSON_HEDLEY_GCC_HAS_WARNING
844 #endif
845 #if defined(__has_warning)
846     #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
847 #else
848     #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
849 #endif
850 
851 #if \
852     (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
853     defined(__clang__) || \
854     JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
855     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
856     JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
857     JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
858     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
859     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
860     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
861     JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
862     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
863     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
864     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
865     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
866     JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
867     JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
868     JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
869     (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
870     #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
871 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
872     #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
873 #else
874     #define JSON_HEDLEY_PRAGMA(value)
875 #endif
876 
877 #if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
878     #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
879 #endif
880 #if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
881     #undef JSON_HEDLEY_DIAGNOSTIC_POP
882 #endif
883 #if defined(__clang__)
884     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
885     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
886 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
887     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
888     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
889 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
890     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
891     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
892 #elif \
893     JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
894     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
895     #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
896     #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
897 #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
898     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
899     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
900 #elif \
901     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
902     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
903     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
904     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
905     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
906     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
907     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
908     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
909 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
910     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
911     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
912 #else
913     #define JSON_HEDLEY_DIAGNOSTIC_PUSH
914     #define JSON_HEDLEY_DIAGNOSTIC_POP
915 #endif
916 
917 /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
918    HEDLEY INTERNAL USE ONLY.  API subject to change without notice. */
919 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
920     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
921 #endif
922 #if defined(__cplusplus)
923 #  if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
924 #    if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
925 #      if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
926 #        define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
927     JSON_HEDLEY_DIAGNOSTIC_PUSH \
928     _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
929     _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
930     _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
931     xpr \
932     JSON_HEDLEY_DIAGNOSTIC_POP
933 #      else
934 #        define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
935     JSON_HEDLEY_DIAGNOSTIC_PUSH \
936     _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
937     _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
938     xpr \
939     JSON_HEDLEY_DIAGNOSTIC_POP
940 #      endif
941 #    else
942 #      define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
943     JSON_HEDLEY_DIAGNOSTIC_PUSH \
944     _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
945     xpr \
946     JSON_HEDLEY_DIAGNOSTIC_POP
947 #    endif
948 #  endif
949 #endif
950 #if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
951     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
952 #endif
953 
954 #if defined(JSON_HEDLEY_CONST_CAST)
955     #undef JSON_HEDLEY_CONST_CAST
956 #endif
957 #if defined(__cplusplus)
958 #  define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
959 #elif \
960   JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
961   JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
962   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
963 #  define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
964         JSON_HEDLEY_DIAGNOSTIC_PUSH \
965         JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
966         ((T) (expr)); \
967         JSON_HEDLEY_DIAGNOSTIC_POP \
968     }))
969 #else
970 #  define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
971 #endif
972 
973 #if defined(JSON_HEDLEY_REINTERPRET_CAST)
974     #undef JSON_HEDLEY_REINTERPRET_CAST
975 #endif
976 #if defined(__cplusplus)
977     #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
978 #else
979     #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
980 #endif
981 
982 #if defined(JSON_HEDLEY_STATIC_CAST)
983     #undef JSON_HEDLEY_STATIC_CAST
984 #endif
985 #if defined(__cplusplus)
986     #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
987 #else
988     #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
989 #endif
990 
991 #if defined(JSON_HEDLEY_CPP_CAST)
992     #undef JSON_HEDLEY_CPP_CAST
993 #endif
994 #if defined(__cplusplus)
995 #  if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
996 #    define JSON_HEDLEY_CPP_CAST(T, expr) \
997     JSON_HEDLEY_DIAGNOSTIC_PUSH \
998     _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
999     ((T) (expr)) \
1000     JSON_HEDLEY_DIAGNOSTIC_POP
1001 #  elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1002 #    define JSON_HEDLEY_CPP_CAST(T, expr) \
1003     JSON_HEDLEY_DIAGNOSTIC_PUSH \
1004     _Pragma("diag_suppress=Pe137") \
1005     JSON_HEDLEY_DIAGNOSTIC_POP
1006 #  else
1007 #    define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1008 #  endif
1009 #else
1010 #  define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1011 #endif
1012 
1013 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1014     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1015 #endif
1016 #if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1017     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1018 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1019     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1020 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1021     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1022 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1023     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1024 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1025     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1026 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1027     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1028 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1029     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1030 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1031     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1032 #elif \
1033     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1034     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1035     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1036     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1037     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1038     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1039     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1040     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1041     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1042     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1043     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1044     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1045 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1046     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1047 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1048     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1049 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1050     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1051 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1052     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1053 #else
1054     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1055 #endif
1056 
1057 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1058     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1059 #endif
1060 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1061     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1062 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1063     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1064 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1065     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1066 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1067     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1068 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1069     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1070 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1071     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1072 #elif \
1073     JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1074     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1075     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1076     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1077     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1078 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1079     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1080 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1081     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1082 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1083     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1084 #else
1085     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1086 #endif
1087 
1088 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1089     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1090 #endif
1091 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1092     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1093 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1094     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1095 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1096     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1097 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1098     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1099 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1100     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1101 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1102     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1103 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1104     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1105 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1106     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1107 #elif \
1108     JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1109     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1110     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1111     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1112 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1113     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1114 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1115     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1116 #else
1117     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1118 #endif
1119 
1120 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1121     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1122 #endif
1123 #if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1124     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1125 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1126     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1127 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1128     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1129 #else
1130     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1131 #endif
1132 
1133 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1134     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1135 #endif
1136 #if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1137     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1138 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1139     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1140 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1141     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1142 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1143     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1144 #else
1145     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1146 #endif
1147 
1148 #if defined(JSON_HEDLEY_DEPRECATED)
1149     #undef JSON_HEDLEY_DEPRECATED
1150 #endif
1151 #if defined(JSON_HEDLEY_DEPRECATED_FOR)
1152     #undef JSON_HEDLEY_DEPRECATED_FOR
1153 #endif
1154 #if \
1155     JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1156     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1157     #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1158     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1159 #elif \
1160     (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1161     JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1162     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1163     JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1164     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1165     JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1166     JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1167     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1168     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1169     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1170     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1171     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1172     #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1173     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1174 #elif defined(__cplusplus) && (__cplusplus >= 201402L)
1175     #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1176     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1177 #elif \
1178     JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1179     JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1180     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1181     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1182     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1183     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1184     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1185     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1186     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1187     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1188     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1189     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1190     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1191     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1192     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1193     JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1194     #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1195     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1196 #elif \
1197     JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1198     JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1199     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1200     #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1201     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1202 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1203     #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1204     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1205 #else
1206     #define JSON_HEDLEY_DEPRECATED(since)
1207     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1208 #endif
1209 
1210 #if defined(JSON_HEDLEY_UNAVAILABLE)
1211     #undef JSON_HEDLEY_UNAVAILABLE
1212 #endif
1213 #if \
1214     JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1215     JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1216     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1217     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1218     #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1219 #else
1220     #define JSON_HEDLEY_UNAVAILABLE(available_since)
1221 #endif
1222 
1223 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1224     #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1225 #endif
1226 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1227     #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1228 #endif
1229 #if \
1230     JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1231     JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1232     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1233     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1234     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1235     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1236     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1237     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1238     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1239     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1240     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1241     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1242     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1243     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1244     (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1245     JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1246     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1247     #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1248     #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1249 #elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1250     #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1251     #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1252 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1253     #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1254     #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1255 #elif defined(_Check_return_) /* SAL */
1256     #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1257     #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1258 #else
1259     #define JSON_HEDLEY_WARN_UNUSED_RESULT
1260     #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1261 #endif
1262 
1263 #if defined(JSON_HEDLEY_SENTINEL)
1264     #undef JSON_HEDLEY_SENTINEL
1265 #endif
1266 #if \
1267     JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1268     JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1269     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1270     JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1271     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1272     #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1273 #else
1274     #define JSON_HEDLEY_SENTINEL(position)
1275 #endif
1276 
1277 #if defined(JSON_HEDLEY_NO_RETURN)
1278     #undef JSON_HEDLEY_NO_RETURN
1279 #endif
1280 #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1281     #define JSON_HEDLEY_NO_RETURN __noreturn
1282 #elif \
1283     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1284     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1285     #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1286 #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1287     #define JSON_HEDLEY_NO_RETURN _Noreturn
1288 #elif defined(__cplusplus) && (__cplusplus >= 201103L)
1289     #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1290 #elif \
1291     JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1292     JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1293     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1294     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1295     JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1296     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1297     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1298     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1299     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1300     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1301     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1302     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1303     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1304     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1305     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1306     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1307     JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1308     #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1309 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1310     #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1311 #elif \
1312     JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1313     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1314     #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1315 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1316     #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1317 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1318     #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1319 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1320     #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1321 #else
1322     #define JSON_HEDLEY_NO_RETURN
1323 #endif
1324 
1325 #if defined(JSON_HEDLEY_NO_ESCAPE)
1326     #undef JSON_HEDLEY_NO_ESCAPE
1327 #endif
1328 #if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1329     #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1330 #else
1331     #define JSON_HEDLEY_NO_ESCAPE
1332 #endif
1333 
1334 #if defined(JSON_HEDLEY_UNREACHABLE)
1335     #undef JSON_HEDLEY_UNREACHABLE
1336 #endif
1337 #if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1338     #undef JSON_HEDLEY_UNREACHABLE_RETURN
1339 #endif
1340 #if defined(JSON_HEDLEY_ASSUME)
1341     #undef JSON_HEDLEY_ASSUME
1342 #endif
1343 #if \
1344     JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1345     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1346     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1347     #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1348 #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1349     #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1350 #elif \
1351     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1352     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1353     #if defined(__cplusplus)
1354         #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1355     #else
1356         #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1357     #endif
1358 #endif
1359 #if \
1360     (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1361     JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1362     JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1363     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1364     JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1365     JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1366     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1367     #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1368 #elif defined(JSON_HEDLEY_ASSUME)
1369     #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1370 #endif
1371 #if !defined(JSON_HEDLEY_ASSUME)
1372     #if defined(JSON_HEDLEY_UNREACHABLE)
1373         #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1374     #else
1375         #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1376     #endif
1377 #endif
1378 #if defined(JSON_HEDLEY_UNREACHABLE)
1379     #if  \
1380         JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1381         JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1382         #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1383     #else
1384         #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1385     #endif
1386 #else
1387     #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1388 #endif
1389 #if !defined(JSON_HEDLEY_UNREACHABLE)
1390     #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1391 #endif
1392 
1393 JSON_HEDLEY_DIAGNOSTIC_PUSH
1394 #if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1395     #pragma clang diagnostic ignored "-Wpedantic"
1396 #endif
1397 #if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1398     #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1399 #endif
1400 #if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1401     #if defined(__clang__)
1402         #pragma clang diagnostic ignored "-Wvariadic-macros"
1403     #elif defined(JSON_HEDLEY_GCC_VERSION)
1404         #pragma GCC diagnostic ignored "-Wvariadic-macros"
1405     #endif
1406 #endif
1407 #if defined(JSON_HEDLEY_NON_NULL)
1408     #undef JSON_HEDLEY_NON_NULL
1409 #endif
1410 #if \
1411     JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1412     JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1413     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1414     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1415     #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1416 #else
1417     #define JSON_HEDLEY_NON_NULL(...)
1418 #endif
1419 JSON_HEDLEY_DIAGNOSTIC_POP
1420 
1421 #if defined(JSON_HEDLEY_PRINTF_FORMAT)
1422     #undef JSON_HEDLEY_PRINTF_FORMAT
1423 #endif
1424 #if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1425     #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1426 #elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1427     #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1428 #elif \
1429     JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1430     JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1431     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1432     JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1433     JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1434     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1435     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1436     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1437     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1438     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1439     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1440     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1441     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1442     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1443     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1444     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1445     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1446     #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1447 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1448     #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1449 #else
1450     #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1451 #endif
1452 
1453 #if defined(JSON_HEDLEY_CONSTEXPR)
1454     #undef JSON_HEDLEY_CONSTEXPR
1455 #endif
1456 #if defined(__cplusplus)
1457     #if __cplusplus >= 201103L
1458         #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1459     #endif
1460 #endif
1461 #if !defined(JSON_HEDLEY_CONSTEXPR)
1462     #define JSON_HEDLEY_CONSTEXPR
1463 #endif
1464 
1465 #if defined(JSON_HEDLEY_PREDICT)
1466     #undef JSON_HEDLEY_PREDICT
1467 #endif
1468 #if defined(JSON_HEDLEY_LIKELY)
1469     #undef JSON_HEDLEY_LIKELY
1470 #endif
1471 #if defined(JSON_HEDLEY_UNLIKELY)
1472     #undef JSON_HEDLEY_UNLIKELY
1473 #endif
1474 #if defined(JSON_HEDLEY_UNPREDICTABLE)
1475     #undef JSON_HEDLEY_UNPREDICTABLE
1476 #endif
1477 #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1478     #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1479 #endif
1480 #if \
1481   (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1482   JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1483   JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1484 #  define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability(  (expr), (value), (probability))
1485 #  define JSON_HEDLEY_PREDICT_TRUE(expr, probability)   __builtin_expect_with_probability(!!(expr),    1   , (probability))
1486 #  define JSON_HEDLEY_PREDICT_FALSE(expr, probability)  __builtin_expect_with_probability(!!(expr),    0   , (probability))
1487 #  define JSON_HEDLEY_LIKELY(expr)                      __builtin_expect                 (!!(expr),    1                  )
1488 #  define JSON_HEDLEY_UNLIKELY(expr)                    __builtin_expect                 (!!(expr),    0                  )
1489 #elif \
1490   (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1491   JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1492   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1493   (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1494   JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1495   JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1496   JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1497   JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1498   JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1499   JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1500   JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1501   JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1502   JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1503   JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1504   JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1505   JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1506 #  define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1507     (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1508 #  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1509     (__extension__ ({ \
1510         double hedley_probability_ = (probability); \
1511         ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1512     }))
1513 #  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1514     (__extension__ ({ \
1515         double hedley_probability_ = (probability); \
1516         ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1517     }))
1518 #  define JSON_HEDLEY_LIKELY(expr)   __builtin_expect(!!(expr), 1)
1519 #  define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1520 #else
1521 #  define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1522 #  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1523 #  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1524 #  define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1525 #  define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1526 #endif
1527 #if !defined(JSON_HEDLEY_UNPREDICTABLE)
1528     #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1529 #endif
1530 
1531 #if defined(JSON_HEDLEY_MALLOC)
1532     #undef JSON_HEDLEY_MALLOC
1533 #endif
1534 #if \
1535     JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1536     JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1537     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1538     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1539     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1540     JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1541     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1542     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1543     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1544     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1545     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1546     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1547     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1548     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1549     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1550     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1551     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1552     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1553     #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1554 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1555     #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1556 #elif \
1557     JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1558     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1559     #define JSON_HEDLEY_MALLOC __declspec(restrict)
1560 #else
1561     #define JSON_HEDLEY_MALLOC
1562 #endif
1563 
1564 #if defined(JSON_HEDLEY_PURE)
1565     #undef JSON_HEDLEY_PURE
1566 #endif
1567 #if \
1568   JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1569   JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1570   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1571   JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1572   JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1573   JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1574   JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1575   (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1576   JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1577   (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1578   JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1579   (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1580   JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1581   (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1582   JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1583   JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1584   JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1585   JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1586   JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1587 #  define JSON_HEDLEY_PURE __attribute__((__pure__))
1588 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1589 #  define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1590 #elif defined(__cplusplus) && \
1591     ( \
1592       JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1593       JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1594       JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1595     )
1596 #  define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1597 #else
1598 #  define JSON_HEDLEY_PURE
1599 #endif
1600 
1601 #if defined(JSON_HEDLEY_CONST)
1602     #undef JSON_HEDLEY_CONST
1603 #endif
1604 #if \
1605     JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1606     JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1607     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1608     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1609     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1610     JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1611     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1612     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1613     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1614     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1615     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1616     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1617     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1618     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1619     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1620     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1621     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1622     JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1623     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1624     #define JSON_HEDLEY_CONST __attribute__((__const__))
1625 #elif \
1626     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1627     #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1628 #else
1629     #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1630 #endif
1631 
1632 #if defined(JSON_HEDLEY_RESTRICT)
1633     #undef JSON_HEDLEY_RESTRICT
1634 #endif
1635 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1636     #define JSON_HEDLEY_RESTRICT restrict
1637 #elif \
1638     JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1639     JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1640     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1641     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1642     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1643     JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1644     JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1645     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1646     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1647     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1648     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1649     (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1650     JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1651     defined(__clang__) || \
1652     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1653     #define JSON_HEDLEY_RESTRICT __restrict
1654 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1655     #define JSON_HEDLEY_RESTRICT _Restrict
1656 #else
1657     #define JSON_HEDLEY_RESTRICT
1658 #endif
1659 
1660 #if defined(JSON_HEDLEY_INLINE)
1661     #undef JSON_HEDLEY_INLINE
1662 #endif
1663 #if \
1664     (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1665     (defined(__cplusplus) && (__cplusplus >= 199711L))
1666     #define JSON_HEDLEY_INLINE inline
1667 #elif \
1668     defined(JSON_HEDLEY_GCC_VERSION) || \
1669     JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1670     #define JSON_HEDLEY_INLINE __inline__
1671 #elif \
1672     JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1673     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1674     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1675     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1676     JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1677     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1678     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1679     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1680     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1681     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1682     #define JSON_HEDLEY_INLINE __inline
1683 #else
1684     #define JSON_HEDLEY_INLINE
1685 #endif
1686 
1687 #if defined(JSON_HEDLEY_ALWAYS_INLINE)
1688     #undef JSON_HEDLEY_ALWAYS_INLINE
1689 #endif
1690 #if \
1691   JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1692   JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1693   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1694   JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1695   JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1696   JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1697   JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1698   (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1699   JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1700   (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1701   JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1702   (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1703   JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1704   (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1705   JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1706   JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1707   JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1708   JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1709   JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1710 #  define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1711 #elif \
1712   JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1713   JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1714 #  define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1715 #elif defined(__cplusplus) && \
1716     ( \
1717       JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1718       JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1719       JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1720       JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1721       JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1722       JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1723     )
1724 #  define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1725 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1726 #  define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1727 #else
1728 #  define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1729 #endif
1730 
1731 #if defined(JSON_HEDLEY_NEVER_INLINE)
1732     #undef JSON_HEDLEY_NEVER_INLINE
1733 #endif
1734 #if \
1735     JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1736     JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1737     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1738     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1739     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1740     JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1741     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1742     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1743     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1744     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1745     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1746     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1747     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1748     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1749     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1750     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1751     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1752     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1753     JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1754     #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1755 #elif \
1756     JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1757     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1758     #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1759 #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1760     #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1761 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1762     #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1763 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1764     #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1765 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1766     #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1767 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1768     #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1769 #else
1770     #define JSON_HEDLEY_NEVER_INLINE
1771 #endif
1772 
1773 #if defined(JSON_HEDLEY_PRIVATE)
1774     #undef JSON_HEDLEY_PRIVATE
1775 #endif
1776 #if defined(JSON_HEDLEY_PUBLIC)
1777     #undef JSON_HEDLEY_PUBLIC
1778 #endif
1779 #if defined(JSON_HEDLEY_IMPORT)
1780     #undef JSON_HEDLEY_IMPORT
1781 #endif
1782 #if defined(_WIN32) || defined(__CYGWIN__)
1783 #  define JSON_HEDLEY_PRIVATE
1784 #  define JSON_HEDLEY_PUBLIC   __declspec(dllexport)
1785 #  define JSON_HEDLEY_IMPORT   __declspec(dllimport)
1786 #else
1787 #  if \
1788     JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1789     JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1790     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1791     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1792     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1793     JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1794     ( \
1795       defined(__TI_EABI__) && \
1796       ( \
1797         (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1798         JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1799       ) \
1800     ) || \
1801     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1802 #    define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1803 #    define JSON_HEDLEY_PUBLIC  __attribute__((__visibility__("default")))
1804 #  else
1805 #    define JSON_HEDLEY_PRIVATE
1806 #    define JSON_HEDLEY_PUBLIC
1807 #  endif
1808 #  define JSON_HEDLEY_IMPORT    extern
1809 #endif
1810 
1811 #if defined(JSON_HEDLEY_NO_THROW)
1812     #undef JSON_HEDLEY_NO_THROW
1813 #endif
1814 #if \
1815     JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
1816     JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1817     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1818     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1819     #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
1820 #elif \
1821     JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
1822     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1823     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1824     #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
1825 #else
1826     #define JSON_HEDLEY_NO_THROW
1827 #endif
1828 
1829 #if defined(JSON_HEDLEY_FALL_THROUGH)
1830     #undef JSON_HEDLEY_FALL_THROUGH
1831 #endif
1832 #if \
1833     JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
1834     JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
1835     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1836     #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
1837 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
1838     #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
1839 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
1840     #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
1841 #elif defined(__fallthrough) /* SAL */
1842     #define JSON_HEDLEY_FALL_THROUGH __fallthrough
1843 #else
1844     #define JSON_HEDLEY_FALL_THROUGH
1845 #endif
1846 
1847 #if defined(JSON_HEDLEY_RETURNS_NON_NULL)
1848     #undef JSON_HEDLEY_RETURNS_NON_NULL
1849 #endif
1850 #if \
1851     JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
1852     JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
1853     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1854     #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
1855 #elif defined(_Ret_notnull_) /* SAL */
1856     #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
1857 #else
1858     #define JSON_HEDLEY_RETURNS_NON_NULL
1859 #endif
1860 
1861 #if defined(JSON_HEDLEY_ARRAY_PARAM)
1862     #undef JSON_HEDLEY_ARRAY_PARAM
1863 #endif
1864 #if \
1865     defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
1866     !defined(__STDC_NO_VLA__) && \
1867     !defined(__cplusplus) && \
1868     !defined(JSON_HEDLEY_PGI_VERSION) && \
1869     !defined(JSON_HEDLEY_TINYC_VERSION)
1870     #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
1871 #else
1872     #define JSON_HEDLEY_ARRAY_PARAM(name)
1873 #endif
1874 
1875 #if defined(JSON_HEDLEY_IS_CONSTANT)
1876     #undef JSON_HEDLEY_IS_CONSTANT
1877 #endif
1878 #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
1879     #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
1880 #endif
1881 /* JSON_HEDLEY_IS_CONSTEXPR_ is for
1882    HEDLEY INTERNAL USE ONLY.  API subject to change without notice. */
1883 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1884     #undef JSON_HEDLEY_IS_CONSTEXPR_
1885 #endif
1886 #if \
1887     JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
1888     JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1889     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1890     JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
1891     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1892     JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1893     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1894     (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
1895     JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1896     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1897     #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
1898 #endif
1899 #if !defined(__cplusplus)
1900 #  if \
1901        JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
1902        JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1903        JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1904        JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1905        JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1906        JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1907        JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
1908 #if defined(__INTPTR_TYPE__)
1909     #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
1910 #else
1911     #include <stdint.h>
1912     #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
1913 #endif
1914 #  elif \
1915        ( \
1916           defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
1917           !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
1918           !defined(JSON_HEDLEY_PGI_VERSION) && \
1919           !defined(JSON_HEDLEY_IAR_VERSION)) || \
1920        (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1921        JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
1922        JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
1923        JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1924        JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
1925 #if defined(__INTPTR_TYPE__)
1926     #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
1927 #else
1928     #include <stdint.h>
1929     #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
1930 #endif
1931 #  elif \
1932        defined(JSON_HEDLEY_GCC_VERSION) || \
1933        defined(JSON_HEDLEY_INTEL_VERSION) || \
1934        defined(JSON_HEDLEY_TINYC_VERSION) || \
1935        defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
1936        JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
1937        defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
1938        defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
1939        defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
1940        defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
1941        defined(__clang__)
1942 #    define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
1943         sizeof(void) != \
1944         sizeof(*( \
1945                   1 ? \
1946                   ((void*) ((expr) * 0L) ) : \
1947 ((struct { char v[sizeof(void) * 2]; } *) 1) \
1948                 ) \
1949               ) \
1950                                             )
1951 #  endif
1952 #endif
1953 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1954     #if !defined(JSON_HEDLEY_IS_CONSTANT)
1955         #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
1956     #endif
1957     #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
1958 #else
1959     #if !defined(JSON_HEDLEY_IS_CONSTANT)
1960         #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
1961     #endif
1962     #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
1963 #endif
1964 
1965 #if defined(JSON_HEDLEY_BEGIN_C_DECLS)
1966     #undef JSON_HEDLEY_BEGIN_C_DECLS
1967 #endif
1968 #if defined(JSON_HEDLEY_END_C_DECLS)
1969     #undef JSON_HEDLEY_END_C_DECLS
1970 #endif
1971 #if defined(JSON_HEDLEY_C_DECL)
1972     #undef JSON_HEDLEY_C_DECL
1973 #endif
1974 #if defined(__cplusplus)
1975     #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
1976     #define JSON_HEDLEY_END_C_DECLS }
1977     #define JSON_HEDLEY_C_DECL extern "C"
1978 #else
1979     #define JSON_HEDLEY_BEGIN_C_DECLS
1980     #define JSON_HEDLEY_END_C_DECLS
1981     #define JSON_HEDLEY_C_DECL
1982 #endif
1983 
1984 #if defined(JSON_HEDLEY_STATIC_ASSERT)
1985     #undef JSON_HEDLEY_STATIC_ASSERT
1986 #endif
1987 #if \
1988   !defined(__cplusplus) && ( \
1989       (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
1990       (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1991       JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
1992       JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1993       defined(_Static_assert) \
1994     )
1995 #  define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
1996 #elif \
1997   (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
1998   JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
1999   JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2000 #  define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2001 #else
2002 #  define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2003 #endif
2004 
2005 #if defined(JSON_HEDLEY_NULL)
2006     #undef JSON_HEDLEY_NULL
2007 #endif
2008 #if defined(__cplusplus)
2009     #if __cplusplus >= 201103L
2010         #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2011     #elif defined(NULL)
2012         #define JSON_HEDLEY_NULL NULL
2013     #else
2014         #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2015     #endif
2016 #elif defined(NULL)
2017     #define JSON_HEDLEY_NULL NULL
2018 #else
2019     #define JSON_HEDLEY_NULL ((void*) 0)
2020 #endif
2021 
2022 #if defined(JSON_HEDLEY_MESSAGE)
2023     #undef JSON_HEDLEY_MESSAGE
2024 #endif
2025 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2026 #  define JSON_HEDLEY_MESSAGE(msg) \
2027     JSON_HEDLEY_DIAGNOSTIC_PUSH \
2028     JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2029     JSON_HEDLEY_PRAGMA(message msg) \
2030     JSON_HEDLEY_DIAGNOSTIC_POP
2031 #elif \
2032   JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2033   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2034 #  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2035 #elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2036 #  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2037 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2038 #  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2039 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2040 #  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2041 #else
2042 #  define JSON_HEDLEY_MESSAGE(msg)
2043 #endif
2044 
2045 #if defined(JSON_HEDLEY_WARNING)
2046     #undef JSON_HEDLEY_WARNING
2047 #endif
2048 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2049 #  define JSON_HEDLEY_WARNING(msg) \
2050     JSON_HEDLEY_DIAGNOSTIC_PUSH \
2051     JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2052     JSON_HEDLEY_PRAGMA(clang warning msg) \
2053     JSON_HEDLEY_DIAGNOSTIC_POP
2054 #elif \
2055   JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2056   JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2057   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2058 #  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2059 #elif \
2060   JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2061   JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2062 #  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2063 #else
2064 #  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2065 #endif
2066 
2067 #if defined(JSON_HEDLEY_REQUIRE)
2068     #undef JSON_HEDLEY_REQUIRE
2069 #endif
2070 #if defined(JSON_HEDLEY_REQUIRE_MSG)
2071     #undef JSON_HEDLEY_REQUIRE_MSG
2072 #endif
2073 #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2074 #  if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2075 #    define JSON_HEDLEY_REQUIRE(expr) \
2076     JSON_HEDLEY_DIAGNOSTIC_PUSH \
2077     _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2078     __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2079     JSON_HEDLEY_DIAGNOSTIC_POP
2080 #    define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2081     JSON_HEDLEY_DIAGNOSTIC_PUSH \
2082     _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2083     __attribute__((diagnose_if(!(expr), msg, "error"))) \
2084     JSON_HEDLEY_DIAGNOSTIC_POP
2085 #  else
2086 #    define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2087 #    define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2088 #  endif
2089 #else
2090 #  define JSON_HEDLEY_REQUIRE(expr)
2091 #  define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2092 #endif
2093 
2094 #if defined(JSON_HEDLEY_FLAGS)
2095     #undef JSON_HEDLEY_FLAGS
2096 #endif
2097 #if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2098     #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2099 #else
2100     #define JSON_HEDLEY_FLAGS
2101 #endif
2102 
2103 #if defined(JSON_HEDLEY_FLAGS_CAST)
2104     #undef JSON_HEDLEY_FLAGS_CAST
2105 #endif
2106 #if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2107 #  define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2108         JSON_HEDLEY_DIAGNOSTIC_PUSH \
2109         _Pragma("warning(disable:188)") \
2110         ((T) (expr)); \
2111         JSON_HEDLEY_DIAGNOSTIC_POP \
2112     }))
2113 #else
2114 #  define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2115 #endif
2116 
2117 #if defined(JSON_HEDLEY_EMPTY_BASES)
2118     #undef JSON_HEDLEY_EMPTY_BASES
2119 #endif
2120 #if \
2121     (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2122     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2123     #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2124 #else
2125     #define JSON_HEDLEY_EMPTY_BASES
2126 #endif
2127 
2128 /* Remaining macros are deprecated. */
2129 
2130 #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2131     #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2132 #endif
2133 #if defined(__clang__)
2134     #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2135 #else
2136     #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2137 #endif
2138 
2139 #if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2140     #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2141 #endif
2142 #define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2143 
2144 #if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2145     #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2146 #endif
2147 #define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2148 
2149 #if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2150     #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2151 #endif
2152 #define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2153 
2154 #if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2155     #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2156 #endif
2157 #define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2158 
2159 #if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2160     #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2161 #endif
2162 #define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2163 
2164 #if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2165     #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2166 #endif
2167 #define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2168 
2169 #if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2170     #undef JSON_HEDLEY_CLANG_HAS_WARNING
2171 #endif
2172 #define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2173 
2174 #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2175 
2176 // #include <nlohmann/detail/meta/detected.hpp>
2177 //     __ _____ _____ _____
2178 //  __|  |   __|     |   | |  JSON for Modern C++
2179 // |  |  |__   |  |  | | | |  version 3.10.5
2180 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
2181 //
2182 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
2183 // SPDX-License-Identifier: MIT
2184 
2185 
2186 
2187 #include <type_traits>
2188 
2189 // #include <nlohmann/detail/meta/void_t.hpp>
2190 //     __ _____ _____ _____
2191 //  __|  |   __|     |   | |  JSON for Modern C++
2192 // |  |  |__   |  |  | | | |  version 3.10.5
2193 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
2194 //
2195 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
2196 // SPDX-License-Identifier: MIT
2197 
2198 
2199 
2200 namespace nlohmann
2201 {
2202 namespace detail
2203 {
2204 template<typename ...Ts> struct make_void
2205 {
2206     using type = void;
2207 };
2208 template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
2209 } // namespace detail
2210 }  // namespace nlohmann
2211 
2212 
2213 // https://en.cppreference.com/w/cpp/experimental/is_detected
2214 namespace nlohmann
2215 {
2216 namespace detail
2217 {
2218 struct nonesuch
2219 {
2220     nonesuch() = delete;
2221     ~nonesuch() = delete;
2222     nonesuch(nonesuch const&) = delete;
2223     nonesuch(nonesuch const&&) = delete;
2224     void operator=(nonesuch const&) = delete;
2225     void operator=(nonesuch&&) = delete;
2226 };
2227 
2228 template<class Default,
2229          class AlwaysVoid,
2230          template<class...> class Op,
2231          class... Args>
2232 struct detector
2233 {
2234     using value_t = std::false_type;
2235     using type = Default;
2236 };
2237 
2238 template<class Default, template<class...> class Op, class... Args>
2239 struct detector<Default, void_t<Op<Args...>>, Op, Args...>
2240 {
2241     using value_t = std::true_type;
2242     using type = Op<Args...>;
2243 };
2244 
2245 template<template<class...> class Op, class... Args>
2246 using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
2247 
2248 template<template<class...> class Op, class... Args>
2249 struct is_detected_lazy : is_detected<Op, Args...> { };
2250 
2251 template<template<class...> class Op, class... Args>
2252 using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
2253 
2254 template<class Default, template<class...> class Op, class... Args>
2255 using detected_or = detector<Default, void, Op, Args...>;
2256 
2257 template<class Default, template<class...> class Op, class... Args>
2258 using detected_or_t = typename detected_or<Default, Op, Args...>::type;
2259 
2260 template<class Expected, template<class...> class Op, class... Args>
2261 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
2262 
2263 template<class To, template<class...> class Op, class... Args>
2264 using is_detected_convertible =
2265     std::is_convertible<detected_t<Op, Args...>, To>;
2266 }  // namespace detail
2267 }  // namespace nlohmann
2268 
2269 
2270 // This file contains all internal macro definitions
2271 // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2272 
2273 // exclude unsupported compilers
2274 #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2275     #if defined(__clang__)
2276         #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2277             #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2278         #endif
2279     #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2280         #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2281             #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2282         #endif
2283     #endif
2284 #endif
2285 
2286 // C++ language standard detection
2287 // if the user manually specified the used c++ version this is skipped
2288 #if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2289     #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2290         #define JSON_HAS_CPP_20
2291         #define JSON_HAS_CPP_17
2292         #define JSON_HAS_CPP_14
2293     #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2294         #define JSON_HAS_CPP_17
2295         #define JSON_HAS_CPP_14
2296     #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2297         #define JSON_HAS_CPP_14
2298     #endif
2299     // the cpp 11 flag is always specified because it is the minimal required version
2300     #define JSON_HAS_CPP_11
2301 #endif
2302 
2303 #ifdef __has_include
2304     #if __has_include(<version>)
2305         #include <version>
2306     #endif
2307 #endif
2308 
2309 #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2310     #ifdef JSON_HAS_CPP_17
2311         #if defined(__cpp_lib_filesystem)
2312             #define JSON_HAS_FILESYSTEM 1
2313         #elif defined(__cpp_lib_experimental_filesystem)
2314             #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2315         #elif !defined(__has_include)
2316             #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2317         #elif __has_include(<filesystem>)
2318             #define JSON_HAS_FILESYSTEM 1
2319         #elif __has_include(<experimental/filesystem>)
2320             #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2321         #endif
2322 
2323         // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2324         #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2325             #undef JSON_HAS_FILESYSTEM
2326             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2327         #endif
2328 
2329         // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2330         #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2331             #undef JSON_HAS_FILESYSTEM
2332             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2333         #endif
2334 
2335         // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2336         #if defined(__clang_major__) && __clang_major__ < 7
2337             #undef JSON_HAS_FILESYSTEM
2338             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2339         #endif
2340 
2341         // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2342         #if defined(_MSC_VER) && _MSC_VER < 1914
2343             #undef JSON_HAS_FILESYSTEM
2344             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2345         #endif
2346 
2347         // no filesystem support before iOS 13
2348         #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2349             #undef JSON_HAS_FILESYSTEM
2350             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2351         #endif
2352 
2353         // no filesystem support before macOS Catalina
2354         #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2355             #undef JSON_HAS_FILESYSTEM
2356             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2357         #endif
2358     #endif
2359 #endif
2360 
2361 #ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2362     #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2363 #endif
2364 
2365 #ifndef JSON_HAS_FILESYSTEM
2366     #define JSON_HAS_FILESYSTEM 0
2367 #endif
2368 
2369 #ifndef JSON_HAS_THREE_WAY_COMPARISON
2370     #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2371         && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2372         #define JSON_HAS_THREE_WAY_COMPARISON 1
2373     #else
2374         #define JSON_HAS_THREE_WAY_COMPARISON 0
2375     #endif
2376 #endif
2377 
2378 #ifndef JSON_HAS_RANGES
2379     // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
2380     #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2381         #define JSON_HAS_RANGES 0
2382     #elif defined(__cpp_lib_ranges)
2383         #define JSON_HAS_RANGES 1
2384     #else
2385         #define JSON_HAS_RANGES 0
2386     #endif
2387 #endif
2388 
2389 #ifdef JSON_HAS_CPP_17
2390     #define JSON_INLINE_VARIABLE inline
2391 #else
2392     #define JSON_INLINE_VARIABLE
2393 #endif
2394 
2395 #if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2396     #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2397 #else
2398     #define JSON_NO_UNIQUE_ADDRESS
2399 #endif
2400 
2401 // disable documentation warnings on clang
2402 #if defined(__clang__)
2403     #pragma clang diagnostic push
2404     #pragma clang diagnostic ignored "-Wdocumentation"
2405     #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2406 #endif
2407 
2408 // allow disabling exceptions
2409 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2410     #define JSON_THROW(exception) throw exception
2411     #define JSON_TRY try
2412     #define JSON_CATCH(exception) catch(exception)
2413     #define JSON_INTERNAL_CATCH(exception) catch(exception)
2414 #else
2415     #include <cstdlib>
2416     #define JSON_THROW(exception) std::abort()
2417     #define JSON_TRY if(true)
2418     #define JSON_CATCH(exception) if(false)
2419     #define JSON_INTERNAL_CATCH(exception) if(false)
2420 #endif
2421 
2422 // override exception macros
2423 #if defined(JSON_THROW_USER)
2424     #undef JSON_THROW
2425     #define JSON_THROW JSON_THROW_USER
2426 #endif
2427 #if defined(JSON_TRY_USER)
2428     #undef JSON_TRY
2429     #define JSON_TRY JSON_TRY_USER
2430 #endif
2431 #if defined(JSON_CATCH_USER)
2432     #undef JSON_CATCH
2433     #define JSON_CATCH JSON_CATCH_USER
2434     #undef JSON_INTERNAL_CATCH
2435     #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2436 #endif
2437 #if defined(JSON_INTERNAL_CATCH_USER)
2438     #undef JSON_INTERNAL_CATCH
2439     #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2440 #endif
2441 
2442 // allow overriding assert
2443 #if !defined(JSON_ASSERT)
2444     #include <cassert> // assert
2445     #define JSON_ASSERT(x) assert(x)
2446 #endif
2447 
2448 // allow to access some private functions (needed by the test suite)
2449 #if defined(JSON_TESTS_PRIVATE)
2450     #define JSON_PRIVATE_UNLESS_TESTED public
2451 #else
2452     #define JSON_PRIVATE_UNLESS_TESTED private
2453 #endif
2454 
2455 /*!
2456 @brief macro to briefly define a mapping between an enum and JSON
2457 @def NLOHMANN_JSON_SERIALIZE_ENUM
2458 @since version 3.4.0
2459 */
2460 #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...)                                            \
2461     template<typename BasicJsonType>                                                            \
2462     inline void to_json(BasicJsonType& j, const ENUM_TYPE& e)                                   \
2463     {                                                                                           \
2464         static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \
2465         static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \
2466         auto it = std::find_if(std::begin(m), std::end(m),                                      \
2467                                [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool  \
2468         {                                                                                       \
2469             return ej_pair.first == e;                                                          \
2470         });                                                                                     \
2471         j = ((it != std::end(m)) ? it : std::begin(m))->second;                                 \
2472     }                                                                                           \
2473     template<typename BasicJsonType>                                                            \
2474     inline void from_json(const BasicJsonType& j, ENUM_TYPE& e)                                 \
2475     {                                                                                           \
2476         static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \
2477         static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \
2478         auto it = std::find_if(std::begin(m), std::end(m),                                      \
2479                                [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2480         {                                                                                       \
2481             return ej_pair.second == j;                                                         \
2482         });                                                                                     \
2483         e = ((it != std::end(m)) ? it : std::begin(m))->first;                                  \
2484     }
2485 
2486 // Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2487 // may be removed in the future once the class is split.
2488 
2489 #define NLOHMANN_BASIC_JSON_TPL_DECLARATION                                \
2490     template<template<typename, typename, typename...> class ObjectType,   \
2491              template<typename, typename...> class ArrayType,              \
2492              class StringType, class BooleanType, class NumberIntegerType, \
2493              class NumberUnsignedType, class NumberFloatType,              \
2494              template<typename> class AllocatorType,                       \
2495              template<typename, typename = void> class JSONSerializer,     \
2496              class BinaryType>
2497 
2498 #define NLOHMANN_BASIC_JSON_TPL                                            \
2499     basic_json<ObjectType, ArrayType, StringType, BooleanType,             \
2500     NumberIntegerType, NumberUnsignedType, NumberFloatType,                \
2501     AllocatorType, JSONSerializer, BinaryType>
2502 
2503 // Macros to simplify conversion from/to types
2504 
2505 #define NLOHMANN_JSON_EXPAND( x ) x
2506 #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
2507 #define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2508         NLOHMANN_JSON_PASTE64, \
2509         NLOHMANN_JSON_PASTE63, \
2510         NLOHMANN_JSON_PASTE62, \
2511         NLOHMANN_JSON_PASTE61, \
2512         NLOHMANN_JSON_PASTE60, \
2513         NLOHMANN_JSON_PASTE59, \
2514         NLOHMANN_JSON_PASTE58, \
2515         NLOHMANN_JSON_PASTE57, \
2516         NLOHMANN_JSON_PASTE56, \
2517         NLOHMANN_JSON_PASTE55, \
2518         NLOHMANN_JSON_PASTE54, \
2519         NLOHMANN_JSON_PASTE53, \
2520         NLOHMANN_JSON_PASTE52, \
2521         NLOHMANN_JSON_PASTE51, \
2522         NLOHMANN_JSON_PASTE50, \
2523         NLOHMANN_JSON_PASTE49, \
2524         NLOHMANN_JSON_PASTE48, \
2525         NLOHMANN_JSON_PASTE47, \
2526         NLOHMANN_JSON_PASTE46, \
2527         NLOHMANN_JSON_PASTE45, \
2528         NLOHMANN_JSON_PASTE44, \
2529         NLOHMANN_JSON_PASTE43, \
2530         NLOHMANN_JSON_PASTE42, \
2531         NLOHMANN_JSON_PASTE41, \
2532         NLOHMANN_JSON_PASTE40, \
2533         NLOHMANN_JSON_PASTE39, \
2534         NLOHMANN_JSON_PASTE38, \
2535         NLOHMANN_JSON_PASTE37, \
2536         NLOHMANN_JSON_PASTE36, \
2537         NLOHMANN_JSON_PASTE35, \
2538         NLOHMANN_JSON_PASTE34, \
2539         NLOHMANN_JSON_PASTE33, \
2540         NLOHMANN_JSON_PASTE32, \
2541         NLOHMANN_JSON_PASTE31, \
2542         NLOHMANN_JSON_PASTE30, \
2543         NLOHMANN_JSON_PASTE29, \
2544         NLOHMANN_JSON_PASTE28, \
2545         NLOHMANN_JSON_PASTE27, \
2546         NLOHMANN_JSON_PASTE26, \
2547         NLOHMANN_JSON_PASTE25, \
2548         NLOHMANN_JSON_PASTE24, \
2549         NLOHMANN_JSON_PASTE23, \
2550         NLOHMANN_JSON_PASTE22, \
2551         NLOHMANN_JSON_PASTE21, \
2552         NLOHMANN_JSON_PASTE20, \
2553         NLOHMANN_JSON_PASTE19, \
2554         NLOHMANN_JSON_PASTE18, \
2555         NLOHMANN_JSON_PASTE17, \
2556         NLOHMANN_JSON_PASTE16, \
2557         NLOHMANN_JSON_PASTE15, \
2558         NLOHMANN_JSON_PASTE14, \
2559         NLOHMANN_JSON_PASTE13, \
2560         NLOHMANN_JSON_PASTE12, \
2561         NLOHMANN_JSON_PASTE11, \
2562         NLOHMANN_JSON_PASTE10, \
2563         NLOHMANN_JSON_PASTE9, \
2564         NLOHMANN_JSON_PASTE8, \
2565         NLOHMANN_JSON_PASTE7, \
2566         NLOHMANN_JSON_PASTE6, \
2567         NLOHMANN_JSON_PASTE5, \
2568         NLOHMANN_JSON_PASTE4, \
2569         NLOHMANN_JSON_PASTE3, \
2570         NLOHMANN_JSON_PASTE2, \
2571         NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2572 #define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2573 #define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2574 #define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2575 #define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2576 #define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2577 #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)
2578 #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)
2579 #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)
2580 #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)
2581 #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)
2582 #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)
2583 #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)
2584 #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)
2585 #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)
2586 #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)
2587 #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)
2588 #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)
2589 #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)
2590 #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)
2591 #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)
2592 #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)
2593 #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)
2594 #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)
2595 #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)
2596 #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)
2597 #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)
2598 #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)
2599 #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)
2600 #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)
2601 #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)
2602 #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)
2603 #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)
2604 #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)
2605 #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)
2606 #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)
2607 #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)
2608 #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)
2609 #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)
2610 #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)
2611 #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)
2612 #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)
2613 #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)
2614 #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)
2615 #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)
2616 #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)
2617 #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)
2618 #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)
2619 #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)
2620 #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)
2621 #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)
2622 #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)
2623 #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)
2624 #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)
2625 #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)
2626 #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)
2627 #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)
2628 #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)
2629 #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)
2630 #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)
2631 #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)
2632 #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)
2633 #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)
2634 #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)
2635 
2636 #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2637 #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2638 #define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
2639 
2640 /*!
2641 @brief macro
2642 @def NLOHMANN_DEFINE_TYPE_INTRUSIVE
2643 @since version 3.9.0
2644 */
2645 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...)  \
2646     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__)) } \
2647     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__)) }
2648 
2649 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...)  \
2650     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__)) } \
2651     friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2652 
2653 /*!
2654 @brief macro
2655 @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
2656 @since version 3.9.0
2657 */
2658 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...)  \
2659     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__)) } \
2660     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__)) }
2661 
2662 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...)  \
2663     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__)) } \
2664     inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2665 
2666 
2667 // inspired from https://stackoverflow.com/a/26745591
2668 // allows to call any std function as if (e.g. with begin):
2669 // using std::begin; begin(x);
2670 //
2671 // it allows using the detected idiom to retrieve the return type
2672 // of such an expression
2673 #define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)                                 \
2674     namespace detail {                                                            \
2675     using std::std_name;                                                          \
2676     \
2677     template<typename... T>                                                       \
2678     using result_of_##std_name = decltype(std_name(std::declval<T>()...));        \
2679     }                                                                             \
2680     \
2681     namespace detail2 {                                                           \
2682     struct std_name##_tag                                                         \
2683     {                                                                             \
2684     };                                                                            \
2685     \
2686     template<typename... T>                                                       \
2687     std_name##_tag std_name(T&&...);                                              \
2688     \
2689     template<typename... T>                                                       \
2690     using result_of_##std_name = decltype(std_name(std::declval<T>()...));        \
2691     \
2692     template<typename... T>                                                       \
2693     struct would_call_std_##std_name                                              \
2694     {                                                                             \
2695         static constexpr auto const value = ::nlohmann::detail::                  \
2696                                             is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2697     };                                                                            \
2698     } /* namespace detail2 */ \
2699     \
2700     template<typename... T>                                                       \
2701     struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...>   \
2702     {                                                                             \
2703     }
2704 
2705 #ifndef JSON_USE_IMPLICIT_CONVERSIONS
2706     #define JSON_USE_IMPLICIT_CONVERSIONS 1
2707 #endif
2708 
2709 #if JSON_USE_IMPLICIT_CONVERSIONS
2710     #define JSON_EXPLICIT
2711 #else
2712     #define JSON_EXPLICIT explicit
2713 #endif
2714 
2715 #ifndef JSON_DIAGNOSTICS
2716     #define JSON_DIAGNOSTICS 0
2717 #endif
2718 
2719 #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
2720     #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
2721 #endif
2722 
2723 #ifndef JSON_DISABLE_ENUM_SERIALIZATION
2724     #define JSON_DISABLE_ENUM_SERIALIZATION 0
2725 #endif
2726 
2727 #if JSON_HAS_THREE_WAY_COMPARISON
2728     #include <compare> // partial_ordering
2729 #endif
2730 
2731 namespace nlohmann
2732 {
2733 namespace detail
2734 {
2735 ///////////////////////////
2736 // JSON type enumeration //
2737 ///////////////////////////
2738 
2739 /*!
2740 @brief the JSON type enumeration
2741 
2742 This enumeration collects the different JSON types. It is internally used to
2743 distinguish the stored values, and the functions @ref basic_json::is_null(),
2744 @ref basic_json::is_object(), @ref basic_json::is_array(),
2745 @ref basic_json::is_string(), @ref basic_json::is_boolean(),
2746 @ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
2747 @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
2748 @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
2749 @ref basic_json::is_structured() rely on it.
2750 
2751 @note There are three enumeration entries (number_integer, number_unsigned, and
2752 number_float), because the library distinguishes these three types for numbers:
2753 @ref basic_json::number_unsigned_t is used for unsigned integers,
2754 @ref basic_json::number_integer_t is used for signed integers, and
2755 @ref basic_json::number_float_t is used for floating-point numbers or to
2756 approximate integers which do not fit in the limits of their respective type.
2757 
2758 @sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
2759 value with the default value for a given type
2760 
2761 @since version 1.0.0
2762 */
2763 enum class value_t : std::uint8_t
2764 {
2765     null,             ///< null value
2766     object,           ///< object (unordered set of name/value pairs)
2767     array,            ///< array (ordered collection of values)
2768     string,           ///< string value
2769     boolean,          ///< boolean value
2770     number_integer,   ///< number value (signed integer)
2771     number_unsigned,  ///< number value (unsigned integer)
2772     number_float,     ///< number value (floating-point)
2773     binary,           ///< binary array (ordered collection of bytes)
2774     discarded         ///< discarded by the parser callback function
2775 };
2776 
2777 /*!
2778 @brief comparison operator for JSON types
2779 
2780 Returns an ordering that is similar to Python:
2781 - order: null < boolean < number < object < array < string < binary
2782 - furthermore, each type is not smaller than itself
2783 - discarded values are not comparable
2784 - binary is represented as a b"" string in python and directly comparable to a
2785   string; however, making a binary array directly comparable with a string would
2786   be surprising behavior in a JSON file.
2787 
2788 @since version 1.0.0
2789 */
2790 #if JSON_HAS_THREE_WAY_COMPARISON
operator <=>(const value_t lhs,const value_t rhs)2791     inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
2792 #else
2793     inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2794 #endif
2795 {
2796     static constexpr std::array<std::uint8_t, 9> order = {{
2797             0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
2798             1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
2799             6 /* binary */
2800         }
2801     };
2802 
2803     const auto l_index = static_cast<std::size_t>(lhs);
2804     const auto r_index = static_cast<std::size_t>(rhs);
2805 #if JSON_HAS_THREE_WAY_COMPARISON
2806     if (l_index < order.size() && r_index < order.size())
2807     {
2808         return order[l_index] <=> order[r_index]; // *NOPAD*
2809     }
2810     return std::partial_ordering::unordered;
2811 #else
2812     return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
2813 #endif
2814 }
2815 
2816 // GCC selects the built-in operator< over an operator rewritten from
2817 // a user-defined spaceship operator
2818 // Clang, MSVC, and ICC select the rewritten candidate
2819 // (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
2820 #if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
operator <(const value_t lhs,const value_t rhs)2821 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2822 {
2823     return std::is_lt(lhs <=> rhs); // *NOPAD*
2824 }
2825 #endif
2826 }  // namespace detail
2827 }  // namespace nlohmann
2828 
2829 // #include <nlohmann/detail/string_escape.hpp>
2830 //     __ _____ _____ _____
2831 //  __|  |   __|     |   | |  JSON for Modern C++
2832 // |  |  |__   |  |  | | | |  version 3.10.5
2833 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
2834 //
2835 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
2836 // SPDX-License-Identifier: MIT
2837 
2838 
2839 
2840 // #include <nlohmann/detail/macro_scope.hpp>
2841 
2842 
2843 namespace nlohmann
2844 {
2845 namespace detail
2846 {
2847 
2848 /*!
2849 @brief replace all occurrences of a substring by another string
2850 
2851 @param[in,out] s  the string to manipulate; changed so that all
2852                occurrences of @a f are replaced with @a t
2853 @param[in]     f  the substring to replace with @a t
2854 @param[in]     t  the string to replace @a f
2855 
2856 @pre The search string @a f must not be empty. **This precondition is
2857 enforced with an assertion.**
2858 
2859 @since version 2.0.0
2860 */
2861 template<typename StringType>
replace_substring(StringType & s,const StringType & f,const StringType & t)2862 inline void replace_substring(StringType& s, const StringType& f,
2863                               const StringType& t)
2864 {
2865     JSON_ASSERT(!f.empty());
2866     for (auto pos = s.find(f);                // find first occurrence of f
2867             pos != StringType::npos;          // make sure f was found
2868             s.replace(pos, f.size(), t),      // replace with t, and
2869             pos = s.find(f, pos + t.size()))  // find next occurrence of f
2870     {}
2871 }
2872 
2873 /*!
2874  * @brief string escaping as described in RFC 6901 (Sect. 4)
2875  * @param[in] s string to escape
2876  * @return    escaped string
2877  *
2878  * Note the order of escaping "~" to "~0" and "/" to "~1" is important.
2879  */
2880 template<typename StringType>
escape(StringType s)2881 inline StringType escape(StringType s)
2882 {
2883     replace_substring(s, StringType{"~"}, StringType{"~0"});
2884     replace_substring(s, StringType{"/"}, StringType{"~1"});
2885     return s;
2886 }
2887 
2888 /*!
2889  * @brief string unescaping as described in RFC 6901 (Sect. 4)
2890  * @param[in] s string to unescape
2891  * @return    unescaped string
2892  *
2893  * Note the order of escaping "~1" to "/" and "~0" to "~" is important.
2894  */
2895 template<typename StringType>
unescape(StringType & s)2896 static void unescape(StringType& s)
2897 {
2898     replace_substring(s, StringType{"~1"}, StringType{"/"});
2899     replace_substring(s, StringType{"~0"}, StringType{"~"});
2900 }
2901 
2902 } // namespace detail
2903 } // namespace nlohmann
2904 
2905 // #include <nlohmann/detail/input/position_t.hpp>
2906 //     __ _____ _____ _____
2907 //  __|  |   __|     |   | |  JSON for Modern C++
2908 // |  |  |__   |  |  | | | |  version 3.10.5
2909 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
2910 //
2911 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
2912 // SPDX-License-Identifier: MIT
2913 
2914 
2915 
2916 #include <cstddef> // size_t
2917 
2918 namespace nlohmann
2919 {
2920 namespace detail
2921 {
2922 /// struct to capture the start position of the current token
2923 struct position_t
2924 {
2925     /// the total number of characters read
2926     std::size_t chars_read_total = 0;
2927     /// the number of characters read in the current line
2928     std::size_t chars_read_current_line = 0;
2929     /// the number of lines read
2930     std::size_t lines_read = 0;
2931 
2932     /// conversion to size_t to preserve SAX interface
operator size_tnlohmann::detail::position_t2933     constexpr operator size_t() const
2934     {
2935         return chars_read_total;
2936     }
2937 };
2938 
2939 } // namespace detail
2940 } // namespace nlohmann
2941 
2942 // #include <nlohmann/detail/macro_scope.hpp>
2943 
2944 // #include <nlohmann/detail/meta/cpp_future.hpp>
2945 //     __ _____ _____ _____
2946 //  __|  |   __|     |   | |  JSON for Modern C++
2947 // |  |  |__   |  |  | | | |  version 3.10.5
2948 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
2949 //
2950 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
2951 // SPDX-FileCopyrightText: 2018 The Abseil Authors
2952 // SPDX-License-Identifier: MIT
2953 
2954 
2955 
2956 #include <cstddef> // size_t
2957 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
2958 #include <utility> // index_sequence, make_index_sequence, index_sequence_for
2959 
2960 // #include <nlohmann/detail/macro_scope.hpp>
2961 
2962 
2963 namespace nlohmann
2964 {
2965 namespace detail
2966 {
2967 
2968 template<typename T>
2969 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
2970 
2971 #ifdef JSON_HAS_CPP_14
2972 
2973 // the following utilities are natively available in C++14
2974 using std::enable_if_t;
2975 using std::index_sequence;
2976 using std::make_index_sequence;
2977 using std::index_sequence_for;
2978 
2979 #else
2980 
2981 // alias templates to reduce boilerplate
2982 template<bool B, typename T = void>
2983 using enable_if_t = typename std::enable_if<B, T>::type;
2984 
2985 // The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
2986 // which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
2987 
2988 //// START OF CODE FROM GOOGLE ABSEIL
2989 
2990 // integer_sequence
2991 //
2992 // Class template representing a compile-time integer sequence. An instantiation
2993 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
2994 // type through its template arguments (which is a common need when
2995 // working with C++11 variadic templates). `absl::integer_sequence` is designed
2996 // to be a drop-in replacement for C++14's `std::integer_sequence`.
2997 //
2998 // Example:
2999 //
3000 //   template< class T, T... Ints >
3001 //   void user_function(integer_sequence<T, Ints...>);
3002 //
3003 //   int main()
3004 //   {
3005 //     // user_function's `T` will be deduced to `int` and `Ints...`
3006 //     // will be deduced to `0, 1, 2, 3, 4`.
3007 //     user_function(make_integer_sequence<int, 5>());
3008 //   }
3009 template <typename T, T... Ints>
3010 struct integer_sequence
3011 {
3012     using value_type = T;
sizenlohmann::detail::integer_sequence3013     static constexpr std::size_t size() noexcept
3014     {
3015         return sizeof...(Ints);
3016     }
3017 };
3018 
3019 // index_sequence
3020 //
3021 // A helper template for an `integer_sequence` of `size_t`,
3022 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3023 // `std::index_sequence`.
3024 template <size_t... Ints>
3025 using index_sequence = integer_sequence<size_t, Ints...>;
3026 
3027 namespace utility_internal
3028 {
3029 
3030 template <typename Seq, size_t SeqSize, size_t Rem>
3031 struct Extend;
3032 
3033 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3034 template <typename T, T... Ints, size_t SeqSize>
3035 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3036 {
3037     using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3038 };
3039 
3040 template <typename T, T... Ints, size_t SeqSize>
3041 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3042 {
3043     using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3044 };
3045 
3046 // Recursion helper for 'make_integer_sequence<T, N>'.
3047 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3048 template <typename T, size_t N>
3049 struct Gen
3050 {
3051     using type =
3052         typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3053 };
3054 
3055 template <typename T>
3056 struct Gen<T, 0>
3057 {
3058     using type = integer_sequence<T>;
3059 };
3060 
3061 }  // namespace utility_internal
3062 
3063 // Compile-time sequences of integers
3064 
3065 // make_integer_sequence
3066 //
3067 // This template alias is equivalent to
3068 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3069 // replacement for C++14's `std::make_integer_sequence`.
3070 template <typename T, T N>
3071 using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
3072 
3073 // make_index_sequence
3074 //
3075 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3076 // and is designed to be a drop-in replacement for C++14's
3077 // `std::make_index_sequence`.
3078 template <size_t N>
3079 using make_index_sequence = make_integer_sequence<size_t, N>;
3080 
3081 // index_sequence_for
3082 //
3083 // Converts a typename pack into an index sequence of the same length, and
3084 // is designed to be a drop-in replacement for C++14's
3085 // `std::index_sequence_for()`
3086 template <typename... Ts>
3087 using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
3088 
3089 //// END OF CODE FROM GOOGLE ABSEIL
3090 
3091 #endif
3092 
3093 // dispatch utility (taken from ranges-v3)
3094 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3095 template<> struct priority_tag<0> {};
3096 
3097 // taken from ranges-v3
3098 template<typename T>
3099 struct static_const
3100 {
3101     static constexpr T value{};
3102 };
3103 
3104 #ifndef JSON_HAS_CPP_17
3105 
3106     template<typename T>
3107     constexpr T static_const<T>::value; // NOLINT(readability-redundant-declaration)
3108 
3109 #endif
3110 
3111 }  // namespace detail
3112 }  // namespace nlohmann
3113 
3114 // #include <nlohmann/detail/meta/type_traits.hpp>
3115 //     __ _____ _____ _____
3116 //  __|  |   __|     |   | |  JSON for Modern C++
3117 // |  |  |__   |  |  | | | |  version 3.10.5
3118 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
3119 //
3120 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3121 // SPDX-License-Identifier: MIT
3122 
3123 
3124 
3125 #include <limits> // numeric_limits
3126 #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3127 #include <utility> // declval
3128 #include <tuple> // tuple
3129 
3130 // #include <nlohmann/detail/macro_scope.hpp>
3131 
3132 
3133 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
3134 //     __ _____ _____ _____
3135 //  __|  |   __|     |   | |  JSON for Modern C++
3136 // |  |  |__   |  |  | | | |  version 3.10.5
3137 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
3138 //
3139 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3140 // SPDX-License-Identifier: MIT
3141 
3142 
3143 
3144 #include <iterator> // random_access_iterator_tag
3145 
3146 // #include <nlohmann/detail/meta/void_t.hpp>
3147 
3148 // #include <nlohmann/detail/meta/cpp_future.hpp>
3149 
3150 
3151 namespace nlohmann
3152 {
3153 namespace detail
3154 {
3155 template<typename It, typename = void>
3156 struct iterator_types {};
3157 
3158 template<typename It>
3159 struct iterator_types <
3160     It,
3161     void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3162     typename It::reference, typename It::iterator_category >>
3163 {
3164     using difference_type = typename It::difference_type;
3165     using value_type = typename It::value_type;
3166     using pointer = typename It::pointer;
3167     using reference = typename It::reference;
3168     using iterator_category = typename It::iterator_category;
3169 };
3170 
3171 // This is required as some compilers implement std::iterator_traits in a way that
3172 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3173 template<typename T, typename = void>
3174 struct iterator_traits
3175 {
3176 };
3177 
3178 template<typename T>
3179 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3180             : iterator_types<T>
3181 {
3182 };
3183 
3184 template<typename T>
3185 struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
3186 {
3187     using iterator_category = std::random_access_iterator_tag;
3188     using value_type = T;
3189     using difference_type = ptrdiff_t;
3190     using pointer = T*;
3191     using reference = T&;
3192 };
3193 } // namespace detail
3194 } // namespace nlohmann
3195 
3196 // #include <nlohmann/detail/meta/call_std/begin.hpp>
3197 //     __ _____ _____ _____
3198 //  __|  |   __|     |   | |  JSON for Modern C++
3199 // |  |  |__   |  |  | | | |  version 3.10.5
3200 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
3201 //
3202 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3203 // SPDX-License-Identifier: MIT
3204 
3205 
3206 
3207 // #include <nlohmann/detail/macro_scope.hpp>
3208 
3209 
3210 namespace nlohmann
3211 {
3212 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3213 } // namespace nlohmann
3214 
3215 // #include <nlohmann/detail/meta/call_std/end.hpp>
3216 //     __ _____ _____ _____
3217 //  __|  |   __|     |   | |  JSON for Modern C++
3218 // |  |  |__   |  |  | | | |  version 3.10.5
3219 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
3220 //
3221 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3222 // SPDX-License-Identifier: MIT
3223 
3224 
3225 
3226 // #include <nlohmann/detail/macro_scope.hpp>
3227 
3228 
3229 namespace nlohmann
3230 {
3231 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3232 }  // namespace nlohmann
3233 
3234 // #include <nlohmann/detail/meta/cpp_future.hpp>
3235 
3236 // #include <nlohmann/detail/meta/detected.hpp>
3237 
3238 // #include <nlohmann/json_fwd.hpp>
3239 //     __ _____ _____ _____
3240 //  __|  |   __|     |   | |  JSON for Modern C++
3241 // |  |  |__   |  |  | | | |  version 3.10.5
3242 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
3243 //
3244 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3245 // SPDX-License-Identifier: MIT
3246 
3247 #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3248 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3249 
3250 #include <cstdint> // int64_t, uint64_t
3251 #include <map> // map
3252 #include <memory> // allocator
3253 #include <string> // string
3254 #include <vector> // vector
3255 
3256 /*!
3257 @brief namespace for Niels Lohmann
3258 @see https://github.com/nlohmann
3259 @since version 1.0.0
3260 */
3261 namespace nlohmann
3262 {
3263 /*!
3264 @brief default JSONSerializer template argument
3265 
3266 This serializer ignores the template arguments and uses ADL
3267 ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
3268 for serialization.
3269 */
3270 template<typename T = void, typename SFINAE = void>
3271 struct adl_serializer;
3272 
3273 /// a class to store JSON values
3274 /// @sa https://json.nlohmann.me/api/basic_json/
3275 template<template<typename U, typename V, typename... Args> class ObjectType =
3276          std::map,
3277          template<typename U, typename... Args> class ArrayType = std::vector,
3278          class StringType = std::string, class BooleanType = bool,
3279          class NumberIntegerType = std::int64_t,
3280          class NumberUnsignedType = std::uint64_t,
3281          class NumberFloatType = double,
3282          template<typename U> class AllocatorType = std::allocator,
3283          template<typename T, typename SFINAE = void> class JSONSerializer =
3284          adl_serializer,
3285          class BinaryType = std::vector<std::uint8_t>>
3286 class basic_json;
3287 
3288 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
3289 /// @sa https://json.nlohmann.me/api/json_pointer/
3290 template<typename BasicJsonType>
3291 class json_pointer;
3292 
3293 /*!
3294 @brief default specialization
3295 @sa https://json.nlohmann.me/api/json/
3296 */
3297 using json = basic_json<>;
3298 
3299 /// @brief a minimal map-like container that preserves insertion order
3300 /// @sa https://json.nlohmann.me/api/ordered_map/
3301 template<class Key, class T, class IgnoredLess, class Allocator>
3302 struct ordered_map;
3303 
3304 /// @brief specialization that maintains the insertion order of object keys
3305 /// @sa https://json.nlohmann.me/api/ordered_json/
3306 using ordered_json = basic_json<nlohmann::ordered_map>;
3307 
3308 }  // namespace nlohmann
3309 
3310 #endif  // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3311 
3312 
3313 namespace nlohmann
3314 {
3315 /*!
3316 @brief detail namespace with internal helper functions
3317 
3318 This namespace collects functions that should not be exposed,
3319 implementations of some @ref basic_json methods, and meta-programming helpers.
3320 
3321 @since version 2.1.0
3322 */
3323 namespace detail
3324 {
3325 /////////////
3326 // helpers //
3327 /////////////
3328 
3329 // Note to maintainers:
3330 //
3331 // Every trait in this file expects a non CV-qualified type.
3332 // The only exceptions are in the 'aliases for detected' section
3333 // (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3334 //
3335 // In this case, T has to be properly CV-qualified to constraint the function arguments
3336 // (e.g. to_json(BasicJsonType&, const T&))
3337 
3338 template<typename> struct is_basic_json : std::false_type {};
3339 
3340 NLOHMANN_BASIC_JSON_TPL_DECLARATION
3341 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3342 
3343 // used by exceptions create() member functions
3344 // true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
3345 // false_type otherwise
3346 template<typename BasicJsonContext>
3347 struct is_basic_json_context :
3348     std::integral_constant < bool,
3349     is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3350     || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3351 {};
3352 
3353 //////////////////////
3354 // json_ref helpers //
3355 //////////////////////
3356 
3357 template<typename>
3358 class json_ref;
3359 
3360 template<typename>
3361 struct is_json_ref : std::false_type {};
3362 
3363 template<typename T>
3364 struct is_json_ref<json_ref<T>> : std::true_type {};
3365 
3366 //////////////////////////
3367 // aliases for detected //
3368 //////////////////////////
3369 
3370 template<typename T>
3371 using mapped_type_t = typename T::mapped_type;
3372 
3373 template<typename T>
3374 using key_type_t = typename T::key_type;
3375 
3376 template<typename T>
3377 using value_type_t = typename T::value_type;
3378 
3379 template<typename T>
3380 using difference_type_t = typename T::difference_type;
3381 
3382 template<typename T>
3383 using pointer_t = typename T::pointer;
3384 
3385 template<typename T>
3386 using reference_t = typename T::reference;
3387 
3388 template<typename T>
3389 using iterator_category_t = typename T::iterator_category;
3390 
3391 template<typename T, typename... Args>
3392 using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3393 
3394 template<typename T, typename... Args>
3395 using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3396 
3397 template<typename T, typename U>
3398 using get_template_function = decltype(std::declval<T>().template get<U>());
3399 
3400 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3401 template<typename BasicJsonType, typename T, typename = void>
3402 struct has_from_json : std::false_type {};
3403 
3404 // trait checking if j.get<T> is valid
3405 // use this trait instead of std::is_constructible or std::is_convertible,
3406 // both rely on, or make use of implicit conversions, and thus fail when T
3407 // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3408 template <typename BasicJsonType, typename T>
3409 struct is_getable
3410 {
3411     static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3412 };
3413 
3414 template<typename BasicJsonType, typename T>
3415 struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3416 {
3417     using serializer = typename BasicJsonType::template json_serializer<T, void>;
3418 
3419     static constexpr bool value =
3420         is_detected_exact<void, from_json_function, serializer,
3421         const BasicJsonType&, T&>::value;
3422 };
3423 
3424 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
3425 // this overload is used for non-default-constructible user-defined-types
3426 template<typename BasicJsonType, typename T, typename = void>
3427 struct has_non_default_from_json : std::false_type {};
3428 
3429 template<typename BasicJsonType, typename T>
3430 struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3431 {
3432     using serializer = typename BasicJsonType::template json_serializer<T, void>;
3433 
3434     static constexpr bool value =
3435         is_detected_exact<T, from_json_function, serializer,
3436         const BasicJsonType&>::value;
3437 };
3438 
3439 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3440 // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3441 template<typename BasicJsonType, typename T, typename = void>
3442 struct has_to_json : std::false_type {};
3443 
3444 template<typename BasicJsonType, typename T>
3445 struct has_to_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, to_json_function, serializer, BasicJsonType&,
3451         T>::value;
3452 };
3453 
3454 template<typename T>
3455 using detect_key_compare = typename T::key_compare;
3456 
3457 template<typename T>
3458 struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3459 
3460 // obtains the actual object key comparator
3461 template<typename BasicJsonType>
3462 struct actual_object_comparator
3463 {
3464     using object_t = typename BasicJsonType::object_t;
3465     using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3466     using type = typename std::conditional < has_key_compare<object_t>::value,
3467           typename object_t::key_compare, object_comparator_t>::type;
3468 };
3469 
3470 template<typename BasicJsonType>
3471 using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
3472 
3473 ///////////////////
3474 // is_ functions //
3475 ///////////////////
3476 
3477 // https://en.cppreference.com/w/cpp/types/conjunction
3478 template<class...> struct conjunction : std::true_type { };
3479 template<class B> struct conjunction<B> : B { };
3480 template<class B, class... Bn>
3481 struct conjunction<B, Bn...>
3482 : std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3483 
3484 // https://en.cppreference.com/w/cpp/types/negation
3485 template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3486 
3487 // Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3488 // std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3489 // This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3490 template <typename T>
3491 struct is_default_constructible : std::is_default_constructible<T> {};
3492 
3493 template <typename T1, typename T2>
3494 struct is_default_constructible<std::pair<T1, T2>>
3495             : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3496 
3497 template <typename T1, typename T2>
3498 struct is_default_constructible<const std::pair<T1, T2>>
3499             : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3500 
3501 template <typename... Ts>
3502 struct is_default_constructible<std::tuple<Ts...>>
3503             : conjunction<is_default_constructible<Ts>...> {};
3504 
3505 template <typename... Ts>
3506 struct is_default_constructible<const std::tuple<Ts...>>
3507             : conjunction<is_default_constructible<Ts>...> {};
3508 
3509 
3510 template <typename T, typename... Args>
3511 struct is_constructible : std::is_constructible<T, Args...> {};
3512 
3513 template <typename T1, typename T2>
3514 struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3515 
3516 template <typename T1, typename T2>
3517 struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3518 
3519 template <typename... Ts>
3520 struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3521 
3522 template <typename... Ts>
3523 struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3524 
3525 
3526 template<typename T, typename = void>
3527 struct is_iterator_traits : std::false_type {};
3528 
3529 template<typename T>
3530 struct is_iterator_traits<iterator_traits<T>>
3531 {
3532   private:
3533     using traits = iterator_traits<T>;
3534 
3535   public:
3536     static constexpr auto value =
3537         is_detected<value_type_t, traits>::value &&
3538         is_detected<difference_type_t, traits>::value &&
3539         is_detected<pointer_t, traits>::value &&
3540         is_detected<iterator_category_t, traits>::value &&
3541         is_detected<reference_t, traits>::value;
3542 };
3543 
3544 template<typename T>
3545 struct is_range
3546 {
3547   private:
3548     using t_ref = typename std::add_lvalue_reference<T>::type;
3549 
3550     using iterator = detected_t<result_of_begin, t_ref>;
3551     using sentinel = detected_t<result_of_end, t_ref>;
3552 
3553     // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3554     // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3555     // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3556     static constexpr auto is_iterator_begin =
3557         is_iterator_traits<iterator_traits<iterator>>::value;
3558 
3559   public:
3560     static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3561 };
3562 
3563 template<typename R>
3564 using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3565 
3566 template<typename T>
3567 using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3568 
3569 // The following implementation of is_complete_type is taken from
3570 // https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3571 // and is written by Xiang Fan who agreed to using it in this library.
3572 
3573 template<typename T, typename = void>
3574 struct is_complete_type : std::false_type {};
3575 
3576 template<typename T>
3577 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3578 
3579 template<typename BasicJsonType, typename CompatibleObjectType,
3580          typename = void>
3581 struct is_compatible_object_type_impl : std::false_type {};
3582 
3583 template<typename BasicJsonType, typename CompatibleObjectType>
3584 struct is_compatible_object_type_impl <
3585     BasicJsonType, CompatibleObjectType,
3586     enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3587     is_detected<key_type_t, CompatibleObjectType>::value >>
3588 {
3589     using object_t = typename BasicJsonType::object_t;
3590 
3591     // macOS's is_constructible does not play well with nonesuch...
3592     static constexpr bool value =
3593         is_constructible<typename object_t::key_type,
3594         typename CompatibleObjectType::key_type>::value &&
3595         is_constructible<typename object_t::mapped_type,
3596         typename CompatibleObjectType::mapped_type>::value;
3597 };
3598 
3599 template<typename BasicJsonType, typename CompatibleObjectType>
3600 struct is_compatible_object_type
3601     : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3602 
3603 template<typename BasicJsonType, typename ConstructibleObjectType,
3604          typename = void>
3605 struct is_constructible_object_type_impl : std::false_type {};
3606 
3607 template<typename BasicJsonType, typename ConstructibleObjectType>
3608 struct is_constructible_object_type_impl <
3609     BasicJsonType, ConstructibleObjectType,
3610     enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3611     is_detected<key_type_t, ConstructibleObjectType>::value >>
3612 {
3613     using object_t = typename BasicJsonType::object_t;
3614 
3615     static constexpr bool value =
3616         (is_default_constructible<ConstructibleObjectType>::value &&
3617          (std::is_move_assignable<ConstructibleObjectType>::value ||
3618           std::is_copy_assignable<ConstructibleObjectType>::value) &&
3619          (is_constructible<typename ConstructibleObjectType::key_type,
3620           typename object_t::key_type>::value &&
3621           std::is_same <
3622           typename object_t::mapped_type,
3623           typename ConstructibleObjectType::mapped_type >::value)) ||
3624         (has_from_json<BasicJsonType,
3625          typename ConstructibleObjectType::mapped_type>::value ||
3626          has_non_default_from_json <
3627          BasicJsonType,
3628          typename ConstructibleObjectType::mapped_type >::value);
3629 };
3630 
3631 template<typename BasicJsonType, typename ConstructibleObjectType>
3632 struct is_constructible_object_type
3633     : is_constructible_object_type_impl<BasicJsonType,
3634       ConstructibleObjectType> {};
3635 
3636 template<typename BasicJsonType, typename CompatibleStringType>
3637 struct is_compatible_string_type
3638 {
3639     static constexpr auto value =
3640         is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
3641 };
3642 
3643 template<typename BasicJsonType, typename ConstructibleStringType>
3644 struct is_constructible_string_type
3645 {
3646     // launder type through decltype() to fix compilation failure on ICPC
3647 #ifdef __INTEL_COMPILER
3648     using laundered_type = decltype(std::declval<ConstructibleStringType>());
3649 #else
3650     using laundered_type = ConstructibleStringType;
3651 #endif
3652 
3653     static constexpr auto value =
3654         is_constructible<laundered_type,
3655         typename BasicJsonType::string_t>::value;
3656 };
3657 
3658 template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3659 struct is_compatible_array_type_impl : std::false_type {};
3660 
3661 template<typename BasicJsonType, typename CompatibleArrayType>
3662 struct is_compatible_array_type_impl <
3663     BasicJsonType, CompatibleArrayType,
3664     enable_if_t <
3665     is_detected<iterator_t, CompatibleArrayType>::value&&
3666     is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3667 // special case for types like std::filesystem::path whose iterator's value_type are themselves
3668 // c.f. https://github.com/nlohmann/json/pull/3073
3669     !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3670 {
3671     static constexpr bool value =
3672         is_constructible<BasicJsonType,
3673         range_value_t<CompatibleArrayType>>::value;
3674 };
3675 
3676 template<typename BasicJsonType, typename CompatibleArrayType>
3677 struct is_compatible_array_type
3678     : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3679 
3680 template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3681 struct is_constructible_array_type_impl : std::false_type {};
3682 
3683 template<typename BasicJsonType, typename ConstructibleArrayType>
3684 struct is_constructible_array_type_impl <
3685     BasicJsonType, ConstructibleArrayType,
3686     enable_if_t<std::is_same<ConstructibleArrayType,
3687     typename BasicJsonType::value_type>::value >>
3688             : std::true_type {};
3689 
3690 template<typename BasicJsonType, typename ConstructibleArrayType>
3691 struct is_constructible_array_type_impl <
3692     BasicJsonType, ConstructibleArrayType,
3693     enable_if_t < !std::is_same<ConstructibleArrayType,
3694     typename BasicJsonType::value_type>::value&&
3695     !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3696     is_default_constructible<ConstructibleArrayType>::value&&
3697 (std::is_move_assignable<ConstructibleArrayType>::value ||
3698  std::is_copy_assignable<ConstructibleArrayType>::value)&&
3699 is_detected<iterator_t, ConstructibleArrayType>::value&&
3700 is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3701 is_detected<range_value_t, ConstructibleArrayType>::value&&
3702 // special case for types like std::filesystem::path whose iterator's value_type are themselves
3703 // c.f. https://github.com/nlohmann/json/pull/3073
3704 !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3705         is_complete_type <
3706         detected_t<range_value_t, ConstructibleArrayType >>::value >>
3707 {
3708     using value_type = range_value_t<ConstructibleArrayType>;
3709 
3710     static constexpr bool value =
3711         std::is_same<value_type,
3712         typename BasicJsonType::array_t::value_type>::value ||
3713         has_from_json<BasicJsonType,
3714         value_type>::value ||
3715         has_non_default_from_json <
3716         BasicJsonType,
3717         value_type >::value;
3718 };
3719 
3720 template<typename BasicJsonType, typename ConstructibleArrayType>
3721 struct is_constructible_array_type
3722     : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3723 
3724 template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3725          typename = void>
3726 struct is_compatible_integer_type_impl : std::false_type {};
3727 
3728 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3729 struct is_compatible_integer_type_impl <
3730     RealIntegerType, CompatibleNumberIntegerType,
3731     enable_if_t < std::is_integral<RealIntegerType>::value&&
3732     std::is_integral<CompatibleNumberIntegerType>::value&&
3733     !std::is_same<bool, CompatibleNumberIntegerType>::value >>
3734 {
3735     // is there an assert somewhere on overflows?
3736     using RealLimits = std::numeric_limits<RealIntegerType>;
3737     using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3738 
3739     static constexpr auto value =
3740         is_constructible<RealIntegerType,
3741         CompatibleNumberIntegerType>::value &&
3742         CompatibleLimits::is_integer &&
3743         RealLimits::is_signed == CompatibleLimits::is_signed;
3744 };
3745 
3746 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3747 struct is_compatible_integer_type
3748     : is_compatible_integer_type_impl<RealIntegerType,
3749       CompatibleNumberIntegerType> {};
3750 
3751 template<typename BasicJsonType, typename CompatibleType, typename = void>
3752 struct is_compatible_type_impl: std::false_type {};
3753 
3754 template<typename BasicJsonType, typename CompatibleType>
3755 struct is_compatible_type_impl <
3756     BasicJsonType, CompatibleType,
3757     enable_if_t<is_complete_type<CompatibleType>::value >>
3758 {
3759     static constexpr bool value =
3760         has_to_json<BasicJsonType, CompatibleType>::value;
3761 };
3762 
3763 template<typename BasicJsonType, typename CompatibleType>
3764 struct is_compatible_type
3765     : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3766 
3767 template<typename T1, typename T2>
3768 struct is_constructible_tuple : std::false_type {};
3769 
3770 template<typename T1, typename... Args>
3771 struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3772 
3773 template<typename BasicJsonType, typename T>
3774 struct is_json_iterator_of : std::false_type {};
3775 
3776 template<typename BasicJsonType>
3777 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
3778 
3779 template<typename BasicJsonType>
3780 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
3781 {};
3782 
3783 // checks if a given type T is a template specialization of Primary
3784 template<template <typename...> class Primary, typename T>
3785 struct is_specialization_of : std::false_type {};
3786 
3787 template<template <typename...> class Primary, typename... Args>
3788 struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
3789 
3790 template<typename T>
3791 using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
3792 
3793 // checks if A and B are comparable using Compare functor
3794 template<typename Compare, typename A, typename B, typename = void>
3795 struct is_comparable : std::false_type {};
3796 
3797 template<typename Compare, typename A, typename B>
3798 struct is_comparable<Compare, A, B, void_t<
3799 decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
3800 decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
3801 >> : std::true_type {};
3802 
3803 template<typename T>
3804 using detect_is_transparent = typename T::is_transparent;
3805 
3806 // type trait to check if KeyType can be used as object key (without a BasicJsonType)
3807 // see is_usable_as_basic_json_key_type below
3808 template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
3809          bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
3810 using is_usable_as_key_type = typename std::conditional <
3811                               is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value
3812                               && !(ExcludeObjectKeyType && std::is_same<KeyType,
3813                                    ObjectKeyType>::value)
3814                               && (!RequireTransparentComparator
3815                                   || is_detected <detect_is_transparent, Comparator>::value)
3816                               && !is_json_pointer<KeyType>::value,
3817                               std::true_type,
3818                               std::false_type >::type;
3819 
3820 // type trait to check if KeyType can be used as object key
3821 // true if:
3822 //   - KeyType is comparable with BasicJsonType::object_t::key_type
3823 //   - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
3824 //   - the comparator is transparent or RequireTransparentComparator is false
3825 //   - KeyType is not a JSON iterator or json_pointer
3826 template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
3827          bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
3828 using is_usable_as_basic_json_key_type = typename std::conditional <
3829         is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
3830         typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
3831         RequireTransparentComparator, ExcludeObjectKeyType>::value
3832         && !is_json_iterator_of<BasicJsonType, KeyType>::value,
3833         std::true_type,
3834         std::false_type >::type;
3835 
3836 template<typename ObjectType, typename KeyType>
3837 using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
3838 
3839 // type trait to check if object_t has an erase() member functions accepting KeyType
3840 template<typename BasicJsonType, typename KeyType>
3841 using has_erase_with_key_type = typename std::conditional <
3842                                 is_detected <
3843                                 detect_erase_with_key_type,
3844                                 typename BasicJsonType::object_t, KeyType >::value,
3845                                 std::true_type,
3846                                 std::false_type >::type;
3847 
3848 // a naive helper to check if a type is an ordered_map (exploits the fact that
3849 // ordered_map inherits capacity() from std::vector)
3850 template <typename T>
3851 struct is_ordered_map
3852 {
3853     using one = char;
3854 
3855     struct two
3856     {
3857         char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3858     };
3859 
3860     template <typename C> static one test( decltype(&C::capacity) ) ;
3861     template <typename C> static two test(...);
3862 
3863     enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
3864 };
3865 
3866 // to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
3867 template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
conditional_static_cast(U value)3868 T conditional_static_cast(U value)
3869 {
3870     return static_cast<T>(value);
3871 }
3872 
3873 template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
conditional_static_cast(U value)3874 T conditional_static_cast(U value)
3875 {
3876     return value;
3877 }
3878 
3879 template<typename... Types>
3880 using all_integral = conjunction<std::is_integral<Types>...>;
3881 
3882 template<typename... Types>
3883 using all_signed = conjunction<std::is_signed<Types>...>;
3884 
3885 template<typename... Types>
3886 using all_unsigned = conjunction<std::is_unsigned<Types>...>;
3887 
3888 // there's a disjunction trait in another PR; replace when merged
3889 template<typename... Types>
3890 using same_sign = std::integral_constant < bool,
3891       all_signed<Types...>::value || all_unsigned<Types...>::value >;
3892 
3893 template<typename OfType, typename T>
3894 using never_out_of_range = std::integral_constant < bool,
3895       (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
3896       || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
3897 
3898 template<typename OfType, typename T,
3899          bool OfTypeSigned = std::is_signed<OfType>::value,
3900          bool TSigned = std::is_signed<T>::value>
3901 struct value_in_range_of_impl2;
3902 
3903 template<typename OfType, typename T>
3904 struct value_in_range_of_impl2<OfType, T, false, false>
3905 {
testnlohmann::detail::value_in_range_of_impl23906     static constexpr bool test(T val)
3907     {
3908         using CommonType = typename std::common_type<OfType, T>::type;
3909         return static_cast<CommonType>(val) <= static_cast<CommonType>(std::numeric_limits<OfType>::max());
3910     }
3911 };
3912 
3913 template<typename OfType, typename T>
3914 struct value_in_range_of_impl2<OfType, T, true, false>
3915 {
testnlohmann::detail::value_in_range_of_impl23916     static constexpr bool test(T val)
3917     {
3918         using CommonType = typename std::common_type<OfType, T>::type;
3919         return static_cast<CommonType>(val) <= static_cast<CommonType>(std::numeric_limits<OfType>::max());
3920     }
3921 };
3922 
3923 template<typename OfType, typename T>
3924 struct value_in_range_of_impl2<OfType, T, false, true>
3925 {
testnlohmann::detail::value_in_range_of_impl23926     static constexpr bool test(T val)
3927     {
3928         using CommonType = typename std::common_type<OfType, T>::type;
3929         return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>(std::numeric_limits<OfType>::max());
3930     }
3931 };
3932 
3933 
3934 template<typename OfType, typename T>
3935 struct value_in_range_of_impl2<OfType, T, true, true>
3936 {
testnlohmann::detail::value_in_range_of_impl23937     static constexpr bool test(T val)
3938     {
3939         using CommonType = typename std::common_type<OfType, T>::type;
3940         return static_cast<CommonType>(val) >= static_cast<CommonType>(std::numeric_limits<OfType>::min())
3941                && static_cast<CommonType>(val) <= static_cast<CommonType>(std::numeric_limits<OfType>::max());
3942     }
3943 };
3944 
3945 template<typename OfType, typename T,
3946          bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
3947          typename = detail::enable_if_t<all_integral<OfType, T>::value>>
3948 struct value_in_range_of_impl1;
3949 
3950 template<typename OfType, typename T>
3951 struct value_in_range_of_impl1<OfType, T, false>
3952 {
testnlohmann::detail::value_in_range_of_impl13953     static constexpr bool test(T val)
3954     {
3955         return value_in_range_of_impl2<OfType, T>::test(val);
3956     }
3957 };
3958 
3959 template<typename OfType, typename T>
3960 struct value_in_range_of_impl1<OfType, T, true>
3961 {
testnlohmann::detail::value_in_range_of_impl13962     static constexpr bool test(T /*val*/)
3963     {
3964         return true;
3965     }
3966 };
3967 
3968 template<typename OfType, typename T>
value_in_range_of(T val)3969 inline constexpr bool value_in_range_of(T val)
3970 {
3971     return value_in_range_of_impl1<OfType, T>::test(val);
3972 }
3973 
3974 }  // namespace detail
3975 }  // namespace nlohmann
3976 
3977 // #include <nlohmann/detail/string_concat.hpp>
3978 //     __ _____ _____ _____
3979 //  __|  |   __|     |   | |  JSON for Modern C++
3980 // |  |  |__   |  |  | | | |  version 3.10.5
3981 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
3982 //
3983 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3984 // SPDX-License-Identifier: MIT
3985 
3986 
3987 
3988 #include <cstring> // strlen
3989 #include <string> // string
3990 #include <utility> // forward
3991 
3992 // #include <nlohmann/detail/meta/cpp_future.hpp>
3993 
3994 // #include <nlohmann/detail/meta/detected.hpp>
3995 
3996 
3997 namespace nlohmann
3998 {
3999 namespace detail
4000 {
4001 
concat_length()4002 inline std::size_t concat_length()
4003 {
4004     return 0;
4005 }
4006 
4007 template<typename... Args>
4008 inline std::size_t concat_length(const char* cstr, Args&& ... rest);
4009 
4010 template<typename StringType, typename... Args>
4011 inline std::size_t concat_length(const StringType& str, Args&& ... rest);
4012 
4013 template<typename... Args>
concat_length(const char,Args &&...rest)4014 inline std::size_t concat_length(const char /*c*/, Args&& ... rest)
4015 {
4016     return 1 + concat_length(std::forward<Args>(rest)...);
4017 }
4018 
4019 template<typename... Args>
concat_length(const char * cstr,Args &&...rest)4020 inline std::size_t concat_length(const char* cstr, Args&& ... rest)
4021 {
4022     // cppcheck-suppress ignoredReturnValue
4023     return ::strlen(cstr) + concat_length(std::forward<Args>(rest)...);
4024 }
4025 
4026 template<typename StringType, typename... Args>
concat_length(const StringType & str,Args &&...rest)4027 inline std::size_t concat_length(const StringType& str, Args&& ... rest)
4028 {
4029     return str.size() + concat_length(std::forward<Args>(rest)...);
4030 }
4031 
4032 template<typename OutStringType>
concat_into(OutStringType &)4033 inline void concat_into(OutStringType& /*out*/)
4034 {}
4035 
4036 template<typename StringType, typename Arg>
4037 using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4038 
4039 template<typename StringType, typename Arg>
4040 using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
4041 
4042 template<typename StringType, typename Arg>
4043 using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4044 
4045 template<typename StringType, typename Arg>
4046 using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
4047 
4048 template<typename StringType, typename Arg>
4049 using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4050 
4051 template<typename StringType, typename Arg>
4052 using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
4053 
4054 template<typename StringType, typename Arg>
4055 using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4056 
4057 template<typename StringType, typename Arg>
4058 using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
4059 
4060 template < typename OutStringType, typename Arg, typename... Args,
4061            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4062                          && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
4063 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4064 
4065 template < typename OutStringType, typename Arg, typename... Args,
4066            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4067                          && !detect_string_can_append_op<OutStringType, Arg>::value
4068                          && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
4069 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4070 
4071 template < typename OutStringType, typename Arg, typename... Args,
4072            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4073                          && !detect_string_can_append_op<OutStringType, Arg>::value
4074                          && !detect_string_can_append_iter<OutStringType, Arg>::value
4075                          && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
4076 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4077 
4078 template<typename OutStringType, typename Arg, typename... Args,
4079          enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
concat_into(OutStringType & out,Arg && arg,Args &&...rest)4080 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4081 {
4082     out.append(std::forward<Arg>(arg));
4083     concat_into(out, std::forward<Args>(rest)...);
4084 }
4085 
4086 template < typename OutStringType, typename Arg, typename... Args,
4087            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4088                          && detect_string_can_append_op<OutStringType, Arg>::value, int > >
concat_into(OutStringType & out,Arg && arg,Args &&...rest)4089 inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4090 {
4091     out += std::forward<Arg>(arg);
4092     concat_into(out, std::forward<Args>(rest)...);
4093 }
4094 
4095 template < typename OutStringType, typename Arg, typename... Args,
4096            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4097                          && !detect_string_can_append_op<OutStringType, Arg>::value
4098                          && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
concat_into(OutStringType & out,const Arg & arg,Args &&...rest)4099 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4100 {
4101     out.append(arg.begin(), arg.end());
4102     concat_into(out, std::forward<Args>(rest)...);
4103 }
4104 
4105 template < typename OutStringType, typename Arg, typename... Args,
4106            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4107                          && !detect_string_can_append_op<OutStringType, Arg>::value
4108                          && !detect_string_can_append_iter<OutStringType, Arg>::value
4109                          && detect_string_can_append_data<OutStringType, Arg>::value, int > >
concat_into(OutStringType & out,const Arg & arg,Args &&...rest)4110 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4111 {
4112     out.append(arg.data(), arg.size());
4113     concat_into(out, std::forward<Args>(rest)...);
4114 }
4115 
4116 template<typename OutStringType = std::string, typename... Args>
concat(Args &&...args)4117 inline OutStringType concat(Args && ... args)
4118 {
4119     OutStringType str;
4120     str.reserve(concat_length(std::forward<Args>(args)...));
4121     concat_into(str, std::forward<Args>(args)...);
4122     return str;
4123 }
4124 
4125 } // namespace detail
4126 } // namespace nlohmann
4127 
4128 
4129 
4130 namespace nlohmann
4131 {
4132 namespace detail
4133 {
4134 ////////////////
4135 // exceptions //
4136 ////////////////
4137 
4138 /// @brief general exception of the @ref basic_json class
4139 /// @sa https://json.nlohmann.me/api/basic_json/exception/
4140 class exception : public std::exception
4141 {
4142   public:
4143     /// returns the explanatory string
what() const4144     const char* what() const noexcept override
4145     {
4146         return m.what();
4147     }
4148 
4149     /// the id of the exception
4150     const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4151 
4152   protected:
4153     JSON_HEDLEY_NON_NULL(3)
exception(int id_,const char * what_arg)4154     exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4155 
name(const std::string & ename,int id_)4156     static std::string name(const std::string& ename, int id_)
4157     {
4158         return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4159     }
4160 
diagnostics(std::nullptr_t)4161     static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4162     {
4163         return "";
4164     }
4165 
4166     template<typename BasicJsonType>
diagnostics(const BasicJsonType * leaf_element)4167     static std::string diagnostics(const BasicJsonType* leaf_element)
4168     {
4169 #if JSON_DIAGNOSTICS
4170         std::vector<std::string> tokens;
4171         for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4172         {
4173             switch (current->m_parent->type())
4174             {
4175                 case value_t::array:
4176                 {
4177                     for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
4178                     {
4179                         if (&current->m_parent->m_value.array->operator[](i) == current)
4180                         {
4181                             tokens.emplace_back(std::to_string(i));
4182                             break;
4183                         }
4184                     }
4185                     break;
4186                 }
4187 
4188                 case value_t::object:
4189                 {
4190                     for (const auto& element : *current->m_parent->m_value.object)
4191                     {
4192                         if (&element.second == current)
4193                         {
4194                             tokens.emplace_back(element.first.c_str());
4195                             break;
4196                         }
4197                     }
4198                     break;
4199                 }
4200 
4201                 case value_t::null: // LCOV_EXCL_LINE
4202                 case value_t::string: // LCOV_EXCL_LINE
4203                 case value_t::boolean: // LCOV_EXCL_LINE
4204                 case value_t::number_integer: // LCOV_EXCL_LINE
4205                 case value_t::number_unsigned: // LCOV_EXCL_LINE
4206                 case value_t::number_float: // LCOV_EXCL_LINE
4207                 case value_t::binary: // LCOV_EXCL_LINE
4208                 case value_t::discarded: // LCOV_EXCL_LINE
4209                 default:   // LCOV_EXCL_LINE
4210                     break; // LCOV_EXCL_LINE
4211             }
4212         }
4213 
4214         if (tokens.empty())
4215         {
4216             return "";
4217         }
4218 
4219         auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4220                                    [](const std::string & a, const std::string & b)
4221         {
4222             return concat(a, '/', detail::escape(b));
4223         });
4224         return concat('(', str, ") ");
4225 #else
4226         static_cast<void>(leaf_element);
4227         return "";
4228 #endif
4229     }
4230 
4231   private:
4232     /// an exception object as storage for error messages
4233     std::runtime_error m;
4234 };
4235 
4236 /// @brief exception indicating a parse error
4237 /// @sa https://json.nlohmann.me/api/basic_json/parse_error/
4238 class parse_error : public exception
4239 {
4240   public:
4241     /*!
4242     @brief create a parse error exception
4243     @param[in] id_       the id of the exception
4244     @param[in] pos       the position where the error occurred (or with
4245                          chars_read_total=0 if the position cannot be
4246                          determined)
4247     @param[in] what_arg  the explanatory string
4248     @return parse_error object
4249     */
4250     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
create(int id_,const position_t & pos,const std::string & what_arg,BasicJsonContext context)4251     static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4252     {
4253         std::string w = concat(exception::name("parse_error", id_), "parse error",
4254                                position_string(pos), ": ", exception::diagnostics(context), what_arg);
4255         return {id_, pos.chars_read_total, w.c_str()};
4256     }
4257 
4258     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
create(int id_,std::size_t byte_,const std::string & what_arg,BasicJsonContext context)4259     static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4260     {
4261         std::string w = concat(exception::name("parse_error", id_), "parse error",
4262                                (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4263                                ": ", exception::diagnostics(context), what_arg);
4264         return {id_, byte_, w.c_str()};
4265     }
4266 
4267     /*!
4268     @brief byte index of the parse error
4269 
4270     The byte index of the last read character in the input file.
4271 
4272     @note For an input with n bytes, 1 is the index of the first character and
4273           n+1 is the index of the terminating null byte or the end of file.
4274           This also holds true when reading a byte vector (CBOR or MessagePack).
4275     */
4276     const std::size_t byte;
4277 
4278   private:
parse_error(int id_,std::size_t byte_,const char * what_arg)4279     parse_error(int id_, std::size_t byte_, const char* what_arg)
4280         : exception(id_, what_arg), byte(byte_) {}
4281 
position_string(const position_t & pos)4282     static std::string position_string(const position_t& pos)
4283     {
4284         return concat(" at line ", std::to_string(pos.lines_read + 1),
4285                       ", column ", std::to_string(pos.chars_read_current_line));
4286     }
4287 };
4288 
4289 /// @brief exception indicating errors with iterators
4290 /// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
4291 class invalid_iterator : public exception
4292 {
4293   public:
4294     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
create(int id_,const std::string & what_arg,BasicJsonContext context)4295     static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4296     {
4297         std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4298         return {id_, w.c_str()};
4299     }
4300 
4301   private:
4302     JSON_HEDLEY_NON_NULL(3)
invalid_iterator(int id_,const char * what_arg)4303     invalid_iterator(int id_, const char* what_arg)
4304         : exception(id_, what_arg) {}
4305 };
4306 
4307 /// @brief exception indicating executing a member function with a wrong type
4308 /// @sa https://json.nlohmann.me/api/basic_json/type_error/
4309 class type_error : public exception
4310 {
4311   public:
4312     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
create(int id_,const std::string & what_arg,BasicJsonContext context)4313     static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4314     {
4315         std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4316         return {id_, w.c_str()};
4317     }
4318 
4319   private:
4320     JSON_HEDLEY_NON_NULL(3)
type_error(int id_,const char * what_arg)4321     type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4322 };
4323 
4324 /// @brief exception indicating access out of the defined range
4325 /// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
4326 class out_of_range : public exception
4327 {
4328   public:
4329     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
create(int id_,const std::string & what_arg,BasicJsonContext context)4330     static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4331     {
4332         std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4333         return {id_, w.c_str()};
4334     }
4335 
4336   private:
4337     JSON_HEDLEY_NON_NULL(3)
out_of_range(int id_,const char * what_arg)4338     out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4339 };
4340 
4341 /// @brief exception indicating other library errors
4342 /// @sa https://json.nlohmann.me/api/basic_json/other_error/
4343 class other_error : public exception
4344 {
4345   public:
4346     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
create(int id_,const std::string & what_arg,BasicJsonContext context)4347     static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4348     {
4349         std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4350         return {id_, w.c_str()};
4351     }
4352 
4353   private:
4354     JSON_HEDLEY_NON_NULL(3)
other_error(int id_,const char * what_arg)4355     other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4356 };
4357 
4358 }  // namespace detail
4359 }  // namespace nlohmann
4360 
4361 // #include <nlohmann/detail/macro_scope.hpp>
4362 
4363 // #include <nlohmann/detail/meta/cpp_future.hpp>
4364 
4365 // #include <nlohmann/detail/meta/identity_tag.hpp>
4366 //     __ _____ _____ _____
4367 //  __|  |   __|     |   | |  JSON for Modern C++
4368 // |  |  |__   |  |  | | | |  version 3.10.5
4369 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
4370 //
4371 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
4372 // SPDX-License-Identifier: MIT
4373 
4374 
4375 
4376 namespace nlohmann
4377 {
4378 namespace detail
4379 {
4380 // dispatching helper struct
4381 template <class T> struct identity_tag {};
4382 }  // namespace detail
4383 }  // namespace nlohmann
4384 
4385 // #include <nlohmann/detail/meta/type_traits.hpp>
4386 
4387 // #include <nlohmann/detail/string_concat.hpp>
4388 
4389 // #include <nlohmann/detail/value_t.hpp>
4390 
4391 
4392 #if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4393 #include <experimental/filesystem>
4394 namespace nlohmann::detail
4395 {
4396 namespace std_fs = std::experimental::filesystem;
4397 } // namespace nlohmann::detail
4398 #elif JSON_HAS_FILESYSTEM
4399 #include <filesystem>
4400 namespace nlohmann::detail
4401 {
4402 namespace std_fs = std::filesystem;
4403 } // namespace nlohmann::detail
4404 #endif
4405 
4406 namespace nlohmann
4407 {
4408 namespace detail
4409 {
4410 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename std::nullptr_t & n)4411 inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4412 {
4413     if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4414     {
4415         JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4416     }
4417     n = nullptr;
4418 }
4419 
4420 // overloads for basic_json template parameters
4421 template < typename BasicJsonType, typename ArithmeticType,
4422            enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4423                          !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4424                          int > = 0 >
get_arithmetic_value(const BasicJsonType & j,ArithmeticType & val)4425 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4426 {
4427     switch (static_cast<value_t>(j))
4428     {
4429         case value_t::number_unsigned:
4430         {
4431             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4432             break;
4433         }
4434         case value_t::number_integer:
4435         {
4436             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4437             break;
4438         }
4439         case value_t::number_float:
4440         {
4441             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4442             break;
4443         }
4444 
4445         case value_t::null:
4446         case value_t::object:
4447         case value_t::array:
4448         case value_t::string:
4449         case value_t::boolean:
4450         case value_t::binary:
4451         case value_t::discarded:
4452         default:
4453             JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4454     }
4455 }
4456 
4457 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::boolean_t & b)4458 inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4459 {
4460     if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4461     {
4462         JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4463     }
4464     b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4465 }
4466 
4467 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::string_t & s)4468 inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4469 {
4470     if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4471     {
4472         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4473     }
4474     s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4475 }
4476 
4477 template <
4478     typename BasicJsonType, typename StringType,
4479     enable_if_t <
4480         std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4481         && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4482         && !is_json_ref<StringType>::value, int > = 0 >
from_json(const BasicJsonType & j,StringType & s)4483 inline void from_json(const BasicJsonType& j, StringType& s)
4484 {
4485     if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4486     {
4487         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4488     }
4489 
4490     s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4491 }
4492 
4493 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::number_float_t & val)4494 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4495 {
4496     get_arithmetic_value(j, val);
4497 }
4498 
4499 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::number_unsigned_t & val)4500 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4501 {
4502     get_arithmetic_value(j, val);
4503 }
4504 
4505 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::number_integer_t & val)4506 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4507 {
4508     get_arithmetic_value(j, val);
4509 }
4510 
4511 #if !JSON_DISABLE_ENUM_SERIALIZATION
4512 template<typename BasicJsonType, typename EnumType,
4513          enable_if_t<std::is_enum<EnumType>::value, int> = 0>
from_json(const BasicJsonType & j,EnumType & e)4514 inline void from_json(const BasicJsonType& j, EnumType& e)
4515 {
4516     typename std::underlying_type<EnumType>::type val;
4517     get_arithmetic_value(j, val);
4518     e = static_cast<EnumType>(val);
4519 }
4520 #endif  // JSON_DISABLE_ENUM_SERIALIZATION
4521 
4522 // forward_list doesn't have an insert method
4523 template<typename BasicJsonType, typename T, typename Allocator,
4524          enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
from_json(const BasicJsonType & j,std::forward_list<T,Allocator> & l)4525 inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4526 {
4527     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4528     {
4529         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4530     }
4531     l.clear();
4532     std::transform(j.rbegin(), j.rend(),
4533                    std::front_inserter(l), [](const BasicJsonType & i)
4534     {
4535         return i.template get<T>();
4536     });
4537 }
4538 
4539 // valarray doesn't have an insert method
4540 template<typename BasicJsonType, typename T,
4541          enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
from_json(const BasicJsonType & j,std::valarray<T> & l)4542 inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
4543 {
4544     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4545     {
4546         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4547     }
4548     l.resize(j.size());
4549     std::transform(j.begin(), j.end(), std::begin(l),
4550                    [](const BasicJsonType & elem)
4551     {
4552         return elem.template get<T>();
4553     });
4554 }
4555 
4556 template<typename BasicJsonType, typename T, std::size_t N>
from_json(const BasicJsonType & j,T (& arr)[N])4557 auto from_json(const BasicJsonType& j, T (&arr)[N])  // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4558 -> decltype(j.template get<T>(), void())
4559 {
4560     for (std::size_t i = 0; i < N; ++i)
4561     {
4562         arr[i] = j.at(i).template get<T>();
4563     }
4564 }
4565 
4566 template<typename BasicJsonType>
from_json_array_impl(const BasicJsonType & j,typename BasicJsonType::array_t & arr,priority_tag<3>)4567 inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
4568 {
4569     arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
4570 }
4571 
4572 template<typename BasicJsonType, typename T, std::size_t N>
from_json_array_impl(const BasicJsonType & j,std::array<T,N> & arr,priority_tag<2>)4573 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
4574                           priority_tag<2> /*unused*/)
4575 -> decltype(j.template get<T>(), void())
4576 {
4577     for (std::size_t i = 0; i < N; ++i)
4578     {
4579         arr[i] = j.at(i).template get<T>();
4580     }
4581 }
4582 
4583 template<typename BasicJsonType, typename ConstructibleArrayType,
4584          enable_if_t<
4585              std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4586              int> = 0>
from_json_array_impl(const BasicJsonType & j,ConstructibleArrayType & arr,priority_tag<1>)4587 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4588 -> decltype(
4589     arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4590     j.template get<typename ConstructibleArrayType::value_type>(),
4591     void())
4592 {
4593     using std::end;
4594 
4595     ConstructibleArrayType ret;
4596     ret.reserve(j.size());
4597     std::transform(j.begin(), j.end(),
4598                    std::inserter(ret, end(ret)), [](const BasicJsonType & i)
4599     {
4600         // get<BasicJsonType>() returns *this, this won't call a from_json
4601         // method when value_type is BasicJsonType
4602         return i.template get<typename ConstructibleArrayType::value_type>();
4603     });
4604     arr = std::move(ret);
4605 }
4606 
4607 template<typename BasicJsonType, typename ConstructibleArrayType,
4608          enable_if_t<
4609              std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4610              int> = 0>
from_json_array_impl(const BasicJsonType & j,ConstructibleArrayType & arr,priority_tag<0>)4611 inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4612                                  priority_tag<0> /*unused*/)
4613 {
4614     using std::end;
4615 
4616     ConstructibleArrayType ret;
4617     std::transform(
4618         j.begin(), j.end(), std::inserter(ret, end(ret)),
4619         [](const BasicJsonType & i)
4620     {
4621         // get<BasicJsonType>() returns *this, this won't call a from_json
4622         // method when value_type is BasicJsonType
4623         return i.template get<typename ConstructibleArrayType::value_type>();
4624     });
4625     arr = std::move(ret);
4626 }
4627 
4628 template < typename BasicJsonType, typename ConstructibleArrayType,
4629            enable_if_t <
4630                is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4631                !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4632                !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4633                !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4634                !is_basic_json<ConstructibleArrayType>::value,
4635                int > = 0 >
from_json(const BasicJsonType & j,ConstructibleArrayType & arr)4636 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4637 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4638 j.template get<typename ConstructibleArrayType::value_type>(),
4639 void())
4640 {
4641     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4642     {
4643         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4644     }
4645 
4646     from_json_array_impl(j, arr, priority_tag<3> {});
4647 }
4648 
4649 template < typename BasicJsonType, typename T, std::size_t... Idx >
from_json_inplace_array_impl(BasicJsonType && j,identity_tag<std::array<T,sizeof...(Idx)>>,index_sequence<Idx...>)4650 std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4651         identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4652 {
4653     return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4654 }
4655 
4656 template < typename BasicJsonType, typename T, std::size_t N >
from_json(BasicJsonType && j,identity_tag<std::array<T,N>> tag)4657 auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4658 -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4659 {
4660     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4661     {
4662         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4663     }
4664 
4665     return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4666 }
4667 
4668 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::binary_t & bin)4669 inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4670 {
4671     if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4672     {
4673         JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
4674     }
4675 
4676     bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4677 }
4678 
4679 template<typename BasicJsonType, typename ConstructibleObjectType,
4680          enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
from_json(const BasicJsonType & j,ConstructibleObjectType & obj)4681 inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
4682 {
4683     if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
4684     {
4685         JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
4686     }
4687 
4688     ConstructibleObjectType ret;
4689     const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4690     using value_type = typename ConstructibleObjectType::value_type;
4691     std::transform(
4692         inner_object->begin(), inner_object->end(),
4693         std::inserter(ret, ret.begin()),
4694         [](typename BasicJsonType::object_t::value_type const & p)
4695     {
4696         return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
4697     });
4698     obj = std::move(ret);
4699 }
4700 
4701 // overload for arithmetic types, not chosen for basic_json template arguments
4702 // (BooleanType, etc..); note: Is it really necessary to provide explicit
4703 // overloads for boolean_t etc. in case of a custom BooleanType which is not
4704 // an arithmetic type?
4705 template < typename BasicJsonType, typename ArithmeticType,
4706            enable_if_t <
4707                std::is_arithmetic<ArithmeticType>::value&&
4708                !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
4709                !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
4710                !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
4711                !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4712                int > = 0 >
from_json(const BasicJsonType & j,ArithmeticType & val)4713 inline void from_json(const BasicJsonType& j, ArithmeticType& val)
4714 {
4715     switch (static_cast<value_t>(j))
4716     {
4717         case value_t::number_unsigned:
4718         {
4719             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4720             break;
4721         }
4722         case value_t::number_integer:
4723         {
4724             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4725             break;
4726         }
4727         case value_t::number_float:
4728         {
4729             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4730             break;
4731         }
4732         case value_t::boolean:
4733         {
4734             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
4735             break;
4736         }
4737 
4738         case value_t::null:
4739         case value_t::object:
4740         case value_t::array:
4741         case value_t::string:
4742         case value_t::binary:
4743         case value_t::discarded:
4744         default:
4745             JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4746     }
4747 }
4748 
4749 template<typename BasicJsonType, typename... Args, std::size_t... Idx>
from_json_tuple_impl_base(BasicJsonType && j,index_sequence<Idx...>)4750 std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
4751 {
4752     return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
4753 }
4754 
4755 template < typename BasicJsonType, class A1, class A2 >
from_json_tuple_impl(BasicJsonType && j,identity_tag<std::pair<A1,A2>>,priority_tag<0>)4756 std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
4757 {
4758     return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
4759             std::forward<BasicJsonType>(j).at(1).template get<A2>()};
4760 }
4761 
4762 template<typename BasicJsonType, typename A1, typename A2>
from_json_tuple_impl(BasicJsonType && j,std::pair<A1,A2> & p,priority_tag<1>)4763 inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
4764 {
4765     p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
4766 }
4767 
4768 template<typename BasicJsonType, typename... Args>
from_json_tuple_impl(BasicJsonType && j,identity_tag<std::tuple<Args...>>,priority_tag<2>)4769 std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
4770 {
4771     return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4772 }
4773 
4774 template<typename BasicJsonType, typename... Args>
from_json_tuple_impl(BasicJsonType && j,std::tuple<Args...> & t,priority_tag<3>)4775 inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
4776 {
4777     t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4778 }
4779 
4780 template<typename BasicJsonType, typename TupleRelated>
from_json(BasicJsonType && j,TupleRelated && t)4781 auto from_json(BasicJsonType&& j, TupleRelated&& t)
4782 -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
4783 {
4784     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4785     {
4786         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4787     }
4788 
4789     return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
4790 }
4791 
4792 template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
4793            typename = enable_if_t < !std::is_constructible <
4794                                         typename BasicJsonType::string_t, Key >::value >>
from_json(const BasicJsonType & j,std::map<Key,Value,Compare,Allocator> & m)4795 inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
4796 {
4797     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4798     {
4799         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4800     }
4801     m.clear();
4802     for (const auto& p : j)
4803     {
4804         if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
4805         {
4806             JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
4807         }
4808         m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4809     }
4810 }
4811 
4812 template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
4813            typename = enable_if_t < !std::is_constructible <
4814                                         typename BasicJsonType::string_t, Key >::value >>
from_json(const BasicJsonType & j,std::unordered_map<Key,Value,Hash,KeyEqual,Allocator> & m)4815 inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
4816 {
4817     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4818     {
4819         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4820     }
4821     m.clear();
4822     for (const auto& p : j)
4823     {
4824         if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
4825         {
4826             JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
4827         }
4828         m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4829     }
4830 }
4831 
4832 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4833 template<typename BasicJsonType>
from_json(const BasicJsonType & j,std_fs::path & p)4834 inline void from_json(const BasicJsonType& j, std_fs::path& p)
4835 {
4836     if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4837     {
4838         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4839     }
4840     p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4841 }
4842 #endif
4843 
4844 struct from_json_fn
4845 {
4846     template<typename BasicJsonType, typename T>
operator ()nlohmann::detail::from_json_fn4847     auto operator()(const BasicJsonType& j, T&& val) const
4848     noexcept(noexcept(from_json(j, std::forward<T>(val))))
4849     -> decltype(from_json(j, std::forward<T>(val)))
4850     {
4851         return from_json(j, std::forward<T>(val));
4852     }
4853 };
4854 }  // namespace detail
4855 
4856 #ifndef JSON_HAS_CPP_17
4857 /// namespace to hold default `from_json` function
4858 /// to see why this is required:
4859 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
4860 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
4861 {
4862 #endif
4863 JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
4864     detail::static_const<detail::from_json_fn>::value;
4865 #ifndef JSON_HAS_CPP_17
4866 } // namespace
4867 #endif
4868 } // namespace nlohmann
4869 
4870 // #include <nlohmann/detail/conversions/to_json.hpp>
4871 //     __ _____ _____ _____
4872 //  __|  |   __|     |   | |  JSON for Modern C++
4873 // |  |  |__   |  |  | | | |  version 3.10.5
4874 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
4875 //
4876 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
4877 // SPDX-License-Identifier: MIT
4878 
4879 
4880 
4881 #include <algorithm> // copy
4882 #include <iterator> // begin, end
4883 #include <string> // string
4884 #include <tuple> // tuple, get
4885 #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
4886 #include <utility> // move, forward, declval, pair
4887 #include <valarray> // valarray
4888 #include <vector> // vector
4889 
4890 // #include <nlohmann/detail/macro_scope.hpp>
4891 
4892 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
4893 //     __ _____ _____ _____
4894 //  __|  |   __|     |   | |  JSON for Modern C++
4895 // |  |  |__   |  |  | | | |  version 3.10.5
4896 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
4897 //
4898 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
4899 // SPDX-License-Identifier: MIT
4900 
4901 
4902 
4903 #include <cstddef> // size_t
4904 #include <iterator> // input_iterator_tag
4905 #include <string> // string, to_string
4906 #include <tuple> // tuple_size, get, tuple_element
4907 #include <utility> // move
4908 
4909 #if JSON_HAS_RANGES
4910     #include <ranges> // enable_borrowed_range
4911 #endif
4912 
4913 // #include <nlohmann/detail/meta/type_traits.hpp>
4914 
4915 // #include <nlohmann/detail/value_t.hpp>
4916 
4917 
4918 namespace nlohmann
4919 {
4920 namespace detail
4921 {
4922 template<typename string_type>
int_to_string(string_type & target,std::size_t value)4923 void int_to_string( string_type& target, std::size_t value )
4924 {
4925     // For ADL
4926     using std::to_string;
4927     target = to_string(value);
4928 }
4929 template<typename IteratorType> class iteration_proxy_value
4930 {
4931   public:
4932     using difference_type = std::ptrdiff_t;
4933     using value_type = iteration_proxy_value;
4934     using pointer = value_type *;
4935     using reference = value_type &;
4936     using iterator_category = std::input_iterator_tag;
4937     using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
4938 
4939   private:
4940     /// the iterator
4941     IteratorType anchor{};
4942     /// an index for arrays (used to create key names)
4943     std::size_t array_index = 0;
4944     /// last stringified array index
4945     mutable std::size_t array_index_last = 0;
4946     /// a string representation of the array index
4947     mutable string_type array_index_str = "0";
4948     /// an empty string (to return a reference for primitive values)
4949     string_type empty_str{};
4950 
4951   public:
4952     explicit iteration_proxy_value() = default;
iteration_proxy_value(IteratorType it,std::size_t array_index_=0)4953     explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
4954     noexcept(std::is_nothrow_move_constructible<IteratorType>::value
4955              && std::is_nothrow_default_constructible<string_type>::value)
4956         : anchor(std::move(it))
4957         , array_index(array_index_)
4958     {}
4959 
4960     iteration_proxy_value(iteration_proxy_value const&) = default;
4961     iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
4962     // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
4963     iteration_proxy_value(iteration_proxy_value&&)
4964     noexcept(std::is_nothrow_move_constructible<IteratorType>::value
4965              && std::is_nothrow_move_constructible<string_type>::value) = default;
4966     iteration_proxy_value& operator=(iteration_proxy_value&&)
4967     noexcept(std::is_nothrow_move_assignable<IteratorType>::value
4968              && std::is_nothrow_move_assignable<string_type>::value) = default;
4969     ~iteration_proxy_value() = default;
4970 
4971     /// dereference operator (needed for range-based for)
operator *() const4972     const iteration_proxy_value& operator*() const
4973     {
4974         return *this;
4975     }
4976 
4977     /// increment operator (needed for range-based for)
operator ++()4978     iteration_proxy_value& operator++()
4979     {
4980         ++anchor;
4981         ++array_index;
4982 
4983         return *this;
4984     }
4985 
operator ++(int)4986     iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
4987     {
4988         auto tmp = iteration_proxy_value(anchor, array_index);
4989         ++anchor;
4990         ++array_index;
4991         return tmp;
4992     }
4993 
4994     /// equality operator (needed for InputIterator)
operator ==(const iteration_proxy_value & o) const4995     bool operator==(const iteration_proxy_value& o) const
4996     {
4997         return anchor == o.anchor;
4998     }
4999 
5000     /// inequality operator (needed for range-based for)
operator !=(const iteration_proxy_value & o) const5001     bool operator!=(const iteration_proxy_value& o) const
5002     {
5003         return anchor != o.anchor;
5004     }
5005 
5006     /// return key of the iterator
key() const5007     const string_type& key() const
5008     {
5009         JSON_ASSERT(anchor.m_object != nullptr);
5010 
5011         switch (anchor.m_object->type())
5012         {
5013             // use integer array index as key
5014             case value_t::array:
5015             {
5016                 if (array_index != array_index_last)
5017                 {
5018                     int_to_string( array_index_str, array_index );
5019                     array_index_last = array_index;
5020                 }
5021                 return array_index_str;
5022             }
5023 
5024             // use key from the object
5025             case value_t::object:
5026                 return anchor.key();
5027 
5028             // use an empty key for all primitive types
5029             case value_t::null:
5030             case value_t::string:
5031             case value_t::boolean:
5032             case value_t::number_integer:
5033             case value_t::number_unsigned:
5034             case value_t::number_float:
5035             case value_t::binary:
5036             case value_t::discarded:
5037             default:
5038                 return empty_str;
5039         }
5040     }
5041 
5042     /// return value of the iterator
value() const5043     typename IteratorType::reference value() const
5044     {
5045         return anchor.value();
5046     }
5047 };
5048 
5049 /// proxy class for the items() function
5050 template<typename IteratorType> class iteration_proxy
5051 {
5052   private:
5053     /// the container to iterate
5054     typename IteratorType::pointer container = nullptr;
5055 
5056   public:
5057     explicit iteration_proxy() = default;
5058 
5059     /// construct iteration proxy from a container
iteration_proxy(typename IteratorType::reference cont)5060     explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5061         : container(&cont) {}
5062 
5063     iteration_proxy(iteration_proxy const&) = default;
5064     iteration_proxy& operator=(iteration_proxy const&) = default;
5065     iteration_proxy(iteration_proxy&&) noexcept = default;
5066     iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5067     ~iteration_proxy() = default;
5068 
5069     /// return iterator begin (needed for range-based for)
begin() const5070     iteration_proxy_value<IteratorType> begin() const noexcept
5071     {
5072         return iteration_proxy_value<IteratorType>(container->begin());
5073     }
5074 
5075     /// return iterator end (needed for range-based for)
end() const5076     iteration_proxy_value<IteratorType> end() const noexcept
5077     {
5078         return iteration_proxy_value<IteratorType>(container->end());
5079     }
5080 };
5081 
5082 // Structured Bindings Support
5083 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
5084 // And see https://github.com/nlohmann/json/pull/1391
5085 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
get(const nlohmann::detail::iteration_proxy_value<IteratorType> & i)5086 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5087 {
5088     return i.key();
5089 }
5090 // Structured Bindings Support
5091 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
5092 // And see https://github.com/nlohmann/json/pull/1391
5093 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
get(const nlohmann::detail::iteration_proxy_value<IteratorType> & i)5094 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5095 {
5096     return i.value();
5097 }
5098 }  // namespace detail
5099 }  // namespace nlohmann
5100 
5101 // The Addition to the STD Namespace is required to add
5102 // Structured Bindings Support to the iteration_proxy_value class
5103 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
5104 // And see https://github.com/nlohmann/json/pull/1391
5105 namespace std
5106 {
5107 #if defined(__clang__)
5108     // Fix: https://github.com/nlohmann/json/issues/1401
5109     #pragma clang diagnostic push
5110     #pragma clang diagnostic ignored "-Wmismatched-tags"
5111 #endif
5112 template<typename IteratorType>
5113 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
5114             : public std::integral_constant<std::size_t, 2> {};
5115 
5116 template<std::size_t N, typename IteratorType>
5117 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
5118 {
5119   public:
5120     using type = decltype(
5121                      get<N>(std::declval <
5122                             ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5123 };
5124 #if defined(__clang__)
5125     #pragma clang diagnostic pop
5126 #endif
5127 } // namespace std
5128 
5129 #if JSON_HAS_RANGES
5130     template <typename IteratorType>
5131     inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5132 #endif
5133 
5134 // #include <nlohmann/detail/meta/cpp_future.hpp>
5135 
5136 // #include <nlohmann/detail/meta/type_traits.hpp>
5137 
5138 // #include <nlohmann/detail/value_t.hpp>
5139 
5140 
5141 #if JSON_HAS_EXPERIMENTAL_FILESYSTEM
5142 #include <experimental/filesystem>
5143 namespace nlohmann::detail
5144 {
5145 namespace std_fs = std::experimental::filesystem;
5146 } // namespace nlohmann::detail
5147 #elif JSON_HAS_FILESYSTEM
5148 #include <filesystem>
5149 namespace nlohmann::detail
5150 {
5151 namespace std_fs = std::filesystem;
5152 } // namespace nlohmann::detail
5153 #endif
5154 
5155 namespace nlohmann
5156 {
5157 namespace detail
5158 {
5159 //////////////////
5160 // constructors //
5161 //////////////////
5162 
5163 /*
5164  * Note all external_constructor<>::construct functions need to call
5165  * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an
5166  * allocated value (e.g., a string). See bug issue
5167  * https://github.com/nlohmann/json/issues/2865 for more information.
5168  */
5169 
5170 template<value_t> struct external_constructor;
5171 
5172 template<>
5173 struct external_constructor<value_t::boolean>
5174 {
5175     template<typename BasicJsonType>
constructnlohmann::detail::external_constructor5176     static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5177     {
5178         j.m_value.destroy(j.m_type);
5179         j.m_type = value_t::boolean;
5180         j.m_value = b;
5181         j.assert_invariant();
5182     }
5183 };
5184 
5185 template<>
5186 struct external_constructor<value_t::string>
5187 {
5188     template<typename BasicJsonType>
constructnlohmann::detail::external_constructor5189     static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5190     {
5191         j.m_value.destroy(j.m_type);
5192         j.m_type = value_t::string;
5193         j.m_value = s;
5194         j.assert_invariant();
5195     }
5196 
5197     template<typename BasicJsonType>
constructnlohmann::detail::external_constructor5198     static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5199     {
5200         j.m_value.destroy(j.m_type);
5201         j.m_type = value_t::string;
5202         j.m_value = std::move(s);
5203         j.assert_invariant();
5204     }
5205 
5206     template < typename BasicJsonType, typename CompatibleStringType,
5207                enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5208                              int > = 0 >
constructnlohmann::detail::external_constructor5209     static void construct(BasicJsonType& j, const CompatibleStringType& str)
5210     {
5211         j.m_value.destroy(j.m_type);
5212         j.m_type = value_t::string;
5213         j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5214         j.assert_invariant();
5215     }
5216 };
5217 
5218 template<>
5219 struct external_constructor<value_t::binary>
5220 {
5221     template<typename BasicJsonType>
constructnlohmann::detail::external_constructor5222     static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5223     {
5224         j.m_value.destroy(j.m_type);
5225         j.m_type = value_t::binary;
5226         j.m_value = typename BasicJsonType::binary_t(b);
5227         j.assert_invariant();
5228     }
5229 
5230     template<typename BasicJsonType>
constructnlohmann::detail::external_constructor5231     static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5232     {
5233         j.m_value.destroy(j.m_type);
5234         j.m_type = value_t::binary;
5235         j.m_value = typename BasicJsonType::binary_t(std::move(b));
5236         j.assert_invariant();
5237     }
5238 };
5239 
5240 template<>
5241 struct external_constructor<value_t::number_float>
5242 {
5243     template<typename BasicJsonType>
constructnlohmann::detail::external_constructor5244     static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5245     {
5246         j.m_value.destroy(j.m_type);
5247         j.m_type = value_t::number_float;
5248         j.m_value = val;
5249         j.assert_invariant();
5250     }
5251 };
5252 
5253 template<>
5254 struct external_constructor<value_t::number_unsigned>
5255 {
5256     template<typename BasicJsonType>
constructnlohmann::detail::external_constructor5257     static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5258     {
5259         j.m_value.destroy(j.m_type);
5260         j.m_type = value_t::number_unsigned;
5261         j.m_value = val;
5262         j.assert_invariant();
5263     }
5264 };
5265 
5266 template<>
5267 struct external_constructor<value_t::number_integer>
5268 {
5269     template<typename BasicJsonType>
constructnlohmann::detail::external_constructor5270     static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5271     {
5272         j.m_value.destroy(j.m_type);
5273         j.m_type = value_t::number_integer;
5274         j.m_value = val;
5275         j.assert_invariant();
5276     }
5277 };
5278 
5279 template<>
5280 struct external_constructor<value_t::array>
5281 {
5282     template<typename BasicJsonType>
constructnlohmann::detail::external_constructor5283     static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5284     {
5285         j.m_value.destroy(j.m_type);
5286         j.m_type = value_t::array;
5287         j.m_value = arr;
5288         j.set_parents();
5289         j.assert_invariant();
5290     }
5291 
5292     template<typename BasicJsonType>
constructnlohmann::detail::external_constructor5293     static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5294     {
5295         j.m_value.destroy(j.m_type);
5296         j.m_type = value_t::array;
5297         j.m_value = std::move(arr);
5298         j.set_parents();
5299         j.assert_invariant();
5300     }
5301 
5302     template < typename BasicJsonType, typename CompatibleArrayType,
5303                enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5304                              int > = 0 >
constructnlohmann::detail::external_constructor5305     static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5306     {
5307         using std::begin;
5308         using std::end;
5309 
5310         j.m_value.destroy(j.m_type);
5311         j.m_type = value_t::array;
5312         j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5313         j.set_parents();
5314         j.assert_invariant();
5315     }
5316 
5317     template<typename BasicJsonType>
constructnlohmann::detail::external_constructor5318     static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5319     {
5320         j.m_value.destroy(j.m_type);
5321         j.m_type = value_t::array;
5322         j.m_value = value_t::array;
5323         j.m_value.array->reserve(arr.size());
5324         for (const bool x : arr)
5325         {
5326             j.m_value.array->push_back(x);
5327             j.set_parent(j.m_value.array->back());
5328         }
5329         j.assert_invariant();
5330     }
5331 
5332     template<typename BasicJsonType, typename T,
5333              enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
constructnlohmann::detail::external_constructor5334     static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5335     {
5336         j.m_value.destroy(j.m_type);
5337         j.m_type = value_t::array;
5338         j.m_value = value_t::array;
5339         j.m_value.array->resize(arr.size());
5340         if (arr.size() > 0)
5341         {
5342             std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
5343         }
5344         j.set_parents();
5345         j.assert_invariant();
5346     }
5347 };
5348 
5349 template<>
5350 struct external_constructor<value_t::object>
5351 {
5352     template<typename BasicJsonType>
constructnlohmann::detail::external_constructor5353     static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5354     {
5355         j.m_value.destroy(j.m_type);
5356         j.m_type = value_t::object;
5357         j.m_value = obj;
5358         j.set_parents();
5359         j.assert_invariant();
5360     }
5361 
5362     template<typename BasicJsonType>
constructnlohmann::detail::external_constructor5363     static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5364     {
5365         j.m_value.destroy(j.m_type);
5366         j.m_type = value_t::object;
5367         j.m_value = std::move(obj);
5368         j.set_parents();
5369         j.assert_invariant();
5370     }
5371 
5372     template < typename BasicJsonType, typename CompatibleObjectType,
5373                enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
constructnlohmann::detail::external_constructor5374     static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5375     {
5376         using std::begin;
5377         using std::end;
5378 
5379         j.m_value.destroy(j.m_type);
5380         j.m_type = value_t::object;
5381         j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5382         j.set_parents();
5383         j.assert_invariant();
5384     }
5385 };
5386 
5387 /////////////
5388 // to_json //
5389 /////////////
5390 
5391 template<typename BasicJsonType, typename T,
5392          enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
to_json(BasicJsonType & j,T b)5393 inline void to_json(BasicJsonType& j, T b) noexcept
5394 {
5395     external_constructor<value_t::boolean>::construct(j, b);
5396 }
5397 
5398 template<typename BasicJsonType,
5399          enable_if_t<std::is_convertible<const std::vector<bool>::reference&, typename BasicJsonType::boolean_t>::value, int> = 0>
to_json(BasicJsonType & j,const std::vector<bool>::reference & b)5400 inline void to_json(BasicJsonType& j, const std::vector<bool>::reference& b) noexcept
5401 {
5402     external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5403 }
5404 
5405 template<typename BasicJsonType, typename CompatibleString,
5406          enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
to_json(BasicJsonType & j,const CompatibleString & s)5407 inline void to_json(BasicJsonType& j, const CompatibleString& s)
5408 {
5409     external_constructor<value_t::string>::construct(j, s);
5410 }
5411 
5412 template<typename BasicJsonType>
to_json(BasicJsonType & j,typename BasicJsonType::string_t && s)5413 inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5414 {
5415     external_constructor<value_t::string>::construct(j, std::move(s));
5416 }
5417 
5418 template<typename BasicJsonType, typename FloatType,
5419          enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
to_json(BasicJsonType & j,FloatType val)5420 inline void to_json(BasicJsonType& j, FloatType val) noexcept
5421 {
5422     external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
5423 }
5424 
5425 template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
5426          enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
to_json(BasicJsonType & j,CompatibleNumberUnsignedType val)5427 inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
5428 {
5429     external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5430 }
5431 
5432 template<typename BasicJsonType, typename CompatibleNumberIntegerType,
5433          enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
to_json(BasicJsonType & j,CompatibleNumberIntegerType val)5434 inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
5435 {
5436     external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
5437 }
5438 
5439 #if !JSON_DISABLE_ENUM_SERIALIZATION
5440 template<typename BasicJsonType, typename EnumType,
5441          enable_if_t<std::is_enum<EnumType>::value, int> = 0>
to_json(BasicJsonType & j,EnumType e)5442 inline void to_json(BasicJsonType& j, EnumType e) noexcept
5443 {
5444     using underlying_type = typename std::underlying_type<EnumType>::type;
5445     external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
5446 }
5447 #endif  // JSON_DISABLE_ENUM_SERIALIZATION
5448 
5449 template<typename BasicJsonType>
to_json(BasicJsonType & j,const std::vector<bool> & e)5450 inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
5451 {
5452     external_constructor<value_t::array>::construct(j, e);
5453 }
5454 
5455 template < typename BasicJsonType, typename CompatibleArrayType,
5456            enable_if_t < is_compatible_array_type<BasicJsonType,
5457                          CompatibleArrayType>::value&&
5458                          !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
5459                          !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
5460                          !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
5461                          !is_basic_json<CompatibleArrayType>::value,
5462                          int > = 0 >
to_json(BasicJsonType & j,const CompatibleArrayType & arr)5463 inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
5464 {
5465     external_constructor<value_t::array>::construct(j, arr);
5466 }
5467 
5468 template<typename BasicJsonType>
to_json(BasicJsonType & j,const typename BasicJsonType::binary_t & bin)5469 inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
5470 {
5471     external_constructor<value_t::binary>::construct(j, bin);
5472 }
5473 
5474 template<typename BasicJsonType, typename T,
5475          enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
to_json(BasicJsonType & j,const std::valarray<T> & arr)5476 inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
5477 {
5478     external_constructor<value_t::array>::construct(j, std::move(arr));
5479 }
5480 
5481 template<typename BasicJsonType>
to_json(BasicJsonType & j,typename BasicJsonType::array_t && arr)5482 inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5483 {
5484     external_constructor<value_t::array>::construct(j, std::move(arr));
5485 }
5486 
5487 template < typename BasicJsonType, typename CompatibleObjectType,
5488            enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
to_json(BasicJsonType & j,const CompatibleObjectType & obj)5489 inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
5490 {
5491     external_constructor<value_t::object>::construct(j, obj);
5492 }
5493 
5494 template<typename BasicJsonType>
to_json(BasicJsonType & j,typename BasicJsonType::object_t && obj)5495 inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5496 {
5497     external_constructor<value_t::object>::construct(j, std::move(obj));
5498 }
5499 
5500 template <
5501     typename BasicJsonType, typename T, std::size_t N,
5502     enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
5503                   const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5504                   int > = 0 >
to_json(BasicJsonType & j,const T (& arr)[N])5505 inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5506 {
5507     external_constructor<value_t::array>::construct(j, arr);
5508 }
5509 
5510 template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
to_json(BasicJsonType & j,const std::pair<T1,T2> & p)5511 inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
5512 {
5513     j = { p.first, p.second };
5514 }
5515 
5516 // for https://github.com/nlohmann/json/pull/1134
5517 template<typename BasicJsonType, typename T,
5518          enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
to_json(BasicJsonType & j,const T & b)5519 inline void to_json(BasicJsonType& j, const T& b)
5520 {
5521     j = { {b.key(), b.value()} };
5522 }
5523 
5524 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
to_json_tuple_impl(BasicJsonType & j,const Tuple & t,index_sequence<Idx...>)5525 inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
5526 {
5527     j = { std::get<Idx>(t)... };
5528 }
5529 
5530 template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
to_json(BasicJsonType & j,const T & t)5531 inline void to_json(BasicJsonType& j, const T& t)
5532 {
5533     to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
5534 }
5535 
5536 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5537 template<typename BasicJsonType>
to_json(BasicJsonType & j,const std_fs::path & p)5538 inline void to_json(BasicJsonType& j, const std_fs::path& p)
5539 {
5540     j = p.string();
5541 }
5542 #endif
5543 
5544 struct to_json_fn
5545 {
5546     template<typename BasicJsonType, typename T>
operator ()nlohmann::detail::to_json_fn5547     auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
5548     -> decltype(to_json(j, std::forward<T>(val)), void())
5549     {
5550         return to_json(j, std::forward<T>(val));
5551     }
5552 };
5553 }  // namespace detail
5554 
5555 #ifndef JSON_HAS_CPP_17
5556 /// namespace to hold default `to_json` function
5557 /// to see why this is required:
5558 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
5559 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5560 {
5561 #endif
5562 JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
5563     detail::static_const<detail::to_json_fn>::value;
5564 #ifndef JSON_HAS_CPP_17
5565 } // namespace
5566 #endif
5567 } // namespace nlohmann
5568 
5569 // #include <nlohmann/detail/meta/identity_tag.hpp>
5570 
5571 // #include <nlohmann/detail/meta/type_traits.hpp>
5572 
5573 
5574 namespace nlohmann
5575 {
5576 
5577 /// @sa https://json.nlohmann.me/api/adl_serializer/
5578 template<typename ValueType, typename>
5579 struct adl_serializer
5580 {
5581     /// @brief convert a JSON value to any value type
5582     /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
5583     template<typename BasicJsonType, typename TargetType = ValueType>
from_jsonnlohmann::adl_serializer5584     static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
5585         noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
5586     -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
5587     {
5588         ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
5589     }
5590 
5591     /// @brief convert a JSON value to any value type
5592     /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
5593     template<typename BasicJsonType, typename TargetType = ValueType>
from_jsonnlohmann::adl_serializer5594     static auto from_json(BasicJsonType && j) noexcept(
5595     noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
5596     -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
5597     {
5598         return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
5599     }
5600 
5601     /// @brief convert any value type to a JSON value
5602     /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
5603     template<typename BasicJsonType, typename TargetType = ValueType>
to_jsonnlohmann::adl_serializer5604     static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
5605         noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
5606     -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
5607     {
5608         ::nlohmann::to_json(j, std::forward<TargetType>(val));
5609     }
5610 };
5611 }  // namespace nlohmann
5612 
5613 // #include <nlohmann/byte_container_with_subtype.hpp>
5614 //     __ _____ _____ _____
5615 //  __|  |   __|     |   | |  JSON for Modern C++
5616 // |  |  |__   |  |  | | | |  version 3.10.5
5617 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5618 //
5619 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
5620 // SPDX-License-Identifier: MIT
5621 
5622 
5623 
5624 #include <cstdint> // uint8_t, uint64_t
5625 #include <tuple> // tie
5626 #include <utility> // move
5627 
5628 namespace nlohmann
5629 {
5630 
5631 /// @brief an internal type for a backed binary type
5632 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
5633 template<typename BinaryType>
5634 class byte_container_with_subtype : public BinaryType
5635 {
5636   public:
5637     using container_type = BinaryType;
5638     using subtype_type = std::uint64_t;
5639 
5640     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
byte_container_with_subtype()5641     byte_container_with_subtype() noexcept(noexcept(container_type()))
5642         : container_type()
5643     {}
5644 
5645     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
byte_container_with_subtype(const container_type & b)5646     byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
5647         : container_type(b)
5648     {}
5649 
5650     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
byte_container_with_subtype(container_type && b)5651     byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
5652         : container_type(std::move(b))
5653     {}
5654 
5655     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
byte_container_with_subtype(const container_type & b,subtype_type subtype_)5656     byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
5657         : container_type(b)
5658         , m_subtype(subtype_)
5659         , m_has_subtype(true)
5660     {}
5661 
5662     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
byte_container_with_subtype(container_type && b,subtype_type subtype_)5663     byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
5664         : container_type(std::move(b))
5665         , m_subtype(subtype_)
5666         , m_has_subtype(true)
5667     {}
5668 
operator ==(const byte_container_with_subtype & rhs) const5669     bool operator==(const byte_container_with_subtype& rhs) const
5670     {
5671         return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
5672                std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5673     }
5674 
operator !=(const byte_container_with_subtype & rhs) const5675     bool operator!=(const byte_container_with_subtype& rhs) const
5676     {
5677         return !(rhs == *this);
5678     }
5679 
5680     /// @brief sets the binary subtype
5681     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/
set_subtype(subtype_type subtype_)5682     void set_subtype(subtype_type subtype_) noexcept
5683     {
5684         m_subtype = subtype_;
5685         m_has_subtype = true;
5686     }
5687 
5688     /// @brief return the binary subtype
5689     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/
subtype() const5690     constexpr subtype_type subtype() const noexcept
5691     {
5692         return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
5693     }
5694 
5695     /// @brief return whether the value has a subtype
5696     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/
has_subtype() const5697     constexpr bool has_subtype() const noexcept
5698     {
5699         return m_has_subtype;
5700     }
5701 
5702     /// @brief clears the binary subtype
5703     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/
clear_subtype()5704     void clear_subtype() noexcept
5705     {
5706         m_subtype = 0;
5707         m_has_subtype = false;
5708     }
5709 
5710   private:
5711     subtype_type m_subtype = 0;
5712     bool m_has_subtype = false;
5713 };
5714 
5715 }  // namespace nlohmann
5716 
5717 // #include <nlohmann/detail/conversions/from_json.hpp>
5718 
5719 // #include <nlohmann/detail/conversions/to_json.hpp>
5720 
5721 // #include <nlohmann/detail/exceptions.hpp>
5722 
5723 // #include <nlohmann/detail/hash.hpp>
5724 //     __ _____ _____ _____
5725 //  __|  |   __|     |   | |  JSON for Modern C++
5726 // |  |  |__   |  |  | | | |  version 3.10.5
5727 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5728 //
5729 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
5730 // SPDX-License-Identifier: MIT
5731 
5732 
5733 
5734 #include <cstdint> // uint8_t
5735 #include <cstddef> // size_t
5736 #include <functional> // hash
5737 
5738 // #include <nlohmann/detail/macro_scope.hpp>
5739 
5740 // #include <nlohmann/detail/value_t.hpp>
5741 
5742 
5743 namespace nlohmann
5744 {
5745 namespace detail
5746 {
5747 
5748 // boost::hash_combine
combine(std::size_t seed,std::size_t h)5749 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
5750 {
5751     seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
5752     return seed;
5753 }
5754 
5755 /*!
5756 @brief hash a JSON value
5757 
5758 The hash function tries to rely on std::hash where possible. Furthermore, the
5759 type of the JSON value is taken into account to have different hash values for
5760 null, 0, 0U, and false, etc.
5761 
5762 @tparam BasicJsonType basic_json specialization
5763 @param j JSON value to hash
5764 @return hash value of j
5765 */
5766 template<typename BasicJsonType>
hash(const BasicJsonType & j)5767 std::size_t hash(const BasicJsonType& j)
5768 {
5769     using string_t = typename BasicJsonType::string_t;
5770     using number_integer_t = typename BasicJsonType::number_integer_t;
5771     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5772     using number_float_t = typename BasicJsonType::number_float_t;
5773 
5774     const auto type = static_cast<std::size_t>(j.type());
5775     switch (j.type())
5776     {
5777         case BasicJsonType::value_t::null:
5778         case BasicJsonType::value_t::discarded:
5779         {
5780             return combine(type, 0);
5781         }
5782 
5783         case BasicJsonType::value_t::object:
5784         {
5785             auto seed = combine(type, j.size());
5786             for (const auto& element : j.items())
5787             {
5788                 const auto h = std::hash<string_t> {}(element.key());
5789                 seed = combine(seed, h);
5790                 seed = combine(seed, hash(element.value()));
5791             }
5792             return seed;
5793         }
5794 
5795         case BasicJsonType::value_t::array:
5796         {
5797             auto seed = combine(type, j.size());
5798             for (const auto& element : j)
5799             {
5800                 seed = combine(seed, hash(element));
5801             }
5802             return seed;
5803         }
5804 
5805         case BasicJsonType::value_t::string:
5806         {
5807             const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
5808             return combine(type, h);
5809         }
5810 
5811         case BasicJsonType::value_t::boolean:
5812         {
5813             const auto h = std::hash<bool> {}(j.template get<bool>());
5814             return combine(type, h);
5815         }
5816 
5817         case BasicJsonType::value_t::number_integer:
5818         {
5819             const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
5820             return combine(type, h);
5821         }
5822 
5823         case BasicJsonType::value_t::number_unsigned:
5824         {
5825             const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
5826             return combine(type, h);
5827         }
5828 
5829         case BasicJsonType::value_t::number_float:
5830         {
5831             const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
5832             return combine(type, h);
5833         }
5834 
5835         case BasicJsonType::value_t::binary:
5836         {
5837             auto seed = combine(type, j.get_binary().size());
5838             const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
5839             seed = combine(seed, h);
5840             seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
5841             for (const auto byte : j.get_binary())
5842             {
5843                 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
5844             }
5845             return seed;
5846         }
5847 
5848         default:                   // LCOV_EXCL_LINE
5849             JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
5850             return 0;              // LCOV_EXCL_LINE
5851     }
5852 }
5853 
5854 }  // namespace detail
5855 }  // namespace nlohmann
5856 
5857 // #include <nlohmann/detail/input/binary_reader.hpp>
5858 //     __ _____ _____ _____
5859 //  __|  |   __|     |   | |  JSON for Modern C++
5860 // |  |  |__   |  |  | | | |  version 3.10.5
5861 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5862 //
5863 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
5864 // SPDX-License-Identifier: MIT
5865 
5866 
5867 
5868 #include <algorithm> // generate_n
5869 #include <array> // array
5870 #include <cmath> // ldexp
5871 #include <cstddef> // size_t
5872 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
5873 #include <cstdio> // snprintf
5874 #include <cstring> // memcpy
5875 #include <iterator> // back_inserter
5876 #include <limits> // numeric_limits
5877 #include <string> // char_traits, string
5878 #include <utility> // make_pair, move
5879 #include <vector> // vector
5880 #include <map> // map
5881 
5882 // #include <nlohmann/detail/exceptions.hpp>
5883 
5884 // #include <nlohmann/detail/input/input_adapters.hpp>
5885 //     __ _____ _____ _____
5886 //  __|  |   __|     |   | |  JSON for Modern C++
5887 // |  |  |__   |  |  | | | |  version 3.10.5
5888 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5889 //
5890 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
5891 // SPDX-License-Identifier: MIT
5892 
5893 
5894 
5895 #include <array> // array
5896 #include <cstddef> // size_t
5897 #include <cstring> // strlen
5898 #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
5899 #include <memory> // shared_ptr, make_shared, addressof
5900 #include <numeric> // accumulate
5901 #include <string> // string, char_traits
5902 #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
5903 #include <utility> // pair, declval
5904 
5905 #ifndef JSON_NO_IO
5906     #include <cstdio>   // FILE *
5907     #include <istream>  // istream
5908 #endif                  // JSON_NO_IO
5909 
5910 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
5911 
5912 // #include <nlohmann/detail/macro_scope.hpp>
5913 
5914 
5915 namespace nlohmann
5916 {
5917 namespace detail
5918 {
5919 /// the supported input formats
5920 enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
5921 
5922 ////////////////////
5923 // input adapters //
5924 ////////////////////
5925 
5926 #ifndef JSON_NO_IO
5927 /*!
5928 Input adapter for stdio file access. This adapter read only 1 byte and do not use any
5929  buffer. This adapter is a very low level adapter.
5930 */
5931 class file_input_adapter
5932 {
5933   public:
5934     using char_type = char;
5935 
5936     JSON_HEDLEY_NON_NULL(2)
file_input_adapter(std::FILE * f)5937     explicit file_input_adapter(std::FILE* f) noexcept
5938         : m_file(f)
5939     {
5940         JSON_ASSERT(m_file != nullptr);
5941     }
5942 
5943     // make class move-only
5944     file_input_adapter(const file_input_adapter&) = delete;
5945     file_input_adapter(file_input_adapter&&) noexcept = default;
5946     file_input_adapter& operator=(const file_input_adapter&) = delete;
5947     file_input_adapter& operator=(file_input_adapter&&) = delete;
5948     ~file_input_adapter() = default;
5949 
get_character()5950     std::char_traits<char>::int_type get_character() noexcept
5951     {
5952         return std::fgetc(m_file);
5953     }
5954 
5955   private:
5956     /// the file pointer to read from
5957     std::FILE* m_file;
5958 };
5959 
5960 
5961 /*!
5962 Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
5963 beginning of input. Does not support changing the underlying std::streambuf
5964 in mid-input. Maintains underlying std::istream and std::streambuf to support
5965 subsequent use of standard std::istream operations to process any input
5966 characters following those used in parsing the JSON input.  Clears the
5967 std::istream flags; any input errors (e.g., EOF) will be detected by the first
5968 subsequent call for input from the std::istream.
5969 */
5970 class input_stream_adapter
5971 {
5972   public:
5973     using char_type = char;
5974 
~input_stream_adapter()5975     ~input_stream_adapter()
5976     {
5977         // clear stream flags; we use underlying streambuf I/O, do not
5978         // maintain ifstream flags, except eof
5979         if (is != nullptr)
5980         {
5981             is->clear(is->rdstate() & std::ios::eofbit);
5982         }
5983     }
5984 
input_stream_adapter(std::istream & i)5985     explicit input_stream_adapter(std::istream& i)
5986         : is(&i), sb(i.rdbuf())
5987     {}
5988 
5989     // delete because of pointer members
5990     input_stream_adapter(const input_stream_adapter&) = delete;
5991     input_stream_adapter& operator=(input_stream_adapter&) = delete;
5992     input_stream_adapter& operator=(input_stream_adapter&&) = delete;
5993 
input_stream_adapter(input_stream_adapter && rhs)5994     input_stream_adapter(input_stream_adapter&& rhs) noexcept
5995         : is(rhs.is), sb(rhs.sb)
5996     {
5997         rhs.is = nullptr;
5998         rhs.sb = nullptr;
5999     }
6000 
6001     // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6002     // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6003     // end up as the same value, e.g. 0xFFFFFFFF.
get_character()6004     std::char_traits<char>::int_type get_character()
6005     {
6006         auto res = sb->sbumpc();
6007         // set eof manually, as we don't use the istream interface.
6008         if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6009         {
6010             is->clear(is->rdstate() | std::ios::eofbit);
6011         }
6012         return res;
6013     }
6014 
6015   private:
6016     /// the associated input stream
6017     std::istream* is = nullptr;
6018     std::streambuf* sb = nullptr;
6019 };
6020 #endif  // JSON_NO_IO
6021 
6022 // General-purpose iterator-based adapter. It might not be as fast as
6023 // theoretically possible for some containers, but it is extremely versatile.
6024 template<typename IteratorType>
6025 class iterator_input_adapter
6026 {
6027   public:
6028     using char_type = typename std::iterator_traits<IteratorType>::value_type;
6029 
iterator_input_adapter(IteratorType first,IteratorType last)6030     iterator_input_adapter(IteratorType first, IteratorType last)
6031         : current(std::move(first)), end(std::move(last))
6032     {}
6033 
get_character()6034     typename std::char_traits<char_type>::int_type get_character()
6035     {
6036         if (JSON_HEDLEY_LIKELY(current != end))
6037         {
6038             auto result = std::char_traits<char_type>::to_int_type(*current);
6039             std::advance(current, 1);
6040             return result;
6041         }
6042 
6043         return std::char_traits<char_type>::eof();
6044     }
6045 
6046   private:
6047     IteratorType current;
6048     IteratorType end;
6049 
6050     template<typename BaseInputAdapter, size_t T>
6051     friend struct wide_string_input_helper;
6052 
empty() const6053     bool empty() const
6054     {
6055         return current == end;
6056     }
6057 };
6058 
6059 
6060 template<typename BaseInputAdapter, size_t T>
6061 struct wide_string_input_helper;
6062 
6063 template<typename BaseInputAdapter>
6064 struct wide_string_input_helper<BaseInputAdapter, 4>
6065 {
6066     // UTF-32
fill_buffernlohmann::detail::wide_string_input_helper6067     static void fill_buffer(BaseInputAdapter& input,
6068                             std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6069                             size_t& utf8_bytes_index,
6070                             size_t& utf8_bytes_filled)
6071     {
6072         utf8_bytes_index = 0;
6073 
6074         if (JSON_HEDLEY_UNLIKELY(input.empty()))
6075         {
6076             utf8_bytes[0] = std::char_traits<char>::eof();
6077             utf8_bytes_filled = 1;
6078         }
6079         else
6080         {
6081             // get the current character
6082             const auto wc = input.get_character();
6083 
6084             // UTF-32 to UTF-8 encoding
6085             if (wc < 0x80)
6086             {
6087                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6088                 utf8_bytes_filled = 1;
6089             }
6090             else if (wc <= 0x7FF)
6091             {
6092                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6093                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6094                 utf8_bytes_filled = 2;
6095             }
6096             else if (wc <= 0xFFFF)
6097             {
6098                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6099                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6100                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6101                 utf8_bytes_filled = 3;
6102             }
6103             else if (wc <= 0x10FFFF)
6104             {
6105                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6106                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6107                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6108                 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6109                 utf8_bytes_filled = 4;
6110             }
6111             else
6112             {
6113                 // unknown character
6114                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6115                 utf8_bytes_filled = 1;
6116             }
6117         }
6118     }
6119 };
6120 
6121 template<typename BaseInputAdapter>
6122 struct wide_string_input_helper<BaseInputAdapter, 2>
6123 {
6124     // UTF-16
fill_buffernlohmann::detail::wide_string_input_helper6125     static void fill_buffer(BaseInputAdapter& input,
6126                             std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6127                             size_t& utf8_bytes_index,
6128                             size_t& utf8_bytes_filled)
6129     {
6130         utf8_bytes_index = 0;
6131 
6132         if (JSON_HEDLEY_UNLIKELY(input.empty()))
6133         {
6134             utf8_bytes[0] = std::char_traits<char>::eof();
6135             utf8_bytes_filled = 1;
6136         }
6137         else
6138         {
6139             // get the current character
6140             const auto wc = input.get_character();
6141 
6142             // UTF-16 to UTF-8 encoding
6143             if (wc < 0x80)
6144             {
6145                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6146                 utf8_bytes_filled = 1;
6147             }
6148             else if (wc <= 0x7FF)
6149             {
6150                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6151                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6152                 utf8_bytes_filled = 2;
6153             }
6154             else if (0xD800 > wc || wc >= 0xE000)
6155             {
6156                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6157                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6158                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6159                 utf8_bytes_filled = 3;
6160             }
6161             else
6162             {
6163                 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6164                 {
6165                     const auto wc2 = static_cast<unsigned int>(input.get_character());
6166                     const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6167                     utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6168                     utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6169                     utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6170                     utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6171                     utf8_bytes_filled = 4;
6172                 }
6173                 else
6174                 {
6175                     utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6176                     utf8_bytes_filled = 1;
6177                 }
6178             }
6179         }
6180     }
6181 };
6182 
6183 // Wraps another input apdater to convert wide character types into individual bytes.
6184 template<typename BaseInputAdapter, typename WideCharType>
6185 class wide_string_input_adapter
6186 {
6187   public:
6188     using char_type = char;
6189 
wide_string_input_adapter(BaseInputAdapter base)6190     wide_string_input_adapter(BaseInputAdapter base)
6191         : base_adapter(base) {}
6192 
get_character()6193     typename std::char_traits<char>::int_type get_character() noexcept
6194     {
6195         // check if buffer needs to be filled
6196         if (utf8_bytes_index == utf8_bytes_filled)
6197         {
6198             fill_buffer<sizeof(WideCharType)>();
6199 
6200             JSON_ASSERT(utf8_bytes_filled > 0);
6201             JSON_ASSERT(utf8_bytes_index == 0);
6202         }
6203 
6204         // use buffer
6205         JSON_ASSERT(utf8_bytes_filled > 0);
6206         JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6207         return utf8_bytes[utf8_bytes_index++];
6208     }
6209 
6210   private:
6211     BaseInputAdapter base_adapter;
6212 
6213     template<size_t T>
fill_buffer()6214     void fill_buffer()
6215     {
6216         wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6217     }
6218 
6219     /// a buffer for UTF-8 bytes
6220     std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6221 
6222     /// index to the utf8_codes array for the next valid byte
6223     std::size_t utf8_bytes_index = 0;
6224     /// number of valid bytes in the utf8_codes array
6225     std::size_t utf8_bytes_filled = 0;
6226 };
6227 
6228 
6229 template<typename IteratorType, typename Enable = void>
6230 struct iterator_input_adapter_factory
6231 {
6232     using iterator_type = IteratorType;
6233     using char_type = typename std::iterator_traits<iterator_type>::value_type;
6234     using adapter_type = iterator_input_adapter<iterator_type>;
6235 
createnlohmann::detail::iterator_input_adapter_factory6236     static adapter_type create(IteratorType first, IteratorType last)
6237     {
6238         return adapter_type(std::move(first), std::move(last));
6239     }
6240 };
6241 
6242 template<typename T>
6243 struct is_iterator_of_multibyte
6244 {
6245     using value_type = typename std::iterator_traits<T>::value_type;
6246     enum
6247     {
6248         value = sizeof(value_type) > 1
6249     };
6250 };
6251 
6252 template<typename IteratorType>
6253 struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
6254 {
6255     using iterator_type = IteratorType;
6256     using char_type = typename std::iterator_traits<iterator_type>::value_type;
6257     using base_adapter_type = iterator_input_adapter<iterator_type>;
6258     using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
6259 
createnlohmann::detail::iterator_input_adapter_factory6260     static adapter_type create(IteratorType first, IteratorType last)
6261     {
6262         return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6263     }
6264 };
6265 
6266 // General purpose iterator-based input
6267 template<typename IteratorType>
input_adapter(IteratorType first,IteratorType last)6268 typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
6269 {
6270     using factory_type = iterator_input_adapter_factory<IteratorType>;
6271     return factory_type::create(first, last);
6272 }
6273 
6274 // Convenience shorthand from container to iterator
6275 // Enables ADL on begin(container) and end(container)
6276 // Encloses the using declarations in namespace for not to leak them to outside scope
6277 
6278 namespace container_input_adapter_factory_impl
6279 {
6280 
6281 using std::begin;
6282 using std::end;
6283 
6284 template<typename ContainerType, typename Enable = void>
6285 struct container_input_adapter_factory {};
6286 
6287 template<typename ContainerType>
6288 struct container_input_adapter_factory< ContainerType,
6289        void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6290        {
6291            using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6292 
createnlohmann::detail::container_input_adapter_factory_impl::container_input_adapter_factory6293            static adapter_type create(const ContainerType& container)
6294 {
6295     return input_adapter(begin(container), end(container));
6296 }
6297        };
6298 
6299 } // namespace container_input_adapter_factory_impl
6300 
6301 template<typename ContainerType>
input_adapter(const ContainerType & container)6302 typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
6303 {
6304     return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
6305 }
6306 
6307 #ifndef JSON_NO_IO
6308 // Special cases with fast paths
input_adapter(std::FILE * file)6309 inline file_input_adapter input_adapter(std::FILE* file)
6310 {
6311     return file_input_adapter(file);
6312 }
6313 
input_adapter(std::istream & stream)6314 inline input_stream_adapter input_adapter(std::istream& stream)
6315 {
6316     return input_stream_adapter(stream);
6317 }
6318 
input_adapter(std::istream && stream)6319 inline input_stream_adapter input_adapter(std::istream&& stream)
6320 {
6321     return input_stream_adapter(stream);
6322 }
6323 #endif  // JSON_NO_IO
6324 
6325 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6326 
6327 // Null-delimited strings, and the like.
6328 template < typename CharT,
6329            typename std::enable_if <
6330                std::is_pointer<CharT>::value&&
6331                !std::is_array<CharT>::value&&
6332                std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6333                sizeof(typename std::remove_pointer<CharT>::type) == 1,
6334                int >::type = 0 >
input_adapter(CharT b)6335 contiguous_bytes_input_adapter input_adapter(CharT b)
6336 {
6337     auto length = std::strlen(reinterpret_cast<const char*>(b));
6338     const auto* ptr = reinterpret_cast<const char*>(b);
6339     return input_adapter(ptr, ptr + length);
6340 }
6341 
6342 template<typename T, std::size_t N>
input_adapter(T (& array)[N])6343 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)
6344 {
6345     return input_adapter(array, array + N);
6346 }
6347 
6348 // This class only handles inputs of input_buffer_adapter type.
6349 // It's required so that expressions like {ptr, len} can be implicitly cast
6350 // to the correct adapter.
6351 class span_input_adapter
6352 {
6353   public:
6354     template < typename CharT,
6355                typename std::enable_if <
6356                    std::is_pointer<CharT>::value&&
6357                    std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6358                    sizeof(typename std::remove_pointer<CharT>::type) == 1,
6359                    int >::type = 0 >
span_input_adapter(CharT b,std::size_t l)6360     span_input_adapter(CharT b, std::size_t l)
6361         : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6362 
6363     template<class IteratorType,
6364              typename std::enable_if<
6365                  std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
6366                  int>::type = 0>
span_input_adapter(IteratorType first,IteratorType last)6367     span_input_adapter(IteratorType first, IteratorType last)
6368         : ia(input_adapter(first, last)) {}
6369 
get()6370     contiguous_bytes_input_adapter&& get()
6371     {
6372         return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6373     }
6374 
6375   private:
6376     contiguous_bytes_input_adapter ia;
6377 };
6378 }  // namespace detail
6379 }  // namespace nlohmann
6380 
6381 // #include <nlohmann/detail/input/json_sax.hpp>
6382 //     __ _____ _____ _____
6383 //  __|  |   __|     |   | |  JSON for Modern C++
6384 // |  |  |__   |  |  | | | |  version 3.10.5
6385 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
6386 //
6387 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
6388 // SPDX-License-Identifier: MIT
6389 
6390 
6391 
6392 #include <cstddef>
6393 #include <string> // string
6394 #include <utility> // move
6395 #include <vector> // vector
6396 
6397 // #include <nlohmann/detail/exceptions.hpp>
6398 
6399 // #include <nlohmann/detail/macro_scope.hpp>
6400 
6401 // #include <nlohmann/detail/string_concat.hpp>
6402 
6403 
6404 namespace nlohmann
6405 {
6406 
6407 /*!
6408 @brief SAX interface
6409 
6410 This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
6411 Each function is called in different situations while the input is parsed. The
6412 boolean return value informs the parser whether to continue processing the
6413 input.
6414 */
6415 template<typename BasicJsonType>
6416 struct json_sax
6417 {
6418     using number_integer_t = typename BasicJsonType::number_integer_t;
6419     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6420     using number_float_t = typename BasicJsonType::number_float_t;
6421     using string_t = typename BasicJsonType::string_t;
6422     using binary_t = typename BasicJsonType::binary_t;
6423 
6424     /*!
6425     @brief a null value was read
6426     @return whether parsing should proceed
6427     */
6428     virtual bool null() = 0;
6429 
6430     /*!
6431     @brief a boolean value was read
6432     @param[in] val  boolean value
6433     @return whether parsing should proceed
6434     */
6435     virtual bool boolean(bool val) = 0;
6436 
6437     /*!
6438     @brief an integer number was read
6439     @param[in] val  integer value
6440     @return whether parsing should proceed
6441     */
6442     virtual bool number_integer(number_integer_t val) = 0;
6443 
6444     /*!
6445     @brief an unsigned integer number was read
6446     @param[in] val  unsigned integer value
6447     @return whether parsing should proceed
6448     */
6449     virtual bool number_unsigned(number_unsigned_t val) = 0;
6450 
6451     /*!
6452     @brief a floating-point number was read
6453     @param[in] val  floating-point value
6454     @param[in] s    raw token value
6455     @return whether parsing should proceed
6456     */
6457     virtual bool number_float(number_float_t val, const string_t& s) = 0;
6458 
6459     /*!
6460     @brief a string value was read
6461     @param[in] val  string value
6462     @return whether parsing should proceed
6463     @note It is safe to move the passed string value.
6464     */
6465     virtual bool string(string_t& val) = 0;
6466 
6467     /*!
6468     @brief a binary value was read
6469     @param[in] val  binary value
6470     @return whether parsing should proceed
6471     @note It is safe to move the passed binary value.
6472     */
6473     virtual bool binary(binary_t& val) = 0;
6474 
6475     /*!
6476     @brief the beginning of an object was read
6477     @param[in] elements  number of object elements or -1 if unknown
6478     @return whether parsing should proceed
6479     @note binary formats may report the number of elements
6480     */
6481     virtual bool start_object(std::size_t elements) = 0;
6482 
6483     /*!
6484     @brief an object key was read
6485     @param[in] val  object key
6486     @return whether parsing should proceed
6487     @note It is safe to move the passed string.
6488     */
6489     virtual bool key(string_t& val) = 0;
6490 
6491     /*!
6492     @brief the end of an object was read
6493     @return whether parsing should proceed
6494     */
6495     virtual bool end_object() = 0;
6496 
6497     /*!
6498     @brief the beginning of an array was read
6499     @param[in] elements  number of array elements or -1 if unknown
6500     @return whether parsing should proceed
6501     @note binary formats may report the number of elements
6502     */
6503     virtual bool start_array(std::size_t elements) = 0;
6504 
6505     /*!
6506     @brief the end of an array was read
6507     @return whether parsing should proceed
6508     */
6509     virtual bool end_array() = 0;
6510 
6511     /*!
6512     @brief a parse error occurred
6513     @param[in] position    the position in the input where the error occurs
6514     @param[in] last_token  the last read token
6515     @param[in] ex          an exception object describing the error
6516     @return whether parsing should proceed (must return false)
6517     */
6518     virtual bool parse_error(std::size_t position,
6519                              const std::string& last_token,
6520                              const detail::exception& ex) = 0;
6521 
6522     json_sax() = default;
6523     json_sax(const json_sax&) = default;
6524     json_sax(json_sax&&) noexcept = default;
6525     json_sax& operator=(const json_sax&) = default;
6526     json_sax& operator=(json_sax&&) noexcept = default;
6527     virtual ~json_sax() = default;
6528 };
6529 
6530 
6531 namespace detail
6532 {
6533 /*!
6534 @brief SAX implementation to create a JSON value from SAX events
6535 
6536 This class implements the @ref json_sax interface and processes the SAX events
6537 to create a JSON value which makes it basically a DOM parser. The structure or
6538 hierarchy of the JSON value is managed by the stack `ref_stack` which contains
6539 a pointer to the respective array or object for each recursion depth.
6540 
6541 After successful parsing, the value that is passed by reference to the
6542 constructor contains the parsed value.
6543 
6544 @tparam BasicJsonType  the JSON type
6545 */
6546 template<typename BasicJsonType>
6547 class json_sax_dom_parser
6548 {
6549   public:
6550     using number_integer_t = typename BasicJsonType::number_integer_t;
6551     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6552     using number_float_t = typename BasicJsonType::number_float_t;
6553     using string_t = typename BasicJsonType::string_t;
6554     using binary_t = typename BasicJsonType::binary_t;
6555 
6556     /*!
6557     @param[in,out] r  reference to a JSON value that is manipulated while
6558                        parsing
6559     @param[in] allow_exceptions_  whether parse errors yield exceptions
6560     */
json_sax_dom_parser(BasicJsonType & r,const bool allow_exceptions_=true)6561     explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
6562         : root(r), allow_exceptions(allow_exceptions_)
6563     {}
6564 
6565     // make class move-only
6566     json_sax_dom_parser(const json_sax_dom_parser&) = delete;
6567     json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6568     json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
6569     json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6570     ~json_sax_dom_parser() = default;
6571 
null()6572     bool null()
6573     {
6574         handle_value(nullptr);
6575         return true;
6576     }
6577 
boolean(bool val)6578     bool boolean(bool val)
6579     {
6580         handle_value(val);
6581         return true;
6582     }
6583 
number_integer(number_integer_t val)6584     bool number_integer(number_integer_t val)
6585     {
6586         handle_value(val);
6587         return true;
6588     }
6589 
number_unsigned(number_unsigned_t val)6590     bool number_unsigned(number_unsigned_t val)
6591     {
6592         handle_value(val);
6593         return true;
6594     }
6595 
number_float(number_float_t val,const string_t &)6596     bool number_float(number_float_t val, const string_t& /*unused*/)
6597     {
6598         handle_value(val);
6599         return true;
6600     }
6601 
string(string_t & val)6602     bool string(string_t& val)
6603     {
6604         handle_value(val);
6605         return true;
6606     }
6607 
binary(binary_t & val)6608     bool binary(binary_t& val)
6609     {
6610         handle_value(std::move(val));
6611         return true;
6612     }
6613 
start_object(std::size_t len)6614     bool start_object(std::size_t len)
6615     {
6616         ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
6617 
6618         if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6619         {
6620             JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6621         }
6622 
6623         return true;
6624     }
6625 
key(string_t & val)6626     bool key(string_t& val)
6627     {
6628         JSON_ASSERT(!ref_stack.empty());
6629         JSON_ASSERT(ref_stack.back()->is_object());
6630 
6631         // add null at given key and store the reference for later
6632         object_element = &(ref_stack.back()->m_value.object->operator[](val));
6633         return true;
6634     }
6635 
end_object()6636     bool end_object()
6637     {
6638         JSON_ASSERT(!ref_stack.empty());
6639         JSON_ASSERT(ref_stack.back()->is_object());
6640 
6641         ref_stack.back()->set_parents();
6642         ref_stack.pop_back();
6643         return true;
6644     }
6645 
start_array(std::size_t len)6646     bool start_array(std::size_t len)
6647     {
6648         ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
6649 
6650         if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6651         {
6652             JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
6653         }
6654 
6655         return true;
6656     }
6657 
end_array()6658     bool end_array()
6659     {
6660         JSON_ASSERT(!ref_stack.empty());
6661         JSON_ASSERT(ref_stack.back()->is_array());
6662 
6663         ref_stack.back()->set_parents();
6664         ref_stack.pop_back();
6665         return true;
6666     }
6667 
6668     template<class Exception>
parse_error(std::size_t,const std::string &,const Exception & ex)6669     bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
6670                      const Exception& ex)
6671     {
6672         errored = true;
6673         static_cast<void>(ex);
6674         if (allow_exceptions)
6675         {
6676             JSON_THROW(ex);
6677         }
6678         return false;
6679     }
6680 
is_errored() const6681     constexpr bool is_errored() const
6682     {
6683         return errored;
6684     }
6685 
6686   private:
6687     /*!
6688     @invariant If the ref stack is empty, then the passed value will be the new
6689                root.
6690     @invariant If the ref stack contains a value, then it is an array or an
6691                object to which we can add elements
6692     */
6693     template<typename Value>
6694     JSON_HEDLEY_RETURNS_NON_NULL
handle_value(Value && v)6695     BasicJsonType* handle_value(Value&& v)
6696     {
6697         if (ref_stack.empty())
6698         {
6699             root = BasicJsonType(std::forward<Value>(v));
6700             return &root;
6701         }
6702 
6703         JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6704 
6705         if (ref_stack.back()->is_array())
6706         {
6707             ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
6708             return &(ref_stack.back()->m_value.array->back());
6709         }
6710 
6711         JSON_ASSERT(ref_stack.back()->is_object());
6712         JSON_ASSERT(object_element);
6713         *object_element = BasicJsonType(std::forward<Value>(v));
6714         return object_element;
6715     }
6716 
6717     /// the parsed JSON value
6718     BasicJsonType& root;
6719     /// stack to model hierarchy of values
6720     std::vector<BasicJsonType*> ref_stack {};
6721     /// helper to hold the reference for the next object element
6722     BasicJsonType* object_element = nullptr;
6723     /// whether a syntax error occurred
6724     bool errored = false;
6725     /// whether to throw exceptions in case of errors
6726     const bool allow_exceptions = true;
6727 };
6728 
6729 template<typename BasicJsonType>
6730 class json_sax_dom_callback_parser
6731 {
6732   public:
6733     using number_integer_t = typename BasicJsonType::number_integer_t;
6734     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6735     using number_float_t = typename BasicJsonType::number_float_t;
6736     using string_t = typename BasicJsonType::string_t;
6737     using binary_t = typename BasicJsonType::binary_t;
6738     using parser_callback_t = typename BasicJsonType::parser_callback_t;
6739     using parse_event_t = typename BasicJsonType::parse_event_t;
6740 
json_sax_dom_callback_parser(BasicJsonType & r,const parser_callback_t cb,const bool allow_exceptions_=true)6741     json_sax_dom_callback_parser(BasicJsonType& r,
6742                                  const parser_callback_t cb,
6743                                  const bool allow_exceptions_ = true)
6744         : root(r), callback(cb), allow_exceptions(allow_exceptions_)
6745     {
6746         keep_stack.push_back(true);
6747     }
6748 
6749     // make class move-only
6750     json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
6751     json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6752     json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
6753     json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6754     ~json_sax_dom_callback_parser() = default;
6755 
null()6756     bool null()
6757     {
6758         handle_value(nullptr);
6759         return true;
6760     }
6761 
boolean(bool val)6762     bool boolean(bool val)
6763     {
6764         handle_value(val);
6765         return true;
6766     }
6767 
number_integer(number_integer_t val)6768     bool number_integer(number_integer_t val)
6769     {
6770         handle_value(val);
6771         return true;
6772     }
6773 
number_unsigned(number_unsigned_t val)6774     bool number_unsigned(number_unsigned_t val)
6775     {
6776         handle_value(val);
6777         return true;
6778     }
6779 
number_float(number_float_t val,const string_t &)6780     bool number_float(number_float_t val, const string_t& /*unused*/)
6781     {
6782         handle_value(val);
6783         return true;
6784     }
6785 
string(string_t & val)6786     bool string(string_t& val)
6787     {
6788         handle_value(val);
6789         return true;
6790     }
6791 
binary(binary_t & val)6792     bool binary(binary_t& val)
6793     {
6794         handle_value(std::move(val));
6795         return true;
6796     }
6797 
start_object(std::size_t len)6798     bool start_object(std::size_t len)
6799     {
6800         // check callback for object start
6801         const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
6802         keep_stack.push_back(keep);
6803 
6804         auto val = handle_value(BasicJsonType::value_t::object, true);
6805         ref_stack.push_back(val.second);
6806 
6807         // check object limit
6808         if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6809         {
6810             JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6811         }
6812 
6813         return true;
6814     }
6815 
key(string_t & val)6816     bool key(string_t& val)
6817     {
6818         BasicJsonType k = BasicJsonType(val);
6819 
6820         // check callback for key
6821         const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
6822         key_keep_stack.push_back(keep);
6823 
6824         // add discarded value at given key and store the reference for later
6825         if (keep && ref_stack.back())
6826         {
6827             object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
6828         }
6829 
6830         return true;
6831     }
6832 
end_object()6833     bool end_object()
6834     {
6835         if (ref_stack.back())
6836         {
6837             if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
6838             {
6839                 // discard object
6840                 *ref_stack.back() = discarded;
6841             }
6842             else
6843             {
6844                 ref_stack.back()->set_parents();
6845             }
6846         }
6847 
6848         JSON_ASSERT(!ref_stack.empty());
6849         JSON_ASSERT(!keep_stack.empty());
6850         ref_stack.pop_back();
6851         keep_stack.pop_back();
6852 
6853         if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
6854         {
6855             // remove discarded value
6856             for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
6857             {
6858                 if (it->is_discarded())
6859                 {
6860                     ref_stack.back()->erase(it);
6861                     break;
6862                 }
6863             }
6864         }
6865 
6866         return true;
6867     }
6868 
start_array(std::size_t len)6869     bool start_array(std::size_t len)
6870     {
6871         const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
6872         keep_stack.push_back(keep);
6873 
6874         auto val = handle_value(BasicJsonType::value_t::array, true);
6875         ref_stack.push_back(val.second);
6876 
6877         // check array limit
6878         if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6879         {
6880             JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
6881         }
6882 
6883         return true;
6884     }
6885 
end_array()6886     bool end_array()
6887     {
6888         bool keep = true;
6889 
6890         if (ref_stack.back())
6891         {
6892             keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
6893             if (keep)
6894             {
6895                 ref_stack.back()->set_parents();
6896             }
6897             else
6898             {
6899                 // discard array
6900                 *ref_stack.back() = discarded;
6901             }
6902         }
6903 
6904         JSON_ASSERT(!ref_stack.empty());
6905         JSON_ASSERT(!keep_stack.empty());
6906         ref_stack.pop_back();
6907         keep_stack.pop_back();
6908 
6909         // remove discarded value
6910         if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
6911         {
6912             ref_stack.back()->m_value.array->pop_back();
6913         }
6914 
6915         return true;
6916     }
6917 
6918     template<class Exception>
parse_error(std::size_t,const std::string &,const Exception & ex)6919     bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
6920                      const Exception& ex)
6921     {
6922         errored = true;
6923         static_cast<void>(ex);
6924         if (allow_exceptions)
6925         {
6926             JSON_THROW(ex);
6927         }
6928         return false;
6929     }
6930 
is_errored() const6931     constexpr bool is_errored() const
6932     {
6933         return errored;
6934     }
6935 
6936   private:
6937     /*!
6938     @param[in] v  value to add to the JSON value we build during parsing
6939     @param[in] skip_callback  whether we should skip calling the callback
6940                function; this is required after start_array() and
6941                start_object() SAX events, because otherwise we would call the
6942                callback function with an empty array or object, respectively.
6943 
6944     @invariant If the ref stack is empty, then the passed value will be the new
6945                root.
6946     @invariant If the ref stack contains a value, then it is an array or an
6947                object to which we can add elements
6948 
6949     @return pair of boolean (whether value should be kept) and pointer (to the
6950             passed value in the ref_stack hierarchy; nullptr if not kept)
6951     */
6952     template<typename Value>
handle_value(Value && v,const bool skip_callback=false)6953     std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
6954     {
6955         JSON_ASSERT(!keep_stack.empty());
6956 
6957         // do not handle this value if we know it would be added to a discarded
6958         // container
6959         if (!keep_stack.back())
6960         {
6961             return {false, nullptr};
6962         }
6963 
6964         // create value
6965         auto value = BasicJsonType(std::forward<Value>(v));
6966 
6967         // check callback
6968         const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
6969 
6970         // do not handle this value if we just learnt it shall be discarded
6971         if (!keep)
6972         {
6973             return {false, nullptr};
6974         }
6975 
6976         if (ref_stack.empty())
6977         {
6978             root = std::move(value);
6979             return {true, &root};
6980         }
6981 
6982         // skip this value if we already decided to skip the parent
6983         // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
6984         if (!ref_stack.back())
6985         {
6986             return {false, nullptr};
6987         }
6988 
6989         // we now only expect arrays and objects
6990         JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6991 
6992         // array
6993         if (ref_stack.back()->is_array())
6994         {
6995             ref_stack.back()->m_value.array->emplace_back(std::move(value));
6996             return {true, &(ref_stack.back()->m_value.array->back())};
6997         }
6998 
6999         // object
7000         JSON_ASSERT(ref_stack.back()->is_object());
7001         // check if we should store an element for the current key
7002         JSON_ASSERT(!key_keep_stack.empty());
7003         const bool store_element = key_keep_stack.back();
7004         key_keep_stack.pop_back();
7005 
7006         if (!store_element)
7007         {
7008             return {false, nullptr};
7009         }
7010 
7011         JSON_ASSERT(object_element);
7012         *object_element = std::move(value);
7013         return {true, object_element};
7014     }
7015 
7016     /// the parsed JSON value
7017     BasicJsonType& root;
7018     /// stack to model hierarchy of values
7019     std::vector<BasicJsonType*> ref_stack {};
7020     /// stack to manage which values to keep
7021     std::vector<bool> keep_stack {};
7022     /// stack to manage which object keys to keep
7023     std::vector<bool> key_keep_stack {};
7024     /// helper to hold the reference for the next object element
7025     BasicJsonType* object_element = nullptr;
7026     /// whether a syntax error occurred
7027     bool errored = false;
7028     /// callback function
7029     const parser_callback_t callback = nullptr;
7030     /// whether to throw exceptions in case of errors
7031     const bool allow_exceptions = true;
7032     /// a discarded value for the callback
7033     BasicJsonType discarded = BasicJsonType::value_t::discarded;
7034 };
7035 
7036 template<typename BasicJsonType>
7037 class json_sax_acceptor
7038 {
7039   public:
7040     using number_integer_t = typename BasicJsonType::number_integer_t;
7041     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7042     using number_float_t = typename BasicJsonType::number_float_t;
7043     using string_t = typename BasicJsonType::string_t;
7044     using binary_t = typename BasicJsonType::binary_t;
7045 
null()7046     bool null()
7047     {
7048         return true;
7049     }
7050 
boolean(bool)7051     bool boolean(bool /*unused*/)
7052     {
7053         return true;
7054     }
7055 
number_integer(number_integer_t)7056     bool number_integer(number_integer_t /*unused*/)
7057     {
7058         return true;
7059     }
7060 
number_unsigned(number_unsigned_t)7061     bool number_unsigned(number_unsigned_t /*unused*/)
7062     {
7063         return true;
7064     }
7065 
number_float(number_float_t,const string_t &)7066     bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
7067     {
7068         return true;
7069     }
7070 
string(string_t &)7071     bool string(string_t& /*unused*/)
7072     {
7073         return true;
7074     }
7075 
binary(binary_t &)7076     bool binary(binary_t& /*unused*/)
7077     {
7078         return true;
7079     }
7080 
start_object(std::size_t=static_cast<std::size_t> (-1))7081     bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7082     {
7083         return true;
7084     }
7085 
key(string_t &)7086     bool key(string_t& /*unused*/)
7087     {
7088         return true;
7089     }
7090 
end_object()7091     bool end_object()
7092     {
7093         return true;
7094     }
7095 
start_array(std::size_t=static_cast<std::size_t> (-1))7096     bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7097     {
7098         return true;
7099     }
7100 
end_array()7101     bool end_array()
7102     {
7103         return true;
7104     }
7105 
parse_error(std::size_t,const std::string &,const detail::exception &)7106     bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
7107     {
7108         return false;
7109     }
7110 };
7111 }  // namespace detail
7112 
7113 }  // namespace nlohmann
7114 
7115 // #include <nlohmann/detail/input/lexer.hpp>
7116 //     __ _____ _____ _____
7117 //  __|  |   __|     |   | |  JSON for Modern C++
7118 // |  |  |__   |  |  | | | |  version 3.10.5
7119 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
7120 //
7121 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7122 // SPDX-License-Identifier: MIT
7123 
7124 
7125 
7126 #include <array> // array
7127 #include <clocale> // localeconv
7128 #include <cstddef> // size_t
7129 #include <cstdio> // snprintf
7130 #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7131 #include <initializer_list> // initializer_list
7132 #include <string> // char_traits, string
7133 #include <utility> // move
7134 #include <vector> // vector
7135 
7136 // #include <nlohmann/detail/input/input_adapters.hpp>
7137 
7138 // #include <nlohmann/detail/input/position_t.hpp>
7139 
7140 // #include <nlohmann/detail/macro_scope.hpp>
7141 
7142 
7143 namespace nlohmann
7144 {
7145 namespace detail
7146 {
7147 ///////////
7148 // lexer //
7149 ///////////
7150 
7151 template<typename BasicJsonType>
7152 class lexer_base
7153 {
7154   public:
7155     /// token types for the parser
7156     enum class token_type
7157     {
7158         uninitialized,    ///< indicating the scanner is uninitialized
7159         literal_true,     ///< the `true` literal
7160         literal_false,    ///< the `false` literal
7161         literal_null,     ///< the `null` literal
7162         value_string,     ///< a string -- use get_string() for actual value
7163         value_unsigned,   ///< an unsigned integer -- use get_number_unsigned() for actual value
7164         value_integer,    ///< a signed integer -- use get_number_integer() for actual value
7165         value_float,      ///< an floating point number -- use get_number_float() for actual value
7166         begin_array,      ///< the character for array begin `[`
7167         begin_object,     ///< the character for object begin `{`
7168         end_array,        ///< the character for array end `]`
7169         end_object,       ///< the character for object end `}`
7170         name_separator,   ///< the name separator `:`
7171         value_separator,  ///< the value separator `,`
7172         parse_error,      ///< indicating a parse error
7173         end_of_input,     ///< indicating the end of the input buffer
7174         literal_or_value  ///< a literal or the begin of a value (only for diagnostics)
7175     };
7176 
7177     /// return name of values of type token_type (only used for errors)
7178     JSON_HEDLEY_RETURNS_NON_NULL
7179     JSON_HEDLEY_CONST
token_type_name(const token_type t)7180     static const char* token_type_name(const token_type t) noexcept
7181     {
7182         switch (t)
7183         {
7184             case token_type::uninitialized:
7185                 return "<uninitialized>";
7186             case token_type::literal_true:
7187                 return "true literal";
7188             case token_type::literal_false:
7189                 return "false literal";
7190             case token_type::literal_null:
7191                 return "null literal";
7192             case token_type::value_string:
7193                 return "string literal";
7194             case token_type::value_unsigned:
7195             case token_type::value_integer:
7196             case token_type::value_float:
7197                 return "number literal";
7198             case token_type::begin_array:
7199                 return "'['";
7200             case token_type::begin_object:
7201                 return "'{'";
7202             case token_type::end_array:
7203                 return "']'";
7204             case token_type::end_object:
7205                 return "'}'";
7206             case token_type::name_separator:
7207                 return "':'";
7208             case token_type::value_separator:
7209                 return "','";
7210             case token_type::parse_error:
7211                 return "<parse error>";
7212             case token_type::end_of_input:
7213                 return "end of input";
7214             case token_type::literal_or_value:
7215                 return "'[', '{', or a literal";
7216             // LCOV_EXCL_START
7217             default: // catch non-enum values
7218                 return "unknown token";
7219                 // LCOV_EXCL_STOP
7220         }
7221     }
7222 };
7223 /*!
7224 @brief lexical analysis
7225 
7226 This class organizes the lexical analysis during JSON deserialization.
7227 */
7228 template<typename BasicJsonType, typename InputAdapterType>
7229 class lexer : public lexer_base<BasicJsonType>
7230 {
7231     using number_integer_t = typename BasicJsonType::number_integer_t;
7232     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7233     using number_float_t = typename BasicJsonType::number_float_t;
7234     using string_t = typename BasicJsonType::string_t;
7235     using char_type = typename InputAdapterType::char_type;
7236     using char_int_type = typename std::char_traits<char_type>::int_type;
7237 
7238   public:
7239     using token_type = typename lexer_base<BasicJsonType>::token_type;
7240 
lexer(InputAdapterType && adapter,bool ignore_comments_=false)7241     explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7242         : ia(std::move(adapter))
7243         , ignore_comments(ignore_comments_)
7244         , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7245     {}
7246 
7247     // delete because of pointer members
7248     lexer(const lexer&) = delete;
7249     lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7250     lexer& operator=(lexer&) = delete;
7251     lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7252     ~lexer() = default;
7253 
7254   private:
7255     /////////////////////
7256     // locales
7257     /////////////////////
7258 
7259     /// return the locale-dependent decimal point
7260     JSON_HEDLEY_PURE
get_decimal_point()7261     static char get_decimal_point() noexcept
7262     {
7263         const auto* loc = localeconv();
7264         JSON_ASSERT(loc != nullptr);
7265         return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7266     }
7267 
7268     /////////////////////
7269     // scan functions
7270     /////////////////////
7271 
7272     /*!
7273     @brief get codepoint from 4 hex characters following `\u`
7274 
7275     For input "\u c1 c2 c3 c4" the codepoint is:
7276       (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
7277     = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
7278 
7279     Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
7280     must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
7281     conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
7282     between the ASCII value of the character and the desired integer value.
7283 
7284     @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
7285             non-hex character)
7286     */
get_codepoint()7287     int get_codepoint()
7288     {
7289         // this function only makes sense after reading `\u`
7290         JSON_ASSERT(current == 'u');
7291         int codepoint = 0;
7292 
7293         const auto factors = { 12u, 8u, 4u, 0u };
7294         for (const auto factor : factors)
7295         {
7296             get();
7297 
7298             if (current >= '0' && current <= '9')
7299             {
7300                 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7301             }
7302             else if (current >= 'A' && current <= 'F')
7303             {
7304                 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7305             }
7306             else if (current >= 'a' && current <= 'f')
7307             {
7308                 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7309             }
7310             else
7311             {
7312                 return -1;
7313             }
7314         }
7315 
7316         JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7317         return codepoint;
7318     }
7319 
7320     /*!
7321     @brief check if the next byte(s) are inside a given range
7322 
7323     Adds the current byte and, for each passed range, reads a new byte and
7324     checks if it is inside the range. If a violation was detected, set up an
7325     error message and return false. Otherwise, return true.
7326 
7327     @param[in] ranges  list of integers; interpreted as list of pairs of
7328                        inclusive lower and upper bound, respectively
7329 
7330     @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
7331          1, 2, or 3 pairs. This precondition is enforced by an assertion.
7332 
7333     @return true if and only if no range violation was detected
7334     */
next_byte_in_range(std::initializer_list<char_int_type> ranges)7335     bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7336     {
7337         JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7338         add(current);
7339 
7340         for (auto range = ranges.begin(); range != ranges.end(); ++range)
7341         {
7342             get();
7343             if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
7344             {
7345                 add(current);
7346             }
7347             else
7348             {
7349                 error_message = "invalid string: ill-formed UTF-8 byte";
7350                 return false;
7351             }
7352         }
7353 
7354         return true;
7355     }
7356 
7357     /*!
7358     @brief scan a string literal
7359 
7360     This function scans a string according to Sect. 7 of RFC 8259. While
7361     scanning, bytes are escaped and copied into buffer token_buffer. Then the
7362     function returns successfully, token_buffer is *not* null-terminated (as it
7363     may contain \0 bytes), and token_buffer.size() is the number of bytes in the
7364     string.
7365 
7366     @return token_type::value_string if string could be successfully scanned,
7367             token_type::parse_error otherwise
7368 
7369     @note In case of errors, variable error_message contains a textual
7370           description.
7371     */
scan_string()7372     token_type scan_string()
7373     {
7374         // reset token_buffer (ignore opening quote)
7375         reset();
7376 
7377         // we entered the function by reading an open quote
7378         JSON_ASSERT(current == '\"');
7379 
7380         while (true)
7381         {
7382             // get next character
7383             switch (get())
7384             {
7385                 // end of file while parsing string
7386                 case std::char_traits<char_type>::eof():
7387                 {
7388                     error_message = "invalid string: missing closing quote";
7389                     return token_type::parse_error;
7390                 }
7391 
7392                 // closing quote
7393                 case '\"':
7394                 {
7395                     return token_type::value_string;
7396                 }
7397 
7398                 // escapes
7399                 case '\\':
7400                 {
7401                     switch (get())
7402                     {
7403                         // quotation mark
7404                         case '\"':
7405                             add('\"');
7406                             break;
7407                         // reverse solidus
7408                         case '\\':
7409                             add('\\');
7410                             break;
7411                         // solidus
7412                         case '/':
7413                             add('/');
7414                             break;
7415                         // backspace
7416                         case 'b':
7417                             add('\b');
7418                             break;
7419                         // form feed
7420                         case 'f':
7421                             add('\f');
7422                             break;
7423                         // line feed
7424                         case 'n':
7425                             add('\n');
7426                             break;
7427                         // carriage return
7428                         case 'r':
7429                             add('\r');
7430                             break;
7431                         // tab
7432                         case 't':
7433                             add('\t');
7434                             break;
7435 
7436                         // unicode escapes
7437                         case 'u':
7438                         {
7439                             const int codepoint1 = get_codepoint();
7440                             int codepoint = codepoint1; // start with codepoint1
7441 
7442                             if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7443                             {
7444                                 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7445                                 return token_type::parse_error;
7446                             }
7447 
7448                             // check if code point is a high surrogate
7449                             if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7450                             {
7451                                 // expect next \uxxxx entry
7452                                 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7453                                 {
7454                                     const int codepoint2 = get_codepoint();
7455 
7456                                     if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7457                                     {
7458                                         error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7459                                         return token_type::parse_error;
7460                                     }
7461 
7462                                     // check if codepoint2 is a low surrogate
7463                                     if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7464                                     {
7465                                         // overwrite codepoint
7466                                         codepoint = static_cast<int>(
7467                                                         // high surrogate occupies the most significant 22 bits
7468                                                         (static_cast<unsigned int>(codepoint1) << 10u)
7469                                                         // low surrogate occupies the least significant 15 bits
7470                                                         + static_cast<unsigned int>(codepoint2)
7471                                                         // there is still the 0xD800, 0xDC00 and 0x10000 noise
7472                                                         // in the result, so we have to subtract with:
7473                                                         // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7474                                                         - 0x35FDC00u);
7475                                     }
7476                                     else
7477                                     {
7478                                         error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7479                                         return token_type::parse_error;
7480                                     }
7481                                 }
7482                                 else
7483                                 {
7484                                     error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7485                                     return token_type::parse_error;
7486                                 }
7487                             }
7488                             else
7489                             {
7490                                 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7491                                 {
7492                                     error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7493                                     return token_type::parse_error;
7494                                 }
7495                             }
7496 
7497                             // result of the above calculation yields a proper codepoint
7498                             JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7499 
7500                             // translate codepoint into bytes
7501                             if (codepoint < 0x80)
7502                             {
7503                                 // 1-byte characters: 0xxxxxxx (ASCII)
7504                                 add(static_cast<char_int_type>(codepoint));
7505                             }
7506                             else if (codepoint <= 0x7FF)
7507                             {
7508                                 // 2-byte characters: 110xxxxx 10xxxxxx
7509                                 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7510                                 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7511                             }
7512                             else if (codepoint <= 0xFFFF)
7513                             {
7514                                 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7515                                 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7516                                 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7517                                 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7518                             }
7519                             else
7520                             {
7521                                 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7522                                 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7523                                 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7524                                 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7525                                 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7526                             }
7527 
7528                             break;
7529                         }
7530 
7531                         // other characters after escape
7532                         default:
7533                             error_message = "invalid string: forbidden character after backslash";
7534                             return token_type::parse_error;
7535                     }
7536 
7537                     break;
7538                 }
7539 
7540                 // invalid control characters
7541                 case 0x00:
7542                 {
7543                     error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7544                     return token_type::parse_error;
7545                 }
7546 
7547                 case 0x01:
7548                 {
7549                     error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7550                     return token_type::parse_error;
7551                 }
7552 
7553                 case 0x02:
7554                 {
7555                     error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7556                     return token_type::parse_error;
7557                 }
7558 
7559                 case 0x03:
7560                 {
7561                     error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7562                     return token_type::parse_error;
7563                 }
7564 
7565                 case 0x04:
7566                 {
7567                     error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7568                     return token_type::parse_error;
7569                 }
7570 
7571                 case 0x05:
7572                 {
7573                     error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7574                     return token_type::parse_error;
7575                 }
7576 
7577                 case 0x06:
7578                 {
7579                     error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7580                     return token_type::parse_error;
7581                 }
7582 
7583                 case 0x07:
7584                 {
7585                     error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7586                     return token_type::parse_error;
7587                 }
7588 
7589                 case 0x08:
7590                 {
7591                     error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7592                     return token_type::parse_error;
7593                 }
7594 
7595                 case 0x09:
7596                 {
7597                     error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7598                     return token_type::parse_error;
7599                 }
7600 
7601                 case 0x0A:
7602                 {
7603                     error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7604                     return token_type::parse_error;
7605                 }
7606 
7607                 case 0x0B:
7608                 {
7609                     error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7610                     return token_type::parse_error;
7611                 }
7612 
7613                 case 0x0C:
7614                 {
7615                     error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7616                     return token_type::parse_error;
7617                 }
7618 
7619                 case 0x0D:
7620                 {
7621                     error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7622                     return token_type::parse_error;
7623                 }
7624 
7625                 case 0x0E:
7626                 {
7627                     error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7628                     return token_type::parse_error;
7629                 }
7630 
7631                 case 0x0F:
7632                 {
7633                     error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7634                     return token_type::parse_error;
7635                 }
7636 
7637                 case 0x10:
7638                 {
7639                     error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7640                     return token_type::parse_error;
7641                 }
7642 
7643                 case 0x11:
7644                 {
7645                     error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7646                     return token_type::parse_error;
7647                 }
7648 
7649                 case 0x12:
7650                 {
7651                     error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7652                     return token_type::parse_error;
7653                 }
7654 
7655                 case 0x13:
7656                 {
7657                     error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7658                     return token_type::parse_error;
7659                 }
7660 
7661                 case 0x14:
7662                 {
7663                     error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7664                     return token_type::parse_error;
7665                 }
7666 
7667                 case 0x15:
7668                 {
7669                     error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7670                     return token_type::parse_error;
7671                 }
7672 
7673                 case 0x16:
7674                 {
7675                     error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7676                     return token_type::parse_error;
7677                 }
7678 
7679                 case 0x17:
7680                 {
7681                     error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7682                     return token_type::parse_error;
7683                 }
7684 
7685                 case 0x18:
7686                 {
7687                     error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7688                     return token_type::parse_error;
7689                 }
7690 
7691                 case 0x19:
7692                 {
7693                     error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7694                     return token_type::parse_error;
7695                 }
7696 
7697                 case 0x1A:
7698                 {
7699                     error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7700                     return token_type::parse_error;
7701                 }
7702 
7703                 case 0x1B:
7704                 {
7705                     error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7706                     return token_type::parse_error;
7707                 }
7708 
7709                 case 0x1C:
7710                 {
7711                     error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7712                     return token_type::parse_error;
7713                 }
7714 
7715                 case 0x1D:
7716                 {
7717                     error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7718                     return token_type::parse_error;
7719                 }
7720 
7721                 case 0x1E:
7722                 {
7723                     error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7724                     return token_type::parse_error;
7725                 }
7726 
7727                 case 0x1F:
7728                 {
7729                     error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7730                     return token_type::parse_error;
7731                 }
7732 
7733                 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7734                 case 0x20:
7735                 case 0x21:
7736                 case 0x23:
7737                 case 0x24:
7738                 case 0x25:
7739                 case 0x26:
7740                 case 0x27:
7741                 case 0x28:
7742                 case 0x29:
7743                 case 0x2A:
7744                 case 0x2B:
7745                 case 0x2C:
7746                 case 0x2D:
7747                 case 0x2E:
7748                 case 0x2F:
7749                 case 0x30:
7750                 case 0x31:
7751                 case 0x32:
7752                 case 0x33:
7753                 case 0x34:
7754                 case 0x35:
7755                 case 0x36:
7756                 case 0x37:
7757                 case 0x38:
7758                 case 0x39:
7759                 case 0x3A:
7760                 case 0x3B:
7761                 case 0x3C:
7762                 case 0x3D:
7763                 case 0x3E:
7764                 case 0x3F:
7765                 case 0x40:
7766                 case 0x41:
7767                 case 0x42:
7768                 case 0x43:
7769                 case 0x44:
7770                 case 0x45:
7771                 case 0x46:
7772                 case 0x47:
7773                 case 0x48:
7774                 case 0x49:
7775                 case 0x4A:
7776                 case 0x4B:
7777                 case 0x4C:
7778                 case 0x4D:
7779                 case 0x4E:
7780                 case 0x4F:
7781                 case 0x50:
7782                 case 0x51:
7783                 case 0x52:
7784                 case 0x53:
7785                 case 0x54:
7786                 case 0x55:
7787                 case 0x56:
7788                 case 0x57:
7789                 case 0x58:
7790                 case 0x59:
7791                 case 0x5A:
7792                 case 0x5B:
7793                 case 0x5D:
7794                 case 0x5E:
7795                 case 0x5F:
7796                 case 0x60:
7797                 case 0x61:
7798                 case 0x62:
7799                 case 0x63:
7800                 case 0x64:
7801                 case 0x65:
7802                 case 0x66:
7803                 case 0x67:
7804                 case 0x68:
7805                 case 0x69:
7806                 case 0x6A:
7807                 case 0x6B:
7808                 case 0x6C:
7809                 case 0x6D:
7810                 case 0x6E:
7811                 case 0x6F:
7812                 case 0x70:
7813                 case 0x71:
7814                 case 0x72:
7815                 case 0x73:
7816                 case 0x74:
7817                 case 0x75:
7818                 case 0x76:
7819                 case 0x77:
7820                 case 0x78:
7821                 case 0x79:
7822                 case 0x7A:
7823                 case 0x7B:
7824                 case 0x7C:
7825                 case 0x7D:
7826                 case 0x7E:
7827                 case 0x7F:
7828                 {
7829                     add(current);
7830                     break;
7831                 }
7832 
7833                 // U+0080..U+07FF: bytes C2..DF 80..BF
7834                 case 0xC2:
7835                 case 0xC3:
7836                 case 0xC4:
7837                 case 0xC5:
7838                 case 0xC6:
7839                 case 0xC7:
7840                 case 0xC8:
7841                 case 0xC9:
7842                 case 0xCA:
7843                 case 0xCB:
7844                 case 0xCC:
7845                 case 0xCD:
7846                 case 0xCE:
7847                 case 0xCF:
7848                 case 0xD0:
7849                 case 0xD1:
7850                 case 0xD2:
7851                 case 0xD3:
7852                 case 0xD4:
7853                 case 0xD5:
7854                 case 0xD6:
7855                 case 0xD7:
7856                 case 0xD8:
7857                 case 0xD9:
7858                 case 0xDA:
7859                 case 0xDB:
7860                 case 0xDC:
7861                 case 0xDD:
7862                 case 0xDE:
7863                 case 0xDF:
7864                 {
7865                     if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
7866                     {
7867                         return token_type::parse_error;
7868                     }
7869                     break;
7870                 }
7871 
7872                 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7873                 case 0xE0:
7874                 {
7875                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7876                     {
7877                         return token_type::parse_error;
7878                     }
7879                     break;
7880                 }
7881 
7882                 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7883                 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7884                 case 0xE1:
7885                 case 0xE2:
7886                 case 0xE3:
7887                 case 0xE4:
7888                 case 0xE5:
7889                 case 0xE6:
7890                 case 0xE7:
7891                 case 0xE8:
7892                 case 0xE9:
7893                 case 0xEA:
7894                 case 0xEB:
7895                 case 0xEC:
7896                 case 0xEE:
7897                 case 0xEF:
7898                 {
7899                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7900                     {
7901                         return token_type::parse_error;
7902                     }
7903                     break;
7904                 }
7905 
7906                 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7907                 case 0xED:
7908                 {
7909                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7910                     {
7911                         return token_type::parse_error;
7912                     }
7913                     break;
7914                 }
7915 
7916                 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7917                 case 0xF0:
7918                 {
7919                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7920                     {
7921                         return token_type::parse_error;
7922                     }
7923                     break;
7924                 }
7925 
7926                 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7927                 case 0xF1:
7928                 case 0xF2:
7929                 case 0xF3:
7930                 {
7931                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7932                     {
7933                         return token_type::parse_error;
7934                     }
7935                     break;
7936                 }
7937 
7938                 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7939                 case 0xF4:
7940                 {
7941                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
7942                     {
7943                         return token_type::parse_error;
7944                     }
7945                     break;
7946                 }
7947 
7948                 // remaining bytes (80..C1 and F5..FF) are ill-formed
7949                 default:
7950                 {
7951                     error_message = "invalid string: ill-formed UTF-8 byte";
7952                     return token_type::parse_error;
7953                 }
7954             }
7955         }
7956     }
7957 
7958     /*!
7959      * @brief scan a comment
7960      * @return whether comment could be scanned successfully
7961      */
scan_comment()7962     bool scan_comment()
7963     {
7964         switch (get())
7965         {
7966             // single-line comments skip input until a newline or EOF is read
7967             case '/':
7968             {
7969                 while (true)
7970                 {
7971                     switch (get())
7972                     {
7973                         case '\n':
7974                         case '\r':
7975                         case std::char_traits<char_type>::eof():
7976                         case '\0':
7977                             return true;
7978 
7979                         default:
7980                             break;
7981                     }
7982                 }
7983             }
7984 
7985             // multi-line comments skip input until */ is read
7986             case '*':
7987             {
7988                 while (true)
7989                 {
7990                     switch (get())
7991                     {
7992                         case std::char_traits<char_type>::eof():
7993                         case '\0':
7994                         {
7995                             error_message = "invalid comment; missing closing '*/'";
7996                             return false;
7997                         }
7998 
7999                         case '*':
8000                         {
8001                             switch (get())
8002                             {
8003                                 case '/':
8004                                     return true;
8005 
8006                                 default:
8007                                 {
8008                                     unget();
8009                                     continue;
8010                                 }
8011                             }
8012                         }
8013 
8014                         default:
8015                             continue;
8016                     }
8017                 }
8018             }
8019 
8020             // unexpected character after reading '/'
8021             default:
8022             {
8023                 error_message = "invalid comment; expecting '/' or '*' after '/'";
8024                 return false;
8025             }
8026         }
8027     }
8028 
8029     JSON_HEDLEY_NON_NULL(2)
strtof(float & f,const char * str,char ** endptr)8030     static void strtof(float& f, const char* str, char** endptr) noexcept
8031     {
8032         f = std::strtof(str, endptr);
8033     }
8034 
8035     JSON_HEDLEY_NON_NULL(2)
strtof(double & f,const char * str,char ** endptr)8036     static void strtof(double& f, const char* str, char** endptr) noexcept
8037     {
8038         f = std::strtod(str, endptr);
8039     }
8040 
8041     JSON_HEDLEY_NON_NULL(2)
strtof(long double & f,const char * str,char ** endptr)8042     static void strtof(long double& f, const char* str, char** endptr) noexcept
8043     {
8044         f = std::strtold(str, endptr);
8045     }
8046 
8047     /*!
8048     @brief scan a number literal
8049 
8050     This function scans a string according to Sect. 6 of RFC 8259.
8051 
8052     The function is realized with a deterministic finite state machine derived
8053     from the grammar described in RFC 8259. Starting in state "init", the
8054     input is read and used to determined the next state. Only state "done"
8055     accepts the number. State "error" is a trap state to model errors. In the
8056     table below, "anything" means any character but the ones listed before.
8057 
8058     state    | 0        | 1-9      | e E      | +       | -       | .        | anything
8059     ---------|----------|----------|----------|---------|---------|----------|-----------
8060     init     | zero     | any1     | [error]  | [error] | minus   | [error]  | [error]
8061     minus    | zero     | any1     | [error]  | [error] | [error] | [error]  | [error]
8062     zero     | done     | done     | exponent | done    | done    | decimal1 | done
8063     any1     | any1     | any1     | exponent | done    | done    | decimal1 | done
8064     decimal1 | decimal2 | decimal2 | [error]  | [error] | [error] | [error]  | [error]
8065     decimal2 | decimal2 | decimal2 | exponent | done    | done    | done     | done
8066     exponent | any2     | any2     | [error]  | sign    | sign    | [error]  | [error]
8067     sign     | any2     | any2     | [error]  | [error] | [error] | [error]  | [error]
8068     any2     | any2     | any2     | done     | done    | done    | done     | done
8069 
8070     The state machine is realized with one label per state (prefixed with
8071     "scan_number_") and `goto` statements between them. The state machine
8072     contains cycles, but any cycle can be left when EOF is read. Therefore,
8073     the function is guaranteed to terminate.
8074 
8075     During scanning, the read bytes are stored in token_buffer. This string is
8076     then converted to a signed integer, an unsigned integer, or a
8077     floating-point number.
8078 
8079     @return token_type::value_unsigned, token_type::value_integer, or
8080             token_type::value_float if number could be successfully scanned,
8081             token_type::parse_error otherwise
8082 
8083     @note The scanner is independent of the current locale. Internally, the
8084           locale's decimal point is used instead of `.` to work with the
8085           locale-dependent converters.
8086     */
scan_number()8087     token_type scan_number()  // lgtm [cpp/use-of-goto]
8088     {
8089         // reset token_buffer to store the number's bytes
8090         reset();
8091 
8092         // the type of the parsed number; initially set to unsigned; will be
8093         // changed if minus sign, decimal point or exponent is read
8094         token_type number_type = token_type::value_unsigned;
8095 
8096         // state (init): we just found out we need to scan a number
8097         switch (current)
8098         {
8099             case '-':
8100             {
8101                 add(current);
8102                 goto scan_number_minus;
8103             }
8104 
8105             case '0':
8106             {
8107                 add(current);
8108                 goto scan_number_zero;
8109             }
8110 
8111             case '1':
8112             case '2':
8113             case '3':
8114             case '4':
8115             case '5':
8116             case '6':
8117             case '7':
8118             case '8':
8119             case '9':
8120             {
8121                 add(current);
8122                 goto scan_number_any1;
8123             }
8124 
8125             // all other characters are rejected outside scan_number()
8126             default:            // LCOV_EXCL_LINE
8127                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8128         }
8129 
8130 scan_number_minus:
8131         // state: we just parsed a leading minus sign
8132         number_type = token_type::value_integer;
8133         switch (get())
8134         {
8135             case '0':
8136             {
8137                 add(current);
8138                 goto scan_number_zero;
8139             }
8140 
8141             case '1':
8142             case '2':
8143             case '3':
8144             case '4':
8145             case '5':
8146             case '6':
8147             case '7':
8148             case '8':
8149             case '9':
8150             {
8151                 add(current);
8152                 goto scan_number_any1;
8153             }
8154 
8155             default:
8156             {
8157                 error_message = "invalid number; expected digit after '-'";
8158                 return token_type::parse_error;
8159             }
8160         }
8161 
8162 scan_number_zero:
8163         // state: we just parse a zero (maybe with a leading minus sign)
8164         switch (get())
8165         {
8166             case '.':
8167             {
8168                 add(decimal_point_char);
8169                 goto scan_number_decimal1;
8170             }
8171 
8172             case 'e':
8173             case 'E':
8174             {
8175                 add(current);
8176                 goto scan_number_exponent;
8177             }
8178 
8179             default:
8180                 goto scan_number_done;
8181         }
8182 
8183 scan_number_any1:
8184         // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8185         switch (get())
8186         {
8187             case '0':
8188             case '1':
8189             case '2':
8190             case '3':
8191             case '4':
8192             case '5':
8193             case '6':
8194             case '7':
8195             case '8':
8196             case '9':
8197             {
8198                 add(current);
8199                 goto scan_number_any1;
8200             }
8201 
8202             case '.':
8203             {
8204                 add(decimal_point_char);
8205                 goto scan_number_decimal1;
8206             }
8207 
8208             case 'e':
8209             case 'E':
8210             {
8211                 add(current);
8212                 goto scan_number_exponent;
8213             }
8214 
8215             default:
8216                 goto scan_number_done;
8217         }
8218 
8219 scan_number_decimal1:
8220         // state: we just parsed a decimal point
8221         number_type = token_type::value_float;
8222         switch (get())
8223         {
8224             case '0':
8225             case '1':
8226             case '2':
8227             case '3':
8228             case '4':
8229             case '5':
8230             case '6':
8231             case '7':
8232             case '8':
8233             case '9':
8234             {
8235                 add(current);
8236                 goto scan_number_decimal2;
8237             }
8238 
8239             default:
8240             {
8241                 error_message = "invalid number; expected digit after '.'";
8242                 return token_type::parse_error;
8243             }
8244         }
8245 
8246 scan_number_decimal2:
8247         // we just parsed at least one number after a decimal point
8248         switch (get())
8249         {
8250             case '0':
8251             case '1':
8252             case '2':
8253             case '3':
8254             case '4':
8255             case '5':
8256             case '6':
8257             case '7':
8258             case '8':
8259             case '9':
8260             {
8261                 add(current);
8262                 goto scan_number_decimal2;
8263             }
8264 
8265             case 'e':
8266             case 'E':
8267             {
8268                 add(current);
8269                 goto scan_number_exponent;
8270             }
8271 
8272             default:
8273                 goto scan_number_done;
8274         }
8275 
8276 scan_number_exponent:
8277         // we just parsed an exponent
8278         number_type = token_type::value_float;
8279         switch (get())
8280         {
8281             case '+':
8282             case '-':
8283             {
8284                 add(current);
8285                 goto scan_number_sign;
8286             }
8287 
8288             case '0':
8289             case '1':
8290             case '2':
8291             case '3':
8292             case '4':
8293             case '5':
8294             case '6':
8295             case '7':
8296             case '8':
8297             case '9':
8298             {
8299                 add(current);
8300                 goto scan_number_any2;
8301             }
8302 
8303             default:
8304             {
8305                 error_message =
8306                     "invalid number; expected '+', '-', or digit after exponent";
8307                 return token_type::parse_error;
8308             }
8309         }
8310 
8311 scan_number_sign:
8312         // we just parsed an exponent sign
8313         switch (get())
8314         {
8315             case '0':
8316             case '1':
8317             case '2':
8318             case '3':
8319             case '4':
8320             case '5':
8321             case '6':
8322             case '7':
8323             case '8':
8324             case '9':
8325             {
8326                 add(current);
8327                 goto scan_number_any2;
8328             }
8329 
8330             default:
8331             {
8332                 error_message = "invalid number; expected digit after exponent sign";
8333                 return token_type::parse_error;
8334             }
8335         }
8336 
8337 scan_number_any2:
8338         // we just parsed a number after the exponent or exponent sign
8339         switch (get())
8340         {
8341             case '0':
8342             case '1':
8343             case '2':
8344             case '3':
8345             case '4':
8346             case '5':
8347             case '6':
8348             case '7':
8349             case '8':
8350             case '9':
8351             {
8352                 add(current);
8353                 goto scan_number_any2;
8354             }
8355 
8356             default:
8357                 goto scan_number_done;
8358         }
8359 
8360 scan_number_done:
8361         // unget the character after the number (we only read it to know that
8362         // we are done scanning a number)
8363         unget();
8364 
8365         char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8366         errno = 0;
8367 
8368         // try to parse integers first and fall back to floats
8369         if (number_type == token_type::value_unsigned)
8370         {
8371             const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8372 
8373             // we checked the number format before
8374             JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8375 
8376             if (errno == 0)
8377             {
8378                 value_unsigned = static_cast<number_unsigned_t>(x);
8379                 if (value_unsigned == x)
8380                 {
8381                     return token_type::value_unsigned;
8382                 }
8383             }
8384         }
8385         else if (number_type == token_type::value_integer)
8386         {
8387             const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8388 
8389             // we checked the number format before
8390             JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8391 
8392             if (errno == 0)
8393             {
8394                 value_integer = static_cast<number_integer_t>(x);
8395                 if (value_integer == x)
8396                 {
8397                     return token_type::value_integer;
8398                 }
8399             }
8400         }
8401 
8402         // this code is reached if we parse a floating-point number or if an
8403         // integer conversion above failed
8404         strtof(value_float, token_buffer.data(), &endptr);
8405 
8406         // we checked the number format before
8407         JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8408 
8409         return token_type::value_float;
8410     }
8411 
8412     /*!
8413     @param[in] literal_text  the literal text to expect
8414     @param[in] length        the length of the passed literal text
8415     @param[in] return_type   the token type to return on success
8416     */
8417     JSON_HEDLEY_NON_NULL(2)
scan_literal(const char_type * literal_text,const std::size_t length,token_type return_type)8418     token_type scan_literal(const char_type* literal_text, const std::size_t length,
8419                             token_type return_type)
8420     {
8421         JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
8422         for (std::size_t i = 1; i < length; ++i)
8423         {
8424             if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8425             {
8426                 error_message = "invalid literal";
8427                 return token_type::parse_error;
8428             }
8429         }
8430         return return_type;
8431     }
8432 
8433     /////////////////////
8434     // input management
8435     /////////////////////
8436 
8437     /// reset token_buffer; current character is beginning of token
reset()8438     void reset() noexcept
8439     {
8440         token_buffer.clear();
8441         token_string.clear();
8442         token_string.push_back(std::char_traits<char_type>::to_char_type(current));
8443     }
8444 
8445     /*
8446     @brief get next character from the input
8447 
8448     This function provides the interface to the used input adapter. It does
8449     not throw in case the input reached EOF, but returns a
8450     `std::char_traits<char>::eof()` in that case.  Stores the scanned characters
8451     for use in error messages.
8452 
8453     @return character read from the input
8454     */
get()8455     char_int_type get()
8456     {
8457         ++position.chars_read_total;
8458         ++position.chars_read_current_line;
8459 
8460         if (next_unget)
8461         {
8462             // just reset the next_unget variable and work with current
8463             next_unget = false;
8464         }
8465         else
8466         {
8467             current = ia.get_character();
8468         }
8469 
8470         if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
8471         {
8472             token_string.push_back(std::char_traits<char_type>::to_char_type(current));
8473         }
8474 
8475         if (current == '\n')
8476         {
8477             ++position.lines_read;
8478             position.chars_read_current_line = 0;
8479         }
8480 
8481         return current;
8482     }
8483 
8484     /*!
8485     @brief unget current character (read it again on next get)
8486 
8487     We implement unget by setting variable next_unget to true. The input is not
8488     changed - we just simulate ungetting by modifying chars_read_total,
8489     chars_read_current_line, and token_string. The next call to get() will
8490     behave as if the unget character is read again.
8491     */
unget()8492     void unget()
8493     {
8494         next_unget = true;
8495 
8496         --position.chars_read_total;
8497 
8498         // in case we "unget" a newline, we have to also decrement the lines_read
8499         if (position.chars_read_current_line == 0)
8500         {
8501             if (position.lines_read > 0)
8502             {
8503                 --position.lines_read;
8504             }
8505         }
8506         else
8507         {
8508             --position.chars_read_current_line;
8509         }
8510 
8511         if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
8512         {
8513             JSON_ASSERT(!token_string.empty());
8514             token_string.pop_back();
8515         }
8516     }
8517 
8518     /// add a character to token_buffer
add(char_int_type c)8519     void add(char_int_type c)
8520     {
8521         token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8522     }
8523 
8524   public:
8525     /////////////////////
8526     // value getters
8527     /////////////////////
8528 
8529     /// return integer value
get_number_integer() const8530     constexpr number_integer_t get_number_integer() const noexcept
8531     {
8532         return value_integer;
8533     }
8534 
8535     /// return unsigned integer value
get_number_unsigned() const8536     constexpr number_unsigned_t get_number_unsigned() const noexcept
8537     {
8538         return value_unsigned;
8539     }
8540 
8541     /// return floating-point value
get_number_float() const8542     constexpr number_float_t get_number_float() const noexcept
8543     {
8544         return value_float;
8545     }
8546 
8547     /// return current string value (implicitly resets the token; useful only once)
get_string()8548     string_t& get_string()
8549     {
8550         return token_buffer;
8551     }
8552 
8553     /////////////////////
8554     // diagnostics
8555     /////////////////////
8556 
8557     /// return position of last read token
get_position() const8558     constexpr position_t get_position() const noexcept
8559     {
8560         return position;
8561     }
8562 
8563     /// return the last read token (for errors only).  Will never contain EOF
8564     /// (an arbitrary value that is not a valid char value, often -1), because
8565     /// 255 may legitimately occur.  May contain NUL, which should be escaped.
get_token_string() const8566     std::string get_token_string() const
8567     {
8568         // escape control characters
8569         std::string result;
8570         for (const auto c : token_string)
8571         {
8572             if (static_cast<unsigned char>(c) <= '\x1F')
8573             {
8574                 // escape control characters
8575                 std::array<char, 9> cs{{}};
8576                 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8577                 result += cs.data();
8578             }
8579             else
8580             {
8581                 // add character as is
8582                 result.push_back(static_cast<std::string::value_type>(c));
8583             }
8584         }
8585 
8586         return result;
8587     }
8588 
8589     /// return syntax error message
8590     JSON_HEDLEY_RETURNS_NON_NULL
get_error_message() const8591     constexpr const char* get_error_message() const noexcept
8592     {
8593         return error_message;
8594     }
8595 
8596     /////////////////////
8597     // actual scanner
8598     /////////////////////
8599 
8600     /*!
8601     @brief skip the UTF-8 byte order mark
8602     @return true iff there is no BOM or the correct BOM has been skipped
8603     */
skip_bom()8604     bool skip_bom()
8605     {
8606         if (get() == 0xEF)
8607         {
8608             // check if we completely parse the BOM
8609             return get() == 0xBB && get() == 0xBF;
8610         }
8611 
8612         // the first character is not the beginning of the BOM; unget it to
8613         // process is later
8614         unget();
8615         return true;
8616     }
8617 
skip_whitespace()8618     void skip_whitespace()
8619     {
8620         do
8621         {
8622             get();
8623         }
8624         while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8625     }
8626 
scan()8627     token_type scan()
8628     {
8629         // initially, skip the BOM
8630         if (position.chars_read_total == 0 && !skip_bom())
8631         {
8632             error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8633             return token_type::parse_error;
8634         }
8635 
8636         // read next character and ignore whitespace
8637         skip_whitespace();
8638 
8639         // ignore comments
8640         while (ignore_comments && current == '/')
8641         {
8642             if (!scan_comment())
8643             {
8644                 return token_type::parse_error;
8645             }
8646 
8647             // skip following whitespace
8648             skip_whitespace();
8649         }
8650 
8651         switch (current)
8652         {
8653             // structural characters
8654             case '[':
8655                 return token_type::begin_array;
8656             case ']':
8657                 return token_type::end_array;
8658             case '{':
8659                 return token_type::begin_object;
8660             case '}':
8661                 return token_type::end_object;
8662             case ':':
8663                 return token_type::name_separator;
8664             case ',':
8665                 return token_type::value_separator;
8666 
8667             // literals
8668             case 't':
8669             {
8670                 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')}};
8671                 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8672             }
8673             case 'f':
8674             {
8675                 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')}};
8676                 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8677             }
8678             case 'n':
8679             {
8680                 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')}};
8681                 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8682             }
8683 
8684             // string
8685             case '\"':
8686                 return scan_string();
8687 
8688             // number
8689             case '-':
8690             case '0':
8691             case '1':
8692             case '2':
8693             case '3':
8694             case '4':
8695             case '5':
8696             case '6':
8697             case '7':
8698             case '8':
8699             case '9':
8700                 return scan_number();
8701 
8702             // end of input (the null byte is needed when parsing from
8703             // string literals)
8704             case '\0':
8705             case std::char_traits<char_type>::eof():
8706                 return token_type::end_of_input;
8707 
8708             // error
8709             default:
8710                 error_message = "invalid literal";
8711                 return token_type::parse_error;
8712         }
8713     }
8714 
8715   private:
8716     /// input adapter
8717     InputAdapterType ia;
8718 
8719     /// whether comments should be ignored (true) or signaled as errors (false)
8720     const bool ignore_comments = false;
8721 
8722     /// the current character
8723     char_int_type current = std::char_traits<char_type>::eof();
8724 
8725     /// whether the next get() call should just return current
8726     bool next_unget = false;
8727 
8728     /// the start position of the current token
8729     position_t position {};
8730 
8731     /// raw input token string (for error messages)
8732     std::vector<char_type> token_string {};
8733 
8734     /// buffer for variable-length tokens (numbers, strings)
8735     string_t token_buffer {};
8736 
8737     /// a description of occurred lexer errors
8738     const char* error_message = "";
8739 
8740     // number values
8741     number_integer_t value_integer = 0;
8742     number_unsigned_t value_unsigned = 0;
8743     number_float_t value_float = 0;
8744 
8745     /// the decimal point
8746     const char_int_type decimal_point_char = '.';
8747 };
8748 }  // namespace detail
8749 }  // namespace nlohmann
8750 
8751 // #include <nlohmann/detail/macro_scope.hpp>
8752 
8753 // #include <nlohmann/detail/meta/is_sax.hpp>
8754 //     __ _____ _____ _____
8755 //  __|  |   __|     |   | |  JSON for Modern C++
8756 // |  |  |__   |  |  | | | |  version 3.10.5
8757 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
8758 //
8759 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
8760 // SPDX-License-Identifier: MIT
8761 
8762 
8763 
8764 #include <cstdint> // size_t
8765 #include <utility> // declval
8766 #include <string> // string
8767 
8768 // #include <nlohmann/detail/meta/detected.hpp>
8769 
8770 // #include <nlohmann/detail/meta/type_traits.hpp>
8771 
8772 
8773 namespace nlohmann
8774 {
8775 namespace detail
8776 {
8777 template<typename T>
8778 using null_function_t = decltype(std::declval<T&>().null());
8779 
8780 template<typename T>
8781 using boolean_function_t =
8782     decltype(std::declval<T&>().boolean(std::declval<bool>()));
8783 
8784 template<typename T, typename Integer>
8785 using number_integer_function_t =
8786     decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
8787 
8788 template<typename T, typename Unsigned>
8789 using number_unsigned_function_t =
8790     decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
8791 
8792 template<typename T, typename Float, typename String>
8793 using number_float_function_t = decltype(std::declval<T&>().number_float(
8794                                     std::declval<Float>(), std::declval<const String&>()));
8795 
8796 template<typename T, typename String>
8797 using string_function_t =
8798     decltype(std::declval<T&>().string(std::declval<String&>()));
8799 
8800 template<typename T, typename Binary>
8801 using binary_function_t =
8802     decltype(std::declval<T&>().binary(std::declval<Binary&>()));
8803 
8804 template<typename T>
8805 using start_object_function_t =
8806     decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
8807 
8808 template<typename T, typename String>
8809 using key_function_t =
8810     decltype(std::declval<T&>().key(std::declval<String&>()));
8811 
8812 template<typename T>
8813 using end_object_function_t = decltype(std::declval<T&>().end_object());
8814 
8815 template<typename T>
8816 using start_array_function_t =
8817     decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
8818 
8819 template<typename T>
8820 using end_array_function_t = decltype(std::declval<T&>().end_array());
8821 
8822 template<typename T, typename Exception>
8823 using parse_error_function_t = decltype(std::declval<T&>().parse_error(
8824         std::declval<std::size_t>(), std::declval<const std::string&>(),
8825         std::declval<const Exception&>()));
8826 
8827 template<typename SAX, typename BasicJsonType>
8828 struct is_sax
8829 {
8830   private:
8831     static_assert(is_basic_json<BasicJsonType>::value,
8832                   "BasicJsonType must be of type basic_json<...>");
8833 
8834     using number_integer_t = typename BasicJsonType::number_integer_t;
8835     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8836     using number_float_t = typename BasicJsonType::number_float_t;
8837     using string_t = typename BasicJsonType::string_t;
8838     using binary_t = typename BasicJsonType::binary_t;
8839     using exception_t = typename BasicJsonType::exception;
8840 
8841   public:
8842     static constexpr bool value =
8843         is_detected_exact<bool, null_function_t, SAX>::value &&
8844         is_detected_exact<bool, boolean_function_t, SAX>::value &&
8845         is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
8846         is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
8847         is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
8848         is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
8849         is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
8850         is_detected_exact<bool, start_object_function_t, SAX>::value &&
8851         is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
8852         is_detected_exact<bool, end_object_function_t, SAX>::value &&
8853         is_detected_exact<bool, start_array_function_t, SAX>::value &&
8854         is_detected_exact<bool, end_array_function_t, SAX>::value &&
8855         is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
8856 };
8857 
8858 template<typename SAX, typename BasicJsonType>
8859 struct is_sax_static_asserts
8860 {
8861   private:
8862     static_assert(is_basic_json<BasicJsonType>::value,
8863                   "BasicJsonType must be of type basic_json<...>");
8864 
8865     using number_integer_t = typename BasicJsonType::number_integer_t;
8866     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8867     using number_float_t = typename BasicJsonType::number_float_t;
8868     using string_t = typename BasicJsonType::string_t;
8869     using binary_t = typename BasicJsonType::binary_t;
8870     using exception_t = typename BasicJsonType::exception;
8871 
8872   public:
8873     static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
8874                   "Missing/invalid function: bool null()");
8875     static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
8876                   "Missing/invalid function: bool boolean(bool)");
8877     static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
8878                   "Missing/invalid function: bool boolean(bool)");
8879     static_assert(
8880         is_detected_exact<bool, number_integer_function_t, SAX,
8881         number_integer_t>::value,
8882         "Missing/invalid function: bool number_integer(number_integer_t)");
8883     static_assert(
8884         is_detected_exact<bool, number_unsigned_function_t, SAX,
8885         number_unsigned_t>::value,
8886         "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
8887     static_assert(is_detected_exact<bool, number_float_function_t, SAX,
8888                   number_float_t, string_t>::value,
8889                   "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
8890     static_assert(
8891         is_detected_exact<bool, string_function_t, SAX, string_t>::value,
8892         "Missing/invalid function: bool string(string_t&)");
8893     static_assert(
8894         is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
8895         "Missing/invalid function: bool binary(binary_t&)");
8896     static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
8897                   "Missing/invalid function: bool start_object(std::size_t)");
8898     static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
8899                   "Missing/invalid function: bool key(string_t&)");
8900     static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
8901                   "Missing/invalid function: bool end_object()");
8902     static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
8903                   "Missing/invalid function: bool start_array(std::size_t)");
8904     static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
8905                   "Missing/invalid function: bool end_array()");
8906     static_assert(
8907         is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
8908         "Missing/invalid function: bool parse_error(std::size_t, const "
8909         "std::string&, const exception&)");
8910 };
8911 }  // namespace detail
8912 }  // namespace nlohmann
8913 
8914 // #include <nlohmann/detail/meta/type_traits.hpp>
8915 
8916 // #include <nlohmann/detail/string_concat.hpp>
8917 
8918 // #include <nlohmann/detail/value_t.hpp>
8919 
8920 
8921 namespace nlohmann
8922 {
8923 namespace detail
8924 {
8925 
8926 /// how to treat CBOR tags
8927 enum class cbor_tag_handler_t
8928 {
8929     error,   ///< throw a parse_error exception in case of a tag
8930     ignore,  ///< ignore tags
8931     store    ///< store tags as binary type
8932 };
8933 
8934 /*!
8935 @brief determine system byte order
8936 
8937 @return true if and only if system's byte order is little endian
8938 
8939 @note from https://stackoverflow.com/a/1001328/266378
8940 */
little_endianness(int num=1)8941 static inline bool little_endianness(int num = 1) noexcept
8942 {
8943     return *reinterpret_cast<char*>(&num) == 1;
8944 }
8945 
8946 
8947 ///////////////////
8948 // binary reader //
8949 ///////////////////
8950 
8951 /*!
8952 @brief deserialization of CBOR, MessagePack, and UBJSON values
8953 */
8954 template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
8955 class binary_reader
8956 {
8957     using number_integer_t = typename BasicJsonType::number_integer_t;
8958     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8959     using number_float_t = typename BasicJsonType::number_float_t;
8960     using string_t = typename BasicJsonType::string_t;
8961     using binary_t = typename BasicJsonType::binary_t;
8962     using json_sax_t = SAX;
8963     using char_type = typename InputAdapterType::char_type;
8964     using char_int_type = typename std::char_traits<char_type>::int_type;
8965 
8966   public:
8967     /*!
8968     @brief create a binary reader
8969 
8970     @param[in] adapter  input adapter to read from
8971     */
binary_reader(InputAdapterType && adapter,const input_format_t format=input_format_t::json)8972     explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
8973     {
8974         (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
8975     }
8976 
8977     // make class move-only
8978     binary_reader(const binary_reader&) = delete;
8979     binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8980     binary_reader& operator=(const binary_reader&) = delete;
8981     binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8982     ~binary_reader() = default;
8983 
8984     /*!
8985     @param[in] format  the binary format to parse
8986     @param[in] sax_    a SAX event processor
8987     @param[in] strict  whether to expect the input to be consumed completed
8988     @param[in] tag_handler  how to treat CBOR tags
8989 
8990     @return whether parsing was successful
8991     */
8992     JSON_HEDLEY_NON_NULL(3)
sax_parse(const input_format_t format,json_sax_t * sax_,const bool strict=true,const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)8993     bool sax_parse(const input_format_t format,
8994                    json_sax_t* sax_,
8995                    const bool strict = true,
8996                    const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
8997     {
8998         sax = sax_;
8999         bool result = false;
9000 
9001         switch (format)
9002         {
9003             case input_format_t::bson:
9004                 result = parse_bson_internal();
9005                 break;
9006 
9007             case input_format_t::cbor:
9008                 result = parse_cbor_internal(true, tag_handler);
9009                 break;
9010 
9011             case input_format_t::msgpack:
9012                 result = parse_msgpack_internal();
9013                 break;
9014 
9015             case input_format_t::ubjson:
9016             case input_format_t::bjdata:
9017                 result = parse_ubjson_internal();
9018                 break;
9019 
9020             case input_format_t::json: // LCOV_EXCL_LINE
9021             default:            // LCOV_EXCL_LINE
9022                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9023         }
9024 
9025         // strict mode: next byte must be EOF
9026         if (result && strict)
9027         {
9028             if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9029             {
9030                 get_ignore_noop();
9031             }
9032             else
9033             {
9034                 get();
9035             }
9036 
9037             if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
9038             {
9039                 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9040                                         exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9041             }
9042         }
9043 
9044         return result;
9045     }
9046 
9047   private:
9048     //////////
9049     // BSON //
9050     //////////
9051 
9052     /*!
9053     @brief Reads in a BSON-object and passes it to the SAX-parser.
9054     @return whether a valid BSON-value was passed to the SAX parser
9055     */
parse_bson_internal()9056     bool parse_bson_internal()
9057     {
9058         std::int32_t document_size{};
9059         get_number<std::int32_t, true>(input_format_t::bson, document_size);
9060 
9061         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
9062         {
9063             return false;
9064         }
9065 
9066         if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
9067         {
9068             return false;
9069         }
9070 
9071         return sax->end_object();
9072     }
9073 
9074     /*!
9075     @brief Parses a C-style string from the BSON input.
9076     @param[in,out] result  A reference to the string variable where the read
9077                             string is to be stored.
9078     @return `true` if the \x00-byte indicating the end of the string was
9079              encountered before the EOF; false` indicates an unexpected EOF.
9080     */
get_bson_cstr(string_t & result)9081     bool get_bson_cstr(string_t& result)
9082     {
9083         auto out = std::back_inserter(result);
9084         while (true)
9085         {
9086             get();
9087             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
9088             {
9089                 return false;
9090             }
9091             if (current == 0x00)
9092             {
9093                 return true;
9094             }
9095             *out++ = static_cast<typename string_t::value_type>(current);
9096         }
9097     }
9098 
9099     /*!
9100     @brief Parses a zero-terminated string of length @a len from the BSON
9101            input.
9102     @param[in] len  The length (including the zero-byte at the end) of the
9103                     string to be read.
9104     @param[in,out] result  A reference to the string variable where the read
9105                             string is to be stored.
9106     @tparam NumberType The type of the length @a len
9107     @pre len >= 1
9108     @return `true` if the string was successfully parsed
9109     */
9110     template<typename NumberType>
get_bson_string(const NumberType len,string_t & result)9111     bool get_bson_string(const NumberType len, string_t& result)
9112     {
9113         if (JSON_HEDLEY_UNLIKELY(len < 1))
9114         {
9115             auto last_token = get_token_string();
9116             return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9117                                     exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
9118         }
9119 
9120         return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
9121     }
9122 
9123     /*!
9124     @brief Parses a byte array input of length @a len from the BSON input.
9125     @param[in] len  The length of the byte array to be read.
9126     @param[in,out] result  A reference to the binary variable where the read
9127                             array is to be stored.
9128     @tparam NumberType The type of the length @a len
9129     @pre len >= 0
9130     @return `true` if the byte array was successfully parsed
9131     */
9132     template<typename NumberType>
get_bson_binary(const NumberType len,binary_t & result)9133     bool get_bson_binary(const NumberType len, binary_t& result)
9134     {
9135         if (JSON_HEDLEY_UNLIKELY(len < 0))
9136         {
9137             auto last_token = get_token_string();
9138             return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9139                                     exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
9140         }
9141 
9142         // All BSON binary values have a subtype
9143         std::uint8_t subtype{};
9144         get_number<std::uint8_t>(input_format_t::bson, subtype);
9145         result.set_subtype(subtype);
9146 
9147         return get_binary(input_format_t::bson, len, result);
9148     }
9149 
9150     /*!
9151     @brief Read a BSON document element of the given @a element_type.
9152     @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
9153     @param[in] element_type_parse_position The position in the input stream,
9154                where the `element_type` was read.
9155     @warning Not all BSON element types are supported yet. An unsupported
9156              @a element_type will give rise to a parse_error.114:
9157              Unsupported BSON record type 0x...
9158     @return whether a valid BSON-object/array was passed to the SAX parser
9159     */
parse_bson_element_internal(const char_int_type element_type,const std::size_t element_type_parse_position)9160     bool parse_bson_element_internal(const char_int_type element_type,
9161                                      const std::size_t element_type_parse_position)
9162     {
9163         switch (element_type)
9164         {
9165             case 0x01: // double
9166             {
9167                 double number{};
9168                 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9169             }
9170 
9171             case 0x02: // string
9172             {
9173                 std::int32_t len{};
9174                 string_t value;
9175                 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
9176             }
9177 
9178             case 0x03: // object
9179             {
9180                 return parse_bson_internal();
9181             }
9182 
9183             case 0x04: // array
9184             {
9185                 return parse_bson_array();
9186             }
9187 
9188             case 0x05: // binary
9189             {
9190                 std::int32_t len{};
9191                 binary_t value;
9192                 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
9193             }
9194 
9195             case 0x08: // boolean
9196             {
9197                 return sax->boolean(get() != 0);
9198             }
9199 
9200             case 0x0A: // null
9201             {
9202                 return sax->null();
9203             }
9204 
9205             case 0x10: // int32
9206             {
9207                 std::int32_t value{};
9208                 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9209             }
9210 
9211             case 0x12: // int64
9212             {
9213                 std::int64_t value{};
9214                 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9215             }
9216 
9217             default: // anything else not supported (yet)
9218             {
9219                 std::array<char, 3> cr{{}};
9220                 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
9221                 std::string cr_str{cr.data()};
9222                 return sax->parse_error(element_type_parse_position, cr_str,
9223                                         parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
9224             }
9225         }
9226     }
9227 
9228     /*!
9229     @brief Read a BSON element list (as specified in the BSON-spec)
9230 
9231     The same binary layout is used for objects and arrays, hence it must be
9232     indicated with the argument @a is_array which one is expected
9233     (true --> array, false --> object).
9234 
9235     @param[in] is_array Determines if the element list being read is to be
9236                         treated as an object (@a is_array == false), or as an
9237                         array (@a is_array == true).
9238     @return whether a valid BSON-object/array was passed to the SAX parser
9239     */
parse_bson_element_list(const bool is_array)9240     bool parse_bson_element_list(const bool is_array)
9241     {
9242         string_t key;
9243 
9244         while (auto element_type = get())
9245         {
9246             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
9247             {
9248                 return false;
9249             }
9250 
9251             const std::size_t element_type_parse_position = chars_read;
9252             if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
9253             {
9254                 return false;
9255             }
9256 
9257             if (!is_array && !sax->key(key))
9258             {
9259                 return false;
9260             }
9261 
9262             if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
9263             {
9264                 return false;
9265             }
9266 
9267             // get_bson_cstr only appends
9268             key.clear();
9269         }
9270 
9271         return true;
9272     }
9273 
9274     /*!
9275     @brief Reads an array from the BSON input and passes it to the SAX-parser.
9276     @return whether a valid BSON-array was passed to the SAX parser
9277     */
parse_bson_array()9278     bool parse_bson_array()
9279     {
9280         std::int32_t document_size{};
9281         get_number<std::int32_t, true>(input_format_t::bson, document_size);
9282 
9283         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
9284         {
9285             return false;
9286         }
9287 
9288         if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
9289         {
9290             return false;
9291         }
9292 
9293         return sax->end_array();
9294     }
9295 
9296     //////////
9297     // CBOR //
9298     //////////
9299 
9300     /*!
9301     @param[in] get_char  whether a new character should be retrieved from the
9302                          input (true) or whether the last read character should
9303                          be considered instead (false)
9304     @param[in] tag_handler how CBOR tags should be treated
9305 
9306     @return whether a valid CBOR value was passed to the SAX parser
9307     */
parse_cbor_internal(const bool get_char,const cbor_tag_handler_t tag_handler)9308     bool parse_cbor_internal(const bool get_char,
9309                              const cbor_tag_handler_t tag_handler)
9310     {
9311         switch (get_char ? get() : current)
9312         {
9313             // EOF
9314             case std::char_traits<char_type>::eof():
9315                 return unexpect_eof(input_format_t::cbor, "value");
9316 
9317             // Integer 0x00..0x17 (0..23)
9318             case 0x00:
9319             case 0x01:
9320             case 0x02:
9321             case 0x03:
9322             case 0x04:
9323             case 0x05:
9324             case 0x06:
9325             case 0x07:
9326             case 0x08:
9327             case 0x09:
9328             case 0x0A:
9329             case 0x0B:
9330             case 0x0C:
9331             case 0x0D:
9332             case 0x0E:
9333             case 0x0F:
9334             case 0x10:
9335             case 0x11:
9336             case 0x12:
9337             case 0x13:
9338             case 0x14:
9339             case 0x15:
9340             case 0x16:
9341             case 0x17:
9342                 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9343 
9344             case 0x18: // Unsigned integer (one-byte uint8_t follows)
9345             {
9346                 std::uint8_t number{};
9347                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9348             }
9349 
9350             case 0x19: // Unsigned integer (two-byte uint16_t follows)
9351             {
9352                 std::uint16_t number{};
9353                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9354             }
9355 
9356             case 0x1A: // Unsigned integer (four-byte uint32_t follows)
9357             {
9358                 std::uint32_t number{};
9359                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9360             }
9361 
9362             case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
9363             {
9364                 std::uint64_t number{};
9365                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9366             }
9367 
9368             // Negative integer -1-0x00..-1-0x17 (-1..-24)
9369             case 0x20:
9370             case 0x21:
9371             case 0x22:
9372             case 0x23:
9373             case 0x24:
9374             case 0x25:
9375             case 0x26:
9376             case 0x27:
9377             case 0x28:
9378             case 0x29:
9379             case 0x2A:
9380             case 0x2B:
9381             case 0x2C:
9382             case 0x2D:
9383             case 0x2E:
9384             case 0x2F:
9385             case 0x30:
9386             case 0x31:
9387             case 0x32:
9388             case 0x33:
9389             case 0x34:
9390             case 0x35:
9391             case 0x36:
9392             case 0x37:
9393                 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
9394 
9395             case 0x38: // Negative integer (one-byte uint8_t follows)
9396             {
9397                 std::uint8_t number{};
9398                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9399             }
9400 
9401             case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
9402             {
9403                 std::uint16_t number{};
9404                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9405             }
9406 
9407             case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
9408             {
9409                 std::uint32_t number{};
9410                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9411             }
9412 
9413             case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
9414             {
9415                 std::uint64_t number{};
9416                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
9417                         - static_cast<number_integer_t>(number));
9418             }
9419 
9420             // Binary data (0x00..0x17 bytes follow)
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: // Binary data (one-byte uint8_t for n follows)
9446             case 0x59: // Binary data (two-byte uint16_t for n follow)
9447             case 0x5A: // Binary data (four-byte uint32_t for n follow)
9448             case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9449             case 0x5F: // Binary data (indefinite length)
9450             {
9451                 binary_t b;
9452                 return get_cbor_binary(b) && sax->binary(b);
9453             }
9454 
9455             // UTF-8 string (0x00..0x17 bytes follow)
9456             case 0x60:
9457             case 0x61:
9458             case 0x62:
9459             case 0x63:
9460             case 0x64:
9461             case 0x65:
9462             case 0x66:
9463             case 0x67:
9464             case 0x68:
9465             case 0x69:
9466             case 0x6A:
9467             case 0x6B:
9468             case 0x6C:
9469             case 0x6D:
9470             case 0x6E:
9471             case 0x6F:
9472             case 0x70:
9473             case 0x71:
9474             case 0x72:
9475             case 0x73:
9476             case 0x74:
9477             case 0x75:
9478             case 0x76:
9479             case 0x77:
9480             case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9481             case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9482             case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9483             case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9484             case 0x7F: // UTF-8 string (indefinite length)
9485             {
9486                 string_t s;
9487                 return get_cbor_string(s) && sax->string(s);
9488             }
9489 
9490             // array (0x00..0x17 data items follow)
9491             case 0x80:
9492             case 0x81:
9493             case 0x82:
9494             case 0x83:
9495             case 0x84:
9496             case 0x85:
9497             case 0x86:
9498             case 0x87:
9499             case 0x88:
9500             case 0x89:
9501             case 0x8A:
9502             case 0x8B:
9503             case 0x8C:
9504             case 0x8D:
9505             case 0x8E:
9506             case 0x8F:
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                 return get_cbor_array(
9516                            conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9517 
9518             case 0x98: // array (one-byte uint8_t for n follows)
9519             {
9520                 std::uint8_t len{};
9521                 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9522             }
9523 
9524             case 0x99: // array (two-byte uint16_t for n follow)
9525             {
9526                 std::uint16_t len{};
9527                 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9528             }
9529 
9530             case 0x9A: // array (four-byte uint32_t for n follow)
9531             {
9532                 std::uint32_t len{};
9533                 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9534             }
9535 
9536             case 0x9B: // array (eight-byte uint64_t for n follow)
9537             {
9538                 std::uint64_t len{};
9539                 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9540             }
9541 
9542             case 0x9F: // array (indefinite length)
9543                 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
9544 
9545             // map (0x00..0x17 pairs of data items follow)
9546             case 0xA0:
9547             case 0xA1:
9548             case 0xA2:
9549             case 0xA3:
9550             case 0xA4:
9551             case 0xA5:
9552             case 0xA6:
9553             case 0xA7:
9554             case 0xA8:
9555             case 0xA9:
9556             case 0xAA:
9557             case 0xAB:
9558             case 0xAC:
9559             case 0xAD:
9560             case 0xAE:
9561             case 0xAF:
9562             case 0xB0:
9563             case 0xB1:
9564             case 0xB2:
9565             case 0xB3:
9566             case 0xB4:
9567             case 0xB5:
9568             case 0xB6:
9569             case 0xB7:
9570                 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9571 
9572             case 0xB8: // map (one-byte uint8_t for n follows)
9573             {
9574                 std::uint8_t len{};
9575                 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9576             }
9577 
9578             case 0xB9: // map (two-byte uint16_t for n follow)
9579             {
9580                 std::uint16_t len{};
9581                 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9582             }
9583 
9584             case 0xBA: // map (four-byte uint32_t for n follow)
9585             {
9586                 std::uint32_t len{};
9587                 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9588             }
9589 
9590             case 0xBB: // map (eight-byte uint64_t for n follow)
9591             {
9592                 std::uint64_t len{};
9593                 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9594             }
9595 
9596             case 0xBF: // map (indefinite length)
9597                 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
9598 
9599             case 0xC6: // tagged item
9600             case 0xC7:
9601             case 0xC8:
9602             case 0xC9:
9603             case 0xCA:
9604             case 0xCB:
9605             case 0xCC:
9606             case 0xCD:
9607             case 0xCE:
9608             case 0xCF:
9609             case 0xD0:
9610             case 0xD1:
9611             case 0xD2:
9612             case 0xD3:
9613             case 0xD4:
9614             case 0xD8: // tagged item (1 bytes follow)
9615             case 0xD9: // tagged item (2 bytes follow)
9616             case 0xDA: // tagged item (4 bytes follow)
9617             case 0xDB: // tagged item (8 bytes follow)
9618             {
9619                 switch (tag_handler)
9620                 {
9621                     case cbor_tag_handler_t::error:
9622                     {
9623                         auto last_token = get_token_string();
9624                         return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9625                                                 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
9626                     }
9627 
9628                     case cbor_tag_handler_t::ignore:
9629                     {
9630                         // ignore binary subtype
9631                         switch (current)
9632                         {
9633                             case 0xD8:
9634                             {
9635                                 std::uint8_t subtype_to_ignore{};
9636                                 get_number(input_format_t::cbor, subtype_to_ignore);
9637                                 break;
9638                             }
9639                             case 0xD9:
9640                             {
9641                                 std::uint16_t subtype_to_ignore{};
9642                                 get_number(input_format_t::cbor, subtype_to_ignore);
9643                                 break;
9644                             }
9645                             case 0xDA:
9646                             {
9647                                 std::uint32_t subtype_to_ignore{};
9648                                 get_number(input_format_t::cbor, subtype_to_ignore);
9649                                 break;
9650                             }
9651                             case 0xDB:
9652                             {
9653                                 std::uint64_t subtype_to_ignore{};
9654                                 get_number(input_format_t::cbor, subtype_to_ignore);
9655                                 break;
9656                             }
9657                             default:
9658                                 break;
9659                         }
9660                         return parse_cbor_internal(true, tag_handler);
9661                     }
9662 
9663                     case cbor_tag_handler_t::store:
9664                     {
9665                         binary_t b;
9666                         // use binary subtype and store in binary container
9667                         switch (current)
9668                         {
9669                             case 0xD8:
9670                             {
9671                                 std::uint8_t subtype{};
9672                                 get_number(input_format_t::cbor, subtype);
9673                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9674                                 break;
9675                             }
9676                             case 0xD9:
9677                             {
9678                                 std::uint16_t subtype{};
9679                                 get_number(input_format_t::cbor, subtype);
9680                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9681                                 break;
9682                             }
9683                             case 0xDA:
9684                             {
9685                                 std::uint32_t subtype{};
9686                                 get_number(input_format_t::cbor, subtype);
9687                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9688                                 break;
9689                             }
9690                             case 0xDB:
9691                             {
9692                                 std::uint64_t subtype{};
9693                                 get_number(input_format_t::cbor, subtype);
9694                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9695                                 break;
9696                             }
9697                             default:
9698                                 return parse_cbor_internal(true, tag_handler);
9699                         }
9700                         get();
9701                         return get_cbor_binary(b) && sax->binary(b);
9702                     }
9703 
9704                     default:                 // LCOV_EXCL_LINE
9705                         JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9706                         return false;        // LCOV_EXCL_LINE
9707                 }
9708             }
9709 
9710             case 0xF4: // false
9711                 return sax->boolean(false);
9712 
9713             case 0xF5: // true
9714                 return sax->boolean(true);
9715 
9716             case 0xF6: // null
9717                 return sax->null();
9718 
9719             case 0xF9: // Half-Precision Float (two-byte IEEE 754)
9720             {
9721                 const auto byte1_raw = get();
9722                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9723                 {
9724                     return false;
9725                 }
9726                 const auto byte2_raw = get();
9727                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9728                 {
9729                     return false;
9730                 }
9731 
9732                 const auto byte1 = static_cast<unsigned char>(byte1_raw);
9733                 const auto byte2 = static_cast<unsigned char>(byte2_raw);
9734 
9735                 // code from RFC 7049, Appendix D, Figure 3:
9736                 // As half-precision floating-point numbers were only added
9737                 // to IEEE 754 in 2008, today's programming platforms often
9738                 // still only have limited support for them. It is very
9739                 // easy to include at least decoding support for them even
9740                 // without such support. An example of a small decoder for
9741                 // half-precision floating-point numbers in the C language
9742                 // is shown in Fig. 3.
9743                 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
9744                 const double val = [&half]
9745                 {
9746                     const int exp = (half >> 10u) & 0x1Fu;
9747                     const unsigned int mant = half & 0x3FFu;
9748                     JSON_ASSERT(0 <= exp&& exp <= 32);
9749                     JSON_ASSERT(mant <= 1024);
9750                     switch (exp)
9751                     {
9752                         case 0:
9753                             return std::ldexp(mant, -24);
9754                         case 31:
9755                             return (mant == 0)
9756                             ? std::numeric_limits<double>::infinity()
9757                             : std::numeric_limits<double>::quiet_NaN();
9758                         default:
9759                             return std::ldexp(mant + 1024, exp - 25);
9760                     }
9761                 }();
9762                 return sax->number_float((half & 0x8000u) != 0
9763                                          ? static_cast<number_float_t>(-val)
9764                                          : static_cast<number_float_t>(val), "");
9765             }
9766 
9767             case 0xFA: // Single-Precision Float (four-byte IEEE 754)
9768             {
9769                 float number{};
9770                 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9771             }
9772 
9773             case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
9774             {
9775                 double number{};
9776                 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9777             }
9778 
9779             default: // anything else (0xFF is handled inside the other types)
9780             {
9781                 auto last_token = get_token_string();
9782                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9783                                         exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
9784             }
9785         }
9786     }
9787 
9788     /*!
9789     @brief reads a CBOR string
9790 
9791     This function first reads starting bytes to determine the expected
9792     string length and then copies this number of bytes into a string.
9793     Additionally, CBOR's strings with indefinite lengths are supported.
9794 
9795     @param[out] result  created string
9796 
9797     @return whether string creation completed
9798     */
get_cbor_string(string_t & result)9799     bool get_cbor_string(string_t& result)
9800     {
9801         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
9802         {
9803             return false;
9804         }
9805 
9806         switch (current)
9807         {
9808             // UTF-8 string (0x00..0x17 bytes follow)
9809             case 0x60:
9810             case 0x61:
9811             case 0x62:
9812             case 0x63:
9813             case 0x64:
9814             case 0x65:
9815             case 0x66:
9816             case 0x67:
9817             case 0x68:
9818             case 0x69:
9819             case 0x6A:
9820             case 0x6B:
9821             case 0x6C:
9822             case 0x6D:
9823             case 0x6E:
9824             case 0x6F:
9825             case 0x70:
9826             case 0x71:
9827             case 0x72:
9828             case 0x73:
9829             case 0x74:
9830             case 0x75:
9831             case 0x76:
9832             case 0x77:
9833             {
9834                 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
9835             }
9836 
9837             case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9838             {
9839                 std::uint8_t len{};
9840                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9841             }
9842 
9843             case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9844             {
9845                 std::uint16_t len{};
9846                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9847             }
9848 
9849             case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9850             {
9851                 std::uint32_t len{};
9852                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9853             }
9854 
9855             case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9856             {
9857                 std::uint64_t len{};
9858                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9859             }
9860 
9861             case 0x7F: // UTF-8 string (indefinite length)
9862             {
9863                 while (get() != 0xFF)
9864                 {
9865                     string_t chunk;
9866                     if (!get_cbor_string(chunk))
9867                     {
9868                         return false;
9869                     }
9870                     result.append(chunk);
9871                 }
9872                 return true;
9873             }
9874 
9875             default:
9876             {
9877                 auto last_token = get_token_string();
9878                 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
9879                                         exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
9880             }
9881         }
9882     }
9883 
9884     /*!
9885     @brief reads a CBOR byte array
9886 
9887     This function first reads starting bytes to determine the expected
9888     byte array length and then copies this number of bytes into the byte array.
9889     Additionally, CBOR's byte arrays with indefinite lengths are supported.
9890 
9891     @param[out] result  created byte array
9892 
9893     @return whether byte array creation completed
9894     */
get_cbor_binary(binary_t & result)9895     bool get_cbor_binary(binary_t& result)
9896     {
9897         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
9898         {
9899             return false;
9900         }
9901 
9902         switch (current)
9903         {
9904             // Binary data (0x00..0x17 bytes follow)
9905             case 0x40:
9906             case 0x41:
9907             case 0x42:
9908             case 0x43:
9909             case 0x44:
9910             case 0x45:
9911             case 0x46:
9912             case 0x47:
9913             case 0x48:
9914             case 0x49:
9915             case 0x4A:
9916             case 0x4B:
9917             case 0x4C:
9918             case 0x4D:
9919             case 0x4E:
9920             case 0x4F:
9921             case 0x50:
9922             case 0x51:
9923             case 0x52:
9924             case 0x53:
9925             case 0x54:
9926             case 0x55:
9927             case 0x56:
9928             case 0x57:
9929             {
9930                 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
9931             }
9932 
9933             case 0x58: // Binary data (one-byte uint8_t for n follows)
9934             {
9935                 std::uint8_t len{};
9936                 return get_number(input_format_t::cbor, len) &&
9937                        get_binary(input_format_t::cbor, len, result);
9938             }
9939 
9940             case 0x59: // Binary data (two-byte uint16_t for n follow)
9941             {
9942                 std::uint16_t len{};
9943                 return get_number(input_format_t::cbor, len) &&
9944                        get_binary(input_format_t::cbor, len, result);
9945             }
9946 
9947             case 0x5A: // Binary data (four-byte uint32_t for n follow)
9948             {
9949                 std::uint32_t len{};
9950                 return get_number(input_format_t::cbor, len) &&
9951                        get_binary(input_format_t::cbor, len, result);
9952             }
9953 
9954             case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9955             {
9956                 std::uint64_t len{};
9957                 return get_number(input_format_t::cbor, len) &&
9958                        get_binary(input_format_t::cbor, len, result);
9959             }
9960 
9961             case 0x5F: // Binary data (indefinite length)
9962             {
9963                 while (get() != 0xFF)
9964                 {
9965                     binary_t chunk;
9966                     if (!get_cbor_binary(chunk))
9967                     {
9968                         return false;
9969                     }
9970                     result.insert(result.end(), chunk.begin(), chunk.end());
9971                 }
9972                 return true;
9973             }
9974 
9975             default:
9976             {
9977                 auto last_token = get_token_string();
9978                 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
9979                                         exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr));
9980             }
9981         }
9982     }
9983 
9984     /*!
9985     @param[in] len  the length of the array or static_cast<std::size_t>(-1) for an
9986                     array of indefinite size
9987     @param[in] tag_handler how CBOR tags should be treated
9988     @return whether array creation completed
9989     */
get_cbor_array(const std::size_t len,const cbor_tag_handler_t tag_handler)9990     bool get_cbor_array(const std::size_t len,
9991                         const cbor_tag_handler_t tag_handler)
9992     {
9993         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
9994         {
9995             return false;
9996         }
9997 
9998         if (len != static_cast<std::size_t>(-1))
9999         {
10000             for (std::size_t i = 0; i < len; ++i)
10001             {
10002                 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10003                 {
10004                     return false;
10005                 }
10006             }
10007         }
10008         else
10009         {
10010             while (get() != 0xFF)
10011             {
10012                 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10013                 {
10014                     return false;
10015                 }
10016             }
10017         }
10018 
10019         return sax->end_array();
10020     }
10021 
10022     /*!
10023     @param[in] len  the length of the object or static_cast<std::size_t>(-1) for an
10024                     object of indefinite size
10025     @param[in] tag_handler how CBOR tags should be treated
10026     @return whether object creation completed
10027     */
get_cbor_object(const std::size_t len,const cbor_tag_handler_t tag_handler)10028     bool get_cbor_object(const std::size_t len,
10029                          const cbor_tag_handler_t tag_handler)
10030     {
10031         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10032         {
10033             return false;
10034         }
10035 
10036         if (len != 0)
10037         {
10038             string_t key;
10039             if (len != static_cast<std::size_t>(-1))
10040             {
10041                 for (std::size_t i = 0; i < len; ++i)
10042                 {
10043                     get();
10044                     if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10045                     {
10046                         return false;
10047                     }
10048 
10049                     if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10050                     {
10051                         return false;
10052                     }
10053                     key.clear();
10054                 }
10055             }
10056             else
10057             {
10058                 while (get() != 0xFF)
10059                 {
10060                     if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10061                     {
10062                         return false;
10063                     }
10064 
10065                     if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10066                     {
10067                         return false;
10068                     }
10069                     key.clear();
10070                 }
10071             }
10072         }
10073 
10074         return sax->end_object();
10075     }
10076 
10077     /////////////
10078     // MsgPack //
10079     /////////////
10080 
10081     /*!
10082     @return whether a valid MessagePack value was passed to the SAX parser
10083     */
parse_msgpack_internal()10084     bool parse_msgpack_internal()
10085     {
10086         switch (get())
10087         {
10088             // EOF
10089             case std::char_traits<char_type>::eof():
10090                 return unexpect_eof(input_format_t::msgpack, "value");
10091 
10092             // positive fixint
10093             case 0x00:
10094             case 0x01:
10095             case 0x02:
10096             case 0x03:
10097             case 0x04:
10098             case 0x05:
10099             case 0x06:
10100             case 0x07:
10101             case 0x08:
10102             case 0x09:
10103             case 0x0A:
10104             case 0x0B:
10105             case 0x0C:
10106             case 0x0D:
10107             case 0x0E:
10108             case 0x0F:
10109             case 0x10:
10110             case 0x11:
10111             case 0x12:
10112             case 0x13:
10113             case 0x14:
10114             case 0x15:
10115             case 0x16:
10116             case 0x17:
10117             case 0x18:
10118             case 0x19:
10119             case 0x1A:
10120             case 0x1B:
10121             case 0x1C:
10122             case 0x1D:
10123             case 0x1E:
10124             case 0x1F:
10125             case 0x20:
10126             case 0x21:
10127             case 0x22:
10128             case 0x23:
10129             case 0x24:
10130             case 0x25:
10131             case 0x26:
10132             case 0x27:
10133             case 0x28:
10134             case 0x29:
10135             case 0x2A:
10136             case 0x2B:
10137             case 0x2C:
10138             case 0x2D:
10139             case 0x2E:
10140             case 0x2F:
10141             case 0x30:
10142             case 0x31:
10143             case 0x32:
10144             case 0x33:
10145             case 0x34:
10146             case 0x35:
10147             case 0x36:
10148             case 0x37:
10149             case 0x38:
10150             case 0x39:
10151             case 0x3A:
10152             case 0x3B:
10153             case 0x3C:
10154             case 0x3D:
10155             case 0x3E:
10156             case 0x3F:
10157             case 0x40:
10158             case 0x41:
10159             case 0x42:
10160             case 0x43:
10161             case 0x44:
10162             case 0x45:
10163             case 0x46:
10164             case 0x47:
10165             case 0x48:
10166             case 0x49:
10167             case 0x4A:
10168             case 0x4B:
10169             case 0x4C:
10170             case 0x4D:
10171             case 0x4E:
10172             case 0x4F:
10173             case 0x50:
10174             case 0x51:
10175             case 0x52:
10176             case 0x53:
10177             case 0x54:
10178             case 0x55:
10179             case 0x56:
10180             case 0x57:
10181             case 0x58:
10182             case 0x59:
10183             case 0x5A:
10184             case 0x5B:
10185             case 0x5C:
10186             case 0x5D:
10187             case 0x5E:
10188             case 0x5F:
10189             case 0x60:
10190             case 0x61:
10191             case 0x62:
10192             case 0x63:
10193             case 0x64:
10194             case 0x65:
10195             case 0x66:
10196             case 0x67:
10197             case 0x68:
10198             case 0x69:
10199             case 0x6A:
10200             case 0x6B:
10201             case 0x6C:
10202             case 0x6D:
10203             case 0x6E:
10204             case 0x6F:
10205             case 0x70:
10206             case 0x71:
10207             case 0x72:
10208             case 0x73:
10209             case 0x74:
10210             case 0x75:
10211             case 0x76:
10212             case 0x77:
10213             case 0x78:
10214             case 0x79:
10215             case 0x7A:
10216             case 0x7B:
10217             case 0x7C:
10218             case 0x7D:
10219             case 0x7E:
10220             case 0x7F:
10221                 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10222 
10223             // fixmap
10224             case 0x80:
10225             case 0x81:
10226             case 0x82:
10227             case 0x83:
10228             case 0x84:
10229             case 0x85:
10230             case 0x86:
10231             case 0x87:
10232             case 0x88:
10233             case 0x89:
10234             case 0x8A:
10235             case 0x8B:
10236             case 0x8C:
10237             case 0x8D:
10238             case 0x8E:
10239             case 0x8F:
10240                 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10241 
10242             // fixarray
10243             case 0x90:
10244             case 0x91:
10245             case 0x92:
10246             case 0x93:
10247             case 0x94:
10248             case 0x95:
10249             case 0x96:
10250             case 0x97:
10251             case 0x98:
10252             case 0x99:
10253             case 0x9A:
10254             case 0x9B:
10255             case 0x9C:
10256             case 0x9D:
10257             case 0x9E:
10258             case 0x9F:
10259                 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10260 
10261             // fixstr
10262             case 0xA0:
10263             case 0xA1:
10264             case 0xA2:
10265             case 0xA3:
10266             case 0xA4:
10267             case 0xA5:
10268             case 0xA6:
10269             case 0xA7:
10270             case 0xA8:
10271             case 0xA9:
10272             case 0xAA:
10273             case 0xAB:
10274             case 0xAC:
10275             case 0xAD:
10276             case 0xAE:
10277             case 0xAF:
10278             case 0xB0:
10279             case 0xB1:
10280             case 0xB2:
10281             case 0xB3:
10282             case 0xB4:
10283             case 0xB5:
10284             case 0xB6:
10285             case 0xB7:
10286             case 0xB8:
10287             case 0xB9:
10288             case 0xBA:
10289             case 0xBB:
10290             case 0xBC:
10291             case 0xBD:
10292             case 0xBE:
10293             case 0xBF:
10294             case 0xD9: // str 8
10295             case 0xDA: // str 16
10296             case 0xDB: // str 32
10297             {
10298                 string_t s;
10299                 return get_msgpack_string(s) && sax->string(s);
10300             }
10301 
10302             case 0xC0: // nil
10303                 return sax->null();
10304 
10305             case 0xC2: // false
10306                 return sax->boolean(false);
10307 
10308             case 0xC3: // true
10309                 return sax->boolean(true);
10310 
10311             case 0xC4: // bin 8
10312             case 0xC5: // bin 16
10313             case 0xC6: // bin 32
10314             case 0xC7: // ext 8
10315             case 0xC8: // ext 16
10316             case 0xC9: // ext 32
10317             case 0xD4: // fixext 1
10318             case 0xD5: // fixext 2
10319             case 0xD6: // fixext 4
10320             case 0xD7: // fixext 8
10321             case 0xD8: // fixext 16
10322             {
10323                 binary_t b;
10324                 return get_msgpack_binary(b) && sax->binary(b);
10325             }
10326 
10327             case 0xCA: // float 32
10328             {
10329                 float number{};
10330                 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10331             }
10332 
10333             case 0xCB: // float 64
10334             {
10335                 double number{};
10336                 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10337             }
10338 
10339             case 0xCC: // uint 8
10340             {
10341                 std::uint8_t number{};
10342                 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10343             }
10344 
10345             case 0xCD: // uint 16
10346             {
10347                 std::uint16_t number{};
10348                 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10349             }
10350 
10351             case 0xCE: // uint 32
10352             {
10353                 std::uint32_t number{};
10354                 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10355             }
10356 
10357             case 0xCF: // uint 64
10358             {
10359                 std::uint64_t number{};
10360                 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10361             }
10362 
10363             case 0xD0: // int 8
10364             {
10365                 std::int8_t number{};
10366                 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10367             }
10368 
10369             case 0xD1: // int 16
10370             {
10371                 std::int16_t number{};
10372                 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10373             }
10374 
10375             case 0xD2: // int 32
10376             {
10377                 std::int32_t number{};
10378                 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10379             }
10380 
10381             case 0xD3: // int 64
10382             {
10383                 std::int64_t number{};
10384                 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10385             }
10386 
10387             case 0xDC: // array 16
10388             {
10389                 std::uint16_t len{};
10390                 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
10391             }
10392 
10393             case 0xDD: // array 32
10394             {
10395                 std::uint32_t len{};
10396                 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
10397             }
10398 
10399             case 0xDE: // map 16
10400             {
10401                 std::uint16_t len{};
10402                 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
10403             }
10404 
10405             case 0xDF: // map 32
10406             {
10407                 std::uint32_t len{};
10408                 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
10409             }
10410 
10411             // negative fixint
10412             case 0xE0:
10413             case 0xE1:
10414             case 0xE2:
10415             case 0xE3:
10416             case 0xE4:
10417             case 0xE5:
10418             case 0xE6:
10419             case 0xE7:
10420             case 0xE8:
10421             case 0xE9:
10422             case 0xEA:
10423             case 0xEB:
10424             case 0xEC:
10425             case 0xED:
10426             case 0xEE:
10427             case 0xEF:
10428             case 0xF0:
10429             case 0xF1:
10430             case 0xF2:
10431             case 0xF3:
10432             case 0xF4:
10433             case 0xF5:
10434             case 0xF6:
10435             case 0xF7:
10436             case 0xF8:
10437             case 0xF9:
10438             case 0xFA:
10439             case 0xFB:
10440             case 0xFC:
10441             case 0xFD:
10442             case 0xFE:
10443             case 0xFF:
10444                 return sax->number_integer(static_cast<std::int8_t>(current));
10445 
10446             default: // anything else
10447             {
10448                 auto last_token = get_token_string();
10449                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10450                                         exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
10451             }
10452         }
10453     }
10454 
10455     /*!
10456     @brief reads a MessagePack string
10457 
10458     This function first reads starting bytes to determine the expected
10459     string length and then copies this number of bytes into a string.
10460 
10461     @param[out] result  created string
10462 
10463     @return whether string creation completed
10464     */
get_msgpack_string(string_t & result)10465     bool get_msgpack_string(string_t& result)
10466     {
10467         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
10468         {
10469             return false;
10470         }
10471 
10472         switch (current)
10473         {
10474             // fixstr
10475             case 0xA0:
10476             case 0xA1:
10477             case 0xA2:
10478             case 0xA3:
10479             case 0xA4:
10480             case 0xA5:
10481             case 0xA6:
10482             case 0xA7:
10483             case 0xA8:
10484             case 0xA9:
10485             case 0xAA:
10486             case 0xAB:
10487             case 0xAC:
10488             case 0xAD:
10489             case 0xAE:
10490             case 0xAF:
10491             case 0xB0:
10492             case 0xB1:
10493             case 0xB2:
10494             case 0xB3:
10495             case 0xB4:
10496             case 0xB5:
10497             case 0xB6:
10498             case 0xB7:
10499             case 0xB8:
10500             case 0xB9:
10501             case 0xBA:
10502             case 0xBB:
10503             case 0xBC:
10504             case 0xBD:
10505             case 0xBE:
10506             case 0xBF:
10507             {
10508                 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
10509             }
10510 
10511             case 0xD9: // str 8
10512             {
10513                 std::uint8_t len{};
10514                 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10515             }
10516 
10517             case 0xDA: // str 16
10518             {
10519                 std::uint16_t len{};
10520                 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10521             }
10522 
10523             case 0xDB: // str 32
10524             {
10525                 std::uint32_t len{};
10526                 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10527             }
10528 
10529             default:
10530             {
10531                 auto last_token = get_token_string();
10532                 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10533                                         exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
10534             }
10535         }
10536     }
10537 
10538     /*!
10539     @brief reads a MessagePack byte array
10540 
10541     This function first reads starting bytes to determine the expected
10542     byte array length and then copies this number of bytes into a byte array.
10543 
10544     @param[out] result  created byte array
10545 
10546     @return whether byte array creation completed
10547     */
get_msgpack_binary(binary_t & result)10548     bool get_msgpack_binary(binary_t& result)
10549     {
10550         // helper function to set the subtype
10551         auto assign_and_return_true = [&result](std::int8_t subtype)
10552         {
10553             result.set_subtype(static_cast<std::uint8_t>(subtype));
10554             return true;
10555         };
10556 
10557         switch (current)
10558         {
10559             case 0xC4: // bin 8
10560             {
10561                 std::uint8_t len{};
10562                 return get_number(input_format_t::msgpack, len) &&
10563                        get_binary(input_format_t::msgpack, len, result);
10564             }
10565 
10566             case 0xC5: // bin 16
10567             {
10568                 std::uint16_t len{};
10569                 return get_number(input_format_t::msgpack, len) &&
10570                        get_binary(input_format_t::msgpack, len, result);
10571             }
10572 
10573             case 0xC6: // bin 32
10574             {
10575                 std::uint32_t len{};
10576                 return get_number(input_format_t::msgpack, len) &&
10577                        get_binary(input_format_t::msgpack, len, result);
10578             }
10579 
10580             case 0xC7: // ext 8
10581             {
10582                 std::uint8_t len{};
10583                 std::int8_t subtype{};
10584                 return get_number(input_format_t::msgpack, len) &&
10585                        get_number(input_format_t::msgpack, subtype) &&
10586                        get_binary(input_format_t::msgpack, len, result) &&
10587                        assign_and_return_true(subtype);
10588             }
10589 
10590             case 0xC8: // ext 16
10591             {
10592                 std::uint16_t len{};
10593                 std::int8_t subtype{};
10594                 return get_number(input_format_t::msgpack, len) &&
10595                        get_number(input_format_t::msgpack, subtype) &&
10596                        get_binary(input_format_t::msgpack, len, result) &&
10597                        assign_and_return_true(subtype);
10598             }
10599 
10600             case 0xC9: // ext 32
10601             {
10602                 std::uint32_t len{};
10603                 std::int8_t subtype{};
10604                 return get_number(input_format_t::msgpack, len) &&
10605                        get_number(input_format_t::msgpack, subtype) &&
10606                        get_binary(input_format_t::msgpack, len, result) &&
10607                        assign_and_return_true(subtype);
10608             }
10609 
10610             case 0xD4: // fixext 1
10611             {
10612                 std::int8_t subtype{};
10613                 return get_number(input_format_t::msgpack, subtype) &&
10614                        get_binary(input_format_t::msgpack, 1, result) &&
10615                        assign_and_return_true(subtype);
10616             }
10617 
10618             case 0xD5: // fixext 2
10619             {
10620                 std::int8_t subtype{};
10621                 return get_number(input_format_t::msgpack, subtype) &&
10622                        get_binary(input_format_t::msgpack, 2, result) &&
10623                        assign_and_return_true(subtype);
10624             }
10625 
10626             case 0xD6: // fixext 4
10627             {
10628                 std::int8_t subtype{};
10629                 return get_number(input_format_t::msgpack, subtype) &&
10630                        get_binary(input_format_t::msgpack, 4, result) &&
10631                        assign_and_return_true(subtype);
10632             }
10633 
10634             case 0xD7: // fixext 8
10635             {
10636                 std::int8_t subtype{};
10637                 return get_number(input_format_t::msgpack, subtype) &&
10638                        get_binary(input_format_t::msgpack, 8, result) &&
10639                        assign_and_return_true(subtype);
10640             }
10641 
10642             case 0xD8: // fixext 16
10643             {
10644                 std::int8_t subtype{};
10645                 return get_number(input_format_t::msgpack, subtype) &&
10646                        get_binary(input_format_t::msgpack, 16, result) &&
10647                        assign_and_return_true(subtype);
10648             }
10649 
10650             default:           // LCOV_EXCL_LINE
10651                 return false;  // LCOV_EXCL_LINE
10652         }
10653     }
10654 
10655     /*!
10656     @param[in] len  the length of the array
10657     @return whether array creation completed
10658     */
get_msgpack_array(const std::size_t len)10659     bool get_msgpack_array(const std::size_t len)
10660     {
10661         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10662         {
10663             return false;
10664         }
10665 
10666         for (std::size_t i = 0; i < len; ++i)
10667         {
10668             if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10669             {
10670                 return false;
10671             }
10672         }
10673 
10674         return sax->end_array();
10675     }
10676 
10677     /*!
10678     @param[in] len  the length of the object
10679     @return whether object creation completed
10680     */
get_msgpack_object(const std::size_t len)10681     bool get_msgpack_object(const std::size_t len)
10682     {
10683         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10684         {
10685             return false;
10686         }
10687 
10688         string_t key;
10689         for (std::size_t i = 0; i < len; ++i)
10690         {
10691             get();
10692             if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
10693             {
10694                 return false;
10695             }
10696 
10697             if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10698             {
10699                 return false;
10700             }
10701             key.clear();
10702         }
10703 
10704         return sax->end_object();
10705     }
10706 
10707     ////////////
10708     // UBJSON //
10709     ////////////
10710 
10711     /*!
10712     @param[in] get_char  whether a new character should be retrieved from the
10713                          input (true, default) or whether the last read
10714                          character should be considered instead
10715 
10716     @return whether a valid UBJSON value was passed to the SAX parser
10717     */
parse_ubjson_internal(const bool get_char=true)10718     bool parse_ubjson_internal(const bool get_char = true)
10719     {
10720         return get_ubjson_value(get_char ? get_ignore_noop() : current);
10721     }
10722 
10723     /*!
10724     @brief reads a UBJSON string
10725 
10726     This function is either called after reading the 'S' byte explicitly
10727     indicating a string, or in case of an object key where the 'S' byte can be
10728     left out.
10729 
10730     @param[out] result   created string
10731     @param[in] get_char  whether a new character should be retrieved from the
10732                          input (true, default) or whether the last read
10733                          character should be considered instead
10734 
10735     @return whether string creation completed
10736     */
get_ubjson_string(string_t & result,const bool get_char=true)10737     bool get_ubjson_string(string_t& result, const bool get_char = true)
10738     {
10739         if (get_char)
10740         {
10741             get();  // TODO(niels): may we ignore N here?
10742         }
10743 
10744         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
10745         {
10746             return false;
10747         }
10748 
10749         switch (current)
10750         {
10751             case 'U':
10752             {
10753                 std::uint8_t len{};
10754                 return get_number(input_format, len) && get_string(input_format, len, result);
10755             }
10756 
10757             case 'i':
10758             {
10759                 std::int8_t len{};
10760                 return get_number(input_format, len) && get_string(input_format, len, result);
10761             }
10762 
10763             case 'I':
10764             {
10765                 std::int16_t len{};
10766                 return get_number(input_format, len) && get_string(input_format, len, result);
10767             }
10768 
10769             case 'l':
10770             {
10771                 std::int32_t len{};
10772                 return get_number(input_format, len) && get_string(input_format, len, result);
10773             }
10774 
10775             case 'L':
10776             {
10777                 std::int64_t len{};
10778                 return get_number(input_format, len) && get_string(input_format, len, result);
10779             }
10780 
10781             case 'u':
10782             {
10783                 if (input_format != input_format_t::bjdata)
10784                 {
10785                     break;
10786                 }
10787                 std::uint16_t len{};
10788                 return get_number(input_format, len) && get_string(input_format, len, result);
10789             }
10790 
10791             case 'm':
10792             {
10793                 if (input_format != input_format_t::bjdata)
10794                 {
10795                     break;
10796                 }
10797                 std::uint32_t len{};
10798                 return get_number(input_format, len) && get_string(input_format, len, result);
10799             }
10800 
10801             case 'M':
10802             {
10803                 if (input_format != input_format_t::bjdata)
10804                 {
10805                     break;
10806                 }
10807                 std::uint64_t len{};
10808                 return get_number(input_format, len) && get_string(input_format, len, result);
10809             }
10810 
10811             default:
10812                 break;
10813         }
10814         auto last_token = get_token_string();
10815         std::string message;
10816 
10817         if (input_format != input_format_t::bjdata)
10818         {
10819             message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
10820         }
10821         else
10822         {
10823             message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
10824         }
10825         return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
10826     }
10827 
10828     /*!
10829     @param[out] dim  an integer vector storing the ND array dimensions
10830     @return whether reading ND array size vector is successful
10831     */
get_ubjson_ndarray_size(std::vector<size_t> & dim)10832     bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
10833     {
10834         std::pair<std::size_t, char_int_type> size_and_type;
10835         size_t dimlen = 0;
10836         bool no_ndarray = true;
10837 
10838         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
10839         {
10840             return false;
10841         }
10842 
10843         if (size_and_type.first != string_t::npos)
10844         {
10845             if (size_and_type.second != 0)
10846             {
10847                 if (size_and_type.second != 'N')
10848                 {
10849                     for (std::size_t i = 0; i < size_and_type.first; ++i)
10850                     {
10851                         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
10852                         {
10853                             return false;
10854                         }
10855                         dim.push_back(dimlen);
10856                     }
10857                 }
10858             }
10859             else
10860             {
10861                 for (std::size_t i = 0; i < size_and_type.first; ++i)
10862                 {
10863                     if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
10864                     {
10865                         return false;
10866                     }
10867                     dim.push_back(dimlen);
10868                 }
10869             }
10870         }
10871         else
10872         {
10873             while (current != ']')
10874             {
10875                 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
10876                 {
10877                     return false;
10878                 }
10879                 dim.push_back(dimlen);
10880                 get_ignore_noop();
10881             }
10882         }
10883         return true;
10884     }
10885 
10886     /*!
10887     @param[out] result  determined size
10888     @param[in,out] is_ndarray  for input, `true` means already inside an ndarray vector
10889                                or ndarray dimension is not allowed; `false` means ndarray
10890                                is allowed; for output, `true` means an ndarray is found;
10891                                is_ndarray can only return `true` when its initial value
10892                                is `false`
10893     @param[in] prefix  type marker if already read, otherwise set to 0
10894 
10895     @return whether size determination completed
10896     */
get_ubjson_size_value(std::size_t & result,bool & is_ndarray,char_int_type prefix=0)10897     bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
10898     {
10899         if (prefix == 0)
10900         {
10901             prefix = get_ignore_noop();
10902         }
10903 
10904         switch (prefix)
10905         {
10906             case 'U':
10907             {
10908                 std::uint8_t number{};
10909                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
10910                 {
10911                     return false;
10912                 }
10913                 result = static_cast<std::size_t>(number);
10914                 return true;
10915             }
10916 
10917             case 'i':
10918             {
10919                 std::int8_t number{};
10920                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
10921                 {
10922                     return false;
10923                 }
10924                 if (number < 0)
10925                 {
10926                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
10927                                             exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
10928                 }
10929                 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
10930                 return true;
10931             }
10932 
10933             case 'I':
10934             {
10935                 std::int16_t number{};
10936                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
10937                 {
10938                     return false;
10939                 }
10940                 if (number < 0)
10941                 {
10942                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
10943                                             exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
10944                 }
10945                 result = static_cast<std::size_t>(number);
10946                 return true;
10947             }
10948 
10949             case 'l':
10950             {
10951                 std::int32_t number{};
10952                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
10953                 {
10954                     return false;
10955                 }
10956                 if (number < 0)
10957                 {
10958                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
10959                                             exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
10960                 }
10961                 result = static_cast<std::size_t>(number);
10962                 return true;
10963             }
10964 
10965             case 'L':
10966             {
10967                 std::int64_t number{};
10968                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
10969                 {
10970                     return false;
10971                 }
10972                 if (number < 0)
10973                 {
10974                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
10975                                             exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
10976                 }
10977                 if (!value_in_range_of<std::size_t>(number))
10978                 {
10979                     return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
10980                                             exception_message(input_format, "integer value overflow", "size"), nullptr));
10981                 }
10982                 result = static_cast<std::size_t>(number);
10983                 return true;
10984             }
10985 
10986             case 'u':
10987             {
10988                 if (input_format != input_format_t::bjdata)
10989                 {
10990                     break;
10991                 }
10992                 std::uint16_t number{};
10993                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
10994                 {
10995                     return false;
10996                 }
10997                 result = static_cast<std::size_t>(number);
10998                 return true;
10999             }
11000 
11001             case 'm':
11002             {
11003                 if (input_format != input_format_t::bjdata)
11004                 {
11005                     break;
11006                 }
11007                 std::uint32_t number{};
11008                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11009                 {
11010                     return false;
11011                 }
11012                 result = conditional_static_cast<std::size_t>(number);
11013                 return true;
11014             }
11015 
11016             case 'M':
11017             {
11018                 if (input_format != input_format_t::bjdata)
11019                 {
11020                     break;
11021                 }
11022                 std::uint64_t number{};
11023                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11024                 {
11025                     return false;
11026                 }
11027                 if (!value_in_range_of<std::size_t>(number))
11028                 {
11029                     return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11030                                             exception_message(input_format, "integer value overflow", "size"), nullptr));
11031                 }
11032                 result = detail::conditional_static_cast<std::size_t>(number);
11033                 return true;
11034             }
11035 
11036             case '[':
11037             {
11038                 if (input_format != input_format_t::bjdata)
11039                 {
11040                     break;
11041                 }
11042                 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
11043                 {
11044                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimentional vector is not allowed", "size"), nullptr));
11045                 }
11046                 std::vector<size_t> dim;
11047                 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11048                 {
11049                     return false;
11050                 }
11051                 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11052                 {
11053                     result = dim.at(dim.size() - 1);
11054                     return true;
11055                 }
11056                 if (!dim.empty())  // if ndarray, convert to an object in JData annotated array format
11057                 {
11058                     for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11059                     {
11060                         if ( i == 0 )
11061                         {
11062                             result = 0;
11063                             return true;
11064                         }
11065                     }
11066 
11067                     string_t key = "_ArraySize_";
11068                     if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
11069                     {
11070                         return false;
11071                     }
11072                     result = 1;
11073                     for (auto i : dim)
11074                     {
11075                         result *= i;
11076                         if (result == 0 || result == string_t::npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be string_t::npos as it is used to initialize size in get_ubjson_size_type()
11077                         {
11078                             return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr));
11079                         }
11080                         if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
11081                         {
11082                             return false;
11083                         }
11084                     }
11085                     is_ndarray = true;
11086                     return sax->end_array();
11087                 }
11088                 result = 0;
11089                 return true;
11090             }
11091 
11092             default:
11093                 break;
11094         }
11095         auto last_token = get_token_string();
11096         std::string message;
11097 
11098         if (input_format != input_format_t::bjdata)
11099         {
11100             message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11101         }
11102         else
11103         {
11104             message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
11105         }
11106         return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
11107     }
11108 
11109     /*!
11110     @brief determine the type and size for a container
11111 
11112     In the optimized UBJSON format, a type and a size can be provided to allow
11113     for a more compact representation.
11114 
11115     @param[out] result  pair of the size and the type
11116     @param[in] inside_ndarray  whether the parser is parsing an ND array dimensional vector
11117 
11118     @return whether pair creation completed
11119     */
get_ubjson_size_type(std::pair<std::size_t,char_int_type> & result,bool inside_ndarray=false)11120     bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
11121     {
11122         result.first = string_t::npos; // size
11123         result.second = 0; // type
11124         bool is_ndarray = false;
11125 
11126         get_ignore_noop();
11127 
11128         if (current == '$')
11129         {
11130             std::vector<char_int_type> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
11131 
11132             result.second = get();  // must not ignore 'N', because 'N' maybe the type
11133             if (JSON_HEDLEY_UNLIKELY( input_format == input_format_t::bjdata && std::find(bjdx.begin(), bjdx.end(), result.second) != bjdx.end() ))
11134             {
11135                 auto last_token = get_token_string();
11136                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11137                                         exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
11138             }
11139 
11140             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
11141             {
11142                 return false;
11143             }
11144 
11145             get_ignore_noop();
11146             if (JSON_HEDLEY_UNLIKELY(current != '#'))
11147             {
11148                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11149                 {
11150                     return false;
11151                 }
11152                 auto last_token = get_token_string();
11153                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11154                                         exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
11155             }
11156 
11157             bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11158             if (input_format == input_format_t::bjdata && is_ndarray)
11159             {
11160                 if (inside_ndarray)
11161                 {
11162                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11163                                             exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
11164                 }
11165                 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
11166             }
11167             return is_error;
11168         }
11169 
11170         if (current == '#')
11171         {
11172             bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11173             if (input_format == input_format_t::bjdata && is_ndarray)
11174             {
11175                 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11176                                         exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
11177             }
11178             return is_error;
11179         }
11180 
11181         return true;
11182     }
11183 
11184     /*!
11185     @param prefix  the previously read or set type prefix
11186     @return whether value creation completed
11187     */
get_ubjson_value(const char_int_type prefix)11188     bool get_ubjson_value(const char_int_type prefix)
11189     {
11190         switch (prefix)
11191         {
11192             case std::char_traits<char_type>::eof():  // EOF
11193                 return unexpect_eof(input_format, "value");
11194 
11195             case 'T':  // true
11196                 return sax->boolean(true);
11197             case 'F':  // false
11198                 return sax->boolean(false);
11199 
11200             case 'Z':  // null
11201                 return sax->null();
11202 
11203             case 'U':
11204             {
11205                 std::uint8_t number{};
11206                 return get_number(input_format, number) && sax->number_unsigned(number);
11207             }
11208 
11209             case 'i':
11210             {
11211                 std::int8_t number{};
11212                 return get_number(input_format, number) && sax->number_integer(number);
11213             }
11214 
11215             case 'I':
11216             {
11217                 std::int16_t number{};
11218                 return get_number(input_format, number) && sax->number_integer(number);
11219             }
11220 
11221             case 'l':
11222             {
11223                 std::int32_t number{};
11224                 return get_number(input_format, number) && sax->number_integer(number);
11225             }
11226 
11227             case 'L':
11228             {
11229                 std::int64_t number{};
11230                 return get_number(input_format, number) && sax->number_integer(number);
11231             }
11232 
11233             case 'u':
11234             {
11235                 if (input_format != input_format_t::bjdata)
11236                 {
11237                     break;
11238                 }
11239                 std::uint16_t number{};
11240                 return get_number(input_format, number) && sax->number_unsigned(number);
11241             }
11242 
11243             case 'm':
11244             {
11245                 if (input_format != input_format_t::bjdata)
11246                 {
11247                     break;
11248                 }
11249                 std::uint32_t number{};
11250                 return get_number(input_format, number) && sax->number_unsigned(number);
11251             }
11252 
11253             case 'M':
11254             {
11255                 if (input_format != input_format_t::bjdata)
11256                 {
11257                     break;
11258                 }
11259                 std::uint64_t number{};
11260                 return get_number(input_format, number) && sax->number_unsigned(number);
11261             }
11262 
11263             case 'h':
11264             {
11265                 if (input_format != input_format_t::bjdata)
11266                 {
11267                     break;
11268                 }
11269                 const auto byte1_raw = get();
11270                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11271                 {
11272                     return false;
11273                 }
11274                 const auto byte2_raw = get();
11275                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11276                 {
11277                     return false;
11278                 }
11279 
11280                 const auto byte1 = static_cast<unsigned char>(byte1_raw);
11281                 const auto byte2 = static_cast<unsigned char>(byte2_raw);
11282 
11283                 // code from RFC 7049, Appendix D, Figure 3:
11284                 // As half-precision floating-point numbers were only added
11285                 // to IEEE 754 in 2008, today's programming platforms often
11286                 // still only have limited support for them. It is very
11287                 // easy to include at least decoding support for them even
11288                 // without such support. An example of a small decoder for
11289                 // half-precision floating-point numbers in the C language
11290                 // is shown in Fig. 3.
11291                 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
11292                 const double val = [&half]
11293                 {
11294                     const int exp = (half >> 10u) & 0x1Fu;
11295                     const unsigned int mant = half & 0x3FFu;
11296                     JSON_ASSERT(0 <= exp&& exp <= 32);
11297                     JSON_ASSERT(mant <= 1024);
11298                     switch (exp)
11299                     {
11300                         case 0:
11301                             return std::ldexp(mant, -24);
11302                         case 31:
11303                             return (mant == 0)
11304                             ? std::numeric_limits<double>::infinity()
11305                             : std::numeric_limits<double>::quiet_NaN();
11306                         default:
11307                             return std::ldexp(mant + 1024, exp - 25);
11308                     }
11309                 }();
11310                 return sax->number_float((half & 0x8000u) != 0
11311                                          ? static_cast<number_float_t>(-val)
11312                                          : static_cast<number_float_t>(val), "");
11313             }
11314 
11315             case 'd':
11316             {
11317                 float number{};
11318                 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11319             }
11320 
11321             case 'D':
11322             {
11323                 double number{};
11324                 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11325             }
11326 
11327             case 'H':
11328             {
11329                 return get_ubjson_high_precision_number();
11330             }
11331 
11332             case 'C':  // char
11333             {
11334                 get();
11335                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
11336                 {
11337                     return false;
11338                 }
11339                 if (JSON_HEDLEY_UNLIKELY(current > 127))
11340                 {
11341                     auto last_token = get_token_string();
11342                     return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11343                                             exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
11344                 }
11345                 string_t s(1, static_cast<typename string_t::value_type>(current));
11346                 return sax->string(s);
11347             }
11348 
11349             case 'S':  // string
11350             {
11351                 string_t s;
11352                 return get_ubjson_string(s) && sax->string(s);
11353             }
11354 
11355             case '[':  // array
11356                 return get_ubjson_array();
11357 
11358             case '{':  // object
11359                 return get_ubjson_object();
11360 
11361             default: // anything else
11362                 break;
11363         }
11364         auto last_token = get_token_string();
11365         return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr));
11366     }
11367 
11368     /*!
11369     @return whether array creation completed
11370     */
get_ubjson_array()11371     bool get_ubjson_array()
11372     {
11373         std::pair<std::size_t, char_int_type> size_and_type;
11374         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11375         {
11376             return false;
11377         }
11378 
11379         // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata):
11380         // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
11381 
11382         if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && (size_and_type.second & (1 << 8)) != 0)
11383         {
11384             std::map<char_int_type, string_t> bjdtype = {{'U', "uint8"},  {'i', "int8"},  {'u', "uint16"}, {'I', "int16"},
11385                 {'m', "uint32"}, {'l', "int32"}, {'M', "uint64"}, {'L', "int64"}, {'d', "single"}, {'D', "double"}, {'C', "char"}
11386             };
11387 
11388             size_and_type.second &= ~(static_cast<char_int_type>(1) << 8);  // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker
11389 
11390             string_t key = "_ArrayType_";
11391             if (JSON_HEDLEY_UNLIKELY(bjdtype.count(size_and_type.second) == 0))
11392             {
11393                 auto last_token = get_token_string();
11394                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11395                                         exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
11396             }
11397 
11398             if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(bjdtype[size_and_type.second]) ))
11399             {
11400                 return false;
11401             }
11402 
11403             if (size_and_type.second == 'C')
11404             {
11405                 size_and_type.second = 'U';
11406             }
11407 
11408             key = "_ArrayData_";
11409             if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
11410             {
11411                 return false;
11412             }
11413 
11414             for (std::size_t i = 0; i < size_and_type.first; ++i)
11415             {
11416                 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11417                 {
11418                     return false;
11419                 }
11420             }
11421 
11422             return (sax->end_array() && sax->end_object());
11423         }
11424 
11425         if (size_and_type.first != string_t::npos)
11426         {
11427             if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
11428             {
11429                 return false;
11430             }
11431 
11432             if (size_and_type.second != 0)
11433             {
11434                 if (size_and_type.second != 'N')
11435                 {
11436                     for (std::size_t i = 0; i < size_and_type.first; ++i)
11437                     {
11438                         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11439                         {
11440                             return false;
11441                         }
11442                     }
11443                 }
11444             }
11445             else
11446             {
11447                 for (std::size_t i = 0; i < size_and_type.first; ++i)
11448                 {
11449                     if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11450                     {
11451                         return false;
11452                     }
11453                 }
11454             }
11455         }
11456         else
11457         {
11458             if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
11459             {
11460                 return false;
11461             }
11462 
11463             while (current != ']')
11464             {
11465                 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
11466                 {
11467                     return false;
11468                 }
11469                 get_ignore_noop();
11470             }
11471         }
11472 
11473         return sax->end_array();
11474     }
11475 
11476     /*!
11477     @return whether object creation completed
11478     */
get_ubjson_object()11479     bool get_ubjson_object()
11480     {
11481         std::pair<std::size_t, char_int_type> size_and_type;
11482         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11483         {
11484             return false;
11485         }
11486 
11487         // do not accept ND-array size in objects in BJData
11488         if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && (size_and_type.second & (1 << 8)) != 0)
11489         {
11490             auto last_token = get_token_string();
11491             return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11492                                     exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
11493         }
11494 
11495         string_t key;
11496         if (size_and_type.first != string_t::npos)
11497         {
11498             if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
11499             {
11500                 return false;
11501             }
11502 
11503             if (size_and_type.second != 0)
11504             {
11505                 for (std::size_t i = 0; i < size_and_type.first; ++i)
11506                 {
11507                     if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11508                     {
11509                         return false;
11510                     }
11511                     if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11512                     {
11513                         return false;
11514                     }
11515                     key.clear();
11516                 }
11517             }
11518             else
11519             {
11520                 for (std::size_t i = 0; i < size_and_type.first; ++i)
11521                 {
11522                     if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11523                     {
11524                         return false;
11525                     }
11526                     if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11527                     {
11528                         return false;
11529                     }
11530                     key.clear();
11531                 }
11532             }
11533         }
11534         else
11535         {
11536             if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
11537             {
11538                 return false;
11539             }
11540 
11541             while (current != '}')
11542             {
11543                 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
11544                 {
11545                     return false;
11546                 }
11547                 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11548                 {
11549                     return false;
11550                 }
11551                 get_ignore_noop();
11552                 key.clear();
11553             }
11554         }
11555 
11556         return sax->end_object();
11557     }
11558 
11559     // Note, no reader for UBJSON binary types is implemented because they do
11560     // not exist
11561 
get_ubjson_high_precision_number()11562     bool get_ubjson_high_precision_number()
11563     {
11564         // get size of following number string
11565         std::size_t size{};
11566         bool no_ndarray = true;
11567         auto res = get_ubjson_size_value(size, no_ndarray);
11568         if (JSON_HEDLEY_UNLIKELY(!res))
11569         {
11570             return res;
11571         }
11572 
11573         // get number string
11574         std::vector<char> number_vector;
11575         for (std::size_t i = 0; i < size; ++i)
11576         {
11577             get();
11578             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11579             {
11580                 return false;
11581             }
11582             number_vector.push_back(static_cast<char>(current));
11583         }
11584 
11585         // parse number string
11586         using ia_type = decltype(detail::input_adapter(number_vector));
11587         auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
11588         const auto result_number = number_lexer.scan();
11589         const auto number_string = number_lexer.get_token_string();
11590         const auto result_remainder = number_lexer.scan();
11591 
11592         using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
11593 
11594         if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
11595         {
11596             return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11597                                     exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11598         }
11599 
11600         switch (result_number)
11601         {
11602             case token_type::value_integer:
11603                 return sax->number_integer(number_lexer.get_number_integer());
11604             case token_type::value_unsigned:
11605                 return sax->number_unsigned(number_lexer.get_number_unsigned());
11606             case token_type::value_float:
11607                 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
11608             case token_type::uninitialized:
11609             case token_type::literal_true:
11610             case token_type::literal_false:
11611             case token_type::literal_null:
11612             case token_type::value_string:
11613             case token_type::begin_array:
11614             case token_type::begin_object:
11615             case token_type::end_array:
11616             case token_type::end_object:
11617             case token_type::name_separator:
11618             case token_type::value_separator:
11619             case token_type::parse_error:
11620             case token_type::end_of_input:
11621             case token_type::literal_or_value:
11622             default:
11623                 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11624                                         exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11625         }
11626     }
11627 
11628     ///////////////////////
11629     // Utility functions //
11630     ///////////////////////
11631 
11632     /*!
11633     @brief get next character from the input
11634 
11635     This function provides the interface to the used input adapter. It does
11636     not throw in case the input reached EOF, but returns a -'ve valued
11637     `std::char_traits<char_type>::eof()` in that case.
11638 
11639     @return character read from the input
11640     */
get()11641     char_int_type get()
11642     {
11643         ++chars_read;
11644         return current = ia.get_character();
11645     }
11646 
11647     /*!
11648     @return character read from the input after ignoring all 'N' entries
11649     */
get_ignore_noop()11650     char_int_type get_ignore_noop()
11651     {
11652         do
11653         {
11654             get();
11655         }
11656         while (current == 'N');
11657 
11658         return current;
11659     }
11660 
11661     /*
11662     @brief read a number from the input
11663 
11664     @tparam NumberType the type of the number
11665     @param[in] format   the current format (for diagnostics)
11666     @param[out] result  number of type @a NumberType
11667 
11668     @return whether conversion completed
11669 
11670     @note This function needs to respect the system's endianness, because
11671           bytes in CBOR, MessagePack, and UBJSON are stored in network order
11672           (big endian) and therefore need reordering on little endian systems.
11673           On the other hand, BSON and BJData use little endian and should reorder
11674           on big endian systems.
11675     */
11676     template<typename NumberType, bool InputIsLittleEndian = false>
get_number(const input_format_t format,NumberType & result)11677     bool get_number(const input_format_t format, NumberType& result)
11678     {
11679         // step 1: read input into array with system's byte order
11680         std::array<std::uint8_t, sizeof(NumberType)> vec{};
11681         for (std::size_t i = 0; i < sizeof(NumberType); ++i)
11682         {
11683             get();
11684             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
11685             {
11686                 return false;
11687             }
11688 
11689             // reverse byte order prior to conversion if necessary
11690             if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
11691             {
11692                 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
11693             }
11694             else
11695             {
11696                 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
11697             }
11698         }
11699 
11700         // step 2: convert array into number of type T and return
11701         std::memcpy(&result, vec.data(), sizeof(NumberType));
11702         return true;
11703     }
11704 
11705     /*!
11706     @brief create a string by reading characters from the input
11707 
11708     @tparam NumberType the type of the number
11709     @param[in] format the current format (for diagnostics)
11710     @param[in] len number of characters to read
11711     @param[out] result string created by reading @a len bytes
11712 
11713     @return whether string creation completed
11714 
11715     @note We can not reserve @a len bytes for the result, because @a len
11716           may be too large. Usually, @ref unexpect_eof() detects the end of
11717           the input before we run out of string memory.
11718     */
11719     template<typename NumberType>
get_string(const input_format_t format,const NumberType len,string_t & result)11720     bool get_string(const input_format_t format,
11721                     const NumberType len,
11722                     string_t& result)
11723     {
11724         bool success = true;
11725         for (NumberType i = 0; i < len; i++)
11726         {
11727             get();
11728             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
11729             {
11730                 success = false;
11731                 break;
11732             }
11733             result.push_back(static_cast<typename string_t::value_type>(current));
11734         }
11735         return success;
11736     }
11737 
11738     /*!
11739     @brief create a byte array by reading bytes from the input
11740 
11741     @tparam NumberType the type of the number
11742     @param[in] format the current format (for diagnostics)
11743     @param[in] len number of bytes to read
11744     @param[out] result byte array created by reading @a len bytes
11745 
11746     @return whether byte array creation completed
11747 
11748     @note We can not reserve @a len bytes for the result, because @a len
11749           may be too large. Usually, @ref unexpect_eof() detects the end of
11750           the input before we run out of memory.
11751     */
11752     template<typename NumberType>
get_binary(const input_format_t format,const NumberType len,binary_t & result)11753     bool get_binary(const input_format_t format,
11754                     const NumberType len,
11755                     binary_t& result)
11756     {
11757         bool success = true;
11758         for (NumberType i = 0; i < len; i++)
11759         {
11760             get();
11761             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
11762             {
11763                 success = false;
11764                 break;
11765             }
11766             result.push_back(static_cast<std::uint8_t>(current));
11767         }
11768         return success;
11769     }
11770 
11771     /*!
11772     @param[in] format   the current format (for diagnostics)
11773     @param[in] context  further context information (for diagnostics)
11774     @return whether the last read character is not EOF
11775     */
11776     JSON_HEDLEY_NON_NULL(3)
unexpect_eof(const input_format_t format,const char * context) const11777     bool unexpect_eof(const input_format_t format, const char* context) const
11778     {
11779         if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
11780         {
11781             return sax->parse_error(chars_read, "<end of file>",
11782                                     parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
11783         }
11784         return true;
11785     }
11786 
11787     /*!
11788     @return a string representation of the last read byte
11789     */
get_token_string() const11790     std::string get_token_string() const
11791     {
11792         std::array<char, 3> cr{{}};
11793         static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
11794         return std::string{cr.data()};
11795     }
11796 
11797     /*!
11798     @param[in] format   the current format
11799     @param[in] detail   a detailed error message
11800     @param[in] context  further context information
11801     @return a message string to use in the parse_error exceptions
11802     */
exception_message(const input_format_t format,const std::string & detail,const std::string & context) const11803     std::string exception_message(const input_format_t format,
11804                                   const std::string& detail,
11805                                   const std::string& context) const
11806     {
11807         std::string error_msg = "syntax error while parsing ";
11808 
11809         switch (format)
11810         {
11811             case input_format_t::cbor:
11812                 error_msg += "CBOR";
11813                 break;
11814 
11815             case input_format_t::msgpack:
11816                 error_msg += "MessagePack";
11817                 break;
11818 
11819             case input_format_t::ubjson:
11820                 error_msg += "UBJSON";
11821                 break;
11822 
11823             case input_format_t::bson:
11824                 error_msg += "BSON";
11825                 break;
11826 
11827             case input_format_t::bjdata:
11828                 error_msg += "BJData";
11829                 break;
11830 
11831             case input_format_t::json: // LCOV_EXCL_LINE
11832             default:            // LCOV_EXCL_LINE
11833                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
11834         }
11835 
11836         return concat(error_msg, ' ', context, ": ", detail);
11837     }
11838 
11839   private:
11840     /// input adapter
11841     InputAdapterType ia;
11842 
11843     /// the current character
11844     char_int_type current = std::char_traits<char_type>::eof();
11845 
11846     /// the number of characters read
11847     std::size_t chars_read = 0;
11848 
11849     /// whether we can assume little endianness
11850     const bool is_little_endian = little_endianness();
11851 
11852     /// input format
11853     const input_format_t input_format = input_format_t::json;
11854 
11855     /// the SAX parser
11856     json_sax_t* sax = nullptr;
11857 };
11858 }  // namespace detail
11859 }  // namespace nlohmann
11860 
11861 // #include <nlohmann/detail/input/input_adapters.hpp>
11862 
11863 // #include <nlohmann/detail/input/lexer.hpp>
11864 
11865 // #include <nlohmann/detail/input/parser.hpp>
11866 //     __ _____ _____ _____
11867 //  __|  |   __|     |   | |  JSON for Modern C++
11868 // |  |  |__   |  |  | | | |  version 3.10.5
11869 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
11870 //
11871 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
11872 // SPDX-License-Identifier: MIT
11873 
11874 
11875 
11876 #include <cmath> // isfinite
11877 #include <cstdint> // uint8_t
11878 #include <functional> // function
11879 #include <string> // string
11880 #include <utility> // move
11881 #include <vector> // vector
11882 
11883 // #include <nlohmann/detail/exceptions.hpp>
11884 
11885 // #include <nlohmann/detail/input/input_adapters.hpp>
11886 
11887 // #include <nlohmann/detail/input/json_sax.hpp>
11888 
11889 // #include <nlohmann/detail/input/lexer.hpp>
11890 
11891 // #include <nlohmann/detail/macro_scope.hpp>
11892 
11893 // #include <nlohmann/detail/meta/is_sax.hpp>
11894 
11895 // #include <nlohmann/detail/string_concat.hpp>
11896 
11897 // #include <nlohmann/detail/value_t.hpp>
11898 
11899 
11900 namespace nlohmann
11901 {
11902 namespace detail
11903 {
11904 ////////////
11905 // parser //
11906 ////////////
11907 
11908 enum class parse_event_t : std::uint8_t
11909 {
11910     /// the parser read `{` and started to process a JSON object
11911     object_start,
11912     /// the parser read `}` and finished processing a JSON object
11913     object_end,
11914     /// the parser read `[` and started to process a JSON array
11915     array_start,
11916     /// the parser read `]` and finished processing a JSON array
11917     array_end,
11918     /// the parser read a key of a value in an object
11919     key,
11920     /// the parser finished reading a JSON value
11921     value
11922 };
11923 
11924 template<typename BasicJsonType>
11925 using parser_callback_t =
11926     std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
11927 
11928 /*!
11929 @brief syntax analysis
11930 
11931 This class implements a recursive descent parser.
11932 */
11933 template<typename BasicJsonType, typename InputAdapterType>
11934 class parser
11935 {
11936     using number_integer_t = typename BasicJsonType::number_integer_t;
11937     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
11938     using number_float_t = typename BasicJsonType::number_float_t;
11939     using string_t = typename BasicJsonType::string_t;
11940     using lexer_t = lexer<BasicJsonType, InputAdapterType>;
11941     using token_type = typename lexer_t::token_type;
11942 
11943   public:
11944     /// a parser reading from an input adapter
parser(InputAdapterType && adapter,const parser_callback_t<BasicJsonType> cb=nullptr,const bool allow_exceptions_=true,const bool skip_comments=false)11945     explicit parser(InputAdapterType&& adapter,
11946                     const parser_callback_t<BasicJsonType> cb = nullptr,
11947                     const bool allow_exceptions_ = true,
11948                     const bool skip_comments = false)
11949         : callback(cb)
11950         , m_lexer(std::move(adapter), skip_comments)
11951         , allow_exceptions(allow_exceptions_)
11952     {
11953         // read first token
11954         get_token();
11955     }
11956 
11957     /*!
11958     @brief public parser interface
11959 
11960     @param[in] strict      whether to expect the last token to be EOF
11961     @param[in,out] result  parsed JSON value
11962 
11963     @throw parse_error.101 in case of an unexpected token
11964     @throw parse_error.102 if to_unicode fails or surrogate error
11965     @throw parse_error.103 if to_unicode fails
11966     */
parse(const bool strict,BasicJsonType & result)11967     void parse(const bool strict, BasicJsonType& result)
11968     {
11969         if (callback)
11970         {
11971             json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
11972             sax_parse_internal(&sdp);
11973 
11974             // in strict mode, input must be completely read
11975             if (strict && (get_token() != token_type::end_of_input))
11976             {
11977                 sdp.parse_error(m_lexer.get_position(),
11978                                 m_lexer.get_token_string(),
11979                                 parse_error::create(101, m_lexer.get_position(),
11980                                                     exception_message(token_type::end_of_input, "value"), nullptr));
11981             }
11982 
11983             // in case of an error, return discarded value
11984             if (sdp.is_errored())
11985             {
11986                 result = value_t::discarded;
11987                 return;
11988             }
11989 
11990             // set top-level value to null if it was discarded by the callback
11991             // function
11992             if (result.is_discarded())
11993             {
11994                 result = nullptr;
11995             }
11996         }
11997         else
11998         {
11999             json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
12000             sax_parse_internal(&sdp);
12001 
12002             // in strict mode, input must be completely read
12003             if (strict && (get_token() != token_type::end_of_input))
12004             {
12005                 sdp.parse_error(m_lexer.get_position(),
12006                                 m_lexer.get_token_string(),
12007                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12008             }
12009 
12010             // in case of an error, return discarded value
12011             if (sdp.is_errored())
12012             {
12013                 result = value_t::discarded;
12014                 return;
12015             }
12016         }
12017 
12018         result.assert_invariant();
12019     }
12020 
12021     /*!
12022     @brief public accept interface
12023 
12024     @param[in] strict  whether to expect the last token to be EOF
12025     @return whether the input is a proper JSON text
12026     */
accept(const bool strict=true)12027     bool accept(const bool strict = true)
12028     {
12029         json_sax_acceptor<BasicJsonType> sax_acceptor;
12030         return sax_parse(&sax_acceptor, strict);
12031     }
12032 
12033     template<typename SAX>
12034     JSON_HEDLEY_NON_NULL(2)
sax_parse(SAX * sax,const bool strict=true)12035     bool sax_parse(SAX* sax, const bool strict = true)
12036     {
12037         (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
12038         const bool result = sax_parse_internal(sax);
12039 
12040         // strict mode: next byte must be EOF
12041         if (result && strict && (get_token() != token_type::end_of_input))
12042         {
12043             return sax->parse_error(m_lexer.get_position(),
12044                                     m_lexer.get_token_string(),
12045                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12046         }
12047 
12048         return result;
12049     }
12050 
12051   private:
12052     template<typename SAX>
12053     JSON_HEDLEY_NON_NULL(2)
sax_parse_internal(SAX * sax)12054     bool sax_parse_internal(SAX* sax)
12055     {
12056         // stack to remember the hierarchy of structured values we are parsing
12057         // true = array; false = object
12058         std::vector<bool> states;
12059         // value to avoid a goto (see comment where set to true)
12060         bool skip_to_state_evaluation = false;
12061 
12062         while (true)
12063         {
12064             if (!skip_to_state_evaluation)
12065             {
12066                 // invariant: get_token() was called before each iteration
12067                 switch (last_token)
12068                 {
12069                     case token_type::begin_object:
12070                     {
12071                         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
12072                         {
12073                             return false;
12074                         }
12075 
12076                         // closing } -> we are done
12077                         if (get_token() == token_type::end_object)
12078                         {
12079                             if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12080                             {
12081                                 return false;
12082                             }
12083                             break;
12084                         }
12085 
12086                         // parse key
12087                         if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
12088                         {
12089                             return sax->parse_error(m_lexer.get_position(),
12090                                                     m_lexer.get_token_string(),
12091                                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12092                         }
12093                         if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12094                         {
12095                             return false;
12096                         }
12097 
12098                         // parse separator (:)
12099                         if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12100                         {
12101                             return sax->parse_error(m_lexer.get_position(),
12102                                                     m_lexer.get_token_string(),
12103                                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12104                         }
12105 
12106                         // remember we are now inside an object
12107                         states.push_back(false);
12108 
12109                         // parse values
12110                         get_token();
12111                         continue;
12112                     }
12113 
12114                     case token_type::begin_array:
12115                     {
12116                         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
12117                         {
12118                             return false;
12119                         }
12120 
12121                         // closing ] -> we are done
12122                         if (get_token() == token_type::end_array)
12123                         {
12124                             if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12125                             {
12126                                 return false;
12127                             }
12128                             break;
12129                         }
12130 
12131                         // remember we are now inside an array
12132                         states.push_back(true);
12133 
12134                         // parse values (no need to call get_token)
12135                         continue;
12136                     }
12137 
12138                     case token_type::value_float:
12139                     {
12140                         const auto res = m_lexer.get_number_float();
12141 
12142                         if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
12143                         {
12144                             return sax->parse_error(m_lexer.get_position(),
12145                                                     m_lexer.get_token_string(),
12146                                                     out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
12147                         }
12148 
12149                         if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
12150                         {
12151                             return false;
12152                         }
12153 
12154                         break;
12155                     }
12156 
12157                     case token_type::literal_false:
12158                     {
12159                         if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
12160                         {
12161                             return false;
12162                         }
12163                         break;
12164                     }
12165 
12166                     case token_type::literal_null:
12167                     {
12168                         if (JSON_HEDLEY_UNLIKELY(!sax->null()))
12169                         {
12170                             return false;
12171                         }
12172                         break;
12173                     }
12174 
12175                     case token_type::literal_true:
12176                     {
12177                         if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
12178                         {
12179                             return false;
12180                         }
12181                         break;
12182                     }
12183 
12184                     case token_type::value_integer:
12185                     {
12186                         if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
12187                         {
12188                             return false;
12189                         }
12190                         break;
12191                     }
12192 
12193                     case token_type::value_string:
12194                     {
12195                         if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
12196                         {
12197                             return false;
12198                         }
12199                         break;
12200                     }
12201 
12202                     case token_type::value_unsigned:
12203                     {
12204                         if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
12205                         {
12206                             return false;
12207                         }
12208                         break;
12209                     }
12210 
12211                     case token_type::parse_error:
12212                     {
12213                         // using "uninitialized" to avoid "expected" message
12214                         return sax->parse_error(m_lexer.get_position(),
12215                                                 m_lexer.get_token_string(),
12216                                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
12217                     }
12218 
12219                     case token_type::uninitialized:
12220                     case token_type::end_array:
12221                     case token_type::end_object:
12222                     case token_type::name_separator:
12223                     case token_type::value_separator:
12224                     case token_type::end_of_input:
12225                     case token_type::literal_or_value:
12226                     default: // the last token was unexpected
12227                     {
12228                         return sax->parse_error(m_lexer.get_position(),
12229                                                 m_lexer.get_token_string(),
12230                                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12231                     }
12232                 }
12233             }
12234             else
12235             {
12236                 skip_to_state_evaluation = false;
12237             }
12238 
12239             // we reached this line after we successfully parsed a value
12240             if (states.empty())
12241             {
12242                 // empty stack: we reached the end of the hierarchy: done
12243                 return true;
12244             }
12245 
12246             if (states.back())  // array
12247             {
12248                 // comma -> next value
12249                 if (get_token() == token_type::value_separator)
12250                 {
12251                     // parse a new value
12252                     get_token();
12253                     continue;
12254                 }
12255 
12256                 // closing ]
12257                 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
12258                 {
12259                     if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12260                     {
12261                         return false;
12262                     }
12263 
12264                     // We are done with this array. Before we can parse a
12265                     // new value, we need to evaluate the new state first.
12266                     // By setting skip_to_state_evaluation to false, we
12267                     // are effectively jumping to the beginning of this if.
12268                     JSON_ASSERT(!states.empty());
12269                     states.pop_back();
12270                     skip_to_state_evaluation = true;
12271                     continue;
12272                 }
12273 
12274                 return sax->parse_error(m_lexer.get_position(),
12275                                         m_lexer.get_token_string(),
12276                                         parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
12277             }
12278 
12279             // states.back() is false -> object
12280 
12281             // comma -> next value
12282             if (get_token() == token_type::value_separator)
12283             {
12284                 // parse key
12285                 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
12286                 {
12287                     return sax->parse_error(m_lexer.get_position(),
12288                                             m_lexer.get_token_string(),
12289                                             parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12290                 }
12291 
12292                 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12293                 {
12294                     return false;
12295                 }
12296 
12297                 // parse separator (:)
12298                 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12299                 {
12300                     return sax->parse_error(m_lexer.get_position(),
12301                                             m_lexer.get_token_string(),
12302                                             parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12303                 }
12304 
12305                 // parse values
12306                 get_token();
12307                 continue;
12308             }
12309 
12310             // closing }
12311             if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
12312             {
12313                 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12314                 {
12315                     return false;
12316                 }
12317 
12318                 // We are done with this object. Before we can parse a
12319                 // new value, we need to evaluate the new state first.
12320                 // By setting skip_to_state_evaluation to false, we
12321                 // are effectively jumping to the beginning of this if.
12322                 JSON_ASSERT(!states.empty());
12323                 states.pop_back();
12324                 skip_to_state_evaluation = true;
12325                 continue;
12326             }
12327 
12328             return sax->parse_error(m_lexer.get_position(),
12329                                     m_lexer.get_token_string(),
12330                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
12331         }
12332     }
12333 
12334     /// get next token from lexer
get_token()12335     token_type get_token()
12336     {
12337         return last_token = m_lexer.scan();
12338     }
12339 
exception_message(const token_type expected,const std::string & context)12340     std::string exception_message(const token_type expected, const std::string& context)
12341     {
12342         std::string error_msg = "syntax error ";
12343 
12344         if (!context.empty())
12345         {
12346             error_msg += concat("while parsing ", context, ' ');
12347         }
12348 
12349         error_msg += "- ";
12350 
12351         if (last_token == token_type::parse_error)
12352         {
12353             error_msg += concat(m_lexer.get_error_message(), "; last read: '",
12354                                 m_lexer.get_token_string(), '\'');
12355         }
12356         else
12357         {
12358             error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
12359         }
12360 
12361         if (expected != token_type::uninitialized)
12362         {
12363             error_msg += concat("; expected ", lexer_t::token_type_name(expected));
12364         }
12365 
12366         return error_msg;
12367     }
12368 
12369   private:
12370     /// callback function
12371     const parser_callback_t<BasicJsonType> callback = nullptr;
12372     /// the type of the last read token
12373     token_type last_token = token_type::uninitialized;
12374     /// the lexer
12375     lexer_t m_lexer;
12376     /// whether to throw exceptions in case of errors
12377     const bool allow_exceptions = true;
12378 };
12379 
12380 }  // namespace detail
12381 }  // namespace nlohmann
12382 
12383 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
12384 //     __ _____ _____ _____
12385 //  __|  |   __|     |   | |  JSON for Modern C++
12386 // |  |  |__   |  |  | | | |  version 3.10.5
12387 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
12388 //
12389 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
12390 // SPDX-License-Identifier: MIT
12391 
12392 
12393 
12394 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12395 //     __ _____ _____ _____
12396 //  __|  |   __|     |   | |  JSON for Modern C++
12397 // |  |  |__   |  |  | | | |  version 3.10.5
12398 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
12399 //
12400 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
12401 // SPDX-License-Identifier: MIT
12402 
12403 
12404 
12405 #include <cstddef> // ptrdiff_t
12406 #include <limits>  // numeric_limits
12407 
12408 // #include <nlohmann/detail/macro_scope.hpp>
12409 
12410 
12411 namespace nlohmann
12412 {
12413 namespace detail
12414 {
12415 /*
12416 @brief an iterator for primitive JSON types
12417 
12418 This class models an iterator for primitive JSON types (boolean, number,
12419 string). It's only purpose is to allow the iterator/const_iterator classes
12420 to "iterate" over primitive values. Internally, the iterator is modeled by
12421 a `difference_type` variable. Value begin_value (`0`) models the begin,
12422 end_value (`1`) models past the end.
12423 */
12424 class primitive_iterator_t
12425 {
12426   private:
12427     using difference_type = std::ptrdiff_t;
12428     static constexpr difference_type begin_value = 0;
12429     static constexpr difference_type end_value = begin_value + 1;
12430 
12431   JSON_PRIVATE_UNLESS_TESTED:
12432     /// iterator as signed integer type
12433     difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
12434 
12435   public:
get_value() const12436     constexpr difference_type get_value() const noexcept
12437     {
12438         return m_it;
12439     }
12440 
12441     /// set iterator to a defined beginning
set_begin()12442     void set_begin() noexcept
12443     {
12444         m_it = begin_value;
12445     }
12446 
12447     /// set iterator to a defined past the end
set_end()12448     void set_end() noexcept
12449     {
12450         m_it = end_value;
12451     }
12452 
12453     /// return whether the iterator can be dereferenced
is_begin() const12454     constexpr bool is_begin() const noexcept
12455     {
12456         return m_it == begin_value;
12457     }
12458 
12459     /// return whether the iterator is at end
is_end() const12460     constexpr bool is_end() const noexcept
12461     {
12462         return m_it == end_value;
12463     }
12464 
operator ==(primitive_iterator_t lhs,primitive_iterator_t rhs)12465     friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12466     {
12467         return lhs.m_it == rhs.m_it;
12468     }
12469 
operator <(primitive_iterator_t lhs,primitive_iterator_t rhs)12470     friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12471     {
12472         return lhs.m_it < rhs.m_it;
12473     }
12474 
operator +(difference_type n)12475     primitive_iterator_t operator+(difference_type n) noexcept
12476     {
12477         auto result = *this;
12478         result += n;
12479         return result;
12480     }
12481 
operator -(primitive_iterator_t lhs,primitive_iterator_t rhs)12482     friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12483     {
12484         return lhs.m_it - rhs.m_it;
12485     }
12486 
operator ++()12487     primitive_iterator_t& operator++() noexcept
12488     {
12489         ++m_it;
12490         return *this;
12491     }
12492 
operator ++(int)12493     primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
12494     {
12495         auto result = *this;
12496         ++m_it;
12497         return result;
12498     }
12499 
operator --()12500     primitive_iterator_t& operator--() noexcept
12501     {
12502         --m_it;
12503         return *this;
12504     }
12505 
operator --(int)12506     primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
12507     {
12508         auto result = *this;
12509         --m_it;
12510         return result;
12511     }
12512 
operator +=(difference_type n)12513     primitive_iterator_t& operator+=(difference_type n) noexcept
12514     {
12515         m_it += n;
12516         return *this;
12517     }
12518 
operator -=(difference_type n)12519     primitive_iterator_t& operator-=(difference_type n) noexcept
12520     {
12521         m_it -= n;
12522         return *this;
12523     }
12524 };
12525 }  // namespace detail
12526 }  // namespace nlohmann
12527 
12528 
12529 namespace nlohmann
12530 {
12531 namespace detail
12532 {
12533 /*!
12534 @brief an iterator value
12535 
12536 @note This structure could easily be a union, but MSVC currently does not allow
12537 unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
12538 */
12539 template<typename BasicJsonType> struct internal_iterator
12540 {
12541     /// iterator for JSON objects
12542     typename BasicJsonType::object_t::iterator object_iterator {};
12543     /// iterator for JSON arrays
12544     typename BasicJsonType::array_t::iterator array_iterator {};
12545     /// generic iterator for all other types
12546     primitive_iterator_t primitive_iterator {};
12547 };
12548 }  // namespace detail
12549 }  // namespace nlohmann
12550 
12551 // #include <nlohmann/detail/iterators/iter_impl.hpp>
12552 //     __ _____ _____ _____
12553 //  __|  |   __|     |   | |  JSON for Modern C++
12554 // |  |  |__   |  |  | | | |  version 3.10.5
12555 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
12556 //
12557 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
12558 // SPDX-License-Identifier: MIT
12559 
12560 
12561 
12562 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
12563 #include <type_traits> // conditional, is_const, remove_const
12564 
12565 // #include <nlohmann/detail/exceptions.hpp>
12566 
12567 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
12568 
12569 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12570 
12571 // #include <nlohmann/detail/macro_scope.hpp>
12572 
12573 // #include <nlohmann/detail/meta/cpp_future.hpp>
12574 
12575 // #include <nlohmann/detail/meta/type_traits.hpp>
12576 
12577 // #include <nlohmann/detail/value_t.hpp>
12578 
12579 
12580 namespace nlohmann
12581 {
12582 namespace detail
12583 {
12584 // forward declare, to be able to friend it later on
12585 template<typename IteratorType> class iteration_proxy;
12586 template<typename IteratorType> class iteration_proxy_value;
12587 
12588 /*!
12589 @brief a template for a bidirectional iterator for the @ref basic_json class
12590 This class implements a both iterators (iterator and const_iterator) for the
12591 @ref basic_json class.
12592 @note An iterator is called *initialized* when a pointer to a JSON value has
12593       been set (e.g., by a constructor or a copy assignment). If the iterator is
12594       default-constructed, it is *uninitialized* and most methods are undefined.
12595       **The library uses assertions to detect calls on uninitialized iterators.**
12596 @requirement The class satisfies the following concept requirements:
12597 -
12598 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
12599   The iterator that can be moved can be moved in both directions (i.e.
12600   incremented and decremented).
12601 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional
12602        iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
12603 */
12604 template<typename BasicJsonType>
12605 class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
12606 {
12607     /// the iterator with BasicJsonType of different const-ness
12608     using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
12609     /// allow basic_json to access private members
12610     friend other_iter_impl;
12611     friend BasicJsonType;
12612     friend iteration_proxy<iter_impl>;
12613     friend iteration_proxy_value<iter_impl>;
12614 
12615     using object_t = typename BasicJsonType::object_t;
12616     using array_t = typename BasicJsonType::array_t;
12617     // make sure BasicJsonType is basic_json or const basic_json
12618     static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
12619                   "iter_impl only accepts (const) basic_json");
12620     // superficial check for the LegacyBidirectionalIterator named requirement
12621     static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
12622                   &&  std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
12623                   "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
12624 
12625   public:
12626     /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
12627     /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
12628     /// A user-defined iterator should provide publicly accessible typedefs named
12629     /// iterator_category, value_type, difference_type, pointer, and reference.
12630     /// Note that value_type is required to be non-const, even for constant iterators.
12631     using iterator_category = std::bidirectional_iterator_tag;
12632 
12633     /// the type of the values when the iterator is dereferenced
12634     using value_type = typename BasicJsonType::value_type;
12635     /// a type to represent differences between iterators
12636     using difference_type = typename BasicJsonType::difference_type;
12637     /// defines a pointer to the type iterated over (value_type)
12638     using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
12639           typename BasicJsonType::const_pointer,
12640           typename BasicJsonType::pointer>::type;
12641     /// defines a reference to the type iterated over (value_type)
12642     using reference =
12643         typename std::conditional<std::is_const<BasicJsonType>::value,
12644         typename BasicJsonType::const_reference,
12645         typename BasicJsonType::reference>::type;
12646 
12647     iter_impl() = default;
12648     ~iter_impl() = default;
12649     iter_impl(iter_impl&&) noexcept = default;
12650     iter_impl& operator=(iter_impl&&) noexcept = default;
12651 
12652     /*!
12653     @brief constructor for a given JSON instance
12654     @param[in] object  pointer to a JSON object for this iterator
12655     @pre object != nullptr
12656     @post The iterator is initialized; i.e. `m_object != nullptr`.
12657     */
iter_impl(pointer object)12658     explicit iter_impl(pointer object) noexcept : m_object(object)
12659     {
12660         JSON_ASSERT(m_object != nullptr);
12661 
12662         switch (m_object->m_type)
12663         {
12664             case value_t::object:
12665             {
12666                 m_it.object_iterator = typename object_t::iterator();
12667                 break;
12668             }
12669 
12670             case value_t::array:
12671             {
12672                 m_it.array_iterator = typename array_t::iterator();
12673                 break;
12674             }
12675 
12676             case value_t::null:
12677             case value_t::string:
12678             case value_t::boolean:
12679             case value_t::number_integer:
12680             case value_t::number_unsigned:
12681             case value_t::number_float:
12682             case value_t::binary:
12683             case value_t::discarded:
12684             default:
12685             {
12686                 m_it.primitive_iterator = primitive_iterator_t();
12687                 break;
12688             }
12689         }
12690     }
12691 
12692     /*!
12693     @note The conventional copy constructor and copy assignment are implicitly
12694           defined. Combined with the following converting constructor and
12695           assignment, they support: (1) copy from iterator to iterator, (2)
12696           copy from const iterator to const iterator, and (3) conversion from
12697           iterator to const iterator. However conversion from const iterator
12698           to iterator is not defined.
12699     */
12700 
12701     /*!
12702     @brief const copy constructor
12703     @param[in] other const iterator to copy from
12704     @note This copy constructor had to be defined explicitly to circumvent a bug
12705           occurring on msvc v19.0 compiler (VS 2015) debug build. For more
12706           information refer to: https://github.com/nlohmann/json/issues/1608
12707     */
iter_impl(const iter_impl<const BasicJsonType> & other)12708     iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
12709         : m_object(other.m_object), m_it(other.m_it)
12710     {}
12711 
12712     /*!
12713     @brief converting assignment
12714     @param[in] other const iterator to copy from
12715     @return const/non-const iterator
12716     @note It is not checked whether @a other is initialized.
12717     */
operator =(const iter_impl<const BasicJsonType> & other)12718     iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
12719     {
12720         if (&other != this)
12721         {
12722             m_object = other.m_object;
12723             m_it = other.m_it;
12724         }
12725         return *this;
12726     }
12727 
12728     /*!
12729     @brief converting constructor
12730     @param[in] other  non-const iterator to copy from
12731     @note It is not checked whether @a other is initialized.
12732     */
iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type> & other)12733     iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
12734         : m_object(other.m_object), m_it(other.m_it)
12735     {}
12736 
12737     /*!
12738     @brief converting assignment
12739     @param[in] other  non-const iterator to copy from
12740     @return const/non-const iterator
12741     @note It is not checked whether @a other is initialized.
12742     */
operator =(const iter_impl<typename std::remove_const<BasicJsonType>::type> & other)12743     iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
12744     {
12745         m_object = other.m_object;
12746         m_it = other.m_it;
12747         return *this;
12748     }
12749 
12750   JSON_PRIVATE_UNLESS_TESTED:
12751     /*!
12752     @brief set the iterator to the first value
12753     @pre The iterator is initialized; i.e. `m_object != nullptr`.
12754     */
12755     void set_begin() noexcept
12756     {
12757         JSON_ASSERT(m_object != nullptr);
12758 
12759         switch (m_object->m_type)
12760         {
12761             case value_t::object:
12762             {
12763                 m_it.object_iterator = m_object->m_value.object->begin();
12764                 break;
12765             }
12766 
12767             case value_t::array:
12768             {
12769                 m_it.array_iterator = m_object->m_value.array->begin();
12770                 break;
12771             }
12772 
12773             case value_t::null:
12774             {
12775                 // set to end so begin()==end() is true: null is empty
12776                 m_it.primitive_iterator.set_end();
12777                 break;
12778             }
12779 
12780             case value_t::string:
12781             case value_t::boolean:
12782             case value_t::number_integer:
12783             case value_t::number_unsigned:
12784             case value_t::number_float:
12785             case value_t::binary:
12786             case value_t::discarded:
12787             default:
12788             {
12789                 m_it.primitive_iterator.set_begin();
12790                 break;
12791             }
12792         }
12793     }
12794 
12795     /*!
12796     @brief set the iterator past the last value
12797     @pre The iterator is initialized; i.e. `m_object != nullptr`.
12798     */
set_end()12799     void set_end() noexcept
12800     {
12801         JSON_ASSERT(m_object != nullptr);
12802 
12803         switch (m_object->m_type)
12804         {
12805             case value_t::object:
12806             {
12807                 m_it.object_iterator = m_object->m_value.object->end();
12808                 break;
12809             }
12810 
12811             case value_t::array:
12812             {
12813                 m_it.array_iterator = m_object->m_value.array->end();
12814                 break;
12815             }
12816 
12817             case value_t::null:
12818             case value_t::string:
12819             case value_t::boolean:
12820             case value_t::number_integer:
12821             case value_t::number_unsigned:
12822             case value_t::number_float:
12823             case value_t::binary:
12824             case value_t::discarded:
12825             default:
12826             {
12827                 m_it.primitive_iterator.set_end();
12828                 break;
12829             }
12830         }
12831     }
12832 
12833   public:
12834     /*!
12835     @brief return a reference to the value pointed to by the iterator
12836     @pre The iterator is initialized; i.e. `m_object != nullptr`.
12837     */
operator *() const12838     reference operator*() const
12839     {
12840         JSON_ASSERT(m_object != nullptr);
12841 
12842         switch (m_object->m_type)
12843         {
12844             case value_t::object:
12845             {
12846                 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
12847                 return m_it.object_iterator->second;
12848             }
12849 
12850             case value_t::array:
12851             {
12852                 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
12853                 return *m_it.array_iterator;
12854             }
12855 
12856             case value_t::null:
12857                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
12858 
12859             case value_t::string:
12860             case value_t::boolean:
12861             case value_t::number_integer:
12862             case value_t::number_unsigned:
12863             case value_t::number_float:
12864             case value_t::binary:
12865             case value_t::discarded:
12866             default:
12867             {
12868                 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
12869                 {
12870                     return *m_object;
12871                 }
12872 
12873                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
12874             }
12875         }
12876     }
12877 
12878     /*!
12879     @brief dereference the iterator
12880     @pre The iterator is initialized; i.e. `m_object != nullptr`.
12881     */
operator ->() const12882     pointer operator->() const
12883     {
12884         JSON_ASSERT(m_object != nullptr);
12885 
12886         switch (m_object->m_type)
12887         {
12888             case value_t::object:
12889             {
12890                 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
12891                 return &(m_it.object_iterator->second);
12892             }
12893 
12894             case value_t::array:
12895             {
12896                 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
12897                 return &*m_it.array_iterator;
12898             }
12899 
12900             case value_t::null:
12901             case value_t::string:
12902             case value_t::boolean:
12903             case value_t::number_integer:
12904             case value_t::number_unsigned:
12905             case value_t::number_float:
12906             case value_t::binary:
12907             case value_t::discarded:
12908             default:
12909             {
12910                 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
12911                 {
12912                     return m_object;
12913                 }
12914 
12915                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
12916             }
12917         }
12918     }
12919 
12920     /*!
12921     @brief post-increment (it++)
12922     @pre The iterator is initialized; i.e. `m_object != nullptr`.
12923     */
operator ++(int)12924     iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
12925     {
12926         auto result = *this;
12927         ++(*this);
12928         return result;
12929     }
12930 
12931     /*!
12932     @brief pre-increment (++it)
12933     @pre The iterator is initialized; i.e. `m_object != nullptr`.
12934     */
operator ++()12935     iter_impl& operator++()
12936     {
12937         JSON_ASSERT(m_object != nullptr);
12938 
12939         switch (m_object->m_type)
12940         {
12941             case value_t::object:
12942             {
12943                 std::advance(m_it.object_iterator, 1);
12944                 break;
12945             }
12946 
12947             case value_t::array:
12948             {
12949                 std::advance(m_it.array_iterator, 1);
12950                 break;
12951             }
12952 
12953             case value_t::null:
12954             case value_t::string:
12955             case value_t::boolean:
12956             case value_t::number_integer:
12957             case value_t::number_unsigned:
12958             case value_t::number_float:
12959             case value_t::binary:
12960             case value_t::discarded:
12961             default:
12962             {
12963                 ++m_it.primitive_iterator;
12964                 break;
12965             }
12966         }
12967 
12968         return *this;
12969     }
12970 
12971     /*!
12972     @brief post-decrement (it--)
12973     @pre The iterator is initialized; i.e. `m_object != nullptr`.
12974     */
operator --(int)12975     iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
12976     {
12977         auto result = *this;
12978         --(*this);
12979         return result;
12980     }
12981 
12982     /*!
12983     @brief pre-decrement (--it)
12984     @pre The iterator is initialized; i.e. `m_object != nullptr`.
12985     */
operator --()12986     iter_impl& operator--()
12987     {
12988         JSON_ASSERT(m_object != nullptr);
12989 
12990         switch (m_object->m_type)
12991         {
12992             case value_t::object:
12993             {
12994                 std::advance(m_it.object_iterator, -1);
12995                 break;
12996             }
12997 
12998             case value_t::array:
12999             {
13000                 std::advance(m_it.array_iterator, -1);
13001                 break;
13002             }
13003 
13004             case value_t::null:
13005             case value_t::string:
13006             case value_t::boolean:
13007             case value_t::number_integer:
13008             case value_t::number_unsigned:
13009             case value_t::number_float:
13010             case value_t::binary:
13011             case value_t::discarded:
13012             default:
13013             {
13014                 --m_it.primitive_iterator;
13015                 break;
13016             }
13017         }
13018 
13019         return *this;
13020     }
13021 
13022     /*!
13023     @brief comparison: equal
13024     @pre The iterator is initialized; i.e. `m_object != nullptr`.
13025     */
13026     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 >
operator ==(const IterImpl & other) const13027     bool operator==(const IterImpl& other) const
13028     {
13029         // if objects are not the same, the comparison is undefined
13030         if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13031         {
13032             JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13033         }
13034 
13035         JSON_ASSERT(m_object != nullptr);
13036 
13037         switch (m_object->m_type)
13038         {
13039             case value_t::object:
13040                 return (m_it.object_iterator == other.m_it.object_iterator);
13041 
13042             case value_t::array:
13043                 return (m_it.array_iterator == other.m_it.array_iterator);
13044 
13045             case value_t::null:
13046             case value_t::string:
13047             case value_t::boolean:
13048             case value_t::number_integer:
13049             case value_t::number_unsigned:
13050             case value_t::number_float:
13051             case value_t::binary:
13052             case value_t::discarded:
13053             default:
13054                 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
13055         }
13056     }
13057 
13058     /*!
13059     @brief comparison: not equal
13060     @pre The iterator is initialized; i.e. `m_object != nullptr`.
13061     */
13062     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 >
operator !=(const IterImpl & other) const13063     bool operator!=(const IterImpl& other) const
13064     {
13065         return !operator==(other);
13066     }
13067 
13068     /*!
13069     @brief comparison: smaller
13070     @pre The iterator is initialized; i.e. `m_object != nullptr`.
13071     */
operator <(const iter_impl & other) const13072     bool operator<(const iter_impl& other) const
13073     {
13074         // if objects are not the same, the comparison is undefined
13075         if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13076         {
13077             JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13078         }
13079 
13080         JSON_ASSERT(m_object != nullptr);
13081 
13082         switch (m_object->m_type)
13083         {
13084             case value_t::object:
13085                 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
13086 
13087             case value_t::array:
13088                 return (m_it.array_iterator < other.m_it.array_iterator);
13089 
13090             case value_t::null:
13091             case value_t::string:
13092             case value_t::boolean:
13093             case value_t::number_integer:
13094             case value_t::number_unsigned:
13095             case value_t::number_float:
13096             case value_t::binary:
13097             case value_t::discarded:
13098             default:
13099                 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
13100         }
13101     }
13102 
13103     /*!
13104     @brief comparison: less than or equal
13105     @pre The iterator is initialized; i.e. `m_object != nullptr`.
13106     */
operator <=(const iter_impl & other) const13107     bool operator<=(const iter_impl& other) const
13108     {
13109         return !other.operator < (*this);
13110     }
13111 
13112     /*!
13113     @brief comparison: greater than
13114     @pre The iterator is initialized; i.e. `m_object != nullptr`.
13115     */
operator >(const iter_impl & other) const13116     bool operator>(const iter_impl& other) const
13117     {
13118         return !operator<=(other);
13119     }
13120 
13121     /*!
13122     @brief comparison: greater than or equal
13123     @pre The iterator is initialized; i.e. `m_object != nullptr`.
13124     */
operator >=(const iter_impl & other) const13125     bool operator>=(const iter_impl& other) const
13126     {
13127         return !operator<(other);
13128     }
13129 
13130     /*!
13131     @brief add to iterator
13132     @pre The iterator is initialized; i.e. `m_object != nullptr`.
13133     */
operator +=(difference_type i)13134     iter_impl& operator+=(difference_type i)
13135     {
13136         JSON_ASSERT(m_object != nullptr);
13137 
13138         switch (m_object->m_type)
13139         {
13140             case value_t::object:
13141                 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13142 
13143             case value_t::array:
13144             {
13145                 std::advance(m_it.array_iterator, i);
13146                 break;
13147             }
13148 
13149             case value_t::null:
13150             case value_t::string:
13151             case value_t::boolean:
13152             case value_t::number_integer:
13153             case value_t::number_unsigned:
13154             case value_t::number_float:
13155             case value_t::binary:
13156             case value_t::discarded:
13157             default:
13158             {
13159                 m_it.primitive_iterator += i;
13160                 break;
13161             }
13162         }
13163 
13164         return *this;
13165     }
13166 
13167     /*!
13168     @brief subtract from iterator
13169     @pre The iterator is initialized; i.e. `m_object != nullptr`.
13170     */
operator -=(difference_type i)13171     iter_impl& operator-=(difference_type i)
13172     {
13173         return operator+=(-i);
13174     }
13175 
13176     /*!
13177     @brief add to iterator
13178     @pre The iterator is initialized; i.e. `m_object != nullptr`.
13179     */
operator +(difference_type i) const13180     iter_impl operator+(difference_type i) const
13181     {
13182         auto result = *this;
13183         result += i;
13184         return result;
13185     }
13186 
13187     /*!
13188     @brief addition of distance and iterator
13189     @pre The iterator is initialized; i.e. `m_object != nullptr`.
13190     */
operator +(difference_type i,const iter_impl & it)13191     friend iter_impl operator+(difference_type i, const iter_impl& it)
13192     {
13193         auto result = it;
13194         result += i;
13195         return result;
13196     }
13197 
13198     /*!
13199     @brief subtract from iterator
13200     @pre The iterator is initialized; i.e. `m_object != nullptr`.
13201     */
operator -(difference_type i) const13202     iter_impl operator-(difference_type i) const
13203     {
13204         auto result = *this;
13205         result -= i;
13206         return result;
13207     }
13208 
13209     /*!
13210     @brief return difference
13211     @pre The iterator is initialized; i.e. `m_object != nullptr`.
13212     */
operator -(const iter_impl & other) const13213     difference_type operator-(const iter_impl& other) const
13214     {
13215         JSON_ASSERT(m_object != nullptr);
13216 
13217         switch (m_object->m_type)
13218         {
13219             case value_t::object:
13220                 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13221 
13222             case value_t::array:
13223                 return m_it.array_iterator - other.m_it.array_iterator;
13224 
13225             case value_t::null:
13226             case value_t::string:
13227             case value_t::boolean:
13228             case value_t::number_integer:
13229             case value_t::number_unsigned:
13230             case value_t::number_float:
13231             case value_t::binary:
13232             case value_t::discarded:
13233             default:
13234                 return m_it.primitive_iterator - other.m_it.primitive_iterator;
13235         }
13236     }
13237 
13238     /*!
13239     @brief access to successor
13240     @pre The iterator is initialized; i.e. `m_object != nullptr`.
13241     */
operator [](difference_type n) const13242     reference operator[](difference_type n) const
13243     {
13244         JSON_ASSERT(m_object != nullptr);
13245 
13246         switch (m_object->m_type)
13247         {
13248             case value_t::object:
13249                 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
13250 
13251             case value_t::array:
13252                 return *std::next(m_it.array_iterator, n);
13253 
13254             case value_t::null:
13255                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13256 
13257             case value_t::string:
13258             case value_t::boolean:
13259             case value_t::number_integer:
13260             case value_t::number_unsigned:
13261             case value_t::number_float:
13262             case value_t::binary:
13263             case value_t::discarded:
13264             default:
13265             {
13266                 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
13267                 {
13268                     return *m_object;
13269                 }
13270 
13271                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13272             }
13273         }
13274     }
13275 
13276     /*!
13277     @brief return the key of an object iterator
13278     @pre The iterator is initialized; i.e. `m_object != nullptr`.
13279     */
key() const13280     const typename object_t::key_type& key() const
13281     {
13282         JSON_ASSERT(m_object != nullptr);
13283 
13284         if (JSON_HEDLEY_LIKELY(m_object->is_object()))
13285         {
13286             return m_it.object_iterator->first;
13287         }
13288 
13289         JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
13290     }
13291 
13292     /*!
13293     @brief return the value of an iterator
13294     @pre The iterator is initialized; i.e. `m_object != nullptr`.
13295     */
value() const13296     reference value() const
13297     {
13298         return operator*();
13299     }
13300 
13301   JSON_PRIVATE_UNLESS_TESTED:
13302     /// associated JSON instance
13303     pointer m_object = nullptr;
13304     /// the actual iterator of the associated instance
13305     internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
13306 };
13307 } // namespace detail
13308 } // namespace nlohmann
13309 
13310 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
13311 
13312 // #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
13313 //     __ _____ _____ _____
13314 //  __|  |   __|     |   | |  JSON for Modern C++
13315 // |  |  |__   |  |  | | | |  version 3.10.5
13316 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
13317 //
13318 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
13319 // SPDX-License-Identifier: MIT
13320 
13321 
13322 
13323 #include <cstddef> // ptrdiff_t
13324 #include <iterator> // reverse_iterator
13325 #include <utility> // declval
13326 
13327 namespace nlohmann
13328 {
13329 namespace detail
13330 {
13331 //////////////////////
13332 // reverse_iterator //
13333 //////////////////////
13334 
13335 /*!
13336 @brief a template for a reverse iterator class
13337 
13338 @tparam Base the base iterator type to reverse. Valid types are @ref
13339 iterator (to create @ref reverse_iterator) and @ref const_iterator (to
13340 create @ref const_reverse_iterator).
13341 
13342 @requirement The class satisfies the following concept requirements:
13343 -
13344 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
13345   The iterator that can be moved can be moved in both directions (i.e.
13346   incremented and decremented).
13347 - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
13348   It is possible to write to the pointed-to element (only if @a Base is
13349   @ref iterator).
13350 
13351 @since version 1.0.0
13352 */
13353 template<typename Base>
13354 class json_reverse_iterator : public std::reverse_iterator<Base>
13355 {
13356   public:
13357     using difference_type = std::ptrdiff_t;
13358     /// shortcut to the reverse iterator adapter
13359     using base_iterator = std::reverse_iterator<Base>;
13360     /// the reference type for the pointed-to element
13361     using reference = typename Base::reference;
13362 
13363     /// create reverse iterator from iterator
json_reverse_iterator(const typename base_iterator::iterator_type & it)13364     explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
13365         : base_iterator(it) {}
13366 
13367     /// create reverse iterator from base class
json_reverse_iterator(const base_iterator & it)13368     explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
13369 
13370     /// post-increment (it++)
operator ++(int)13371     json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
13372     {
13373         return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
13374     }
13375 
13376     /// pre-increment (++it)
operator ++()13377     json_reverse_iterator& operator++()
13378     {
13379         return static_cast<json_reverse_iterator&>(base_iterator::operator++());
13380     }
13381 
13382     /// post-decrement (it--)
operator --(int)13383     json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
13384     {
13385         return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
13386     }
13387 
13388     /// pre-decrement (--it)
operator --()13389     json_reverse_iterator& operator--()
13390     {
13391         return static_cast<json_reverse_iterator&>(base_iterator::operator--());
13392     }
13393 
13394     /// add to iterator
operator +=(difference_type i)13395     json_reverse_iterator& operator+=(difference_type i)
13396     {
13397         return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
13398     }
13399 
13400     /// add to iterator
operator +(difference_type i) const13401     json_reverse_iterator operator+(difference_type i) const
13402     {
13403         return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
13404     }
13405 
13406     /// subtract from iterator
operator -(difference_type i) const13407     json_reverse_iterator operator-(difference_type i) const
13408     {
13409         return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
13410     }
13411 
13412     /// return difference
operator -(const json_reverse_iterator & other) const13413     difference_type operator-(const json_reverse_iterator& other) const
13414     {
13415         return base_iterator(*this) - base_iterator(other);
13416     }
13417 
13418     /// access to successor
operator [](difference_type n) const13419     reference operator[](difference_type n) const
13420     {
13421         return *(this->operator+(n));
13422     }
13423 
13424     /// return the key of an object iterator
key() const13425     auto key() const -> decltype(std::declval<Base>().key())
13426     {
13427         auto it = --this->base();
13428         return it.key();
13429     }
13430 
13431     /// return the value of an iterator
value() const13432     reference value() const
13433     {
13434         auto it = --this->base();
13435         return it.operator * ();
13436     }
13437 };
13438 }  // namespace detail
13439 }  // namespace nlohmann
13440 
13441 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13442 
13443 // #include <nlohmann/detail/json_pointer.hpp>
13444 //     __ _____ _____ _____
13445 //  __|  |   __|     |   | |  JSON for Modern C++
13446 // |  |  |__   |  |  | | | |  version 3.10.5
13447 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
13448 //
13449 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
13450 // SPDX-License-Identifier: MIT
13451 
13452 
13453 
13454 #include <algorithm> // all_of
13455 #include <cctype> // isdigit
13456 #include <cerrno> // errno, ERANGE
13457 #include <cstdlib> // strtoull
13458 #include <limits> // max
13459 #include <numeric> // accumulate
13460 #include <string> // string
13461 #include <utility> // move
13462 #include <vector> // vector
13463 
13464 // #include <nlohmann/detail/exceptions.hpp>
13465 
13466 // #include <nlohmann/detail/macro_scope.hpp>
13467 
13468 // #include <nlohmann/detail/string_concat.hpp>
13469 
13470 // #include <nlohmann/detail/string_escape.hpp>
13471 
13472 // #include <nlohmann/detail/value_t.hpp>
13473 
13474 
13475 namespace nlohmann
13476 {
13477 
13478 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
13479 /// @sa https://json.nlohmann.me/api/json_pointer/
13480 template<typename RefStringType>
13481 class json_pointer
13482 {
13483     // allow basic_json to access private members
13484     NLOHMANN_BASIC_JSON_TPL_DECLARATION
13485     friend class basic_json;
13486 
13487     template<typename>
13488     friend class json_pointer;
13489 
13490     template<typename T>
13491     struct string_t_helper
13492     {
13493         using type = T;
13494     };
13495 
13496     NLOHMANN_BASIC_JSON_TPL_DECLARATION
13497     struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
13498     {
13499         using type = StringType;
13500     };
13501 
13502   public:
13503     // for backwards compatibility accept BasicJsonType
13504     using string_t = typename string_t_helper<RefStringType>::type;
13505 
13506     /// @brief create JSON pointer
13507     /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
json_pointer(const string_t & s="")13508     explicit json_pointer(const string_t& s = "")
13509         : reference_tokens(split(s))
13510     {}
13511 
13512     /// @brief return a string representation of the JSON pointer
13513     /// @sa https://json.nlohmann.me/api/json_pointer/to_string/
to_string() const13514     string_t to_string() const
13515     {
13516         return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
13517                                string_t{},
13518                                [](const string_t& a, const string_t& b)
13519         {
13520             return detail::concat(a, '/', detail::escape(b));
13521         });
13522     }
13523 
13524     /// @brief return a string representation of the JSON pointer
13525     /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
operator string_t() const13526     operator string_t() const
13527     {
13528         return to_string();
13529     }
13530 
13531     /// @brief append another JSON pointer at the end of this JSON pointer
13532     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
operator /=(const json_pointer & ptr)13533     json_pointer& operator/=(const json_pointer& ptr)
13534     {
13535         reference_tokens.insert(reference_tokens.end(),
13536                                 ptr.reference_tokens.begin(),
13537                                 ptr.reference_tokens.end());
13538         return *this;
13539     }
13540 
13541     /// @brief append an unescaped reference token at the end of this JSON pointer
13542     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
operator /=(string_t token)13543     json_pointer& operator/=(string_t token)
13544     {
13545         push_back(std::move(token));
13546         return *this;
13547     }
13548 
13549     /// @brief append an array index at the end of this JSON pointer
13550     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
operator /=(std::size_t array_idx)13551     json_pointer& operator/=(std::size_t array_idx)
13552     {
13553         return *this /= std::to_string(array_idx);
13554     }
13555 
13556     /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
13557     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
operator /(const json_pointer & lhs,const json_pointer & rhs)13558     friend json_pointer operator/(const json_pointer& lhs,
13559                                   const json_pointer& rhs)
13560     {
13561         return json_pointer(lhs) /= rhs;
13562     }
13563 
13564     /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
13565     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
operator /(const json_pointer & lhs,string_t token)13566     friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
13567     {
13568         return json_pointer(lhs) /= std::move(token);
13569     }
13570 
13571     /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
13572     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
operator /(const json_pointer & lhs,std::size_t array_idx)13573     friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
13574     {
13575         return json_pointer(lhs) /= array_idx;
13576     }
13577 
13578     /// @brief returns the parent of this JSON pointer
13579     /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
parent_pointer() const13580     json_pointer parent_pointer() const
13581     {
13582         if (empty())
13583         {
13584             return *this;
13585         }
13586 
13587         json_pointer res = *this;
13588         res.pop_back();
13589         return res;
13590     }
13591 
13592     /// @brief remove last reference token
13593     /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
pop_back()13594     void pop_back()
13595     {
13596         if (JSON_HEDLEY_UNLIKELY(empty()))
13597         {
13598             JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13599         }
13600 
13601         reference_tokens.pop_back();
13602     }
13603 
13604     /// @brief return last reference token
13605     /// @sa https://json.nlohmann.me/api/json_pointer/back/
back() const13606     const string_t& back() const
13607     {
13608         if (JSON_HEDLEY_UNLIKELY(empty()))
13609         {
13610             JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13611         }
13612 
13613         return reference_tokens.back();
13614     }
13615 
13616     /// @brief append an unescaped token at the end of the reference pointer
13617     /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
push_back(const string_t & token)13618     void push_back(const string_t& token)
13619     {
13620         reference_tokens.push_back(token);
13621     }
13622 
13623     /// @brief append an unescaped token at the end of the reference pointer
13624     /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
push_back(string_t && token)13625     void push_back(string_t&& token)
13626     {
13627         reference_tokens.push_back(std::move(token));
13628     }
13629 
13630     /// @brief return whether pointer points to the root document
13631     /// @sa https://json.nlohmann.me/api/json_pointer/empty/
empty() const13632     bool empty() const noexcept
13633     {
13634         return reference_tokens.empty();
13635     }
13636 
13637   private:
13638     /*!
13639     @param[in] s  reference token to be converted into an array index
13640 
13641     @return integer representation of @a s
13642 
13643     @throw parse_error.106  if an array index begins with '0'
13644     @throw parse_error.109  if an array index begins not with a digit
13645     @throw out_of_range.404 if string @a s could not be converted to an integer
13646     @throw out_of_range.410 if an array index exceeds size_type
13647     */
13648     template<typename BasicJsonType>
array_index(const string_t & s)13649     static typename BasicJsonType::size_type array_index(const string_t& s)
13650     {
13651         using size_type = typename BasicJsonType::size_type;
13652 
13653         // error condition (cf. RFC 6901, Sect. 4)
13654         if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
13655         {
13656             JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
13657         }
13658 
13659         // error condition (cf. RFC 6901, Sect. 4)
13660         if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
13661         {
13662             JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
13663         }
13664 
13665         const char* p = s.c_str();
13666         char* p_end = nullptr;
13667         errno = 0; // strtoull doesn't reset errno
13668         unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
13669         if (p == p_end // invalid input or empty string
13670                 || errno == ERANGE // out of range
13671                 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
13672         {
13673             JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
13674         }
13675 
13676         // only triggered on special platforms (like 32bit), see also
13677         // https://github.com/nlohmann/json/pull/2203
13678         if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))  // NOLINT(runtime/int)
13679         {
13680             JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr));   // LCOV_EXCL_LINE
13681         }
13682 
13683         return static_cast<size_type>(res);
13684     }
13685 
13686   JSON_PRIVATE_UNLESS_TESTED:
13687     json_pointer top() const
13688     {
13689         if (JSON_HEDLEY_UNLIKELY(empty()))
13690         {
13691             JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13692         }
13693 
13694         json_pointer result = *this;
13695         result.reference_tokens = {reference_tokens[0]};
13696         return result;
13697     }
13698 
13699   private:
13700     /*!
13701     @brief create and return a reference to the pointed to value
13702 
13703     @complexity Linear in the number of reference tokens.
13704 
13705     @throw parse_error.109 if array index is not a number
13706     @throw type_error.313 if value cannot be unflattened
13707     */
13708     template<typename BasicJsonType>
get_and_create(BasicJsonType & j) const13709     BasicJsonType& get_and_create(BasicJsonType& j) const
13710     {
13711         auto* result = &j;
13712 
13713         // in case no reference tokens exist, return a reference to the JSON value
13714         // j which will be overwritten by a primitive value
13715         for (const auto& reference_token : reference_tokens)
13716         {
13717             switch (result->type())
13718             {
13719                 case detail::value_t::null:
13720                 {
13721                     if (reference_token == "0")
13722                     {
13723                         // start a new array if reference token is 0
13724                         result = &result->operator[](0);
13725                     }
13726                     else
13727                     {
13728                         // start a new object otherwise
13729                         result = &result->operator[](reference_token);
13730                     }
13731                     break;
13732                 }
13733 
13734                 case detail::value_t::object:
13735                 {
13736                     // create an entry in the object
13737                     result = &result->operator[](reference_token);
13738                     break;
13739                 }
13740 
13741                 case detail::value_t::array:
13742                 {
13743                     // create an entry in the array
13744                     result = &result->operator[](array_index<BasicJsonType>(reference_token));
13745                     break;
13746                 }
13747 
13748                 /*
13749                 The following code is only reached if there exists a reference
13750                 token _and_ the current value is primitive. In this case, we have
13751                 an error situation, because primitive values may only occur as
13752                 single value; that is, with an empty list of reference tokens.
13753                 */
13754                 case detail::value_t::string:
13755                 case detail::value_t::boolean:
13756                 case detail::value_t::number_integer:
13757                 case detail::value_t::number_unsigned:
13758                 case detail::value_t::number_float:
13759                 case detail::value_t::binary:
13760                 case detail::value_t::discarded:
13761                 default:
13762                     JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
13763             }
13764         }
13765 
13766         return *result;
13767     }
13768 
13769     /*!
13770     @brief return a reference to the pointed to value
13771 
13772     @note This version does not throw if a value is not present, but tries to
13773           create nested values instead. For instance, calling this function
13774           with pointer `"/this/that"` on a null value is equivalent to calling
13775           `operator[]("this").operator[]("that")` on that value, effectively
13776           changing the null value to an object.
13777 
13778     @param[in] ptr  a JSON value
13779 
13780     @return reference to the JSON value pointed to by the JSON pointer
13781 
13782     @complexity Linear in the length of the JSON pointer.
13783 
13784     @throw parse_error.106   if an array index begins with '0'
13785     @throw parse_error.109   if an array index was not a number
13786     @throw out_of_range.404  if the JSON pointer can not be resolved
13787     */
13788     template<typename BasicJsonType>
get_unchecked(BasicJsonType * ptr) const13789     BasicJsonType& get_unchecked(BasicJsonType* ptr) const
13790     {
13791         for (const auto& reference_token : reference_tokens)
13792         {
13793             // convert null values to arrays or objects before continuing
13794             if (ptr->is_null())
13795             {
13796                 // check if reference token is a number
13797                 const bool nums =
13798                     std::all_of(reference_token.begin(), reference_token.end(),
13799                                 [](const unsigned char x)
13800                 {
13801                     return std::isdigit(x);
13802                 });
13803 
13804                 // change value to array for numbers or "-" or to object otherwise
13805                 *ptr = (nums || reference_token == "-")
13806                        ? detail::value_t::array
13807                        : detail::value_t::object;
13808             }
13809 
13810             switch (ptr->type())
13811             {
13812                 case detail::value_t::object:
13813                 {
13814                     // use unchecked object access
13815                     ptr = &ptr->operator[](reference_token);
13816                     break;
13817                 }
13818 
13819                 case detail::value_t::array:
13820                 {
13821                     if (reference_token == "-")
13822                     {
13823                         // explicitly treat "-" as index beyond the end
13824                         ptr = &ptr->operator[](ptr->m_value.array->size());
13825                     }
13826                     else
13827                     {
13828                         // convert array index to number; unchecked access
13829                         ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
13830                     }
13831                     break;
13832                 }
13833 
13834                 case detail::value_t::null:
13835                 case detail::value_t::string:
13836                 case detail::value_t::boolean:
13837                 case detail::value_t::number_integer:
13838                 case detail::value_t::number_unsigned:
13839                 case detail::value_t::number_float:
13840                 case detail::value_t::binary:
13841                 case detail::value_t::discarded:
13842                 default:
13843                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
13844             }
13845         }
13846 
13847         return *ptr;
13848     }
13849 
13850     /*!
13851     @throw parse_error.106   if an array index begins with '0'
13852     @throw parse_error.109   if an array index was not a number
13853     @throw out_of_range.402  if the array index '-' is used
13854     @throw out_of_range.404  if the JSON pointer can not be resolved
13855     */
13856     template<typename BasicJsonType>
get_checked(BasicJsonType * ptr) const13857     BasicJsonType& get_checked(BasicJsonType* ptr) const
13858     {
13859         for (const auto& reference_token : reference_tokens)
13860         {
13861             switch (ptr->type())
13862             {
13863                 case detail::value_t::object:
13864                 {
13865                     // note: at performs range check
13866                     ptr = &ptr->at(reference_token);
13867                     break;
13868                 }
13869 
13870                 case detail::value_t::array:
13871                 {
13872                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
13873                     {
13874                         // "-" always fails the range check
13875                         JSON_THROW(detail::out_of_range::create(402, detail::concat(
13876                                 "array index '-' (", std::to_string(ptr->m_value.array->size()),
13877                                 ") is out of range"), ptr));
13878                     }
13879 
13880                     // note: at performs range check
13881                     ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
13882                     break;
13883                 }
13884 
13885                 case detail::value_t::null:
13886                 case detail::value_t::string:
13887                 case detail::value_t::boolean:
13888                 case detail::value_t::number_integer:
13889                 case detail::value_t::number_unsigned:
13890                 case detail::value_t::number_float:
13891                 case detail::value_t::binary:
13892                 case detail::value_t::discarded:
13893                 default:
13894                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
13895             }
13896         }
13897 
13898         return *ptr;
13899     }
13900 
13901     /*!
13902     @brief return a const reference to the pointed to value
13903 
13904     @param[in] ptr  a JSON value
13905 
13906     @return const reference to the JSON value pointed to by the JSON
13907     pointer
13908 
13909     @throw parse_error.106   if an array index begins with '0'
13910     @throw parse_error.109   if an array index was not a number
13911     @throw out_of_range.402  if the array index '-' is used
13912     @throw out_of_range.404  if the JSON pointer can not be resolved
13913     */
13914     template<typename BasicJsonType>
get_unchecked(const BasicJsonType * ptr) const13915     const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
13916     {
13917         for (const auto& reference_token : reference_tokens)
13918         {
13919             switch (ptr->type())
13920             {
13921                 case detail::value_t::object:
13922                 {
13923                     // use unchecked object access
13924                     ptr = &ptr->operator[](reference_token);
13925                     break;
13926                 }
13927 
13928                 case detail::value_t::array:
13929                 {
13930                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
13931                     {
13932                         // "-" cannot be used for const access
13933                         JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr));
13934                     }
13935 
13936                     // use unchecked array access
13937                     ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
13938                     break;
13939                 }
13940 
13941                 case detail::value_t::null:
13942                 case detail::value_t::string:
13943                 case detail::value_t::boolean:
13944                 case detail::value_t::number_integer:
13945                 case detail::value_t::number_unsigned:
13946                 case detail::value_t::number_float:
13947                 case detail::value_t::binary:
13948                 case detail::value_t::discarded:
13949                 default:
13950                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
13951             }
13952         }
13953 
13954         return *ptr;
13955     }
13956 
13957     /*!
13958     @throw parse_error.106   if an array index begins with '0'
13959     @throw parse_error.109   if an array index was not a number
13960     @throw out_of_range.402  if the array index '-' is used
13961     @throw out_of_range.404  if the JSON pointer can not be resolved
13962     */
13963     template<typename BasicJsonType>
get_checked(const BasicJsonType * ptr) const13964     const BasicJsonType& get_checked(const BasicJsonType* ptr) const
13965     {
13966         for (const auto& reference_token : reference_tokens)
13967         {
13968             switch (ptr->type())
13969             {
13970                 case detail::value_t::object:
13971                 {
13972                     // note: at performs range check
13973                     ptr = &ptr->at(reference_token);
13974                     break;
13975                 }
13976 
13977                 case detail::value_t::array:
13978                 {
13979                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
13980                     {
13981                         // "-" always fails the range check
13982                         JSON_THROW(detail::out_of_range::create(402, detail::concat(
13983                                 "array index '-' (", std::to_string(ptr->m_value.array->size()),
13984                                 ") is out of range"), ptr));
13985                     }
13986 
13987                     // note: at performs range check
13988                     ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
13989                     break;
13990                 }
13991 
13992                 case detail::value_t::null:
13993                 case detail::value_t::string:
13994                 case detail::value_t::boolean:
13995                 case detail::value_t::number_integer:
13996                 case detail::value_t::number_unsigned:
13997                 case detail::value_t::number_float:
13998                 case detail::value_t::binary:
13999                 case detail::value_t::discarded:
14000                 default:
14001                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14002             }
14003         }
14004 
14005         return *ptr;
14006     }
14007 
14008     /*!
14009     @throw parse_error.106   if an array index begins with '0'
14010     @throw parse_error.109   if an array index was not a number
14011     */
14012     template<typename BasicJsonType>
contains(const BasicJsonType * ptr) const14013     bool contains(const BasicJsonType* ptr) const
14014     {
14015         for (const auto& reference_token : reference_tokens)
14016         {
14017             switch (ptr->type())
14018             {
14019                 case detail::value_t::object:
14020                 {
14021                     if (!ptr->contains(reference_token))
14022                     {
14023                         // we did not find the key in the object
14024                         return false;
14025                     }
14026 
14027                     ptr = &ptr->operator[](reference_token);
14028                     break;
14029                 }
14030 
14031                 case detail::value_t::array:
14032                 {
14033                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14034                     {
14035                         // "-" always fails the range check
14036                         return false;
14037                     }
14038                     if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
14039                     {
14040                         // invalid char
14041                         return false;
14042                     }
14043                     if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
14044                     {
14045                         if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
14046                         {
14047                             // first char should be between '1' and '9'
14048                             return false;
14049                         }
14050                         for (std::size_t i = 1; i < reference_token.size(); i++)
14051                         {
14052                             if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
14053                             {
14054                                 // other char should be between '0' and '9'
14055                                 return false;
14056                             }
14057                         }
14058                     }
14059 
14060                     const auto idx = array_index<BasicJsonType>(reference_token);
14061                     if (idx >= ptr->size())
14062                     {
14063                         // index out of range
14064                         return false;
14065                     }
14066 
14067                     ptr = &ptr->operator[](idx);
14068                     break;
14069                 }
14070 
14071                 case detail::value_t::null:
14072                 case detail::value_t::string:
14073                 case detail::value_t::boolean:
14074                 case detail::value_t::number_integer:
14075                 case detail::value_t::number_unsigned:
14076                 case detail::value_t::number_float:
14077                 case detail::value_t::binary:
14078                 case detail::value_t::discarded:
14079                 default:
14080                 {
14081                     // we do not expect primitive values if there is still a
14082                     // reference token to process
14083                     return false;
14084                 }
14085             }
14086         }
14087 
14088         // no reference token left means we found a primitive value
14089         return true;
14090     }
14091 
14092     /*!
14093     @brief split the string input to reference tokens
14094 
14095     @note This function is only called by the json_pointer constructor.
14096           All exceptions below are documented there.
14097 
14098     @throw parse_error.107  if the pointer is not empty or begins with '/'
14099     @throw parse_error.108  if character '~' is not followed by '0' or '1'
14100     */
split(const string_t & reference_string)14101     static std::vector<string_t> split(const string_t& reference_string)
14102     {
14103         std::vector<string_t> result;
14104 
14105         // special case: empty reference string -> no reference tokens
14106         if (reference_string.empty())
14107         {
14108             return result;
14109         }
14110 
14111         // check if nonempty reference string begins with slash
14112         if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
14113         {
14114             JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
14115         }
14116 
14117         // extract the reference tokens:
14118         // - slash: position of the last read slash (or end of string)
14119         // - start: position after the previous slash
14120         for (
14121             // search for the first slash after the first character
14122             std::size_t slash = reference_string.find_first_of('/', 1),
14123             // set the beginning of the first reference token
14124             start = 1;
14125             // we can stop if start == 0 (if slash == string_t::npos)
14126             start != 0;
14127             // set the beginning of the next reference token
14128             // (will eventually be 0 if slash == string_t::npos)
14129             start = (slash == string_t::npos) ? 0 : slash + 1,
14130             // find next slash
14131             slash = reference_string.find_first_of('/', start))
14132         {
14133             // use the text between the beginning of the reference token
14134             // (start) and the last slash (slash).
14135             auto reference_token = reference_string.substr(start, slash - start);
14136 
14137             // check reference tokens are properly escaped
14138             for (std::size_t pos = reference_token.find_first_of('~');
14139                     pos != string_t::npos;
14140                     pos = reference_token.find_first_of('~', pos + 1))
14141             {
14142                 JSON_ASSERT(reference_token[pos] == '~');
14143 
14144                 // ~ must be followed by 0 or 1
14145                 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
14146                                          (reference_token[pos + 1] != '0' &&
14147                                           reference_token[pos + 1] != '1')))
14148                 {
14149                     JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
14150                 }
14151             }
14152 
14153             // finally, store the reference token
14154             detail::unescape(reference_token);
14155             result.push_back(reference_token);
14156         }
14157 
14158         return result;
14159     }
14160 
14161   private:
14162     /*!
14163     @param[in] reference_string  the reference string to the current value
14164     @param[in] value             the value to consider
14165     @param[in,out] result        the result object to insert values to
14166 
14167     @note Empty objects or arrays are flattened to `null`.
14168     */
14169     template<typename BasicJsonType>
flatten(const string_t & reference_string,const BasicJsonType & value,BasicJsonType & result)14170     static void flatten(const string_t& reference_string,
14171                         const BasicJsonType& value,
14172                         BasicJsonType& result)
14173     {
14174         switch (value.type())
14175         {
14176             case detail::value_t::array:
14177             {
14178                 if (value.m_value.array->empty())
14179                 {
14180                     // flatten empty array as null
14181                     result[reference_string] = nullptr;
14182                 }
14183                 else
14184                 {
14185                     // iterate array and use index as reference string
14186                     for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
14187                     {
14188                         flatten(detail::concat(reference_string, '/', std::to_string(i)),
14189                                 value.m_value.array->operator[](i), result);
14190                     }
14191                 }
14192                 break;
14193             }
14194 
14195             case detail::value_t::object:
14196             {
14197                 if (value.m_value.object->empty())
14198                 {
14199                     // flatten empty object as null
14200                     result[reference_string] = nullptr;
14201                 }
14202                 else
14203                 {
14204                     // iterate object and use keys as reference string
14205                     for (const auto& element : *value.m_value.object)
14206                     {
14207                         flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
14208                     }
14209                 }
14210                 break;
14211             }
14212 
14213             case detail::value_t::null:
14214             case detail::value_t::string:
14215             case detail::value_t::boolean:
14216             case detail::value_t::number_integer:
14217             case detail::value_t::number_unsigned:
14218             case detail::value_t::number_float:
14219             case detail::value_t::binary:
14220             case detail::value_t::discarded:
14221             default:
14222             {
14223                 // add primitive value with its reference string
14224                 result[reference_string] = value;
14225                 break;
14226             }
14227         }
14228     }
14229 
14230     /*!
14231     @param[in] value  flattened JSON
14232 
14233     @return unflattened JSON
14234 
14235     @throw parse_error.109 if array index is not a number
14236     @throw type_error.314  if value is not an object
14237     @throw type_error.315  if object values are not primitive
14238     @throw type_error.313  if value cannot be unflattened
14239     */
14240     template<typename BasicJsonType>
14241     static BasicJsonType
unflatten(const BasicJsonType & value)14242     unflatten(const BasicJsonType& value)
14243     {
14244         if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
14245         {
14246             JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
14247         }
14248 
14249         BasicJsonType result;
14250 
14251         // iterate the JSON object values
14252         for (const auto& element : *value.m_value.object)
14253         {
14254             if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
14255             {
14256                 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
14257             }
14258 
14259             // assign value to reference pointed to by JSON pointer; Note that if
14260             // the JSON pointer is "" (i.e., points to the whole value), function
14261             // get_and_create returns a reference to result itself. An assignment
14262             // will then create a primitive value.
14263             json_pointer(element.first).get_and_create(result) = element.second;
14264         }
14265 
14266         return result;
14267     }
14268 
14269     // can't use conversion operator because of ambiguity
convert() const14270     json_pointer<string_t> convert() const&
14271     {
14272         json_pointer<string_t> result;
14273         result.reference_tokens = reference_tokens;
14274         return result;
14275     }
14276 
convert()14277     json_pointer<string_t> convert()&&
14278     {
14279         json_pointer<string_t> result;
14280         result.reference_tokens = std::move(reference_tokens);
14281         return result;
14282     }
14283 
14284     /*!
14285     @brief compares two JSON pointers for equality
14286 
14287     @param[in] lhs  JSON pointer to compare
14288     @param[in] rhs  JSON pointer to compare
14289     @return whether @a lhs is equal to @a rhs
14290 
14291     @complexity Linear in the length of the JSON pointer
14292 
14293     @exceptionsafety No-throw guarantee: this function never throws exceptions.
14294     */
14295     template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14296     // NOLINTNEXTLINE(readability-redundant-declaration)
14297     friend bool operator==(json_pointer<RefStringTypeLhs> const& lhs,
14298                            json_pointer<RefStringTypeRhs> const& rhs) noexcept;
14299 
14300     /*!
14301     @brief compares two JSON pointers for inequality
14302 
14303     @param[in] lhs  JSON pointer to compare
14304     @param[in] rhs  JSON pointer to compare
14305     @return whether @a lhs is not equal @a rhs
14306 
14307     @complexity Linear in the length of the JSON pointer
14308 
14309     @exceptionsafety No-throw guarantee: this function never throws exceptions.
14310     */
14311     template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14312     // NOLINTNEXTLINE(readability-redundant-declaration)
14313     friend bool operator!=(json_pointer<RefStringTypeLhs> const& lhs,
14314                            json_pointer<RefStringTypeRhs> const& rhs) noexcept;
14315 
14316     /// the reference tokens
14317     std::vector<string_t> reference_tokens;
14318 };
14319 
14320 // functions cannot be defined inside class due to ODR violations
14321 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
operator ==(json_pointer<RefStringTypeLhs> const & lhs,json_pointer<RefStringTypeRhs> const & rhs)14322 inline bool operator==(json_pointer<RefStringTypeLhs> const& lhs,
14323                        json_pointer<RefStringTypeRhs> const& rhs) noexcept
14324 {
14325     return lhs.reference_tokens == rhs.reference_tokens;
14326 }
14327 
14328 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
operator !=(json_pointer<RefStringTypeLhs> const & lhs,json_pointer<RefStringTypeRhs> const & rhs)14329 inline bool operator!=(json_pointer<RefStringTypeLhs> const& lhs,
14330                        json_pointer<RefStringTypeRhs> const& rhs) noexcept
14331 {
14332     return !(lhs == rhs);
14333 }
14334 }  // namespace nlohmann
14335 
14336 // #include <nlohmann/detail/json_ref.hpp>
14337 //     __ _____ _____ _____
14338 //  __|  |   __|     |   | |  JSON for Modern C++
14339 // |  |  |__   |  |  | | | |  version 3.10.5
14340 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
14341 //
14342 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
14343 // SPDX-License-Identifier: MIT
14344 
14345 
14346 
14347 #include <initializer_list>
14348 #include <utility>
14349 
14350 // #include <nlohmann/detail/meta/type_traits.hpp>
14351 
14352 
14353 namespace nlohmann
14354 {
14355 namespace detail
14356 {
14357 template<typename BasicJsonType>
14358 class json_ref
14359 {
14360   public:
14361     using value_type = BasicJsonType;
14362 
json_ref(value_type && value)14363     json_ref(value_type&& value)
14364         : owned_value(std::move(value))
14365     {}
14366 
json_ref(const value_type & value)14367     json_ref(const value_type& value)
14368         : value_ref(&value)
14369     {}
14370 
json_ref(std::initializer_list<json_ref> init)14371     json_ref(std::initializer_list<json_ref> init)
14372         : owned_value(init)
14373     {}
14374 
14375     template <
14376         class... Args,
14377         enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
json_ref(Args &&...args)14378     json_ref(Args && ... args)
14379         : owned_value(std::forward<Args>(args)...)
14380     {}
14381 
14382     // class should be movable only
14383     json_ref(json_ref&&) noexcept = default;
14384     json_ref(const json_ref&) = delete;
14385     json_ref& operator=(const json_ref&) = delete;
14386     json_ref& operator=(json_ref&&) = delete;
14387     ~json_ref() = default;
14388 
moved_or_copied() const14389     value_type moved_or_copied() const
14390     {
14391         if (value_ref == nullptr)
14392         {
14393             return std::move(owned_value);
14394         }
14395         return *value_ref;
14396     }
14397 
operator *() const14398     value_type const& operator*() const
14399     {
14400         return value_ref ? *value_ref : owned_value;
14401     }
14402 
operator ->() const14403     value_type const* operator->() const
14404     {
14405         return &** this;
14406     }
14407 
14408   private:
14409     mutable value_type owned_value = nullptr;
14410     value_type const* value_ref = nullptr;
14411 };
14412 }  // namespace detail
14413 }  // namespace nlohmann
14414 
14415 // #include <nlohmann/detail/macro_scope.hpp>
14416 
14417 // #include <nlohmann/detail/string_concat.hpp>
14418 
14419 // #include <nlohmann/detail/string_escape.hpp>
14420 
14421 // #include <nlohmann/detail/meta/cpp_future.hpp>
14422 
14423 // #include <nlohmann/detail/meta/type_traits.hpp>
14424 
14425 // #include <nlohmann/detail/output/binary_writer.hpp>
14426 //     __ _____ _____ _____
14427 //  __|  |   __|     |   | |  JSON for Modern C++
14428 // |  |  |__   |  |  | | | |  version 3.10.5
14429 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
14430 //
14431 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
14432 // SPDX-License-Identifier: MIT
14433 
14434 
14435 
14436 #include <algorithm> // reverse
14437 #include <array> // array
14438 #include <map> // map
14439 #include <cmath> // isnan, isinf
14440 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
14441 #include <cstring> // memcpy
14442 #include <limits> // numeric_limits
14443 #include <string> // string
14444 #include <utility> // move
14445 #include <vector> // vector
14446 
14447 // #include <nlohmann/detail/input/binary_reader.hpp>
14448 
14449 // #include <nlohmann/detail/macro_scope.hpp>
14450 
14451 // #include <nlohmann/detail/output/output_adapters.hpp>
14452 //     __ _____ _____ _____
14453 //  __|  |   __|     |   | |  JSON for Modern C++
14454 // |  |  |__   |  |  | | | |  version 3.10.5
14455 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
14456 //
14457 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
14458 // SPDX-License-Identifier: MIT
14459 
14460 
14461 
14462 #include <algorithm> // copy
14463 #include <cstddef> // size_t
14464 #include <iterator> // back_inserter
14465 #include <memory> // shared_ptr, make_shared
14466 #include <string> // basic_string
14467 #include <vector> // vector
14468 
14469 #ifndef JSON_NO_IO
14470     #include <ios>      // streamsize
14471     #include <ostream>  // basic_ostream
14472 #endif  // JSON_NO_IO
14473 
14474 // #include <nlohmann/detail/macro_scope.hpp>
14475 
14476 
14477 namespace nlohmann
14478 {
14479 namespace detail
14480 {
14481 /// abstract output adapter interface
14482 template<typename CharType> struct output_adapter_protocol
14483 {
14484     virtual void write_character(CharType c) = 0;
14485     virtual void write_characters(const CharType* s, std::size_t length) = 0;
14486     virtual ~output_adapter_protocol() = default;
14487 
14488     output_adapter_protocol() = default;
14489     output_adapter_protocol(const output_adapter_protocol&) = default;
14490     output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
14491     output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
14492     output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
14493 };
14494 
14495 /// a type to simplify interfaces
14496 template<typename CharType>
14497 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
14498 
14499 /// output adapter for byte vectors
14500 template<typename CharType, typename AllocatorType = std::allocator<CharType>>
14501 class output_vector_adapter : public output_adapter_protocol<CharType>
14502 {
14503   public:
output_vector_adapter(std::vector<CharType,AllocatorType> & vec)14504     explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
14505         : v(vec)
14506     {}
14507 
write_character(CharType c)14508     void write_character(CharType c) override
14509     {
14510         v.push_back(c);
14511     }
14512 
14513     JSON_HEDLEY_NON_NULL(2)
write_characters(const CharType * s,std::size_t length)14514     void write_characters(const CharType* s, std::size_t length) override
14515     {
14516         v.insert(v.end(), s, s + length);
14517     }
14518 
14519   private:
14520     std::vector<CharType, AllocatorType>& v;
14521 };
14522 
14523 #ifndef JSON_NO_IO
14524 /// output adapter for output streams
14525 template<typename CharType>
14526 class output_stream_adapter : public output_adapter_protocol<CharType>
14527 {
14528   public:
output_stream_adapter(std::basic_ostream<CharType> & s)14529     explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
14530         : stream(s)
14531     {}
14532 
write_character(CharType c)14533     void write_character(CharType c) override
14534     {
14535         stream.put(c);
14536     }
14537 
14538     JSON_HEDLEY_NON_NULL(2)
write_characters(const CharType * s,std::size_t length)14539     void write_characters(const CharType* s, std::size_t length) override
14540     {
14541         stream.write(s, static_cast<std::streamsize>(length));
14542     }
14543 
14544   private:
14545     std::basic_ostream<CharType>& stream;
14546 };
14547 #endif  // JSON_NO_IO
14548 
14549 /// output adapter for basic_string
14550 template<typename CharType, typename StringType = std::basic_string<CharType>>
14551 class output_string_adapter : public output_adapter_protocol<CharType>
14552 {
14553   public:
output_string_adapter(StringType & s)14554     explicit output_string_adapter(StringType& s) noexcept
14555         : str(s)
14556     {}
14557 
write_character(CharType c)14558     void write_character(CharType c) override
14559     {
14560         str.push_back(c);
14561     }
14562 
14563     JSON_HEDLEY_NON_NULL(2)
write_characters(const CharType * s,std::size_t length)14564     void write_characters(const CharType* s, std::size_t length) override
14565     {
14566         str.append(s, length);
14567     }
14568 
14569   private:
14570     StringType& str;
14571 };
14572 
14573 template<typename CharType, typename StringType = std::basic_string<CharType>>
14574 class output_adapter
14575 {
14576   public:
14577     template<typename AllocatorType = std::allocator<CharType>>
output_adapter(std::vector<CharType,AllocatorType> & vec)14578     output_adapter(std::vector<CharType, AllocatorType>& vec)
14579         : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
14580 
14581 #ifndef JSON_NO_IO
output_adapter(std::basic_ostream<CharType> & s)14582     output_adapter(std::basic_ostream<CharType>& s)
14583         : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
14584 #endif  // JSON_NO_IO
14585 
output_adapter(StringType & s)14586     output_adapter(StringType& s)
14587         : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
14588 
operator output_adapter_t<CharType>()14589     operator output_adapter_t<CharType>()
14590     {
14591         return oa;
14592     }
14593 
14594   private:
14595     output_adapter_t<CharType> oa = nullptr;
14596 };
14597 }  // namespace detail
14598 }  // namespace nlohmann
14599 
14600 // #include <nlohmann/detail/string_concat.hpp>
14601 
14602 
14603 namespace nlohmann
14604 {
14605 namespace detail
14606 {
14607 ///////////////////
14608 // binary writer //
14609 ///////////////////
14610 
14611 /*!
14612 @brief serialization to CBOR and MessagePack values
14613 */
14614 template<typename BasicJsonType, typename CharType>
14615 class binary_writer
14616 {
14617     using string_t = typename BasicJsonType::string_t;
14618     using binary_t = typename BasicJsonType::binary_t;
14619     using number_float_t = typename BasicJsonType::number_float_t;
14620 
14621   public:
14622     /*!
14623     @brief create a binary writer
14624 
14625     @param[in] adapter  output adapter to write to
14626     */
binary_writer(output_adapter_t<CharType> adapter)14627     explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
14628     {
14629         JSON_ASSERT(oa);
14630     }
14631 
14632     /*!
14633     @param[in] j  JSON value to serialize
14634     @pre       j.type() == value_t::object
14635     */
write_bson(const BasicJsonType & j)14636     void write_bson(const BasicJsonType& j)
14637     {
14638         switch (j.type())
14639         {
14640             case value_t::object:
14641             {
14642                 write_bson_object(*j.m_value.object);
14643                 break;
14644             }
14645 
14646             case value_t::null:
14647             case value_t::array:
14648             case value_t::string:
14649             case value_t::boolean:
14650             case value_t::number_integer:
14651             case value_t::number_unsigned:
14652             case value_t::number_float:
14653             case value_t::binary:
14654             case value_t::discarded:
14655             default:
14656             {
14657                 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
14658             }
14659         }
14660     }
14661 
14662     /*!
14663     @param[in] j  JSON value to serialize
14664     */
write_cbor(const BasicJsonType & j)14665     void write_cbor(const BasicJsonType& j)
14666     {
14667         switch (j.type())
14668         {
14669             case value_t::null:
14670             {
14671                 oa->write_character(to_char_type(0xF6));
14672                 break;
14673             }
14674 
14675             case value_t::boolean:
14676             {
14677                 oa->write_character(j.m_value.boolean
14678                                     ? to_char_type(0xF5)
14679                                     : to_char_type(0xF4));
14680                 break;
14681             }
14682 
14683             case value_t::number_integer:
14684             {
14685                 if (j.m_value.number_integer >= 0)
14686                 {
14687                     // CBOR does not differentiate between positive signed
14688                     // integers and unsigned integers. Therefore, we used the
14689                     // code from the value_t::number_unsigned case here.
14690                     if (j.m_value.number_integer <= 0x17)
14691                     {
14692                         write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
14693                     }
14694                     else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
14695                     {
14696                         oa->write_character(to_char_type(0x18));
14697                         write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
14698                     }
14699                     else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
14700                     {
14701                         oa->write_character(to_char_type(0x19));
14702                         write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
14703                     }
14704                     else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
14705                     {
14706                         oa->write_character(to_char_type(0x1A));
14707                         write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
14708                     }
14709                     else
14710                     {
14711                         oa->write_character(to_char_type(0x1B));
14712                         write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
14713                     }
14714                 }
14715                 else
14716                 {
14717                     // The conversions below encode the sign in the first
14718                     // byte, and the value is converted to a positive number.
14719                     const auto positive_number = -1 - j.m_value.number_integer;
14720                     if (j.m_value.number_integer >= -24)
14721                     {
14722                         write_number(static_cast<std::uint8_t>(0x20 + positive_number));
14723                     }
14724                     else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
14725                     {
14726                         oa->write_character(to_char_type(0x38));
14727                         write_number(static_cast<std::uint8_t>(positive_number));
14728                     }
14729                     else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
14730                     {
14731                         oa->write_character(to_char_type(0x39));
14732                         write_number(static_cast<std::uint16_t>(positive_number));
14733                     }
14734                     else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
14735                     {
14736                         oa->write_character(to_char_type(0x3A));
14737                         write_number(static_cast<std::uint32_t>(positive_number));
14738                     }
14739                     else
14740                     {
14741                         oa->write_character(to_char_type(0x3B));
14742                         write_number(static_cast<std::uint64_t>(positive_number));
14743                     }
14744                 }
14745                 break;
14746             }
14747 
14748             case value_t::number_unsigned:
14749             {
14750                 if (j.m_value.number_unsigned <= 0x17)
14751                 {
14752                     write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
14753                 }
14754                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
14755                 {
14756                     oa->write_character(to_char_type(0x18));
14757                     write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
14758                 }
14759                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
14760                 {
14761                     oa->write_character(to_char_type(0x19));
14762                     write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
14763                 }
14764                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
14765                 {
14766                     oa->write_character(to_char_type(0x1A));
14767                     write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
14768                 }
14769                 else
14770                 {
14771                     oa->write_character(to_char_type(0x1B));
14772                     write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
14773                 }
14774                 break;
14775             }
14776 
14777             case value_t::number_float:
14778             {
14779                 if (std::isnan(j.m_value.number_float))
14780                 {
14781                     // NaN is 0xf97e00 in CBOR
14782                     oa->write_character(to_char_type(0xF9));
14783                     oa->write_character(to_char_type(0x7E));
14784                     oa->write_character(to_char_type(0x00));
14785                 }
14786                 else if (std::isinf(j.m_value.number_float))
14787                 {
14788                     // Infinity is 0xf97c00, -Infinity is 0xf9fc00
14789                     oa->write_character(to_char_type(0xf9));
14790                     oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
14791                     oa->write_character(to_char_type(0x00));
14792                 }
14793                 else
14794                 {
14795                     write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
14796                 }
14797                 break;
14798             }
14799 
14800             case value_t::string:
14801             {
14802                 // step 1: write control byte and the string length
14803                 const auto N = j.m_value.string->size();
14804                 if (N <= 0x17)
14805                 {
14806                     write_number(static_cast<std::uint8_t>(0x60 + N));
14807                 }
14808                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
14809                 {
14810                     oa->write_character(to_char_type(0x78));
14811                     write_number(static_cast<std::uint8_t>(N));
14812                 }
14813                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
14814                 {
14815                     oa->write_character(to_char_type(0x79));
14816                     write_number(static_cast<std::uint16_t>(N));
14817                 }
14818                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
14819                 {
14820                     oa->write_character(to_char_type(0x7A));
14821                     write_number(static_cast<std::uint32_t>(N));
14822                 }
14823                 // LCOV_EXCL_START
14824                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
14825                 {
14826                     oa->write_character(to_char_type(0x7B));
14827                     write_number(static_cast<std::uint64_t>(N));
14828                 }
14829                 // LCOV_EXCL_STOP
14830 
14831                 // step 2: write the string
14832                 oa->write_characters(
14833                     reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
14834                     j.m_value.string->size());
14835                 break;
14836             }
14837 
14838             case value_t::array:
14839             {
14840                 // step 1: write control byte and the array size
14841                 const auto N = j.m_value.array->size();
14842                 if (N <= 0x17)
14843                 {
14844                     write_number(static_cast<std::uint8_t>(0x80 + N));
14845                 }
14846                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
14847                 {
14848                     oa->write_character(to_char_type(0x98));
14849                     write_number(static_cast<std::uint8_t>(N));
14850                 }
14851                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
14852                 {
14853                     oa->write_character(to_char_type(0x99));
14854                     write_number(static_cast<std::uint16_t>(N));
14855                 }
14856                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
14857                 {
14858                     oa->write_character(to_char_type(0x9A));
14859                     write_number(static_cast<std::uint32_t>(N));
14860                 }
14861                 // LCOV_EXCL_START
14862                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
14863                 {
14864                     oa->write_character(to_char_type(0x9B));
14865                     write_number(static_cast<std::uint64_t>(N));
14866                 }
14867                 // LCOV_EXCL_STOP
14868 
14869                 // step 2: write each element
14870                 for (const auto& el : *j.m_value.array)
14871                 {
14872                     write_cbor(el);
14873                 }
14874                 break;
14875             }
14876 
14877             case value_t::binary:
14878             {
14879                 if (j.m_value.binary->has_subtype())
14880                 {
14881                     if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
14882                     {
14883                         write_number(static_cast<std::uint8_t>(0xd8));
14884                         write_number(static_cast<std::uint8_t>(j.m_value.binary->subtype()));
14885                     }
14886                     else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
14887                     {
14888                         write_number(static_cast<std::uint8_t>(0xd9));
14889                         write_number(static_cast<std::uint16_t>(j.m_value.binary->subtype()));
14890                     }
14891                     else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
14892                     {
14893                         write_number(static_cast<std::uint8_t>(0xda));
14894                         write_number(static_cast<std::uint32_t>(j.m_value.binary->subtype()));
14895                     }
14896                     else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
14897                     {
14898                         write_number(static_cast<std::uint8_t>(0xdb));
14899                         write_number(static_cast<std::uint64_t>(j.m_value.binary->subtype()));
14900                     }
14901                 }
14902 
14903                 // step 1: write control byte and the binary array size
14904                 const auto N = j.m_value.binary->size();
14905                 if (N <= 0x17)
14906                 {
14907                     write_number(static_cast<std::uint8_t>(0x40 + N));
14908                 }
14909                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
14910                 {
14911                     oa->write_character(to_char_type(0x58));
14912                     write_number(static_cast<std::uint8_t>(N));
14913                 }
14914                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
14915                 {
14916                     oa->write_character(to_char_type(0x59));
14917                     write_number(static_cast<std::uint16_t>(N));
14918                 }
14919                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
14920                 {
14921                     oa->write_character(to_char_type(0x5A));
14922                     write_number(static_cast<std::uint32_t>(N));
14923                 }
14924                 // LCOV_EXCL_START
14925                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
14926                 {
14927                     oa->write_character(to_char_type(0x5B));
14928                     write_number(static_cast<std::uint64_t>(N));
14929                 }
14930                 // LCOV_EXCL_STOP
14931 
14932                 // step 2: write each element
14933                 oa->write_characters(
14934                     reinterpret_cast<const CharType*>(j.m_value.binary->data()),
14935                     N);
14936 
14937                 break;
14938             }
14939 
14940             case value_t::object:
14941             {
14942                 // step 1: write control byte and the object size
14943                 const auto N = j.m_value.object->size();
14944                 if (N <= 0x17)
14945                 {
14946                     write_number(static_cast<std::uint8_t>(0xA0 + N));
14947                 }
14948                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
14949                 {
14950                     oa->write_character(to_char_type(0xB8));
14951                     write_number(static_cast<std::uint8_t>(N));
14952                 }
14953                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
14954                 {
14955                     oa->write_character(to_char_type(0xB9));
14956                     write_number(static_cast<std::uint16_t>(N));
14957                 }
14958                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
14959                 {
14960                     oa->write_character(to_char_type(0xBA));
14961                     write_number(static_cast<std::uint32_t>(N));
14962                 }
14963                 // LCOV_EXCL_START
14964                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
14965                 {
14966                     oa->write_character(to_char_type(0xBB));
14967                     write_number(static_cast<std::uint64_t>(N));
14968                 }
14969                 // LCOV_EXCL_STOP
14970 
14971                 // step 2: write each element
14972                 for (const auto& el : *j.m_value.object)
14973                 {
14974                     write_cbor(el.first);
14975                     write_cbor(el.second);
14976                 }
14977                 break;
14978             }
14979 
14980             case value_t::discarded:
14981             default:
14982                 break;
14983         }
14984     }
14985 
14986     /*!
14987     @param[in] j  JSON value to serialize
14988     */
write_msgpack(const BasicJsonType & j)14989     void write_msgpack(const BasicJsonType& j)
14990     {
14991         switch (j.type())
14992         {
14993             case value_t::null: // nil
14994             {
14995                 oa->write_character(to_char_type(0xC0));
14996                 break;
14997             }
14998 
14999             case value_t::boolean: // true and false
15000             {
15001                 oa->write_character(j.m_value.boolean
15002                                     ? to_char_type(0xC3)
15003                                     : to_char_type(0xC2));
15004                 break;
15005             }
15006 
15007             case value_t::number_integer:
15008             {
15009                 if (j.m_value.number_integer >= 0)
15010                 {
15011                     // MessagePack does not differentiate between positive
15012                     // signed integers and unsigned integers. Therefore, we used
15013                     // the code from the value_t::number_unsigned case here.
15014                     if (j.m_value.number_unsigned < 128)
15015                     {
15016                         // positive fixnum
15017                         write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
15018                     }
15019                     else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15020                     {
15021                         // uint 8
15022                         oa->write_character(to_char_type(0xCC));
15023                         write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
15024                     }
15025                     else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15026                     {
15027                         // uint 16
15028                         oa->write_character(to_char_type(0xCD));
15029                         write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
15030                     }
15031                     else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15032                     {
15033                         // uint 32
15034                         oa->write_character(to_char_type(0xCE));
15035                         write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
15036                     }
15037                     else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15038                     {
15039                         // uint 64
15040                         oa->write_character(to_char_type(0xCF));
15041                         write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
15042                     }
15043                 }
15044                 else
15045                 {
15046                     if (j.m_value.number_integer >= -32)
15047                     {
15048                         // negative fixnum
15049                         write_number(static_cast<std::int8_t>(j.m_value.number_integer));
15050                     }
15051                     else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
15052                              j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
15053                     {
15054                         // int 8
15055                         oa->write_character(to_char_type(0xD0));
15056                         write_number(static_cast<std::int8_t>(j.m_value.number_integer));
15057                     }
15058                     else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
15059                              j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
15060                     {
15061                         // int 16
15062                         oa->write_character(to_char_type(0xD1));
15063                         write_number(static_cast<std::int16_t>(j.m_value.number_integer));
15064                     }
15065                     else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
15066                              j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
15067                     {
15068                         // int 32
15069                         oa->write_character(to_char_type(0xD2));
15070                         write_number(static_cast<std::int32_t>(j.m_value.number_integer));
15071                     }
15072                     else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
15073                              j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
15074                     {
15075                         // int 64
15076                         oa->write_character(to_char_type(0xD3));
15077                         write_number(static_cast<std::int64_t>(j.m_value.number_integer));
15078                     }
15079                 }
15080                 break;
15081             }
15082 
15083             case value_t::number_unsigned:
15084             {
15085                 if (j.m_value.number_unsigned < 128)
15086                 {
15087                     // positive fixnum
15088                     write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
15089                 }
15090                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15091                 {
15092                     // uint 8
15093                     oa->write_character(to_char_type(0xCC));
15094                     write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
15095                 }
15096                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15097                 {
15098                     // uint 16
15099                     oa->write_character(to_char_type(0xCD));
15100                     write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
15101                 }
15102                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15103                 {
15104                     // uint 32
15105                     oa->write_character(to_char_type(0xCE));
15106                     write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
15107                 }
15108                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15109                 {
15110                     // uint 64
15111                     oa->write_character(to_char_type(0xCF));
15112                     write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
15113                 }
15114                 break;
15115             }
15116 
15117             case value_t::number_float:
15118             {
15119                 write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
15120                 break;
15121             }
15122 
15123             case value_t::string:
15124             {
15125                 // step 1: write control byte and the string length
15126                 const auto N = j.m_value.string->size();
15127                 if (N <= 31)
15128                 {
15129                     // fixstr
15130                     write_number(static_cast<std::uint8_t>(0xA0 | N));
15131                 }
15132                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15133                 {
15134                     // str 8
15135                     oa->write_character(to_char_type(0xD9));
15136                     write_number(static_cast<std::uint8_t>(N));
15137                 }
15138                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15139                 {
15140                     // str 16
15141                     oa->write_character(to_char_type(0xDA));
15142                     write_number(static_cast<std::uint16_t>(N));
15143                 }
15144                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15145                 {
15146                     // str 32
15147                     oa->write_character(to_char_type(0xDB));
15148                     write_number(static_cast<std::uint32_t>(N));
15149                 }
15150 
15151                 // step 2: write the string
15152                 oa->write_characters(
15153                     reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
15154                     j.m_value.string->size());
15155                 break;
15156             }
15157 
15158             case value_t::array:
15159             {
15160                 // step 1: write control byte and the array size
15161                 const auto N = j.m_value.array->size();
15162                 if (N <= 15)
15163                 {
15164                     // fixarray
15165                     write_number(static_cast<std::uint8_t>(0x90 | N));
15166                 }
15167                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15168                 {
15169                     // array 16
15170                     oa->write_character(to_char_type(0xDC));
15171                     write_number(static_cast<std::uint16_t>(N));
15172                 }
15173                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15174                 {
15175                     // array 32
15176                     oa->write_character(to_char_type(0xDD));
15177                     write_number(static_cast<std::uint32_t>(N));
15178                 }
15179 
15180                 // step 2: write each element
15181                 for (const auto& el : *j.m_value.array)
15182                 {
15183                     write_msgpack(el);
15184                 }
15185                 break;
15186             }
15187 
15188             case value_t::binary:
15189             {
15190                 // step 0: determine if the binary type has a set subtype to
15191                 // determine whether or not to use the ext or fixext types
15192                 const bool use_ext = j.m_value.binary->has_subtype();
15193 
15194                 // step 1: write control byte and the byte string length
15195                 const auto N = j.m_value.binary->size();
15196                 if (N <= (std::numeric_limits<std::uint8_t>::max)())
15197                 {
15198                     std::uint8_t output_type{};
15199                     bool fixed = true;
15200                     if (use_ext)
15201                     {
15202                         switch (N)
15203                         {
15204                             case 1:
15205                                 output_type = 0xD4; // fixext 1
15206                                 break;
15207                             case 2:
15208                                 output_type = 0xD5; // fixext 2
15209                                 break;
15210                             case 4:
15211                                 output_type = 0xD6; // fixext 4
15212                                 break;
15213                             case 8:
15214                                 output_type = 0xD7; // fixext 8
15215                                 break;
15216                             case 16:
15217                                 output_type = 0xD8; // fixext 16
15218                                 break;
15219                             default:
15220                                 output_type = 0xC7; // ext 8
15221                                 fixed = false;
15222                                 break;
15223                         }
15224 
15225                     }
15226                     else
15227                     {
15228                         output_type = 0xC4; // bin 8
15229                         fixed = false;
15230                     }
15231 
15232                     oa->write_character(to_char_type(output_type));
15233                     if (!fixed)
15234                     {
15235                         write_number(static_cast<std::uint8_t>(N));
15236                     }
15237                 }
15238                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15239                 {
15240                     std::uint8_t output_type = use_ext
15241                                                ? 0xC8 // ext 16
15242                                                : 0xC5; // bin 16
15243 
15244                     oa->write_character(to_char_type(output_type));
15245                     write_number(static_cast<std::uint16_t>(N));
15246                 }
15247                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15248                 {
15249                     std::uint8_t output_type = use_ext
15250                                                ? 0xC9 // ext 32
15251                                                : 0xC6; // bin 32
15252 
15253                     oa->write_character(to_char_type(output_type));
15254                     write_number(static_cast<std::uint32_t>(N));
15255                 }
15256 
15257                 // step 1.5: if this is an ext type, write the subtype
15258                 if (use_ext)
15259                 {
15260                     write_number(static_cast<std::int8_t>(j.m_value.binary->subtype()));
15261                 }
15262 
15263                 // step 2: write the byte string
15264                 oa->write_characters(
15265                     reinterpret_cast<const CharType*>(j.m_value.binary->data()),
15266                     N);
15267 
15268                 break;
15269             }
15270 
15271             case value_t::object:
15272             {
15273                 // step 1: write control byte and the object size
15274                 const auto N = j.m_value.object->size();
15275                 if (N <= 15)
15276                 {
15277                     // fixmap
15278                     write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
15279                 }
15280                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15281                 {
15282                     // map 16
15283                     oa->write_character(to_char_type(0xDE));
15284                     write_number(static_cast<std::uint16_t>(N));
15285                 }
15286                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15287                 {
15288                     // map 32
15289                     oa->write_character(to_char_type(0xDF));
15290                     write_number(static_cast<std::uint32_t>(N));
15291                 }
15292 
15293                 // step 2: write each element
15294                 for (const auto& el : *j.m_value.object)
15295                 {
15296                     write_msgpack(el.first);
15297                     write_msgpack(el.second);
15298                 }
15299                 break;
15300             }
15301 
15302             case value_t::discarded:
15303             default:
15304                 break;
15305         }
15306     }
15307 
15308     /*!
15309     @param[in] j  JSON value to serialize
15310     @param[in] use_count   whether to use '#' prefixes (optimized format)
15311     @param[in] use_type    whether to use '$' prefixes (optimized format)
15312     @param[in] add_prefix  whether prefixes need to be used for this value
15313     @param[in] use_bjdata  whether write in BJData format, default is false
15314     */
write_ubjson(const BasicJsonType & j,const bool use_count,const bool use_type,const bool add_prefix=true,const bool use_bjdata=false)15315     void write_ubjson(const BasicJsonType& j, const bool use_count,
15316                       const bool use_type, const bool add_prefix = true,
15317                       const bool use_bjdata = false)
15318     {
15319         switch (j.type())
15320         {
15321             case value_t::null:
15322             {
15323                 if (add_prefix)
15324                 {
15325                     oa->write_character(to_char_type('Z'));
15326                 }
15327                 break;
15328             }
15329 
15330             case value_t::boolean:
15331             {
15332                 if (add_prefix)
15333                 {
15334                     oa->write_character(j.m_value.boolean
15335                                         ? to_char_type('T')
15336                                         : to_char_type('F'));
15337                 }
15338                 break;
15339             }
15340 
15341             case value_t::number_integer:
15342             {
15343                 write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix, use_bjdata);
15344                 break;
15345             }
15346 
15347             case value_t::number_unsigned:
15348             {
15349                 write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix, use_bjdata);
15350                 break;
15351             }
15352 
15353             case value_t::number_float:
15354             {
15355                 write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix, use_bjdata);
15356                 break;
15357             }
15358 
15359             case value_t::string:
15360             {
15361                 if (add_prefix)
15362                 {
15363                     oa->write_character(to_char_type('S'));
15364                 }
15365                 write_number_with_ubjson_prefix(j.m_value.string->size(), true, use_bjdata);
15366                 oa->write_characters(
15367                     reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
15368                     j.m_value.string->size());
15369                 break;
15370             }
15371 
15372             case value_t::array:
15373             {
15374                 if (add_prefix)
15375                 {
15376                     oa->write_character(to_char_type('['));
15377                 }
15378 
15379                 bool prefix_required = true;
15380                 if (use_type && !j.m_value.array->empty())
15381                 {
15382                     JSON_ASSERT(use_count);
15383                     const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15384                     const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
15385                                                          [this, first_prefix, use_bjdata](const BasicJsonType & v)
15386                     {
15387                         return ubjson_prefix(v, use_bjdata) == first_prefix;
15388                     });
15389 
15390                     std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15391 
15392                     if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15393                     {
15394                         prefix_required = false;
15395                         oa->write_character(to_char_type('$'));
15396                         oa->write_character(first_prefix);
15397                     }
15398                 }
15399 
15400                 if (use_count)
15401                 {
15402                     oa->write_character(to_char_type('#'));
15403                     write_number_with_ubjson_prefix(j.m_value.array->size(), true, use_bjdata);
15404                 }
15405 
15406                 for (const auto& el : *j.m_value.array)
15407                 {
15408                     write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
15409                 }
15410 
15411                 if (!use_count)
15412                 {
15413                     oa->write_character(to_char_type(']'));
15414                 }
15415 
15416                 break;
15417             }
15418 
15419             case value_t::binary:
15420             {
15421                 if (add_prefix)
15422                 {
15423                     oa->write_character(to_char_type('['));
15424                 }
15425 
15426                 if (use_type && !j.m_value.binary->empty())
15427                 {
15428                     JSON_ASSERT(use_count);
15429                     oa->write_character(to_char_type('$'));
15430                     oa->write_character('U');
15431                 }
15432 
15433                 if (use_count)
15434                 {
15435                     oa->write_character(to_char_type('#'));
15436                     write_number_with_ubjson_prefix(j.m_value.binary->size(), true, use_bjdata);
15437                 }
15438 
15439                 if (use_type)
15440                 {
15441                     oa->write_characters(
15442                         reinterpret_cast<const CharType*>(j.m_value.binary->data()),
15443                         j.m_value.binary->size());
15444                 }
15445                 else
15446                 {
15447                     for (size_t i = 0; i < j.m_value.binary->size(); ++i)
15448                     {
15449                         oa->write_character(to_char_type('U'));
15450                         oa->write_character(j.m_value.binary->data()[i]);
15451                     }
15452                 }
15453 
15454                 if (!use_count)
15455                 {
15456                     oa->write_character(to_char_type(']'));
15457                 }
15458 
15459                 break;
15460             }
15461 
15462             case value_t::object:
15463             {
15464                 if (use_bjdata && j.m_value.object->size() == 3 && j.m_value.object->find("_ArrayType_") != j.m_value.object->end() && j.m_value.object->find("_ArraySize_") != j.m_value.object->end() && j.m_value.object->find("_ArrayData_") != j.m_value.object->end())
15465                 {
15466                     if (!write_bjdata_ndarray(*j.m_value.object, use_count, use_type))  // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
15467                     {
15468                         break;
15469                     }
15470                 }
15471 
15472                 if (add_prefix)
15473                 {
15474                     oa->write_character(to_char_type('{'));
15475                 }
15476 
15477                 bool prefix_required = true;
15478                 if (use_type && !j.m_value.object->empty())
15479                 {
15480                     JSON_ASSERT(use_count);
15481                     const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15482                     const bool same_prefix = std::all_of(j.begin(), j.end(),
15483                                                          [this, first_prefix, use_bjdata](const BasicJsonType & v)
15484                     {
15485                         return ubjson_prefix(v, use_bjdata) == first_prefix;
15486                     });
15487 
15488                     std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15489 
15490                     if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15491                     {
15492                         prefix_required = false;
15493                         oa->write_character(to_char_type('$'));
15494                         oa->write_character(first_prefix);
15495                     }
15496                 }
15497 
15498                 if (use_count)
15499                 {
15500                     oa->write_character(to_char_type('#'));
15501                     write_number_with_ubjson_prefix(j.m_value.object->size(), true, use_bjdata);
15502                 }
15503 
15504                 for (const auto& el : *j.m_value.object)
15505                 {
15506                     write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
15507                     oa->write_characters(
15508                         reinterpret_cast<const CharType*>(el.first.c_str()),
15509                         el.first.size());
15510                     write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
15511                 }
15512 
15513                 if (!use_count)
15514                 {
15515                     oa->write_character(to_char_type('}'));
15516                 }
15517 
15518                 break;
15519             }
15520 
15521             case value_t::discarded:
15522             default:
15523                 break;
15524         }
15525     }
15526 
15527   private:
15528     //////////
15529     // BSON //
15530     //////////
15531 
15532     /*!
15533     @return The size of a BSON document entry header, including the id marker
15534             and the entry name size (and its null-terminator).
15535     */
calc_bson_entry_header_size(const string_t & name,const BasicJsonType & j)15536     static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
15537     {
15538         const auto it = name.find(static_cast<typename string_t::value_type>(0));
15539         if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
15540         {
15541             JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
15542             static_cast<void>(j);
15543         }
15544 
15545         return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
15546     }
15547 
15548     /*!
15549     @brief Writes the given @a element_type and @a name to the output adapter
15550     */
write_bson_entry_header(const string_t & name,const std::uint8_t element_type)15551     void write_bson_entry_header(const string_t& name,
15552                                  const std::uint8_t element_type)
15553     {
15554         oa->write_character(to_char_type(element_type)); // boolean
15555         oa->write_characters(
15556             reinterpret_cast<const CharType*>(name.c_str()),
15557             name.size() + 1u);
15558     }
15559 
15560     /*!
15561     @brief Writes a BSON element with key @a name and boolean value @a value
15562     */
write_bson_boolean(const string_t & name,const bool value)15563     void write_bson_boolean(const string_t& name,
15564                             const bool value)
15565     {
15566         write_bson_entry_header(name, 0x08);
15567         oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
15568     }
15569 
15570     /*!
15571     @brief Writes a BSON element with key @a name and double value @a value
15572     */
write_bson_double(const string_t & name,const double value)15573     void write_bson_double(const string_t& name,
15574                            const double value)
15575     {
15576         write_bson_entry_header(name, 0x01);
15577         write_number<double>(value, true);
15578     }
15579 
15580     /*!
15581     @return The size of the BSON-encoded string in @a value
15582     */
calc_bson_string_size(const string_t & value)15583     static std::size_t calc_bson_string_size(const string_t& value)
15584     {
15585         return sizeof(std::int32_t) + value.size() + 1ul;
15586     }
15587 
15588     /*!
15589     @brief Writes a BSON element with key @a name and string value @a value
15590     */
write_bson_string(const string_t & name,const string_t & value)15591     void write_bson_string(const string_t& name,
15592                            const string_t& value)
15593     {
15594         write_bson_entry_header(name, 0x02);
15595 
15596         write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
15597         oa->write_characters(
15598             reinterpret_cast<const CharType*>(value.c_str()),
15599             value.size() + 1);
15600     }
15601 
15602     /*!
15603     @brief Writes a BSON element with key @a name and null value
15604     */
write_bson_null(const string_t & name)15605     void write_bson_null(const string_t& name)
15606     {
15607         write_bson_entry_header(name, 0x0A);
15608     }
15609 
15610     /*!
15611     @return The size of the BSON-encoded integer @a value
15612     */
calc_bson_integer_size(const std::int64_t value)15613     static std::size_t calc_bson_integer_size(const std::int64_t value)
15614     {
15615         return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
15616                ? sizeof(std::int32_t)
15617                : sizeof(std::int64_t);
15618     }
15619 
15620     /*!
15621     @brief Writes a BSON element with key @a name and integer @a value
15622     */
write_bson_integer(const string_t & name,const std::int64_t value)15623     void write_bson_integer(const string_t& name,
15624                             const std::int64_t value)
15625     {
15626         if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
15627         {
15628             write_bson_entry_header(name, 0x10); // int32
15629             write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
15630         }
15631         else
15632         {
15633             write_bson_entry_header(name, 0x12); // int64
15634             write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
15635         }
15636     }
15637 
15638     /*!
15639     @return The size of the BSON-encoded unsigned integer in @a j
15640     */
calc_bson_unsigned_size(const std::uint64_t value)15641     static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
15642     {
15643         return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
15644                ? sizeof(std::int32_t)
15645                : sizeof(std::int64_t);
15646     }
15647 
15648     /*!
15649     @brief Writes a BSON element with key @a name and unsigned @a value
15650     */
write_bson_unsigned(const string_t & name,const BasicJsonType & j)15651     void write_bson_unsigned(const string_t& name,
15652                              const BasicJsonType& j)
15653     {
15654         if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
15655         {
15656             write_bson_entry_header(name, 0x10 /* int32 */);
15657             write_number<std::int32_t>(static_cast<std::int32_t>(j.m_value.number_unsigned), true);
15658         }
15659         else if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
15660         {
15661             write_bson_entry_header(name, 0x12 /* int64 */);
15662             write_number<std::int64_t>(static_cast<std::int64_t>(j.m_value.number_unsigned), true);
15663         }
15664         else
15665         {
15666             JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
15667         }
15668     }
15669 
15670     /*!
15671     @brief Writes a BSON element with key @a name and object @a value
15672     */
write_bson_object_entry(const string_t & name,const typename BasicJsonType::object_t & value)15673     void write_bson_object_entry(const string_t& name,
15674                                  const typename BasicJsonType::object_t& value)
15675     {
15676         write_bson_entry_header(name, 0x03); // object
15677         write_bson_object(value);
15678     }
15679 
15680     /*!
15681     @return The size of the BSON-encoded array @a value
15682     */
calc_bson_array_size(const typename BasicJsonType::array_t & value)15683     static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
15684     {
15685         std::size_t array_index = 0ul;
15686 
15687         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)
15688         {
15689             return result + calc_bson_element_size(std::to_string(array_index++), el);
15690         });
15691 
15692         return sizeof(std::int32_t) + embedded_document_size + 1ul;
15693     }
15694 
15695     /*!
15696     @return The size of the BSON-encoded binary array @a value
15697     */
calc_bson_binary_size(const typename BasicJsonType::binary_t & value)15698     static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
15699     {
15700         return sizeof(std::int32_t) + value.size() + 1ul;
15701     }
15702 
15703     /*!
15704     @brief Writes a BSON element with key @a name and array @a value
15705     */
write_bson_array(const string_t & name,const typename BasicJsonType::array_t & value)15706     void write_bson_array(const string_t& name,
15707                           const typename BasicJsonType::array_t& value)
15708     {
15709         write_bson_entry_header(name, 0x04); // array
15710         write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
15711 
15712         std::size_t array_index = 0ul;
15713 
15714         for (const auto& el : value)
15715         {
15716             write_bson_element(std::to_string(array_index++), el);
15717         }
15718 
15719         oa->write_character(to_char_type(0x00));
15720     }
15721 
15722     /*!
15723     @brief Writes a BSON element with key @a name and binary value @a value
15724     */
write_bson_binary(const string_t & name,const binary_t & value)15725     void write_bson_binary(const string_t& name,
15726                            const binary_t& value)
15727     {
15728         write_bson_entry_header(name, 0x05);
15729 
15730         write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
15731         write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
15732 
15733         oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
15734     }
15735 
15736     /*!
15737     @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
15738     @return The calculated size for the BSON document entry for @a j with the given @a name.
15739     */
calc_bson_element_size(const string_t & name,const BasicJsonType & j)15740     static std::size_t calc_bson_element_size(const string_t& name,
15741             const BasicJsonType& j)
15742     {
15743         const auto header_size = calc_bson_entry_header_size(name, j);
15744         switch (j.type())
15745         {
15746             case value_t::object:
15747                 return header_size + calc_bson_object_size(*j.m_value.object);
15748 
15749             case value_t::array:
15750                 return header_size + calc_bson_array_size(*j.m_value.array);
15751 
15752             case value_t::binary:
15753                 return header_size + calc_bson_binary_size(*j.m_value.binary);
15754 
15755             case value_t::boolean:
15756                 return header_size + 1ul;
15757 
15758             case value_t::number_float:
15759                 return header_size + 8ul;
15760 
15761             case value_t::number_integer:
15762                 return header_size + calc_bson_integer_size(j.m_value.number_integer);
15763 
15764             case value_t::number_unsigned:
15765                 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
15766 
15767             case value_t::string:
15768                 return header_size + calc_bson_string_size(*j.m_value.string);
15769 
15770             case value_t::null:
15771                 return header_size + 0ul;
15772 
15773             // LCOV_EXCL_START
15774             case value_t::discarded:
15775             default:
15776                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
15777                 return 0ul;
15778                 // LCOV_EXCL_STOP
15779         }
15780     }
15781 
15782     /*!
15783     @brief Serializes the JSON value @a j to BSON and associates it with the
15784            key @a name.
15785     @param name The name to associate with the JSON entity @a j within the
15786                 current BSON document
15787     */
write_bson_element(const string_t & name,const BasicJsonType & j)15788     void write_bson_element(const string_t& name,
15789                             const BasicJsonType& j)
15790     {
15791         switch (j.type())
15792         {
15793             case value_t::object:
15794                 return write_bson_object_entry(name, *j.m_value.object);
15795 
15796             case value_t::array:
15797                 return write_bson_array(name, *j.m_value.array);
15798 
15799             case value_t::binary:
15800                 return write_bson_binary(name, *j.m_value.binary);
15801 
15802             case value_t::boolean:
15803                 return write_bson_boolean(name, j.m_value.boolean);
15804 
15805             case value_t::number_float:
15806                 return write_bson_double(name, j.m_value.number_float);
15807 
15808             case value_t::number_integer:
15809                 return write_bson_integer(name, j.m_value.number_integer);
15810 
15811             case value_t::number_unsigned:
15812                 return write_bson_unsigned(name, j);
15813 
15814             case value_t::string:
15815                 return write_bson_string(name, *j.m_value.string);
15816 
15817             case value_t::null:
15818                 return write_bson_null(name);
15819 
15820             // LCOV_EXCL_START
15821             case value_t::discarded:
15822             default:
15823                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
15824                 return;
15825                 // LCOV_EXCL_STOP
15826         }
15827     }
15828 
15829     /*!
15830     @brief Calculates the size of the BSON serialization of the given
15831            JSON-object @a j.
15832     @param[in] value  JSON value to serialize
15833     @pre       value.type() == value_t::object
15834     */
calc_bson_object_size(const typename BasicJsonType::object_t & value)15835     static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
15836     {
15837         std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
15838                                     [](size_t result, const typename BasicJsonType::object_t::value_type & el)
15839         {
15840             return result += calc_bson_element_size(el.first, el.second);
15841         });
15842 
15843         return sizeof(std::int32_t) + document_size + 1ul;
15844     }
15845 
15846     /*!
15847     @param[in] value  JSON value to serialize
15848     @pre       value.type() == value_t::object
15849     */
write_bson_object(const typename BasicJsonType::object_t & value)15850     void write_bson_object(const typename BasicJsonType::object_t& value)
15851     {
15852         write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
15853 
15854         for (const auto& el : value)
15855         {
15856             write_bson_element(el.first, el.second);
15857         }
15858 
15859         oa->write_character(to_char_type(0x00));
15860     }
15861 
15862     //////////
15863     // CBOR //
15864     //////////
15865 
get_cbor_float_prefix(float)15866     static constexpr CharType get_cbor_float_prefix(float /*unused*/)
15867     {
15868         return to_char_type(0xFA);  // Single-Precision Float
15869     }
15870 
get_cbor_float_prefix(double)15871     static constexpr CharType get_cbor_float_prefix(double /*unused*/)
15872     {
15873         return to_char_type(0xFB);  // Double-Precision Float
15874     }
15875 
15876     /////////////
15877     // MsgPack //
15878     /////////////
15879 
get_msgpack_float_prefix(float)15880     static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
15881     {
15882         return to_char_type(0xCA);  // float 32
15883     }
15884 
get_msgpack_float_prefix(double)15885     static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
15886     {
15887         return to_char_type(0xCB);  // float 64
15888     }
15889 
15890     ////////////
15891     // UBJSON //
15892     ////////////
15893 
15894     // UBJSON: write number (floating point)
15895     template<typename NumberType, typename std::enable_if<
15896                  std::is_floating_point<NumberType>::value, int>::type = 0>
write_number_with_ubjson_prefix(const NumberType n,const bool add_prefix,const bool use_bjdata)15897     void write_number_with_ubjson_prefix(const NumberType n,
15898                                          const bool add_prefix,
15899                                          const bool use_bjdata)
15900     {
15901         if (add_prefix)
15902         {
15903             oa->write_character(get_ubjson_float_prefix(n));
15904         }
15905         write_number(n, use_bjdata);
15906     }
15907 
15908     // UBJSON: write number (unsigned integer)
15909     template<typename NumberType, typename std::enable_if<
15910                  std::is_unsigned<NumberType>::value, int>::type = 0>
write_number_with_ubjson_prefix(const NumberType n,const bool add_prefix,const bool use_bjdata)15911     void write_number_with_ubjson_prefix(const NumberType n,
15912                                          const bool add_prefix,
15913                                          const bool use_bjdata)
15914     {
15915         if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
15916         {
15917             if (add_prefix)
15918             {
15919                 oa->write_character(to_char_type('i'));  // int8
15920             }
15921             write_number(static_cast<std::uint8_t>(n), use_bjdata);
15922         }
15923         else if (n <= (std::numeric_limits<std::uint8_t>::max)())
15924         {
15925             if (add_prefix)
15926             {
15927                 oa->write_character(to_char_type('U'));  // uint8
15928             }
15929             write_number(static_cast<std::uint8_t>(n), use_bjdata);
15930         }
15931         else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
15932         {
15933             if (add_prefix)
15934             {
15935                 oa->write_character(to_char_type('I'));  // int16
15936             }
15937             write_number(static_cast<std::int16_t>(n), use_bjdata);
15938         }
15939         else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
15940         {
15941             if (add_prefix)
15942             {
15943                 oa->write_character(to_char_type('u'));  // uint16 - bjdata only
15944             }
15945             write_number(static_cast<std::uint16_t>(n), use_bjdata);
15946         }
15947         else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
15948         {
15949             if (add_prefix)
15950             {
15951                 oa->write_character(to_char_type('l'));  // int32
15952             }
15953             write_number(static_cast<std::int32_t>(n), use_bjdata);
15954         }
15955         else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
15956         {
15957             if (add_prefix)
15958             {
15959                 oa->write_character(to_char_type('m'));  // uint32 - bjdata only
15960             }
15961             write_number(static_cast<std::uint32_t>(n), use_bjdata);
15962         }
15963         else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
15964         {
15965             if (add_prefix)
15966             {
15967                 oa->write_character(to_char_type('L'));  // int64
15968             }
15969             write_number(static_cast<std::int64_t>(n), use_bjdata);
15970         }
15971         else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
15972         {
15973             if (add_prefix)
15974             {
15975                 oa->write_character(to_char_type('M'));  // uint64 - bjdata only
15976             }
15977             write_number(static_cast<std::uint64_t>(n), use_bjdata);
15978         }
15979         else
15980         {
15981             if (add_prefix)
15982             {
15983                 oa->write_character(to_char_type('H'));  // high-precision number
15984             }
15985 
15986             const auto number = BasicJsonType(n).dump();
15987             write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
15988             for (std::size_t i = 0; i < number.size(); ++i)
15989             {
15990                 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
15991             }
15992         }
15993     }
15994 
15995     // UBJSON: write number (signed integer)
15996     template < typename NumberType, typename std::enable_if <
15997                    std::is_signed<NumberType>::value&&
15998                    !std::is_floating_point<NumberType>::value, int >::type = 0 >
write_number_with_ubjson_prefix(const NumberType n,const bool add_prefix,const bool use_bjdata)15999     void write_number_with_ubjson_prefix(const NumberType n,
16000                                          const bool add_prefix,
16001                                          const bool use_bjdata)
16002     {
16003         if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
16004         {
16005             if (add_prefix)
16006             {
16007                 oa->write_character(to_char_type('i'));  // int8
16008             }
16009             write_number(static_cast<std::int8_t>(n), use_bjdata);
16010         }
16011         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)()))
16012         {
16013             if (add_prefix)
16014             {
16015                 oa->write_character(to_char_type('U'));  // uint8
16016             }
16017             write_number(static_cast<std::uint8_t>(n), use_bjdata);
16018         }
16019         else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
16020         {
16021             if (add_prefix)
16022             {
16023                 oa->write_character(to_char_type('I'));  // int16
16024             }
16025             write_number(static_cast<std::int16_t>(n), use_bjdata);
16026         }
16027         else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
16028         {
16029             if (add_prefix)
16030             {
16031                 oa->write_character(to_char_type('u'));  // uint16 - bjdata only
16032             }
16033             write_number(static_cast<uint16_t>(n), use_bjdata);
16034         }
16035         else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
16036         {
16037             if (add_prefix)
16038             {
16039                 oa->write_character(to_char_type('l'));  // int32
16040             }
16041             write_number(static_cast<std::int32_t>(n), use_bjdata);
16042         }
16043         else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
16044         {
16045             if (add_prefix)
16046             {
16047                 oa->write_character(to_char_type('m'));  // uint32 - bjdata only
16048             }
16049             write_number(static_cast<uint32_t>(n), use_bjdata);
16050         }
16051         else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
16052         {
16053             if (add_prefix)
16054             {
16055                 oa->write_character(to_char_type('L'));  // int64
16056             }
16057             write_number(static_cast<std::int64_t>(n), use_bjdata);
16058         }
16059         // LCOV_EXCL_START
16060         else
16061         {
16062             if (add_prefix)
16063             {
16064                 oa->write_character(to_char_type('H'));  // high-precision number
16065             }
16066 
16067             const auto number = BasicJsonType(n).dump();
16068             write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16069             for (std::size_t i = 0; i < number.size(); ++i)
16070             {
16071                 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16072             }
16073         }
16074         // LCOV_EXCL_STOP
16075     }
16076 
16077     /*!
16078     @brief determine the type prefix of container values
16079     */
ubjson_prefix(const BasicJsonType & j,const bool use_bjdata) const16080     CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
16081     {
16082         switch (j.type())
16083         {
16084             case value_t::null:
16085                 return 'Z';
16086 
16087             case value_t::boolean:
16088                 return j.m_value.boolean ? 'T' : 'F';
16089 
16090             case value_t::number_integer:
16091             {
16092                 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)())
16093                 {
16094                     return 'i';
16095                 }
16096                 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)())
16097                 {
16098                     return 'U';
16099                 }
16100                 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)())
16101                 {
16102                     return 'I';
16103                 }
16104                 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
16105                 {
16106                     return 'u';
16107                 }
16108                 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)())
16109                 {
16110                     return 'l';
16111                 }
16112                 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
16113                 {
16114                     return 'm';
16115                 }
16116                 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)())
16117                 {
16118                     return 'L';
16119                 }
16120                 // anything else is treated as high-precision number
16121                 return 'H'; // LCOV_EXCL_LINE
16122             }
16123 
16124             case value_t::number_unsigned:
16125             {
16126                 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16127                 {
16128                     return 'i';
16129                 }
16130                 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
16131                 {
16132                     return 'U';
16133                 }
16134                 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16135                 {
16136                     return 'I';
16137                 }
16138                 if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
16139                 {
16140                     return 'u';
16141                 }
16142                 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16143                 {
16144                     return 'l';
16145                 }
16146                 if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
16147                 {
16148                     return 'm';
16149                 }
16150                 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16151                 {
16152                     return 'L';
16153                 }
16154                 if (use_bjdata && j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16155                 {
16156                     return 'M';
16157                 }
16158                 // anything else is treated as high-precision number
16159                 return 'H'; // LCOV_EXCL_LINE
16160             }
16161 
16162             case value_t::number_float:
16163                 return get_ubjson_float_prefix(j.m_value.number_float);
16164 
16165             case value_t::string:
16166                 return 'S';
16167 
16168             case value_t::array: // fallthrough
16169             case value_t::binary:
16170                 return '[';
16171 
16172             case value_t::object:
16173                 return '{';
16174 
16175             case value_t::discarded:
16176             default:  // discarded values
16177                 return 'N';
16178         }
16179     }
16180 
get_ubjson_float_prefix(float)16181     static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
16182     {
16183         return 'd';  // float 32
16184     }
16185 
get_ubjson_float_prefix(double)16186     static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
16187     {
16188         return 'D';  // float 64
16189     }
16190 
16191     /*!
16192     @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid
16193     */
write_bjdata_ndarray(const typename BasicJsonType::object_t & value,const bool use_count,const bool use_type)16194     bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
16195     {
16196         std::map<string_t, CharType> bjdtype = {{"uint8", 'U'},  {"int8", 'i'},  {"uint16", 'u'}, {"int16", 'I'},
16197             {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
16198         };
16199 
16200         string_t key = "_ArrayType_";
16201         auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
16202         if (it == bjdtype.end())
16203         {
16204             return true;
16205         }
16206         CharType dtype = it->second;
16207 
16208         key = "_ArraySize_";
16209         std::size_t len = (value.at(key).empty() ? 0 : 1);
16210         for (const auto& el : value.at(key))
16211         {
16212             len *= static_cast<std::size_t>(el.m_value.number_unsigned);
16213         }
16214 
16215         key = "_ArrayData_";
16216         if (value.at(key).size() != len)
16217         {
16218             return true;
16219         }
16220 
16221         oa->write_character('[');
16222         oa->write_character('$');
16223         oa->write_character(dtype);
16224         oa->write_character('#');
16225 
16226         key = "_ArraySize_";
16227         write_ubjson(value.at(key), use_count, use_type, true,  true);
16228 
16229         key = "_ArrayData_";
16230         if (dtype == 'U' || dtype == 'C')
16231         {
16232             for (const auto& el : value.at(key))
16233             {
16234                 write_number(static_cast<std::uint8_t>(el.m_value.number_unsigned), true);
16235             }
16236         }
16237         else if (dtype == 'i')
16238         {
16239             for (const auto& el : value.at(key))
16240             {
16241                 write_number(static_cast<std::int8_t>(el.m_value.number_integer), true);
16242             }
16243         }
16244         else if (dtype == 'u')
16245         {
16246             for (const auto& el : value.at(key))
16247             {
16248                 write_number(static_cast<std::uint16_t>(el.m_value.number_unsigned), true);
16249             }
16250         }
16251         else if (dtype == 'I')
16252         {
16253             for (const auto& el : value.at(key))
16254             {
16255                 write_number(static_cast<std::int16_t>(el.m_value.number_integer), true);
16256             }
16257         }
16258         else if (dtype == 'm')
16259         {
16260             for (const auto& el : value.at(key))
16261             {
16262                 write_number(static_cast<std::uint32_t>(el.m_value.number_unsigned), true);
16263             }
16264         }
16265         else if (dtype == 'l')
16266         {
16267             for (const auto& el : value.at(key))
16268             {
16269                 write_number(static_cast<std::int32_t>(el.m_value.number_integer), true);
16270             }
16271         }
16272         else if (dtype == 'M')
16273         {
16274             for (const auto& el : value.at(key))
16275             {
16276                 write_number(static_cast<std::uint64_t>(el.m_value.number_unsigned), true);
16277             }
16278         }
16279         else if (dtype == 'L')
16280         {
16281             for (const auto& el : value.at(key))
16282             {
16283                 write_number(static_cast<std::int64_t>(el.m_value.number_integer), true);
16284             }
16285         }
16286         else if (dtype == 'd')
16287         {
16288             for (const auto& el : value.at(key))
16289             {
16290                 write_number(static_cast<float>(el.m_value.number_float), true);
16291             }
16292         }
16293         else if (dtype == 'D')
16294         {
16295             for (const auto& el : value.at(key))
16296             {
16297                 write_number(static_cast<double>(el.m_value.number_float), true);
16298             }
16299         }
16300         return false;
16301     }
16302 
16303     ///////////////////////
16304     // Utility functions //
16305     ///////////////////////
16306 
16307     /*
16308     @brief write a number to output input
16309     @param[in] n number of type @a NumberType
16310     @param[in] OutputIsLittleEndian Set to true if output data is
16311                                  required to be little endian
16312     @tparam NumberType the type of the number
16313 
16314     @note This function needs to respect the system's endianness, because bytes
16315           in CBOR, MessagePack, and UBJSON are stored in network order (big
16316           endian) and therefore need reordering on little endian systems.
16317           On the other hand, BSON and BJData use little endian and should reorder
16318           on big endian systems.
16319     */
16320     template<typename NumberType>
write_number(const NumberType n,const bool OutputIsLittleEndian=false)16321     void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
16322     {
16323         // step 1: write number to array of length NumberType
16324         std::array<CharType, sizeof(NumberType)> vec{};
16325         std::memcpy(vec.data(), &n, sizeof(NumberType));
16326 
16327         // step 2: write array to output (with possible reordering)
16328         if (is_little_endian != OutputIsLittleEndian)
16329         {
16330             // reverse byte order prior to conversion if necessary
16331             std::reverse(vec.begin(), vec.end());
16332         }
16333 
16334         oa->write_characters(vec.data(), sizeof(NumberType));
16335     }
16336 
write_compact_float(const number_float_t n,detail::input_format_t format)16337     void write_compact_float(const number_float_t n, detail::input_format_t format)
16338     {
16339 #ifdef __GNUC__
16340 #pragma GCC diagnostic push
16341 #pragma GCC diagnostic ignored "-Wfloat-equal"
16342 #endif
16343         if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
16344                 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
16345                 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
16346         {
16347             oa->write_character(format == detail::input_format_t::cbor
16348                                 ? get_cbor_float_prefix(static_cast<float>(n))
16349                                 : get_msgpack_float_prefix(static_cast<float>(n)));
16350             write_number(static_cast<float>(n));
16351         }
16352         else
16353         {
16354             oa->write_character(format == detail::input_format_t::cbor
16355                                 ? get_cbor_float_prefix(n)
16356                                 : get_msgpack_float_prefix(n));
16357             write_number(n);
16358         }
16359 #ifdef __GNUC__
16360 #pragma GCC diagnostic pop
16361 #endif
16362     }
16363 
16364   public:
16365     // The following to_char_type functions are implement the conversion
16366     // between uint8_t and CharType. In case CharType is not unsigned,
16367     // such a conversion is required to allow values greater than 128.
16368     // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
16369     template < typename C = CharType,
16370                enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
to_char_type(std::uint8_t x)16371     static constexpr CharType to_char_type(std::uint8_t x) noexcept
16372     {
16373         return *reinterpret_cast<char*>(&x);
16374     }
16375 
16376     template < typename C = CharType,
16377                enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
to_char_type(std::uint8_t x)16378     static CharType to_char_type(std::uint8_t x) noexcept
16379     {
16380         static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
16381         static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
16382         CharType result;
16383         std::memcpy(&result, &x, sizeof(x));
16384         return result;
16385     }
16386 
16387     template<typename C = CharType,
16388              enable_if_t<std::is_unsigned<C>::value>* = nullptr>
to_char_type(std::uint8_t x)16389     static constexpr CharType to_char_type(std::uint8_t x) noexcept
16390     {
16391         return x;
16392     }
16393 
16394     template < typename InputCharType, typename C = CharType,
16395                enable_if_t <
16396                    std::is_signed<C>::value &&
16397                    std::is_signed<char>::value &&
16398                    std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
16399                    > * = nullptr >
to_char_type(InputCharType x)16400     static constexpr CharType to_char_type(InputCharType x) noexcept
16401     {
16402         return x;
16403     }
16404 
16405   private:
16406     /// whether we can assume little endianness
16407     const bool is_little_endian = little_endianness();
16408 
16409     /// the output
16410     output_adapter_t<CharType> oa = nullptr;
16411 };
16412 }  // namespace detail
16413 }  // namespace nlohmann
16414 
16415 // #include <nlohmann/detail/output/output_adapters.hpp>
16416 
16417 // #include <nlohmann/detail/output/serializer.hpp>
16418 //     __ _____ _____ _____
16419 //  __|  |   __|     |   | |  JSON for Modern C++
16420 // |  |  |__   |  |  | | | |  version 3.10.5
16421 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
16422 //
16423 // SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <[email protected]>
16424 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
16425 // SPDX-License-Identifier: MIT
16426 
16427 
16428 
16429 #include <algorithm> // reverse, remove, fill, find, none_of
16430 #include <array> // array
16431 #include <clocale> // localeconv, lconv
16432 #include <cmath> // labs, isfinite, isnan, signbit
16433 #include <cstddef> // size_t, ptrdiff_t
16434 #include <cstdint> // uint8_t
16435 #include <cstdio> // snprintf
16436 #include <limits> // numeric_limits
16437 #include <string> // string, char_traits
16438 #include <iomanip> // setfill, setw
16439 #include <type_traits> // is_same
16440 #include <utility> // move
16441 
16442 // #include <nlohmann/detail/conversions/to_chars.hpp>
16443 //     __ _____ _____ _____
16444 //  __|  |   __|     |   | |  JSON for Modern C++
16445 // |  |  |__   |  |  | | | |  version 3.10.5
16446 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
16447 //
16448 // SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
16449 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
16450 // SPDX-License-Identifier: MIT
16451 
16452 
16453 
16454 #include <array> // array
16455 #include <cmath>   // signbit, isfinite
16456 #include <cstdint> // intN_t, uintN_t
16457 #include <cstring> // memcpy, memmove
16458 #include <limits> // numeric_limits
16459 #include <type_traits> // conditional
16460 
16461 // #include <nlohmann/detail/macro_scope.hpp>
16462 
16463 
16464 namespace nlohmann
16465 {
16466 namespace detail
16467 {
16468 
16469 /*!
16470 @brief implements the Grisu2 algorithm for binary to decimal floating-point
16471 conversion.
16472 
16473 This implementation is a slightly modified version of the reference
16474 implementation which may be obtained from
16475 http://florian.loitsch.com/publications (bench.tar.gz).
16476 
16477 The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
16478 
16479 For a detailed description of the algorithm see:
16480 
16481 [1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
16482     Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
16483     Language Design and Implementation, PLDI 2010
16484 [2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
16485     Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
16486     Design and Implementation, PLDI 1996
16487 */
16488 namespace dtoa_impl
16489 {
16490 
16491 template<typename Target, typename Source>
reinterpret_bits(const Source source)16492 Target reinterpret_bits(const Source source)
16493 {
16494     static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
16495 
16496     Target target;
16497     std::memcpy(&target, &source, sizeof(Source));
16498     return target;
16499 }
16500 
16501 struct diyfp // f * 2^e
16502 {
16503     static constexpr int kPrecision = 64; // = q
16504 
16505     std::uint64_t f = 0;
16506     int e = 0;
16507 
diyfpnlohmann::detail::dtoa_impl::diyfp16508     constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
16509 
16510     /*!
16511     @brief returns x - y
16512     @pre x.e == y.e and x.f >= y.f
16513     */
subnlohmann::detail::dtoa_impl::diyfp16514     static diyfp sub(const diyfp& x, const diyfp& y) noexcept
16515     {
16516         JSON_ASSERT(x.e == y.e);
16517         JSON_ASSERT(x.f >= y.f);
16518 
16519         return {x.f - y.f, x.e};
16520     }
16521 
16522     /*!
16523     @brief returns x * y
16524     @note The result is rounded. (Only the upper q bits are returned.)
16525     */
mulnlohmann::detail::dtoa_impl::diyfp16526     static diyfp mul(const diyfp& x, const diyfp& y) noexcept
16527     {
16528         static_assert(kPrecision == 64, "internal error");
16529 
16530         // Computes:
16531         //  f = round((x.f * y.f) / 2^q)
16532         //  e = x.e + y.e + q
16533 
16534         // Emulate the 64-bit * 64-bit multiplication:
16535         //
16536         // p = u * v
16537         //   = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
16538         //   = (u_lo v_lo         ) + 2^32 ((u_lo v_hi         ) + (u_hi v_lo         )) + 2^64 (u_hi v_hi         )
16539         //   = (p0                ) + 2^32 ((p1                ) + (p2                )) + 2^64 (p3                )
16540         //   = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3                )
16541         //   = (p0_lo             ) + 2^32 (p0_hi + p1_lo + p2_lo                      ) + 2^64 (p1_hi + p2_hi + p3)
16542         //   = (p0_lo             ) + 2^32 (Q                                          ) + 2^64 (H                 )
16543         //   = (p0_lo             ) + 2^32 (Q_lo + 2^32 Q_hi                           ) + 2^64 (H                 )
16544         //
16545         // (Since Q might be larger than 2^32 - 1)
16546         //
16547         //   = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
16548         //
16549         // (Q_hi + H does not overflow a 64-bit int)
16550         //
16551         //   = p_lo + 2^64 p_hi
16552 
16553         const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
16554         const std::uint64_t u_hi = x.f >> 32u;
16555         const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
16556         const std::uint64_t v_hi = y.f >> 32u;
16557 
16558         const std::uint64_t p0 = u_lo * v_lo;
16559         const std::uint64_t p1 = u_lo * v_hi;
16560         const std::uint64_t p2 = u_hi * v_lo;
16561         const std::uint64_t p3 = u_hi * v_hi;
16562 
16563         const std::uint64_t p0_hi = p0 >> 32u;
16564         const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
16565         const std::uint64_t p1_hi = p1 >> 32u;
16566         const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
16567         const std::uint64_t p2_hi = p2 >> 32u;
16568 
16569         std::uint64_t Q = p0_hi + p1_lo + p2_lo;
16570 
16571         // The full product might now be computed as
16572         //
16573         // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
16574         // p_lo = p0_lo + (Q << 32)
16575         //
16576         // But in this particular case here, the full p_lo is not required.
16577         // Effectively we only need to add the highest bit in p_lo to p_hi (and
16578         // Q_hi + 1 does not overflow).
16579 
16580         Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
16581 
16582         const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
16583 
16584         return {h, x.e + y.e + 64};
16585     }
16586 
16587     /*!
16588     @brief normalize x such that the significand is >= 2^(q-1)
16589     @pre x.f != 0
16590     */
normalizenlohmann::detail::dtoa_impl::diyfp16591     static diyfp normalize(diyfp x) noexcept
16592     {
16593         JSON_ASSERT(x.f != 0);
16594 
16595         while ((x.f >> 63u) == 0)
16596         {
16597             x.f <<= 1u;
16598             x.e--;
16599         }
16600 
16601         return x;
16602     }
16603 
16604     /*!
16605     @brief normalize x such that the result has the exponent E
16606     @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
16607     */
normalize_tonlohmann::detail::dtoa_impl::diyfp16608     static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
16609     {
16610         const int delta = x.e - target_exponent;
16611 
16612         JSON_ASSERT(delta >= 0);
16613         JSON_ASSERT(((x.f << delta) >> delta) == x.f);
16614 
16615         return {x.f << delta, target_exponent};
16616     }
16617 };
16618 
16619 struct boundaries
16620 {
16621     diyfp w;
16622     diyfp minus;
16623     diyfp plus;
16624 };
16625 
16626 /*!
16627 Compute the (normalized) diyfp representing the input number 'value' and its
16628 boundaries.
16629 
16630 @pre value must be finite and positive
16631 */
16632 template<typename FloatType>
compute_boundaries(FloatType value)16633 boundaries compute_boundaries(FloatType value)
16634 {
16635     JSON_ASSERT(std::isfinite(value));
16636     JSON_ASSERT(value > 0);
16637 
16638     // Convert the IEEE representation into a diyfp.
16639     //
16640     // If v is denormal:
16641     //      value = 0.F * 2^(1 - bias) = (          F) * 2^(1 - bias - (p-1))
16642     // If v is normalized:
16643     //      value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
16644 
16645     static_assert(std::numeric_limits<FloatType>::is_iec559,
16646                   "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
16647 
16648     constexpr int      kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
16649     constexpr int      kBias      = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
16650     constexpr int      kMinExp    = 1 - kBias;
16651     constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
16652 
16653     using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
16654 
16655     const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
16656     const std::uint64_t E = bits >> (kPrecision - 1);
16657     const std::uint64_t F = bits & (kHiddenBit - 1);
16658 
16659     const bool is_denormal = E == 0;
16660     const diyfp v = is_denormal
16661                     ? diyfp(F, kMinExp)
16662                     : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
16663 
16664     // Compute the boundaries m- and m+ of the floating-point value
16665     // v = f * 2^e.
16666     //
16667     // Determine v- and v+, the floating-point predecessor and successor if v,
16668     // respectively.
16669     //
16670     //      v- = v - 2^e        if f != 2^(p-1) or e == e_min                (A)
16671     //         = v - 2^(e-1)    if f == 2^(p-1) and e > e_min                (B)
16672     //
16673     //      v+ = v + 2^e
16674     //
16675     // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
16676     // between m- and m+ round to v, regardless of how the input rounding
16677     // algorithm breaks ties.
16678     //
16679     //      ---+-------------+-------------+-------------+-------------+---  (A)
16680     //         v-            m-            v             m+            v+
16681     //
16682     //      -----------------+------+------+-------------+-------------+---  (B)
16683     //                       v-     m-     v             m+            v+
16684 
16685     const bool lower_boundary_is_closer = F == 0 && E > 1;
16686     const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
16687     const diyfp m_minus = lower_boundary_is_closer
16688                           ? diyfp(4 * v.f - 1, v.e - 2)  // (B)
16689                           : diyfp(2 * v.f - 1, v.e - 1); // (A)
16690 
16691     // Determine the normalized w+ = m+.
16692     const diyfp w_plus = diyfp::normalize(m_plus);
16693 
16694     // Determine w- = m- such that e_(w-) = e_(w+).
16695     const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
16696 
16697     return {diyfp::normalize(v), w_minus, w_plus};
16698 }
16699 
16700 // Given normalized diyfp w, Grisu needs to find a (normalized) cached
16701 // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
16702 // within a certain range [alpha, gamma] (Definition 3.2 from [1])
16703 //
16704 //      alpha <= e = e_c + e_w + q <= gamma
16705 //
16706 // or
16707 //
16708 //      f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
16709 //                          <= f_c * f_w * 2^gamma
16710 //
16711 // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
16712 //
16713 //      2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
16714 //
16715 // or
16716 //
16717 //      2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
16718 //
16719 // The choice of (alpha,gamma) determines the size of the table and the form of
16720 // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
16721 // in practice:
16722 //
16723 // The idea is to cut the number c * w = f * 2^e into two parts, which can be
16724 // processed independently: An integral part p1, and a fractional part p2:
16725 //
16726 //      f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
16727 //              = (f div 2^-e) + (f mod 2^-e) * 2^e
16728 //              = p1 + p2 * 2^e
16729 //
16730 // The conversion of p1 into decimal form requires a series of divisions and
16731 // modulos by (a power of) 10. These operations are faster for 32-bit than for
16732 // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
16733 // achieved by choosing
16734 //
16735 //      -e >= 32   or   e <= -32 := gamma
16736 //
16737 // In order to convert the fractional part
16738 //
16739 //      p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
16740 //
16741 // into decimal form, the fraction is repeatedly multiplied by 10 and the digits
16742 // d[-i] are extracted in order:
16743 //
16744 //      (10 * p2) div 2^-e = d[-1]
16745 //      (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
16746 //
16747 // The multiplication by 10 must not overflow. It is sufficient to choose
16748 //
16749 //      10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
16750 //
16751 // Since p2 = f mod 2^-e < 2^-e,
16752 //
16753 //      -e <= 60   or   e >= -60 := alpha
16754 
16755 constexpr int kAlpha = -60;
16756 constexpr int kGamma = -32;
16757 
16758 struct cached_power // c = f * 2^e ~= 10^k
16759 {
16760     std::uint64_t f;
16761     int e;
16762     int k;
16763 };
16764 
16765 /*!
16766 For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
16767 power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
16768 satisfies (Definition 3.2 from [1])
16769 
16770      alpha <= e_c + e + q <= gamma.
16771 */
get_cached_power_for_binary_exponent(int e)16772 inline cached_power get_cached_power_for_binary_exponent(int e)
16773 {
16774     // Now
16775     //
16776     //      alpha <= e_c + e + q <= gamma                                    (1)
16777     //      ==> f_c * 2^alpha <= c * 2^e * 2^q
16778     //
16779     // and since the c's are normalized, 2^(q-1) <= f_c,
16780     //
16781     //      ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
16782     //      ==> 2^(alpha - e - 1) <= c
16783     //
16784     // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
16785     //
16786     //      k = ceil( log_10( 2^(alpha - e - 1) ) )
16787     //        = ceil( (alpha - e - 1) * log_10(2) )
16788     //
16789     // From the paper:
16790     // "In theory the result of the procedure could be wrong since c is rounded,
16791     //  and the computation itself is approximated [...]. In practice, however,
16792     //  this simple function is sufficient."
16793     //
16794     // For IEEE double precision floating-point numbers converted into
16795     // normalized diyfp's w = f * 2^e, with q = 64,
16796     //
16797     //      e >= -1022      (min IEEE exponent)
16798     //           -52        (p - 1)
16799     //           -52        (p - 1, possibly normalize denormal IEEE numbers)
16800     //           -11        (normalize the diyfp)
16801     //         = -1137
16802     //
16803     // and
16804     //
16805     //      e <= +1023      (max IEEE exponent)
16806     //           -52        (p - 1)
16807     //           -11        (normalize the diyfp)
16808     //         = 960
16809     //
16810     // This binary exponent range [-1137,960] results in a decimal exponent
16811     // range [-307,324]. One does not need to store a cached power for each
16812     // k in this range. For each such k it suffices to find a cached power
16813     // such that the exponent of the product lies in [alpha,gamma].
16814     // This implies that the difference of the decimal exponents of adjacent
16815     // table entries must be less than or equal to
16816     //
16817     //      floor( (gamma - alpha) * log_10(2) ) = 8.
16818     //
16819     // (A smaller distance gamma-alpha would require a larger table.)
16820 
16821     // NB:
16822     // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
16823 
16824     constexpr int kCachedPowersMinDecExp = -300;
16825     constexpr int kCachedPowersDecStep = 8;
16826 
16827     static constexpr std::array<cached_power, 79> kCachedPowers =
16828     {
16829         {
16830             { 0xAB70FE17C79AC6CA, -1060, -300 },
16831             { 0xFF77B1FCBEBCDC4F, -1034, -292 },
16832             { 0xBE5691EF416BD60C, -1007, -284 },
16833             { 0x8DD01FAD907FFC3C,  -980, -276 },
16834             { 0xD3515C2831559A83,  -954, -268 },
16835             { 0x9D71AC8FADA6C9B5,  -927, -260 },
16836             { 0xEA9C227723EE8BCB,  -901, -252 },
16837             { 0xAECC49914078536D,  -874, -244 },
16838             { 0x823C12795DB6CE57,  -847, -236 },
16839             { 0xC21094364DFB5637,  -821, -228 },
16840             { 0x9096EA6F3848984F,  -794, -220 },
16841             { 0xD77485CB25823AC7,  -768, -212 },
16842             { 0xA086CFCD97BF97F4,  -741, -204 },
16843             { 0xEF340A98172AACE5,  -715, -196 },
16844             { 0xB23867FB2A35B28E,  -688, -188 },
16845             { 0x84C8D4DFD2C63F3B,  -661, -180 },
16846             { 0xC5DD44271AD3CDBA,  -635, -172 },
16847             { 0x936B9FCEBB25C996,  -608, -164 },
16848             { 0xDBAC6C247D62A584,  -582, -156 },
16849             { 0xA3AB66580D5FDAF6,  -555, -148 },
16850             { 0xF3E2F893DEC3F126,  -529, -140 },
16851             { 0xB5B5ADA8AAFF80B8,  -502, -132 },
16852             { 0x87625F056C7C4A8B,  -475, -124 },
16853             { 0xC9BCFF6034C13053,  -449, -116 },
16854             { 0x964E858C91BA2655,  -422, -108 },
16855             { 0xDFF9772470297EBD,  -396, -100 },
16856             { 0xA6DFBD9FB8E5B88F,  -369,  -92 },
16857             { 0xF8A95FCF88747D94,  -343,  -84 },
16858             { 0xB94470938FA89BCF,  -316,  -76 },
16859             { 0x8A08F0F8BF0F156B,  -289,  -68 },
16860             { 0xCDB02555653131B6,  -263,  -60 },
16861             { 0x993FE2C6D07B7FAC,  -236,  -52 },
16862             { 0xE45C10C42A2B3B06,  -210,  -44 },
16863             { 0xAA242499697392D3,  -183,  -36 },
16864             { 0xFD87B5F28300CA0E,  -157,  -28 },
16865             { 0xBCE5086492111AEB,  -130,  -20 },
16866             { 0x8CBCCC096F5088CC,  -103,  -12 },
16867             { 0xD1B71758E219652C,   -77,   -4 },
16868             { 0x9C40000000000000,   -50,    4 },
16869             { 0xE8D4A51000000000,   -24,   12 },
16870             { 0xAD78EBC5AC620000,     3,   20 },
16871             { 0x813F3978F8940984,    30,   28 },
16872             { 0xC097CE7BC90715B3,    56,   36 },
16873             { 0x8F7E32CE7BEA5C70,    83,   44 },
16874             { 0xD5D238A4ABE98068,   109,   52 },
16875             { 0x9F4F2726179A2245,   136,   60 },
16876             { 0xED63A231D4C4FB27,   162,   68 },
16877             { 0xB0DE65388CC8ADA8,   189,   76 },
16878             { 0x83C7088E1AAB65DB,   216,   84 },
16879             { 0xC45D1DF942711D9A,   242,   92 },
16880             { 0x924D692CA61BE758,   269,  100 },
16881             { 0xDA01EE641A708DEA,   295,  108 },
16882             { 0xA26DA3999AEF774A,   322,  116 },
16883             { 0xF209787BB47D6B85,   348,  124 },
16884             { 0xB454E4A179DD1877,   375,  132 },
16885             { 0x865B86925B9BC5C2,   402,  140 },
16886             { 0xC83553C5C8965D3D,   428,  148 },
16887             { 0x952AB45CFA97A0B3,   455,  156 },
16888             { 0xDE469FBD99A05FE3,   481,  164 },
16889             { 0xA59BC234DB398C25,   508,  172 },
16890             { 0xF6C69A72A3989F5C,   534,  180 },
16891             { 0xB7DCBF5354E9BECE,   561,  188 },
16892             { 0x88FCF317F22241E2,   588,  196 },
16893             { 0xCC20CE9BD35C78A5,   614,  204 },
16894             { 0x98165AF37B2153DF,   641,  212 },
16895             { 0xE2A0B5DC971F303A,   667,  220 },
16896             { 0xA8D9D1535CE3B396,   694,  228 },
16897             { 0xFB9B7CD9A4A7443C,   720,  236 },
16898             { 0xBB764C4CA7A44410,   747,  244 },
16899             { 0x8BAB8EEFB6409C1A,   774,  252 },
16900             { 0xD01FEF10A657842C,   800,  260 },
16901             { 0x9B10A4E5E9913129,   827,  268 },
16902             { 0xE7109BFBA19C0C9D,   853,  276 },
16903             { 0xAC2820D9623BF429,   880,  284 },
16904             { 0x80444B5E7AA7CF85,   907,  292 },
16905             { 0xBF21E44003ACDD2D,   933,  300 },
16906             { 0x8E679C2F5E44FF8F,   960,  308 },
16907             { 0xD433179D9C8CB841,   986,  316 },
16908             { 0x9E19DB92B4E31BA9,  1013,  324 },
16909         }
16910     };
16911 
16912     // This computation gives exactly the same results for k as
16913     //      k = ceil((kAlpha - e - 1) * 0.30102999566398114)
16914     // for |e| <= 1500, but doesn't require floating-point operations.
16915     // NB: log_10(2) ~= 78913 / 2^18
16916     JSON_ASSERT(e >= -1500);
16917     JSON_ASSERT(e <=  1500);
16918     const int f = kAlpha - e - 1;
16919     const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
16920 
16921     const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
16922     JSON_ASSERT(index >= 0);
16923     JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
16924 
16925     const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
16926     JSON_ASSERT(kAlpha <= cached.e + e + 64);
16927     JSON_ASSERT(kGamma >= cached.e + e + 64);
16928 
16929     return cached;
16930 }
16931 
16932 /*!
16933 For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
16934 For n == 0, returns 1 and sets pow10 := 1.
16935 */
find_largest_pow10(const std::uint32_t n,std::uint32_t & pow10)16936 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
16937 {
16938     // LCOV_EXCL_START
16939     if (n >= 1000000000)
16940     {
16941         pow10 = 1000000000;
16942         return 10;
16943     }
16944     // LCOV_EXCL_STOP
16945     if (n >= 100000000)
16946     {
16947         pow10 = 100000000;
16948         return  9;
16949     }
16950     if (n >= 10000000)
16951     {
16952         pow10 = 10000000;
16953         return  8;
16954     }
16955     if (n >= 1000000)
16956     {
16957         pow10 = 1000000;
16958         return  7;
16959     }
16960     if (n >= 100000)
16961     {
16962         pow10 = 100000;
16963         return  6;
16964     }
16965     if (n >= 10000)
16966     {
16967         pow10 = 10000;
16968         return  5;
16969     }
16970     if (n >= 1000)
16971     {
16972         pow10 = 1000;
16973         return  4;
16974     }
16975     if (n >= 100)
16976     {
16977         pow10 = 100;
16978         return  3;
16979     }
16980     if (n >= 10)
16981     {
16982         pow10 = 10;
16983         return  2;
16984     }
16985 
16986     pow10 = 1;
16987     return 1;
16988 }
16989 
grisu2_round(char * buf,int len,std::uint64_t dist,std::uint64_t delta,std::uint64_t rest,std::uint64_t ten_k)16990 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
16991                          std::uint64_t rest, std::uint64_t ten_k)
16992 {
16993     JSON_ASSERT(len >= 1);
16994     JSON_ASSERT(dist <= delta);
16995     JSON_ASSERT(rest <= delta);
16996     JSON_ASSERT(ten_k > 0);
16997 
16998     //               <--------------------------- delta ---->
16999     //                                  <---- dist --------->
17000     // --------------[------------------+-------------------]--------------
17001     //               M-                 w                   M+
17002     //
17003     //                                  ten_k
17004     //                                <------>
17005     //                                       <---- rest ---->
17006     // --------------[------------------+----+--------------]--------------
17007     //                                  w    V
17008     //                                       = buf * 10^k
17009     //
17010     // ten_k represents a unit-in-the-last-place in the decimal representation
17011     // stored in buf.
17012     // Decrement buf by ten_k while this takes buf closer to w.
17013 
17014     // The tests are written in this order to avoid overflow in unsigned
17015     // integer arithmetic.
17016 
17017     while (rest < dist
17018             && delta - rest >= ten_k
17019             && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
17020     {
17021         JSON_ASSERT(buf[len - 1] != '0');
17022         buf[len - 1]--;
17023         rest += ten_k;
17024     }
17025 }
17026 
17027 /*!
17028 Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
17029 M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
17030 */
grisu2_digit_gen(char * buffer,int & length,int & decimal_exponent,diyfp M_minus,diyfp w,diyfp M_plus)17031 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
17032                              diyfp M_minus, diyfp w, diyfp M_plus)
17033 {
17034     static_assert(kAlpha >= -60, "internal error");
17035     static_assert(kGamma <= -32, "internal error");
17036 
17037     // Generates the digits (and the exponent) of a decimal floating-point
17038     // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
17039     // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
17040     //
17041     //               <--------------------------- delta ---->
17042     //                                  <---- dist --------->
17043     // --------------[------------------+-------------------]--------------
17044     //               M-                 w                   M+
17045     //
17046     // Grisu2 generates the digits of M+ from left to right and stops as soon as
17047     // V is in [M-,M+].
17048 
17049     JSON_ASSERT(M_plus.e >= kAlpha);
17050     JSON_ASSERT(M_plus.e <= kGamma);
17051 
17052     std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
17053     std::uint64_t dist  = diyfp::sub(M_plus, w      ).f; // (significand of (M+ - w ), implicit exponent is e)
17054 
17055     // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
17056     //
17057     //      M+ = f * 2^e
17058     //         = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
17059     //         = ((p1        ) * 2^-e + (p2        )) * 2^e
17060     //         = p1 + p2 * 2^e
17061 
17062     const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
17063 
17064     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.)
17065     std::uint64_t p2 = M_plus.f & (one.f - 1);                    // p2 = f mod 2^-e
17066 
17067     // 1)
17068     //
17069     // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
17070 
17071     JSON_ASSERT(p1 > 0);
17072 
17073     std::uint32_t pow10{};
17074     const int k = find_largest_pow10(p1, pow10);
17075 
17076     //      10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
17077     //
17078     //      p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
17079     //         = (d[k-1]         ) * 10^(k-1) + (p1 mod 10^(k-1))
17080     //
17081     //      M+ = p1                                             + p2 * 2^e
17082     //         = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1))          + p2 * 2^e
17083     //         = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
17084     //         = d[k-1] * 10^(k-1) + (                         rest) * 2^e
17085     //
17086     // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
17087     //
17088     //      p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
17089     //
17090     // but stop as soon as
17091     //
17092     //      rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
17093 
17094     int n = k;
17095     while (n > 0)
17096     {
17097         // Invariants:
17098         //      M+ = buffer * 10^n + (p1 + p2 * 2^e)    (buffer = 0 for n = k)
17099         //      pow10 = 10^(n-1) <= p1 < 10^n
17100         //
17101         const std::uint32_t d = p1 / pow10;  // d = p1 div 10^(n-1)
17102         const std::uint32_t r = p1 % pow10;  // r = p1 mod 10^(n-1)
17103         //
17104         //      M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
17105         //         = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
17106         //
17107         JSON_ASSERT(d <= 9);
17108         buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17109         //
17110         //      M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
17111         //
17112         p1 = r;
17113         n--;
17114         //
17115         //      M+ = buffer * 10^n + (p1 + p2 * 2^e)
17116         //      pow10 = 10^n
17117         //
17118 
17119         // Now check if enough digits have been generated.
17120         // Compute
17121         //
17122         //      p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
17123         //
17124         // Note:
17125         // Since rest and delta share the same exponent e, it suffices to
17126         // compare the significands.
17127         const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
17128         if (rest <= delta)
17129         {
17130             // V = buffer * 10^n, with M- <= V <= M+.
17131 
17132             decimal_exponent += n;
17133 
17134             // We may now just stop. But instead look if the buffer could be
17135             // decremented to bring V closer to w.
17136             //
17137             // pow10 = 10^n is now 1 ulp in the decimal representation V.
17138             // The rounding procedure works with diyfp's with an implicit
17139             // exponent of e.
17140             //
17141             //      10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
17142             //
17143             const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
17144             grisu2_round(buffer, length, dist, delta, rest, ten_n);
17145 
17146             return;
17147         }
17148 
17149         pow10 /= 10;
17150         //
17151         //      pow10 = 10^(n-1) <= p1 < 10^n
17152         // Invariants restored.
17153     }
17154 
17155     // 2)
17156     //
17157     // The digits of the integral part have been generated:
17158     //
17159     //      M+ = d[k-1]...d[1]d[0] + p2 * 2^e
17160     //         = buffer            + p2 * 2^e
17161     //
17162     // Now generate the digits of the fractional part p2 * 2^e.
17163     //
17164     // Note:
17165     // No decimal point is generated: the exponent is adjusted instead.
17166     //
17167     // p2 actually represents the fraction
17168     //
17169     //      p2 * 2^e
17170     //          = p2 / 2^-e
17171     //          = d[-1] / 10^1 + d[-2] / 10^2 + ...
17172     //
17173     // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
17174     //
17175     //      p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
17176     //                      + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
17177     //
17178     // using
17179     //
17180     //      10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
17181     //                = (                   d) * 2^-e + (                   r)
17182     //
17183     // or
17184     //      10^m * p2 * 2^e = d + r * 2^e
17185     //
17186     // i.e.
17187     //
17188     //      M+ = buffer + p2 * 2^e
17189     //         = buffer + 10^-m * (d + r * 2^e)
17190     //         = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
17191     //
17192     // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
17193 
17194     JSON_ASSERT(p2 > delta);
17195 
17196     int m = 0;
17197     for (;;)
17198     {
17199         // Invariant:
17200         //      M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
17201         //         = buffer * 10^-m + 10^-m * (p2                                 ) * 2^e
17202         //         = buffer * 10^-m + 10^-m * (1/10 * (10 * p2)                   ) * 2^e
17203         //         = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
17204         //
17205         JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
17206         p2 *= 10;
17207         const std::uint64_t d = p2 >> -one.e;     // d = (10 * p2) div 2^-e
17208         const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
17209         //
17210         //      M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
17211         //         = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
17212         //         = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
17213         //
17214         JSON_ASSERT(d <= 9);
17215         buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17216         //
17217         //      M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
17218         //
17219         p2 = r;
17220         m++;
17221         //
17222         //      M+ = buffer * 10^-m + 10^-m * p2 * 2^e
17223         // Invariant restored.
17224 
17225         // Check if enough digits have been generated.
17226         //
17227         //      10^-m * p2 * 2^e <= delta * 2^e
17228         //              p2 * 2^e <= 10^m * delta * 2^e
17229         //                    p2 <= 10^m * delta
17230         delta *= 10;
17231         dist  *= 10;
17232         if (p2 <= delta)
17233         {
17234             break;
17235         }
17236     }
17237 
17238     // V = buffer * 10^-m, with M- <= V <= M+.
17239 
17240     decimal_exponent -= m;
17241 
17242     // 1 ulp in the decimal representation is now 10^-m.
17243     // Since delta and dist are now scaled by 10^m, we need to do the
17244     // same with ulp in order to keep the units in sync.
17245     //
17246     //      10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
17247     //
17248     const std::uint64_t ten_m = one.f;
17249     grisu2_round(buffer, length, dist, delta, p2, ten_m);
17250 
17251     // By construction this algorithm generates the shortest possible decimal
17252     // number (Loitsch, Theorem 6.2) which rounds back to w.
17253     // For an input number of precision p, at least
17254     //
17255     //      N = 1 + ceil(p * log_10(2))
17256     //
17257     // decimal digits are sufficient to identify all binary floating-point
17258     // numbers (Matula, "In-and-Out conversions").
17259     // This implies that the algorithm does not produce more than N decimal
17260     // digits.
17261     //
17262     //      N = 17 for p = 53 (IEEE double precision)
17263     //      N = 9  for p = 24 (IEEE single precision)
17264 }
17265 
17266 /*!
17267 v = buf * 10^decimal_exponent
17268 len is the length of the buffer (number of decimal digits)
17269 The buffer must be large enough, i.e. >= max_digits10.
17270 */
17271 JSON_HEDLEY_NON_NULL(1)
grisu2(char * buf,int & len,int & decimal_exponent,diyfp m_minus,diyfp v,diyfp m_plus)17272 inline void grisu2(char* buf, int& len, int& decimal_exponent,
17273                    diyfp m_minus, diyfp v, diyfp m_plus)
17274 {
17275     JSON_ASSERT(m_plus.e == m_minus.e);
17276     JSON_ASSERT(m_plus.e == v.e);
17277 
17278     //  --------(-----------------------+-----------------------)--------    (A)
17279     //          m-                      v                       m+
17280     //
17281     //  --------------------(-----------+-----------------------)--------    (B)
17282     //                      m-          v                       m+
17283     //
17284     // First scale v (and m- and m+) such that the exponent is in the range
17285     // [alpha, gamma].
17286 
17287     const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
17288 
17289     const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
17290 
17291     // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
17292     const diyfp w       = diyfp::mul(v,       c_minus_k);
17293     const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
17294     const diyfp w_plus  = diyfp::mul(m_plus,  c_minus_k);
17295 
17296     //  ----(---+---)---------------(---+---)---------------(---+---)----
17297     //          w-                      w                       w+
17298     //          = c*m-                  = c*v                   = c*m+
17299     //
17300     // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
17301     // w+ are now off by a small amount.
17302     // In fact:
17303     //
17304     //      w - v * 10^k < 1 ulp
17305     //
17306     // To account for this inaccuracy, add resp. subtract 1 ulp.
17307     //
17308     //  --------+---[---------------(---+---)---------------]---+--------
17309     //          w-  M-                  w                   M+  w+
17310     //
17311     // Now any number in [M-, M+] (bounds included) will round to w when input,
17312     // regardless of how the input rounding algorithm breaks ties.
17313     //
17314     // And digit_gen generates the shortest possible such number in [M-, M+].
17315     // Note that this does not mean that Grisu2 always generates the shortest
17316     // possible number in the interval (m-, m+).
17317     const diyfp M_minus(w_minus.f + 1, w_minus.e);
17318     const diyfp M_plus (w_plus.f  - 1, w_plus.e );
17319 
17320     decimal_exponent = -cached.k; // = -(-k) = k
17321 
17322     grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
17323 }
17324 
17325 /*!
17326 v = buf * 10^decimal_exponent
17327 len is the length of the buffer (number of decimal digits)
17328 The buffer must be large enough, i.e. >= max_digits10.
17329 */
17330 template<typename FloatType>
17331 JSON_HEDLEY_NON_NULL(1)
grisu2(char * buf,int & len,int & decimal_exponent,FloatType value)17332 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
17333 {
17334     static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
17335                   "internal error: not enough precision");
17336 
17337     JSON_ASSERT(std::isfinite(value));
17338     JSON_ASSERT(value > 0);
17339 
17340     // If the neighbors (and boundaries) of 'value' are always computed for double-precision
17341     // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
17342     // decimal representations are not exactly "short".
17343     //
17344     // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
17345     // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
17346     // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
17347     // does.
17348     // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
17349     // representation using the corresponding std::from_chars function recovers value exactly". That
17350     // indicates that single precision floating-point numbers should be recovered using
17351     // 'std::strtof'.
17352     //
17353     // NB: If the neighbors are computed for single-precision numbers, there is a single float
17354     //     (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
17355     //     value is off by 1 ulp.
17356 #if 0
17357     const boundaries w = compute_boundaries(static_cast<double>(value));
17358 #else
17359     const boundaries w = compute_boundaries(value);
17360 #endif
17361 
17362     grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
17363 }
17364 
17365 /*!
17366 @brief appends a decimal representation of e to buf
17367 @return a pointer to the element following the exponent.
17368 @pre -1000 < e < 1000
17369 */
17370 JSON_HEDLEY_NON_NULL(1)
17371 JSON_HEDLEY_RETURNS_NON_NULL
append_exponent(char * buf,int e)17372 inline char* append_exponent(char* buf, int e)
17373 {
17374     JSON_ASSERT(e > -1000);
17375     JSON_ASSERT(e <  1000);
17376 
17377     if (e < 0)
17378     {
17379         e = -e;
17380         *buf++ = '-';
17381     }
17382     else
17383     {
17384         *buf++ = '+';
17385     }
17386 
17387     auto k = static_cast<std::uint32_t>(e);
17388     if (k < 10)
17389     {
17390         // Always print at least two digits in the exponent.
17391         // This is for compatibility with printf("%g").
17392         *buf++ = '0';
17393         *buf++ = static_cast<char>('0' + k);
17394     }
17395     else if (k < 100)
17396     {
17397         *buf++ = static_cast<char>('0' + k / 10);
17398         k %= 10;
17399         *buf++ = static_cast<char>('0' + k);
17400     }
17401     else
17402     {
17403         *buf++ = static_cast<char>('0' + k / 100);
17404         k %= 100;
17405         *buf++ = static_cast<char>('0' + k / 10);
17406         k %= 10;
17407         *buf++ = static_cast<char>('0' + k);
17408     }
17409 
17410     return buf;
17411 }
17412 
17413 /*!
17414 @brief prettify v = buf * 10^decimal_exponent
17415 
17416 If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
17417 notation. Otherwise it will be printed in exponential notation.
17418 
17419 @pre min_exp < 0
17420 @pre max_exp > 0
17421 */
17422 JSON_HEDLEY_NON_NULL(1)
17423 JSON_HEDLEY_RETURNS_NON_NULL
format_buffer(char * buf,int len,int decimal_exponent,int min_exp,int max_exp)17424 inline char* format_buffer(char* buf, int len, int decimal_exponent,
17425                            int min_exp, int max_exp)
17426 {
17427     JSON_ASSERT(min_exp < 0);
17428     JSON_ASSERT(max_exp > 0);
17429 
17430     const int k = len;
17431     const int n = len + decimal_exponent;
17432 
17433     // v = buf * 10^(n-k)
17434     // k is the length of the buffer (number of decimal digits)
17435     // n is the position of the decimal point relative to the start of the buffer.
17436 
17437     if (k <= n && n <= max_exp)
17438     {
17439         // digits[000]
17440         // len <= max_exp + 2
17441 
17442         std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
17443         // Make it look like a floating-point number (#362, #378)
17444         buf[n + 0] = '.';
17445         buf[n + 1] = '0';
17446         return buf + (static_cast<size_t>(n) + 2);
17447     }
17448 
17449     if (0 < n && n <= max_exp)
17450     {
17451         // dig.its
17452         // len <= max_digits10 + 1
17453 
17454         JSON_ASSERT(k > n);
17455 
17456         std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
17457         buf[n] = '.';
17458         return buf + (static_cast<size_t>(k) + 1U);
17459     }
17460 
17461     if (min_exp < n && n <= 0)
17462     {
17463         // 0.[000]digits
17464         // len <= 2 + (-min_exp - 1) + max_digits10
17465 
17466         std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
17467         buf[0] = '0';
17468         buf[1] = '.';
17469         std::memset(buf + 2, '0', static_cast<size_t>(-n));
17470         return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
17471     }
17472 
17473     if (k == 1)
17474     {
17475         // dE+123
17476         // len <= 1 + 5
17477 
17478         buf += 1;
17479     }
17480     else
17481     {
17482         // d.igitsE+123
17483         // len <= max_digits10 + 1 + 5
17484 
17485         std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
17486         buf[1] = '.';
17487         buf += 1 + static_cast<size_t>(k);
17488     }
17489 
17490     *buf++ = 'e';
17491     return append_exponent(buf, n - 1);
17492 }
17493 
17494 } // namespace dtoa_impl
17495 
17496 /*!
17497 @brief generates a decimal representation of the floating-point number value in [first, last).
17498 
17499 The format of the resulting decimal representation is similar to printf's %g
17500 format. Returns an iterator pointing past-the-end of the decimal representation.
17501 
17502 @note The input number must be finite, i.e. NaN's and Inf's are not supported.
17503 @note The buffer must be large enough.
17504 @note The result is NOT null-terminated.
17505 */
17506 template<typename FloatType>
17507 JSON_HEDLEY_NON_NULL(1, 2)
17508 JSON_HEDLEY_RETURNS_NON_NULL
to_chars(char * first,const char * last,FloatType value)17509 char* to_chars(char* first, const char* last, FloatType value)
17510 {
17511     static_cast<void>(last); // maybe unused - fix warning
17512     JSON_ASSERT(std::isfinite(value));
17513 
17514     // Use signbit(value) instead of (value < 0) since signbit works for -0.
17515     if (std::signbit(value))
17516     {
17517         value = -value;
17518         *first++ = '-';
17519     }
17520 
17521 #ifdef __GNUC__
17522 #pragma GCC diagnostic push
17523 #pragma GCC diagnostic ignored "-Wfloat-equal"
17524 #endif
17525     if (value == 0) // +-0
17526     {
17527         *first++ = '0';
17528         // Make it look like a floating-point number (#362, #378)
17529         *first++ = '.';
17530         *first++ = '0';
17531         return first;
17532     }
17533 #ifdef __GNUC__
17534 #pragma GCC diagnostic pop
17535 #endif
17536 
17537     JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
17538 
17539     // Compute v = buffer * 10^decimal_exponent.
17540     // The decimal digits are stored in the buffer, which needs to be interpreted
17541     // as an unsigned decimal integer.
17542     // len is the length of the buffer, i.e. the number of decimal digits.
17543     int len = 0;
17544     int decimal_exponent = 0;
17545     dtoa_impl::grisu2(first, len, decimal_exponent, value);
17546 
17547     JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
17548 
17549     // Format the buffer like printf("%.*g", prec, value)
17550     constexpr int kMinExp = -4;
17551     // Use digits10 here to increase compatibility with version 2.
17552     constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
17553 
17554     JSON_ASSERT(last - first >= kMaxExp + 2);
17555     JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
17556     JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
17557 
17558     return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
17559 }
17560 
17561 } // namespace detail
17562 } // namespace nlohmann
17563 
17564 // #include <nlohmann/detail/exceptions.hpp>
17565 
17566 // #include <nlohmann/detail/macro_scope.hpp>
17567 
17568 // #include <nlohmann/detail/meta/cpp_future.hpp>
17569 
17570 // #include <nlohmann/detail/output/binary_writer.hpp>
17571 
17572 // #include <nlohmann/detail/output/output_adapters.hpp>
17573 
17574 // #include <nlohmann/detail/string_concat.hpp>
17575 
17576 // #include <nlohmann/detail/value_t.hpp>
17577 
17578 
17579 namespace nlohmann
17580 {
17581 namespace detail
17582 {
17583 ///////////////////
17584 // serialization //
17585 ///////////////////
17586 
17587 /// how to treat decoding errors
17588 enum class error_handler_t
17589 {
17590     strict,  ///< throw a type_error exception in case of invalid UTF-8
17591     replace, ///< replace invalid UTF-8 sequences with U+FFFD
17592     ignore   ///< ignore invalid UTF-8 sequences
17593 };
17594 
17595 template<typename BasicJsonType>
17596 class serializer
17597 {
17598     using string_t = typename BasicJsonType::string_t;
17599     using number_float_t = typename BasicJsonType::number_float_t;
17600     using number_integer_t = typename BasicJsonType::number_integer_t;
17601     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
17602     using binary_char_t = typename BasicJsonType::binary_t::value_type;
17603     static constexpr std::uint8_t UTF8_ACCEPT = 0;
17604     static constexpr std::uint8_t UTF8_REJECT = 1;
17605 
17606   public:
17607     /*!
17608     @param[in] s  output stream to serialize to
17609     @param[in] ichar  indentation character to use
17610     @param[in] error_handler_  how to react on decoding errors
17611     */
serializer(output_adapter_t<char> s,const char ichar,error_handler_t error_handler_=error_handler_t::strict)17612     serializer(output_adapter_t<char> s, const char ichar,
17613                error_handler_t error_handler_ = error_handler_t::strict)
17614         : o(std::move(s))
17615         , loc(std::localeconv())
17616         , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
17617         , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
17618         , indent_char(ichar)
17619         , indent_string(512, indent_char)
17620         , error_handler(error_handler_)
17621     {}
17622 
17623     // delete because of pointer members
17624     serializer(const serializer&) = delete;
17625     serializer& operator=(const serializer&) = delete;
17626     serializer(serializer&&) = delete;
17627     serializer& operator=(serializer&&) = delete;
17628     ~serializer() = default;
17629 
17630     /*!
17631     @brief internal implementation of the serialization function
17632 
17633     This function is called by the public member function dump and organizes
17634     the serialization internally. The indentation level is propagated as
17635     additional parameter. In case of arrays and objects, the function is
17636     called recursively.
17637 
17638     - strings and object keys are escaped using `escape_string()`
17639     - integer numbers are converted implicitly via `operator<<`
17640     - floating-point numbers are converted to a string using `"%g"` format
17641     - binary values are serialized as objects containing the subtype and the
17642       byte array
17643 
17644     @param[in] val               value to serialize
17645     @param[in] pretty_print      whether the output shall be pretty-printed
17646     @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
17647     in the output are escaped with `\uXXXX` sequences, and the result consists
17648     of ASCII characters only.
17649     @param[in] indent_step       the indent level
17650     @param[in] current_indent    the current indent level (only used internally)
17651     */
dump(const BasicJsonType & val,const bool pretty_print,const bool ensure_ascii,const unsigned int indent_step,const unsigned int current_indent=0)17652     void dump(const BasicJsonType& val,
17653               const bool pretty_print,
17654               const bool ensure_ascii,
17655               const unsigned int indent_step,
17656               const unsigned int current_indent = 0)
17657     {
17658         switch (val.m_type)
17659         {
17660             case value_t::object:
17661             {
17662                 if (val.m_value.object->empty())
17663                 {
17664                     o->write_characters("{}", 2);
17665                     return;
17666                 }
17667 
17668                 if (pretty_print)
17669                 {
17670                     o->write_characters("{\n", 2);
17671 
17672                     // variable to hold indentation for recursive calls
17673                     const auto new_indent = current_indent + indent_step;
17674                     if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
17675                     {
17676                         indent_string.resize(indent_string.size() * 2, ' ');
17677                     }
17678 
17679                     // first n-1 elements
17680                     auto i = val.m_value.object->cbegin();
17681                     for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
17682                     {
17683                         o->write_characters(indent_string.c_str(), new_indent);
17684                         o->write_character('\"');
17685                         dump_escaped(i->first, ensure_ascii);
17686                         o->write_characters("\": ", 3);
17687                         dump(i->second, true, ensure_ascii, indent_step, new_indent);
17688                         o->write_characters(",\n", 2);
17689                     }
17690 
17691                     // last element
17692                     JSON_ASSERT(i != val.m_value.object->cend());
17693                     JSON_ASSERT(std::next(i) == val.m_value.object->cend());
17694                     o->write_characters(indent_string.c_str(), new_indent);
17695                     o->write_character('\"');
17696                     dump_escaped(i->first, ensure_ascii);
17697                     o->write_characters("\": ", 3);
17698                     dump(i->second, true, ensure_ascii, indent_step, new_indent);
17699 
17700                     o->write_character('\n');
17701                     o->write_characters(indent_string.c_str(), current_indent);
17702                     o->write_character('}');
17703                 }
17704                 else
17705                 {
17706                     o->write_character('{');
17707 
17708                     // first n-1 elements
17709                     auto i = val.m_value.object->cbegin();
17710                     for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
17711                     {
17712                         o->write_character('\"');
17713                         dump_escaped(i->first, ensure_ascii);
17714                         o->write_characters("\":", 2);
17715                         dump(i->second, false, ensure_ascii, indent_step, current_indent);
17716                         o->write_character(',');
17717                     }
17718 
17719                     // last element
17720                     JSON_ASSERT(i != val.m_value.object->cend());
17721                     JSON_ASSERT(std::next(i) == val.m_value.object->cend());
17722                     o->write_character('\"');
17723                     dump_escaped(i->first, ensure_ascii);
17724                     o->write_characters("\":", 2);
17725                     dump(i->second, false, ensure_ascii, indent_step, current_indent);
17726 
17727                     o->write_character('}');
17728                 }
17729 
17730                 return;
17731             }
17732 
17733             case value_t::array:
17734             {
17735                 if (val.m_value.array->empty())
17736                 {
17737                     o->write_characters("[]", 2);
17738                     return;
17739                 }
17740 
17741                 if (pretty_print)
17742                 {
17743                     o->write_characters("[\n", 2);
17744 
17745                     // variable to hold indentation for recursive calls
17746                     const auto new_indent = current_indent + indent_step;
17747                     if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
17748                     {
17749                         indent_string.resize(indent_string.size() * 2, ' ');
17750                     }
17751 
17752                     // first n-1 elements
17753                     for (auto i = val.m_value.array->cbegin();
17754                             i != val.m_value.array->cend() - 1; ++i)
17755                     {
17756                         o->write_characters(indent_string.c_str(), new_indent);
17757                         dump(*i, true, ensure_ascii, indent_step, new_indent);
17758                         o->write_characters(",\n", 2);
17759                     }
17760 
17761                     // last element
17762                     JSON_ASSERT(!val.m_value.array->empty());
17763                     o->write_characters(indent_string.c_str(), new_indent);
17764                     dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
17765 
17766                     o->write_character('\n');
17767                     o->write_characters(indent_string.c_str(), current_indent);
17768                     o->write_character(']');
17769                 }
17770                 else
17771                 {
17772                     o->write_character('[');
17773 
17774                     // first n-1 elements
17775                     for (auto i = val.m_value.array->cbegin();
17776                             i != val.m_value.array->cend() - 1; ++i)
17777                     {
17778                         dump(*i, false, ensure_ascii, indent_step, current_indent);
17779                         o->write_character(',');
17780                     }
17781 
17782                     // last element
17783                     JSON_ASSERT(!val.m_value.array->empty());
17784                     dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
17785 
17786                     o->write_character(']');
17787                 }
17788 
17789                 return;
17790             }
17791 
17792             case value_t::string:
17793             {
17794                 o->write_character('\"');
17795                 dump_escaped(*val.m_value.string, ensure_ascii);
17796                 o->write_character('\"');
17797                 return;
17798             }
17799 
17800             case value_t::binary:
17801             {
17802                 if (pretty_print)
17803                 {
17804                     o->write_characters("{\n", 2);
17805 
17806                     // variable to hold indentation for recursive calls
17807                     const auto new_indent = current_indent + indent_step;
17808                     if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
17809                     {
17810                         indent_string.resize(indent_string.size() * 2, ' ');
17811                     }
17812 
17813                     o->write_characters(indent_string.c_str(), new_indent);
17814 
17815                     o->write_characters("\"bytes\": [", 10);
17816 
17817                     if (!val.m_value.binary->empty())
17818                     {
17819                         for (auto i = val.m_value.binary->cbegin();
17820                                 i != val.m_value.binary->cend() - 1; ++i)
17821                         {
17822                             dump_integer(*i);
17823                             o->write_characters(", ", 2);
17824                         }
17825                         dump_integer(val.m_value.binary->back());
17826                     }
17827 
17828                     o->write_characters("],\n", 3);
17829                     o->write_characters(indent_string.c_str(), new_indent);
17830 
17831                     o->write_characters("\"subtype\": ", 11);
17832                     if (val.m_value.binary->has_subtype())
17833                     {
17834                         dump_integer(val.m_value.binary->subtype());
17835                     }
17836                     else
17837                     {
17838                         o->write_characters("null", 4);
17839                     }
17840                     o->write_character('\n');
17841                     o->write_characters(indent_string.c_str(), current_indent);
17842                     o->write_character('}');
17843                 }
17844                 else
17845                 {
17846                     o->write_characters("{\"bytes\":[", 10);
17847 
17848                     if (!val.m_value.binary->empty())
17849                     {
17850                         for (auto i = val.m_value.binary->cbegin();
17851                                 i != val.m_value.binary->cend() - 1; ++i)
17852                         {
17853                             dump_integer(*i);
17854                             o->write_character(',');
17855                         }
17856                         dump_integer(val.m_value.binary->back());
17857                     }
17858 
17859                     o->write_characters("],\"subtype\":", 12);
17860                     if (val.m_value.binary->has_subtype())
17861                     {
17862                         dump_integer(val.m_value.binary->subtype());
17863                         o->write_character('}');
17864                     }
17865                     else
17866                     {
17867                         o->write_characters("null}", 5);
17868                     }
17869                 }
17870                 return;
17871             }
17872 
17873             case value_t::boolean:
17874             {
17875                 if (val.m_value.boolean)
17876                 {
17877                     o->write_characters("true", 4);
17878                 }
17879                 else
17880                 {
17881                     o->write_characters("false", 5);
17882                 }
17883                 return;
17884             }
17885 
17886             case value_t::number_integer:
17887             {
17888                 dump_integer(val.m_value.number_integer);
17889                 return;
17890             }
17891 
17892             case value_t::number_unsigned:
17893             {
17894                 dump_integer(val.m_value.number_unsigned);
17895                 return;
17896             }
17897 
17898             case value_t::number_float:
17899             {
17900                 dump_float(val.m_value.number_float);
17901                 return;
17902             }
17903 
17904             case value_t::discarded:
17905             {
17906                 o->write_characters("<discarded>", 11);
17907                 return;
17908             }
17909 
17910             case value_t::null:
17911             {
17912                 o->write_characters("null", 4);
17913                 return;
17914             }
17915 
17916             default:            // LCOV_EXCL_LINE
17917                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
17918         }
17919     }
17920 
17921   JSON_PRIVATE_UNLESS_TESTED:
17922     /*!
17923     @brief dump escaped string
17924 
17925     Escape a string by replacing certain special characters by a sequence of an
17926     escape character (backslash) and another character and other control
17927     characters by a sequence of "\u" followed by a four-digit hex
17928     representation. The escaped string is written to output stream @a o.
17929 
17930     @param[in] s  the string to escape
17931     @param[in] ensure_ascii  whether to escape non-ASCII characters with
17932                              \uXXXX sequences
17933 
17934     @complexity Linear in the length of string @a s.
17935     */
17936     void dump_escaped(const string_t& s, const bool ensure_ascii)
17937     {
17938         std::uint32_t codepoint{};
17939         std::uint8_t state = UTF8_ACCEPT;
17940         std::size_t bytes = 0;  // number of bytes written to string_buffer
17941 
17942         // number of bytes written at the point of the last valid byte
17943         std::size_t bytes_after_last_accept = 0;
17944         std::size_t undumped_chars = 0;
17945 
17946         for (std::size_t i = 0; i < s.size(); ++i)
17947         {
17948             const auto byte = static_cast<std::uint8_t>(s[i]);
17949 
17950             switch (decode(state, codepoint, byte))
17951             {
17952                 case UTF8_ACCEPT:  // decode found a new code point
17953                 {
17954                     switch (codepoint)
17955                     {
17956                         case 0x08: // backspace
17957                         {
17958                             string_buffer[bytes++] = '\\';
17959                             string_buffer[bytes++] = 'b';
17960                             break;
17961                         }
17962 
17963                         case 0x09: // horizontal tab
17964                         {
17965                             string_buffer[bytes++] = '\\';
17966                             string_buffer[bytes++] = 't';
17967                             break;
17968                         }
17969 
17970                         case 0x0A: // newline
17971                         {
17972                             string_buffer[bytes++] = '\\';
17973                             string_buffer[bytes++] = 'n';
17974                             break;
17975                         }
17976 
17977                         case 0x0C: // formfeed
17978                         {
17979                             string_buffer[bytes++] = '\\';
17980                             string_buffer[bytes++] = 'f';
17981                             break;
17982                         }
17983 
17984                         case 0x0D: // carriage return
17985                         {
17986                             string_buffer[bytes++] = '\\';
17987                             string_buffer[bytes++] = 'r';
17988                             break;
17989                         }
17990 
17991                         case 0x22: // quotation mark
17992                         {
17993                             string_buffer[bytes++] = '\\';
17994                             string_buffer[bytes++] = '\"';
17995                             break;
17996                         }
17997 
17998                         case 0x5C: // reverse solidus
17999                         {
18000                             string_buffer[bytes++] = '\\';
18001                             string_buffer[bytes++] = '\\';
18002                             break;
18003                         }
18004 
18005                         default:
18006                         {
18007                             // escape control characters (0x00..0x1F) or, if
18008                             // ensure_ascii parameter is used, non-ASCII characters
18009                             if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
18010                             {
18011                                 if (codepoint <= 0xFFFF)
18012                                 {
18013                                     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18014                                     static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
18015                                                                       static_cast<std::uint16_t>(codepoint)));
18016                                     bytes += 6;
18017                                 }
18018                                 else
18019                                 {
18020                                     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18021                                     static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
18022                                                                       static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
18023                                                                       static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
18024                                     bytes += 12;
18025                                 }
18026                             }
18027                             else
18028                             {
18029                                 // copy byte to buffer (all previous bytes
18030                                 // been copied have in default case above)
18031                                 string_buffer[bytes++] = s[i];
18032                             }
18033                             break;
18034                         }
18035                     }
18036 
18037                     // write buffer and reset index; there must be 13 bytes
18038                     // left, as this is the maximal number of bytes to be
18039                     // written ("\uxxxx\uxxxx\0") for one code point
18040                     if (string_buffer.size() - bytes < 13)
18041                     {
18042                         o->write_characters(string_buffer.data(), bytes);
18043                         bytes = 0;
18044                     }
18045 
18046                     // remember the byte position of this accept
18047                     bytes_after_last_accept = bytes;
18048                     undumped_chars = 0;
18049                     break;
18050                 }
18051 
18052                 case UTF8_REJECT:  // decode found invalid UTF-8 byte
18053                 {
18054                     switch (error_handler)
18055                     {
18056                         case error_handler_t::strict:
18057                         {
18058                             JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
18059                         }
18060 
18061                         case error_handler_t::ignore:
18062                         case error_handler_t::replace:
18063                         {
18064                             // in case we saw this character the first time, we
18065                             // would like to read it again, because the byte
18066                             // may be OK for itself, but just not OK for the
18067                             // previous sequence
18068                             if (undumped_chars > 0)
18069                             {
18070                                 --i;
18071                             }
18072 
18073                             // reset length buffer to the last accepted index;
18074                             // thus removing/ignoring the invalid characters
18075                             bytes = bytes_after_last_accept;
18076 
18077                             if (error_handler == error_handler_t::replace)
18078                             {
18079                                 // add a replacement character
18080                                 if (ensure_ascii)
18081                                 {
18082                                     string_buffer[bytes++] = '\\';
18083                                     string_buffer[bytes++] = 'u';
18084                                     string_buffer[bytes++] = 'f';
18085                                     string_buffer[bytes++] = 'f';
18086                                     string_buffer[bytes++] = 'f';
18087                                     string_buffer[bytes++] = 'd';
18088                                 }
18089                                 else
18090                                 {
18091                                     string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
18092                                     string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
18093                                     string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
18094                                 }
18095 
18096                                 // write buffer and reset index; there must be 13 bytes
18097                                 // left, as this is the maximal number of bytes to be
18098                                 // written ("\uxxxx\uxxxx\0") for one code point
18099                                 if (string_buffer.size() - bytes < 13)
18100                                 {
18101                                     o->write_characters(string_buffer.data(), bytes);
18102                                     bytes = 0;
18103                                 }
18104 
18105                                 bytes_after_last_accept = bytes;
18106                             }
18107 
18108                             undumped_chars = 0;
18109 
18110                             // continue processing the string
18111                             state = UTF8_ACCEPT;
18112                             break;
18113                         }
18114 
18115                         default:            // LCOV_EXCL_LINE
18116                             JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18117                     }
18118                     break;
18119                 }
18120 
18121                 default:  // decode found yet incomplete multi-byte code point
18122                 {
18123                     if (!ensure_ascii)
18124                     {
18125                         // code point will not be escaped - copy byte to buffer
18126                         string_buffer[bytes++] = s[i];
18127                     }
18128                     ++undumped_chars;
18129                     break;
18130                 }
18131             }
18132         }
18133 
18134         // we finished processing the string
18135         if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
18136         {
18137             // write buffer
18138             if (bytes > 0)
18139             {
18140                 o->write_characters(string_buffer.data(), bytes);
18141             }
18142         }
18143         else
18144         {
18145             // we finish reading, but do not accept: string was incomplete
18146             switch (error_handler)
18147             {
18148                 case error_handler_t::strict:
18149                 {
18150                     JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
18151                 }
18152 
18153                 case error_handler_t::ignore:
18154                 {
18155                     // write all accepted bytes
18156                     o->write_characters(string_buffer.data(), bytes_after_last_accept);
18157                     break;
18158                 }
18159 
18160                 case error_handler_t::replace:
18161                 {
18162                     // write all accepted bytes
18163                     o->write_characters(string_buffer.data(), bytes_after_last_accept);
18164                     // add a replacement character
18165                     if (ensure_ascii)
18166                     {
18167                         o->write_characters("\\ufffd", 6);
18168                     }
18169                     else
18170                     {
18171                         o->write_characters("\xEF\xBF\xBD", 3);
18172                     }
18173                     break;
18174                 }
18175 
18176                 default:            // LCOV_EXCL_LINE
18177                     JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18178             }
18179         }
18180     }
18181 
18182   private:
18183     /*!
18184     @brief count digits
18185 
18186     Count the number of decimal (base 10) digits for an input unsigned integer.
18187 
18188     @param[in] x  unsigned integer number to count its digits
18189     @return    number of decimal digits
18190     */
count_digits(number_unsigned_t x)18191     inline unsigned int count_digits(number_unsigned_t x) noexcept
18192     {
18193         unsigned int n_digits = 1;
18194         for (;;)
18195         {
18196             if (x < 10)
18197             {
18198                 return n_digits;
18199             }
18200             if (x < 100)
18201             {
18202                 return n_digits + 1;
18203             }
18204             if (x < 1000)
18205             {
18206                 return n_digits + 2;
18207             }
18208             if (x < 10000)
18209             {
18210                 return n_digits + 3;
18211             }
18212             x = x / 10000u;
18213             n_digits += 4;
18214         }
18215     }
18216 
18217     /*!
18218      * @brief convert a byte to a uppercase hex representation
18219      * @param[in] byte byte to represent
18220      * @return representation ("00".."FF")
18221      */
hex_bytes(std::uint8_t byte)18222     static std::string hex_bytes(std::uint8_t byte)
18223     {
18224         std::string result = "FF";
18225         constexpr const char* nibble_to_hex = "0123456789ABCDEF";
18226         result[0] = nibble_to_hex[byte / 16];
18227         result[1] = nibble_to_hex[byte % 16];
18228         return result;
18229     }
18230 
18231     // templates to avoid warnings about useless casts
18232     template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
is_negative_number(NumberType x)18233     bool is_negative_number(NumberType x)
18234     {
18235         return x < 0;
18236     }
18237 
18238     template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
is_negative_number(NumberType)18239     bool is_negative_number(NumberType /*unused*/)
18240     {
18241         return false;
18242     }
18243 
18244     /*!
18245     @brief dump an integer
18246 
18247     Dump a given integer to output stream @a o. Works internally with
18248     @a number_buffer.
18249 
18250     @param[in] x  integer number (signed or unsigned) to dump
18251     @tparam NumberType either @a number_integer_t or @a number_unsigned_t
18252     */
18253     template < typename NumberType, detail::enable_if_t <
18254                    std::is_integral<NumberType>::value ||
18255                    std::is_same<NumberType, number_unsigned_t>::value ||
18256                    std::is_same<NumberType, number_integer_t>::value ||
18257                    std::is_same<NumberType, binary_char_t>::value,
18258                    int > = 0 >
dump_integer(NumberType x)18259     void dump_integer(NumberType x)
18260     {
18261         static constexpr std::array<std::array<char, 2>, 100> digits_to_99
18262         {
18263             {
18264                 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
18265                 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
18266                 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
18267                 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
18268                 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
18269                 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
18270                 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
18271                 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
18272                 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
18273                 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
18274             }
18275         };
18276 
18277         // special case for "0"
18278         if (x == 0)
18279         {
18280             o->write_character('0');
18281             return;
18282         }
18283 
18284         // use a pointer to fill the buffer
18285         auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18286 
18287         number_unsigned_t abs_value;
18288 
18289         unsigned int n_chars{};
18290 
18291         if (is_negative_number(x))
18292         {
18293             *buffer_ptr = '-';
18294             abs_value = remove_sign(static_cast<number_integer_t>(x));
18295 
18296             // account one more byte for the minus sign
18297             n_chars = 1 + count_digits(abs_value);
18298         }
18299         else
18300         {
18301             abs_value = static_cast<number_unsigned_t>(x);
18302             n_chars = count_digits(abs_value);
18303         }
18304 
18305         // spare 1 byte for '\0'
18306         JSON_ASSERT(n_chars < number_buffer.size() - 1);
18307 
18308         // jump to the end to generate the string from backward,
18309         // so we later avoid reversing the result
18310         buffer_ptr += n_chars;
18311 
18312         // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
18313         // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
18314         while (abs_value >= 100)
18315         {
18316             const auto digits_index = static_cast<unsigned>((abs_value % 100));
18317             abs_value /= 100;
18318             *(--buffer_ptr) = digits_to_99[digits_index][1];
18319             *(--buffer_ptr) = digits_to_99[digits_index][0];
18320         }
18321 
18322         if (abs_value >= 10)
18323         {
18324             const auto digits_index = static_cast<unsigned>(abs_value);
18325             *(--buffer_ptr) = digits_to_99[digits_index][1];
18326             *(--buffer_ptr) = digits_to_99[digits_index][0];
18327         }
18328         else
18329         {
18330             *(--buffer_ptr) = static_cast<char>('0' + abs_value);
18331         }
18332 
18333         o->write_characters(number_buffer.data(), n_chars);
18334     }
18335 
18336     /*!
18337     @brief dump a floating-point number
18338 
18339     Dump a given floating-point number to output stream @a o. Works internally
18340     with @a number_buffer.
18341 
18342     @param[in] x  floating-point number to dump
18343     */
dump_float(number_float_t x)18344     void dump_float(number_float_t x)
18345     {
18346         // NaN / inf
18347         if (!std::isfinite(x))
18348         {
18349             o->write_characters("null", 4);
18350             return;
18351         }
18352 
18353         // If number_float_t is an IEEE-754 single or double precision number,
18354         // use the Grisu2 algorithm to produce short numbers which are
18355         // guaranteed to round-trip, using strtof and strtod, resp.
18356         //
18357         // NB: The test below works if <long double> == <double>.
18358         static constexpr bool is_ieee_single_or_double
18359             = (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) ||
18360               (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);
18361 
18362         dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
18363     }
18364 
dump_float(number_float_t x,std::true_type)18365     void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
18366     {
18367         auto* begin = number_buffer.data();
18368         auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
18369 
18370         o->write_characters(begin, static_cast<size_t>(end - begin));
18371     }
18372 
dump_float(number_float_t x,std::false_type)18373     void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
18374     {
18375         // get number of digits for a float -> text -> float round-trip
18376         static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
18377 
18378         // the actual conversion
18379         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18380         std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
18381 
18382         // negative value indicates an error
18383         JSON_ASSERT(len > 0);
18384         // check if buffer was large enough
18385         JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
18386 
18387         // erase thousands separator
18388         if (thousands_sep != '\0')
18389         {
18390             // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
18391             const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
18392             std::fill(end, number_buffer.end(), '\0');
18393             JSON_ASSERT((end - number_buffer.begin()) <= len);
18394             len = (end - number_buffer.begin());
18395         }
18396 
18397         // convert decimal point to '.'
18398         if (decimal_point != '\0' && decimal_point != '.')
18399         {
18400             // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
18401             const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
18402             if (dec_pos != number_buffer.end())
18403             {
18404                 *dec_pos = '.';
18405             }
18406         }
18407 
18408         o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
18409 
18410         // determine if we need to append ".0"
18411         const bool value_is_int_like =
18412             std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
18413                          [](char c)
18414         {
18415             return c == '.' || c == 'e';
18416         });
18417 
18418         if (value_is_int_like)
18419         {
18420             o->write_characters(".0", 2);
18421         }
18422     }
18423 
18424     /*!
18425     @brief check whether a string is UTF-8 encoded
18426 
18427     The function checks each byte of a string whether it is UTF-8 encoded. The
18428     result of the check is stored in the @a state parameter. The function must
18429     be called initially with state 0 (accept). State 1 means the string must
18430     be rejected, because the current byte is not allowed. If the string is
18431     completely processed, but the state is non-zero, the string ended
18432     prematurely; that is, the last byte indicated more bytes should have
18433     followed.
18434 
18435     @param[in,out] state  the state of the decoding
18436     @param[in,out] codep  codepoint (valid only if resulting state is UTF8_ACCEPT)
18437     @param[in] byte       next byte to decode
18438     @return               new state
18439 
18440     @note The function has been edited: a std::array is used.
18441 
18442     @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <[email protected]>
18443     @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
18444     */
decode(std::uint8_t & state,std::uint32_t & codep,const std::uint8_t byte)18445     static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
18446     {
18447         static const std::array<std::uint8_t, 400> utf8d =
18448         {
18449             {
18450                 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
18451                 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
18452                 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
18453                 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
18454                 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
18455                 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
18456                 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
18457                 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
18458                 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
18459                 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
18460                 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
18461                 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
18462                 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
18463                 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
18464             }
18465         };
18466 
18467         JSON_ASSERT(byte < utf8d.size());
18468         const std::uint8_t type = utf8d[byte];
18469 
18470         codep = (state != UTF8_ACCEPT)
18471                 ? (byte & 0x3fu) | (codep << 6u)
18472                 : (0xFFu >> type) & (byte);
18473 
18474         std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
18475         JSON_ASSERT(index < 400);
18476         state = utf8d[index];
18477         return state;
18478     }
18479 
18480     /*
18481      * Overload to make the compiler happy while it is instantiating
18482      * dump_integer for number_unsigned_t.
18483      * Must never be called.
18484      */
remove_sign(number_unsigned_t x)18485     number_unsigned_t remove_sign(number_unsigned_t x)
18486     {
18487         JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18488         return x; // LCOV_EXCL_LINE
18489     }
18490 
18491     /*
18492      * Helper function for dump_integer
18493      *
18494      * This function takes a negative signed integer and returns its absolute
18495      * value as unsigned integer. The plus/minus shuffling is necessary as we can
18496      * not directly remove the sign of an arbitrary signed integer as the
18497      * absolute values of INT_MIN and INT_MAX are usually not the same. See
18498      * #1708 for details.
18499      */
remove_sign(number_integer_t x)18500     inline number_unsigned_t remove_sign(number_integer_t x) noexcept
18501     {
18502         JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
18503         return static_cast<number_unsigned_t>(-(x + 1)) + 1;
18504     }
18505 
18506   private:
18507     /// the output of the serializer
18508     output_adapter_t<char> o = nullptr;
18509 
18510     /// a (hopefully) large enough character buffer
18511     std::array<char, 64> number_buffer{{}};
18512 
18513     /// the locale
18514     const std::lconv* loc = nullptr;
18515     /// the locale's thousand separator character
18516     const char thousands_sep = '\0';
18517     /// the locale's decimal point character
18518     const char decimal_point = '\0';
18519 
18520     /// string buffer
18521     std::array<char, 512> string_buffer{{}};
18522 
18523     /// the indentation character
18524     const char indent_char;
18525     /// the indentation string
18526     string_t indent_string;
18527 
18528     /// error_handler how to react on decoding errors
18529     const error_handler_t error_handler;
18530 };
18531 }  // namespace detail
18532 }  // namespace nlohmann
18533 
18534 // #include <nlohmann/detail/value_t.hpp>
18535 
18536 // #include <nlohmann/json_fwd.hpp>
18537 
18538 // #include <nlohmann/ordered_map.hpp>
18539 //     __ _____ _____ _____
18540 //  __|  |   __|     |   | |  JSON for Modern C++
18541 // |  |  |__   |  |  | | | |  version 3.10.5
18542 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
18543 //
18544 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
18545 // SPDX-License-Identifier: MIT
18546 
18547 
18548 
18549 #include <functional> // equal_to, less
18550 #include <initializer_list> // initializer_list
18551 #include <iterator> // input_iterator_tag, iterator_traits
18552 #include <memory> // allocator
18553 #include <stdexcept> // for out_of_range
18554 #include <type_traits> // enable_if, is_convertible
18555 #include <utility> // pair
18556 #include <vector> // vector
18557 
18558 // #include <nlohmann/detail/macro_scope.hpp>
18559 
18560 // #include <nlohmann/detail/meta/type_traits.hpp>
18561 
18562 
18563 namespace nlohmann
18564 {
18565 
18566 /// ordered_map: a minimal map-like container that preserves insertion order
18567 /// for use within nlohmann::basic_json<ordered_map>
18568 template <class Key, class T, class IgnoredLess = std::less<Key>,
18569           class Allocator = std::allocator<std::pair<const Key, T>>>
18570                   struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
18571 {
18572     using key_type = Key;
18573     using mapped_type = T;
18574     using Container = std::vector<std::pair<const Key, T>, Allocator>;
18575     using iterator = typename Container::iterator;
18576     using const_iterator = typename Container::const_iterator;
18577     using size_type = typename Container::size_type;
18578     using value_type = typename Container::value_type;
18579 #ifdef JSON_HAS_CPP_14
18580     using key_compare = std::equal_to<>;
18581 #else
18582     using key_compare = std::equal_to<Key>;
18583 #endif
18584 
18585     // Explicit constructors instead of `using Container::Container`
18586     // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
ordered_mapnlohmann::ordered_map18587     ordered_map() noexcept(noexcept(Container())) : Container{} {}
ordered_mapnlohmann::ordered_map18588     explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
18589     template <class It>
ordered_mapnlohmann::ordered_map18590     ordered_map(It first, It last, const Allocator& alloc = Allocator())
18591         : Container{first, last, alloc} {}
ordered_mapnlohmann::ordered_map18592     ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
18593         : Container{init, alloc} {}
18594 
emplacenlohmann::ordered_map18595     std::pair<iterator, bool> emplace(const key_type& key, T&& t)
18596     {
18597         for (auto it = this->begin(); it != this->end(); ++it)
18598         {
18599             if (m_compare(it->first, key))
18600             {
18601                 return {it, false};
18602             }
18603         }
18604         Container::emplace_back(key, std::forward<T>(t));
18605         return {std::prev(this->end()), true};
18606     }
18607 
18608     template<class KeyType, detail::enable_if_t<
18609                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
emplacenlohmann::ordered_map18610     std::pair<iterator, bool> emplace(KeyType && key, T && t)
18611     {
18612         for (auto it = this->begin(); it != this->end(); ++it)
18613         {
18614             if (m_compare(it->first, key))
18615             {
18616                 return {it, false};
18617             }
18618         }
18619         Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
18620         return {std::prev(this->end()), true};
18621     }
18622 
operator []nlohmann::ordered_map18623     T& operator[](const key_type& key)
18624     {
18625         return emplace(key, T{}).first->second;
18626     }
18627 
18628     template<class KeyType, detail::enable_if_t<
18629                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
operator []nlohmann::ordered_map18630     T & operator[](KeyType && key)
18631     {
18632         return emplace(std::forward<KeyType>(key), T{}).first->second;
18633     }
18634 
operator []nlohmann::ordered_map18635     const T& operator[](const key_type& key) const
18636     {
18637         return at(key);
18638     }
18639 
18640     template<class KeyType, detail::enable_if_t<
18641                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
operator []nlohmann::ordered_map18642     const T & operator[](KeyType && key) const
18643     {
18644         return at(std::forward<KeyType>(key));
18645     }
18646 
atnlohmann::ordered_map18647     T& at(const key_type& key)
18648     {
18649         for (auto it = this->begin(); it != this->end(); ++it)
18650         {
18651             if (m_compare(it->first, key))
18652             {
18653                 return it->second;
18654             }
18655         }
18656 
18657         JSON_THROW(std::out_of_range("key not found"));
18658     }
18659 
18660     template<class KeyType, detail::enable_if_t<
18661                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
atnlohmann::ordered_map18662     T & at(KeyType && key)
18663     {
18664         for (auto it = this->begin(); it != this->end(); ++it)
18665         {
18666             if (m_compare(it->first, key))
18667             {
18668                 return it->second;
18669             }
18670         }
18671 
18672         JSON_THROW(std::out_of_range("key not found"));
18673     }
18674 
atnlohmann::ordered_map18675     const T& at(const key_type& key) const
18676     {
18677         for (auto it = this->begin(); it != this->end(); ++it)
18678         {
18679             if (m_compare(it->first, key))
18680             {
18681                 return it->second;
18682             }
18683         }
18684 
18685         JSON_THROW(std::out_of_range("key not found"));
18686     }
18687 
18688     template<class KeyType, detail::enable_if_t<
18689                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
atnlohmann::ordered_map18690     const T & at(KeyType && key) const
18691     {
18692         for (auto it = this->begin(); it != this->end(); ++it)
18693         {
18694             if (m_compare(it->first, key))
18695             {
18696                 return it->second;
18697             }
18698         }
18699 
18700         JSON_THROW(std::out_of_range("key not found"));
18701     }
18702 
erasenlohmann::ordered_map18703     size_type erase(const key_type& key)
18704     {
18705         for (auto it = this->begin(); it != this->end(); ++it)
18706         {
18707             if (m_compare(it->first, key))
18708             {
18709                 // Since we cannot move const Keys, re-construct them in place
18710                 for (auto next = it; ++next != this->end(); ++it)
18711                 {
18712                     it->~value_type(); // Destroy but keep allocation
18713                     new (&*it) value_type{std::move(*next)};
18714                 }
18715                 Container::pop_back();
18716                 return 1;
18717             }
18718         }
18719         return 0;
18720     }
18721 
18722     template<class KeyType, detail::enable_if_t<
18723                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
erasenlohmann::ordered_map18724     size_type erase(KeyType && key)
18725     {
18726         for (auto it = this->begin(); it != this->end(); ++it)
18727         {
18728             if (m_compare(it->first, key))
18729             {
18730                 // Since we cannot move const Keys, re-construct them in place
18731                 for (auto next = it; ++next != this->end(); ++it)
18732                 {
18733                     it->~value_type(); // Destroy but keep allocation
18734                     new (&*it) value_type{std::move(*next)};
18735                 }
18736                 Container::pop_back();
18737                 return 1;
18738             }
18739         }
18740         return 0;
18741     }
18742 
erasenlohmann::ordered_map18743     iterator erase(iterator pos)
18744     {
18745         return erase(pos, std::next(pos));
18746     }
18747 
erasenlohmann::ordered_map18748     iterator erase(iterator first, iterator last)
18749     {
18750         if (first == last)
18751         {
18752             return first;
18753         }
18754 
18755         const auto elements_affected = std::distance(first, last);
18756         const auto offset = std::distance(Container::begin(), first);
18757 
18758         // This is the start situation. We need to delete elements_affected
18759         // elements (3 in this example: e, f, g), and need to return an
18760         // iterator past the last deleted element (h in this example).
18761         // Note that offset is the distance from the start of the vector
18762         // to first. We will need this later.
18763 
18764         // [ a, b, c, d, e, f, g, h, i, j ]
18765         //               ^        ^
18766         //             first    last
18767 
18768         // Since we cannot move const Keys, we re-construct them in place.
18769         // We start at first and re-construct (viz. copy) the elements from
18770         // the back of the vector. Example for first iteration:
18771 
18772         //               ,--------.
18773         //               v        |   destroy e and re-construct with h
18774         // [ a, b, c, d, e, f, g, h, i, j ]
18775         //               ^        ^
18776         //               it       it + elements_affected
18777 
18778         for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
18779         {
18780             it->~value_type(); // destroy but keep allocation
18781             new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
18782         }
18783 
18784         // [ a, b, c, d, h, i, j, h, i, j ]
18785         //               ^        ^
18786         //             first    last
18787 
18788         // remove the unneeded elements at the end of the vector
18789         Container::resize(this->size() - static_cast<size_type>(elements_affected));
18790 
18791         // [ a, b, c, d, h, i, j ]
18792         //               ^        ^
18793         //             first    last
18794 
18795         // first is now pointing past the last deleted element, but we cannot
18796         // use this iterator, because it may have been invalidated by the
18797         // resize call. Instead, we can return begin() + offset.
18798         return Container::begin() + offset;
18799     }
18800 
countnlohmann::ordered_map18801     size_type count(const key_type& key) const
18802     {
18803         for (auto it = this->begin(); it != this->end(); ++it)
18804         {
18805             if (m_compare(it->first, key))
18806             {
18807                 return 1;
18808             }
18809         }
18810         return 0;
18811     }
18812 
18813     template<class KeyType, detail::enable_if_t<
18814                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
countnlohmann::ordered_map18815     size_type count(KeyType && key) const
18816     {
18817         for (auto it = this->begin(); it != this->end(); ++it)
18818         {
18819             if (m_compare(it->first, key))
18820             {
18821                 return 1;
18822             }
18823         }
18824         return 0;
18825     }
18826 
findnlohmann::ordered_map18827     iterator find(const key_type& key)
18828     {
18829         for (auto it = this->begin(); it != this->end(); ++it)
18830         {
18831             if (m_compare(it->first, key))
18832             {
18833                 return it;
18834             }
18835         }
18836         return Container::end();
18837     }
18838 
18839     template<class KeyType, detail::enable_if_t<
18840                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
findnlohmann::ordered_map18841     iterator find(KeyType && key)
18842     {
18843         for (auto it = this->begin(); it != this->end(); ++it)
18844         {
18845             if (m_compare(it->first, key))
18846             {
18847                 return it;
18848             }
18849         }
18850         return Container::end();
18851     }
18852 
findnlohmann::ordered_map18853     const_iterator find(const key_type& key) const
18854     {
18855         for (auto it = this->begin(); it != this->end(); ++it)
18856         {
18857             if (m_compare(it->first, key))
18858             {
18859                 return it;
18860             }
18861         }
18862         return Container::end();
18863     }
18864 
insertnlohmann::ordered_map18865     std::pair<iterator, bool> insert( value_type&& value )
18866     {
18867         return emplace(value.first, std::move(value.second));
18868     }
18869 
insertnlohmann::ordered_map18870     std::pair<iterator, bool> insert( const value_type& value )
18871     {
18872         for (auto it = this->begin(); it != this->end(); ++it)
18873         {
18874             if (m_compare(it->first, value.first))
18875             {
18876                 return {it, false};
18877             }
18878         }
18879         Container::push_back(value);
18880         return {--this->end(), true};
18881     }
18882 
18883     template<typename InputIt>
18884     using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
18885             std::input_iterator_tag>::value>::type;
18886 
18887     template<typename InputIt, typename = require_input_iter<InputIt>>
insertnlohmann::ordered_map18888     void insert(InputIt first, InputIt last)
18889     {
18890         for (auto it = first; it != last; ++it)
18891         {
18892             insert(*it);
18893         }
18894     }
18895 
18896 private:
18897     JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
18898 };
18899 
18900 }  // namespace nlohmann
18901 
18902 
18903 #if defined(JSON_HAS_CPP_17)
18904     #include <any>
18905     #include <string_view>
18906 #endif
18907 
18908 /*!
18909 @brief namespace for Niels Lohmann
18910 @see https://github.com/nlohmann
18911 @since version 1.0.0
18912 */
18913 namespace nlohmann
18914 {
18915 
18916 /*!
18917 @brief a class to store JSON values
18918 
18919 @internal
18920 @invariant The member variables @a m_value and @a m_type have the following
18921 relationship:
18922 - If `m_type == value_t::object`, then `m_value.object != nullptr`.
18923 - If `m_type == value_t::array`, then `m_value.array != nullptr`.
18924 - If `m_type == value_t::string`, then `m_value.string != nullptr`.
18925 The invariants are checked by member function assert_invariant().
18926 
18927 @note ObjectType trick from https://stackoverflow.com/a/9860911
18928 @endinternal
18929 
18930 @since version 1.0.0
18931 
18932 @nosubgrouping
18933 */
18934 NLOHMANN_BASIC_JSON_TPL_DECLARATION
18935 class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
18936 {
18937   private:
18938     template<detail::value_t> friend struct detail::external_constructor;
18939 
18940     template<typename>
18941     friend class ::nlohmann::json_pointer;
18942     // can be restored when json_pointer backwards compatibility is removed
18943     // friend ::nlohmann::json_pointer<StringType>;
18944 
18945     template<typename BasicJsonType, typename InputType>
18946     friend class ::nlohmann::detail::parser;
18947     friend ::nlohmann::detail::serializer<basic_json>;
18948     template<typename BasicJsonType>
18949     friend class ::nlohmann::detail::iter_impl;
18950     template<typename BasicJsonType, typename CharType>
18951     friend class ::nlohmann::detail::binary_writer;
18952     template<typename BasicJsonType, typename InputType, typename SAX>
18953     friend class ::nlohmann::detail::binary_reader;
18954     template<typename BasicJsonType>
18955     friend class ::nlohmann::detail::json_sax_dom_parser;
18956     template<typename BasicJsonType>
18957     friend class ::nlohmann::detail::json_sax_dom_callback_parser;
18958     friend class ::nlohmann::detail::exception;
18959 
18960     /// workaround type for MSVC
18961     using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
18962 
18963   JSON_PRIVATE_UNLESS_TESTED:
18964     // convenience aliases for types residing in namespace detail;
18965     using lexer = ::nlohmann::detail::lexer_base<basic_json>;
18966 
18967     template<typename InputAdapterType>
parser(InputAdapterType adapter,detail::parser_callback_t<basic_json> cb=nullptr,const bool allow_exceptions=true,const bool ignore_comments=false)18968     static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
18969         InputAdapterType adapter,
18970         detail::parser_callback_t<basic_json>cb = nullptr,
18971         const bool allow_exceptions = true,
18972         const bool ignore_comments = false
18973                                  )
18974     {
18975         return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
18976                 std::move(cb), allow_exceptions, ignore_comments);
18977     }
18978 
18979   private:
18980     using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
18981     template<typename BasicJsonType>
18982     using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
18983     template<typename BasicJsonType>
18984     using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
18985     template<typename Iterator>
18986     using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
18987     template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
18988 
18989     template<typename CharType>
18990     using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
18991 
18992     template<typename InputType>
18993     using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
18994     template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
18995 
18996   JSON_PRIVATE_UNLESS_TESTED:
18997     using serializer = ::nlohmann::detail::serializer<basic_json>;
18998 
18999   public:
19000     using value_t = detail::value_t;
19001     /// JSON Pointer, see @ref nlohmann::json_pointer
19002     using json_pointer = ::nlohmann::json_pointer<StringType>;
19003     template<typename T, typename SFINAE>
19004     using json_serializer = JSONSerializer<T, SFINAE>;
19005     /// how to treat decoding errors
19006     using error_handler_t = detail::error_handler_t;
19007     /// how to treat CBOR tags
19008     using cbor_tag_handler_t = detail::cbor_tag_handler_t;
19009     /// helper type for initializer lists of basic_json values
19010     using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
19011 
19012     using input_format_t = detail::input_format_t;
19013     /// SAX interface type, see @ref nlohmann::json_sax
19014     using json_sax_t = json_sax<basic_json>;
19015 
19016     ////////////////
19017     // exceptions //
19018     ////////////////
19019 
19020     /// @name exceptions
19021     /// Classes to implement user-defined exceptions.
19022     /// @{
19023 
19024     using exception = detail::exception;
19025     using parse_error = detail::parse_error;
19026     using invalid_iterator = detail::invalid_iterator;
19027     using type_error = detail::type_error;
19028     using out_of_range = detail::out_of_range;
19029     using other_error = detail::other_error;
19030 
19031     /// @}
19032 
19033 
19034     /////////////////////
19035     // container types //
19036     /////////////////////
19037 
19038     /// @name container types
19039     /// The canonic container types to use @ref basic_json like any other STL
19040     /// container.
19041     /// @{
19042 
19043     /// the type of elements in a basic_json container
19044     using value_type = basic_json;
19045 
19046     /// the type of an element reference
19047     using reference = value_type&;
19048     /// the type of an element const reference
19049     using const_reference = const value_type&;
19050 
19051     /// a type to represent differences between iterators
19052     using difference_type = std::ptrdiff_t;
19053     /// a type to represent container sizes
19054     using size_type = std::size_t;
19055 
19056     /// the allocator type
19057     using allocator_type = AllocatorType<basic_json>;
19058 
19059     /// the type of an element pointer
19060     using pointer = typename std::allocator_traits<allocator_type>::pointer;
19061     /// the type of an element const pointer
19062     using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
19063 
19064     /// an iterator for a basic_json container
19065     using iterator = iter_impl<basic_json>;
19066     /// a const iterator for a basic_json container
19067     using const_iterator = iter_impl<const basic_json>;
19068     /// a reverse iterator for a basic_json container
19069     using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
19070     /// a const reverse iterator for a basic_json container
19071     using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
19072 
19073     /// @}
19074 
19075 
19076     /// @brief returns the allocator associated with the container
19077     /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
get_allocator()19078     static allocator_type get_allocator()
19079     {
19080         return allocator_type();
19081     }
19082 
19083     /// @brief returns version information on the library
19084     /// @sa https://json.nlohmann.me/api/basic_json/meta/
19085     JSON_HEDLEY_WARN_UNUSED_RESULT
meta()19086     static basic_json meta()
19087     {
19088         basic_json result;
19089 
19090         result["copyright"] = "(C) 2013-2022 Niels Lohmann";
19091         result["name"] = "JSON for Modern C++";
19092         result["url"] = "https://github.com/nlohmann/json";
19093         result["version"]["string"] =
19094             detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
19095                            std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
19096                            std::to_string(NLOHMANN_JSON_VERSION_PATCH));
19097         result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
19098         result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
19099         result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
19100 
19101 #ifdef _WIN32
19102         result["platform"] = "win32";
19103 #elif defined __linux__
19104         result["platform"] = "linux";
19105 #elif defined __APPLE__
19106         result["platform"] = "apple";
19107 #elif defined __unix__
19108         result["platform"] = "unix";
19109 #else
19110         result["platform"] = "unknown";
19111 #endif
19112 
19113 #if defined(__ICC) || defined(__INTEL_COMPILER)
19114         result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
19115 #elif defined(__clang__)
19116         result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
19117 #elif defined(__GNUC__) || defined(__GNUG__)
19118         result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
19119                     std::to_string(__GNUC__), '.',
19120                     std::to_string(__GNUC_MINOR__), '.',
19121                     std::to_string(__GNUC_PATCHLEVEL__))
19122             }
19123         };
19124 #elif defined(__HP_cc) || defined(__HP_aCC)
19125         result["compiler"] = "hp"
19126 #elif defined(__IBMCPP__)
19127         result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
19128 #elif defined(_MSC_VER)
19129         result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
19130 #elif defined(__PGI)
19131         result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
19132 #elif defined(__SUNPRO_CC)
19133         result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
19134 #else
19135         result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
19136 #endif
19137 
19138 
19139 #if defined(_MSVC_LANG)
19140         result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
19141 #elif defined(__cplusplus)
19142         result["compiler"]["c++"] = std::to_string(__cplusplus);
19143 #else
19144         result["compiler"]["c++"] = "unknown";
19145 #endif
19146         return result;
19147     }
19148 
19149 
19150     ///////////////////////////
19151     // JSON value data types //
19152     ///////////////////////////
19153 
19154     /// @name JSON value data types
19155     /// The data types to store a JSON value. These types are derived from
19156     /// the template arguments passed to class @ref basic_json.
19157     /// @{
19158 
19159     /// @brief default object key comparator type
19160     /// The actual object key comparator type (@ref object_comparator_t) may be
19161     /// different.
19162     /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
19163 #if defined(JSON_HAS_CPP_14)
19164     // use of transparent comparator avoids unnecessary repeated construction of temporaries
19165     // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
19166     using default_object_comparator_t = std::less<>;
19167 #else
19168     using default_object_comparator_t = std::less<StringType>;
19169 #endif
19170 
19171     /// @brief a type for an object
19172     /// @sa https://json.nlohmann.me/api/basic_json/object_t/
19173     using object_t = ObjectType<StringType,
19174           basic_json,
19175           default_object_comparator_t,
19176           AllocatorType<std::pair<const StringType,
19177           basic_json>>>;
19178 
19179     /// @brief a type for an array
19180     /// @sa https://json.nlohmann.me/api/basic_json/array_t/
19181     using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
19182 
19183     /// @brief a type for a string
19184     /// @sa https://json.nlohmann.me/api/basic_json/string_t/
19185     using string_t = StringType;
19186 
19187     /// @brief a type for a boolean
19188     /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
19189     using boolean_t = BooleanType;
19190 
19191     /// @brief a type for a number (integer)
19192     /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
19193     using number_integer_t = NumberIntegerType;
19194 
19195     /// @brief a type for a number (unsigned)
19196     /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
19197     using number_unsigned_t = NumberUnsignedType;
19198 
19199     /// @brief a type for a number (floating-point)
19200     /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
19201     using number_float_t = NumberFloatType;
19202 
19203     /// @brief a type for a packed binary type
19204     /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
19205     using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
19206 
19207     /// @brief object key comparator type
19208     /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
19209     using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
19210 
19211     /// @}
19212 
19213   private:
19214 
19215     /// helper for exception-safe object creation
19216     template<typename T, typename... Args>
19217     JSON_HEDLEY_RETURNS_NON_NULL
create(Args &&...args)19218     static T* create(Args&& ... args)
19219     {
19220         AllocatorType<T> alloc;
19221         using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
19222 
19223         auto deleter = [&](T * obj)
19224         {
19225             AllocatorTraits::deallocate(alloc, obj, 1);
19226         };
19227         std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
19228         AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
19229         JSON_ASSERT(obj != nullptr);
19230         return obj.release();
19231     }
19232 
19233     ////////////////////////
19234     // JSON value storage //
19235     ////////////////////////
19236 
19237   JSON_PRIVATE_UNLESS_TESTED:
19238     /*!
19239     @brief a JSON value
19240 
19241     The actual storage for a JSON value of the @ref basic_json class. This
19242     union combines the different storage types for the JSON value types
19243     defined in @ref value_t.
19244 
19245     JSON type | value_t type    | used type
19246     --------- | --------------- | ------------------------
19247     object    | object          | pointer to @ref object_t
19248     array     | array           | pointer to @ref array_t
19249     string    | string          | pointer to @ref string_t
19250     boolean   | boolean         | @ref boolean_t
19251     number    | number_integer  | @ref number_integer_t
19252     number    | number_unsigned | @ref number_unsigned_t
19253     number    | number_float    | @ref number_float_t
19254     binary    | binary          | pointer to @ref binary_t
19255     null      | null            | *no value is stored*
19256 
19257     @note Variable-length types (objects, arrays, and strings) are stored as
19258     pointers. The size of the union should not exceed 64 bits if the default
19259     value types are used.
19260 
19261     @since version 1.0.0
19262     */
19263     union json_value
19264     {
19265         /// object (stored with pointer to save storage)
19266         object_t* object;
19267         /// array (stored with pointer to save storage)
19268         array_t* array;
19269         /// string (stored with pointer to save storage)
19270         string_t* string;
19271         /// binary (stored with pointer to save storage)
19272         binary_t* binary;
19273         /// boolean
19274         boolean_t boolean;
19275         /// number (integer)
19276         number_integer_t number_integer;
19277         /// number (unsigned integer)
19278         number_unsigned_t number_unsigned;
19279         /// number (floating-point)
19280         number_float_t number_float;
19281 
19282         /// default constructor (for null values)
19283         json_value() = default;
19284         /// constructor for booleans
json_value(boolean_t v)19285         json_value(boolean_t v) noexcept : boolean(v) {}
19286         /// constructor for numbers (integer)
json_value(number_integer_t v)19287         json_value(number_integer_t v) noexcept : number_integer(v) {}
19288         /// constructor for numbers (unsigned)
json_value(number_unsigned_t v)19289         json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
19290         /// constructor for numbers (floating-point)
json_value(number_float_t v)19291         json_value(number_float_t v) noexcept : number_float(v) {}
19292         /// constructor for empty values of a given type
json_value(value_t t)19293         json_value(value_t t)
19294         {
19295             switch (t)
19296             {
19297                 case value_t::object:
19298                 {
19299                     object = create<object_t>();
19300                     break;
19301                 }
19302 
19303                 case value_t::array:
19304                 {
19305                     array = create<array_t>();
19306                     break;
19307                 }
19308 
19309                 case value_t::string:
19310                 {
19311                     string = create<string_t>("");
19312                     break;
19313                 }
19314 
19315                 case value_t::binary:
19316                 {
19317                     binary = create<binary_t>();
19318                     break;
19319                 }
19320 
19321                 case value_t::boolean:
19322                 {
19323                     boolean = static_cast<boolean_t>(false);
19324                     break;
19325                 }
19326 
19327                 case value_t::number_integer:
19328                 {
19329                     number_integer = static_cast<number_integer_t>(0);
19330                     break;
19331                 }
19332 
19333                 case value_t::number_unsigned:
19334                 {
19335                     number_unsigned = static_cast<number_unsigned_t>(0);
19336                     break;
19337                 }
19338 
19339                 case value_t::number_float:
19340                 {
19341                     number_float = static_cast<number_float_t>(0.0);
19342                     break;
19343                 }
19344 
19345                 case value_t::null:
19346                 {
19347                     object = nullptr;  // silence warning, see #821
19348                     break;
19349                 }
19350 
19351                 case value_t::discarded:
19352                 default:
19353                 {
19354                     object = nullptr;  // silence warning, see #821
19355                     if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
19356                     {
19357                         JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5", nullptr)); // LCOV_EXCL_LINE
19358                     }
19359                     break;
19360                 }
19361             }
19362         }
19363 
19364         /// constructor for strings
json_value(const string_t & value)19365         json_value(const string_t& value) : string(create<string_t>(value)) {}
19366 
19367         /// constructor for rvalue strings
json_value(string_t && value)19368         json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
19369 
19370         /// constructor for objects
json_value(const object_t & value)19371         json_value(const object_t& value) : object(create<object_t>(value)) {}
19372 
19373         /// constructor for rvalue objects
json_value(object_t && value)19374         json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
19375 
19376         /// constructor for arrays
json_value(const array_t & value)19377         json_value(const array_t& value) : array(create<array_t>(value)) {}
19378 
19379         /// constructor for rvalue arrays
json_value(array_t && value)19380         json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
19381 
19382         /// constructor for binary arrays
json_value(const typename binary_t::container_type & value)19383         json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
19384 
19385         /// constructor for rvalue binary arrays
json_value(typename binary_t::container_type && value)19386         json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
19387 
19388         /// constructor for binary arrays (internal type)
json_value(const binary_t & value)19389         json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
19390 
19391         /// constructor for rvalue binary arrays (internal type)
json_value(binary_t && value)19392         json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
19393 
destroy(value_t t)19394         void destroy(value_t t)
19395         {
19396             if (t == value_t::array || t == value_t::object)
19397             {
19398                 // flatten the current json_value to a heap-allocated stack
19399                 std::vector<basic_json> stack;
19400 
19401                 // move the top-level items to stack
19402                 if (t == value_t::array)
19403                 {
19404                     stack.reserve(array->size());
19405                     std::move(array->begin(), array->end(), std::back_inserter(stack));
19406                 }
19407                 else
19408                 {
19409                     stack.reserve(object->size());
19410                     for (auto&& it : *object)
19411                     {
19412                         stack.push_back(std::move(it.second));
19413                     }
19414                 }
19415 
19416                 while (!stack.empty())
19417                 {
19418                     // move the last item to local variable to be processed
19419                     basic_json current_item(std::move(stack.back()));
19420                     stack.pop_back();
19421 
19422                     // if current_item is array/object, move
19423                     // its children to the stack to be processed later
19424                     if (current_item.is_array())
19425                     {
19426                         std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack));
19427 
19428                         current_item.m_value.array->clear();
19429                     }
19430                     else if (current_item.is_object())
19431                     {
19432                         for (auto&& it : *current_item.m_value.object)
19433                         {
19434                             stack.push_back(std::move(it.second));
19435                         }
19436 
19437                         current_item.m_value.object->clear();
19438                     }
19439 
19440                     // it's now safe that current_item get destructed
19441                     // since it doesn't have any children
19442                 }
19443             }
19444 
19445             switch (t)
19446             {
19447                 case value_t::object:
19448                 {
19449                     AllocatorType<object_t> alloc;
19450                     std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
19451                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
19452                     break;
19453                 }
19454 
19455                 case value_t::array:
19456                 {
19457                     AllocatorType<array_t> alloc;
19458                     std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
19459                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
19460                     break;
19461                 }
19462 
19463                 case value_t::string:
19464                 {
19465                     AllocatorType<string_t> alloc;
19466                     std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
19467                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
19468                     break;
19469                 }
19470 
19471                 case value_t::binary:
19472                 {
19473                     AllocatorType<binary_t> alloc;
19474                     std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
19475                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
19476                     break;
19477                 }
19478 
19479                 case value_t::null:
19480                 case value_t::boolean:
19481                 case value_t::number_integer:
19482                 case value_t::number_unsigned:
19483                 case value_t::number_float:
19484                 case value_t::discarded:
19485                 default:
19486                 {
19487                     break;
19488                 }
19489             }
19490         }
19491     };
19492 
19493   private:
19494     /*!
19495     @brief checks the class invariants
19496 
19497     This function asserts the class invariants. It needs to be called at the
19498     end of every constructor to make sure that created objects respect the
19499     invariant. Furthermore, it has to be called each time the type of a JSON
19500     value is changed, because the invariant expresses a relationship between
19501     @a m_type and @a m_value.
19502 
19503     Furthermore, the parent relation is checked for arrays and objects: If
19504     @a check_parents true and the value is an array or object, then the
19505     container's elements must have the current value as parent.
19506 
19507     @param[in] check_parents  whether the parent relation should be checked.
19508                The value is true by default and should only be set to false
19509                during destruction of objects when the invariant does not
19510                need to hold.
19511     */
assert_invariant(bool check_parents=true) const19512     void assert_invariant(bool check_parents = true) const noexcept
19513     {
19514         JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
19515         JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
19516         JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
19517         JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
19518 
19519 #if JSON_DIAGNOSTICS
19520         JSON_TRY
19521         {
19522             // cppcheck-suppress assertWithSideEffect
19523             JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
19524             {
19525                 return j.m_parent == this;
19526             }));
19527         }
19528         JSON_CATCH(...) {} // LCOV_EXCL_LINE
19529 #endif
19530         static_cast<void>(check_parents);
19531     }
19532 
set_parents()19533     void set_parents()
19534     {
19535 #if JSON_DIAGNOSTICS
19536         switch (m_type)
19537         {
19538             case value_t::array:
19539             {
19540                 for (auto& element : *m_value.array)
19541                 {
19542                     element.m_parent = this;
19543                 }
19544                 break;
19545             }
19546 
19547             case value_t::object:
19548             {
19549                 for (auto& element : *m_value.object)
19550                 {
19551                     element.second.m_parent = this;
19552                 }
19553                 break;
19554             }
19555 
19556             case value_t::null:
19557             case value_t::string:
19558             case value_t::boolean:
19559             case value_t::number_integer:
19560             case value_t::number_unsigned:
19561             case value_t::number_float:
19562             case value_t::binary:
19563             case value_t::discarded:
19564             default:
19565                 break;
19566         }
19567 #endif
19568     }
19569 
set_parents(iterator it,typename iterator::difference_type count_set_parents)19570     iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
19571     {
19572 #if JSON_DIAGNOSTICS
19573         for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
19574         {
19575             (it + i)->m_parent = this;
19576         }
19577 #else
19578         static_cast<void>(count_set_parents);
19579 #endif
19580         return it;
19581     }
19582 
set_parent(reference j,std::size_t old_capacity=static_cast<std::size_t> (-1))19583     reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
19584     {
19585 #if JSON_DIAGNOSTICS
19586         if (old_capacity != static_cast<std::size_t>(-1))
19587         {
19588             // see https://github.com/nlohmann/json/issues/2838
19589             JSON_ASSERT(type() == value_t::array);
19590             if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
19591             {
19592                 // capacity has changed: update all parents
19593                 set_parents();
19594                 return j;
19595             }
19596         }
19597 
19598         // ordered_json uses a vector internally, so pointers could have
19599         // been invalidated; see https://github.com/nlohmann/json/issues/2962
19600 #ifdef JSON_HEDLEY_MSVC_VERSION
19601 #pragma warning(push )
19602 #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
19603 #endif
19604         if (detail::is_ordered_map<object_t>::value)
19605         {
19606             set_parents();
19607             return j;
19608         }
19609 #ifdef JSON_HEDLEY_MSVC_VERSION
19610 #pragma warning( pop )
19611 #endif
19612 
19613         j.m_parent = this;
19614 #else
19615         static_cast<void>(j);
19616         static_cast<void>(old_capacity);
19617 #endif
19618         return j;
19619     }
19620 
19621   public:
19622     //////////////////////////
19623     // JSON parser callback //
19624     //////////////////////////
19625 
19626     /// @brief parser event types
19627     /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
19628     using parse_event_t = detail::parse_event_t;
19629 
19630     /// @brief per-element parser callback type
19631     /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
19632     using parser_callback_t = detail::parser_callback_t<basic_json>;
19633 
19634     //////////////////
19635     // constructors //
19636     //////////////////
19637 
19638     /// @name constructors and destructors
19639     /// Constructors of class @ref basic_json, copy/move constructor, copy
19640     /// assignment, static functions creating objects, and the destructor.
19641     /// @{
19642 
19643     /// @brief create an empty value with a given type
19644     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
basic_json(const value_t v)19645     basic_json(const value_t v)
19646         : m_type(v), m_value(v)
19647     {
19648         assert_invariant();
19649     }
19650 
19651     /// @brief create a null object
19652     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
basic_json(std::nullptr_t=nullptr)19653     basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
19654         : basic_json(value_t::null)
19655     {
19656         assert_invariant();
19657     }
19658 
19659     /// @brief create a JSON value from compatible types
19660     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
19661     template < typename CompatibleType,
19662                typename U = detail::uncvref_t<CompatibleType>,
19663                detail::enable_if_t <
19664                    !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
basic_json(CompatibleType && val)19665     basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
19666                 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
19667                                            std::forward<CompatibleType>(val))))
19668     {
19669         JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
19670         set_parents();
19671         assert_invariant();
19672     }
19673 
19674     /// @brief create a JSON value from an existing one
19675     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
19676     template < typename BasicJsonType,
19677                detail::enable_if_t <
19678                    detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
basic_json(const BasicJsonType & val)19679     basic_json(const BasicJsonType& val)
19680     {
19681         using other_boolean_t = typename BasicJsonType::boolean_t;
19682         using other_number_float_t = typename BasicJsonType::number_float_t;
19683         using other_number_integer_t = typename BasicJsonType::number_integer_t;
19684         using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
19685         using other_string_t = typename BasicJsonType::string_t;
19686         using other_object_t = typename BasicJsonType::object_t;
19687         using other_array_t = typename BasicJsonType::array_t;
19688         using other_binary_t = typename BasicJsonType::binary_t;
19689 
19690         switch (val.type())
19691         {
19692             case value_t::boolean:
19693                 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
19694                 break;
19695             case value_t::number_float:
19696                 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
19697                 break;
19698             case value_t::number_integer:
19699                 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
19700                 break;
19701             case value_t::number_unsigned:
19702                 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
19703                 break;
19704             case value_t::string:
19705                 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
19706                 break;
19707             case value_t::object:
19708                 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
19709                 break;
19710             case value_t::array:
19711                 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
19712                 break;
19713             case value_t::binary:
19714                 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
19715                 break;
19716             case value_t::null:
19717                 *this = nullptr;
19718                 break;
19719             case value_t::discarded:
19720                 m_type = value_t::discarded;
19721                 break;
19722             default:            // LCOV_EXCL_LINE
19723                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19724         }
19725         JSON_ASSERT(m_type == val.type());
19726         set_parents();
19727         assert_invariant();
19728     }
19729 
19730     /// @brief create a container (array or object) from an initializer list
19731     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
basic_json(initializer_list_t init,bool type_deduction=true,value_t manual_type=value_t::array)19732     basic_json(initializer_list_t init,
19733                bool type_deduction = true,
19734                value_t manual_type = value_t::array)
19735     {
19736         // check if each element is an array with two elements whose first
19737         // element is a string
19738         bool is_an_object = std::all_of(init.begin(), init.end(),
19739                                         [](const detail::json_ref<basic_json>& element_ref)
19740         {
19741             return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
19742         });
19743 
19744         // adjust type if type deduction is not wanted
19745         if (!type_deduction)
19746         {
19747             // if array is wanted, do not create an object though possible
19748             if (manual_type == value_t::array)
19749             {
19750                 is_an_object = false;
19751             }
19752 
19753             // if object is wanted but impossible, throw an exception
19754             if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
19755             {
19756                 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
19757             }
19758         }
19759 
19760         if (is_an_object)
19761         {
19762             // the initializer list is a list of pairs -> create object
19763             m_type = value_t::object;
19764             m_value = value_t::object;
19765 
19766             for (auto& element_ref : init)
19767             {
19768                 auto element = element_ref.moved_or_copied();
19769                 m_value.object->emplace(
19770                     std::move(*((*element.m_value.array)[0].m_value.string)),
19771                     std::move((*element.m_value.array)[1]));
19772             }
19773         }
19774         else
19775         {
19776             // the initializer list describes an array -> create array
19777             m_type = value_t::array;
19778             m_value.array = create<array_t>(init.begin(), init.end());
19779         }
19780 
19781         set_parents();
19782         assert_invariant();
19783     }
19784 
19785     /// @brief explicitly create a binary array (without subtype)
19786     /// @sa https://json.nlohmann.me/api/basic_json/binary/
19787     JSON_HEDLEY_WARN_UNUSED_RESULT
binary(const typename binary_t::container_type & init)19788     static basic_json binary(const typename binary_t::container_type& init)
19789     {
19790         auto res = basic_json();
19791         res.m_type = value_t::binary;
19792         res.m_value = init;
19793         return res;
19794     }
19795 
19796     /// @brief explicitly create a binary array (with subtype)
19797     /// @sa https://json.nlohmann.me/api/basic_json/binary/
19798     JSON_HEDLEY_WARN_UNUSED_RESULT
binary(const typename binary_t::container_type & init,typename binary_t::subtype_type subtype)19799     static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
19800     {
19801         auto res = basic_json();
19802         res.m_type = value_t::binary;
19803         res.m_value = binary_t(init, subtype);
19804         return res;
19805     }
19806 
19807     /// @brief explicitly create a binary array
19808     /// @sa https://json.nlohmann.me/api/basic_json/binary/
19809     JSON_HEDLEY_WARN_UNUSED_RESULT
binary(typename binary_t::container_type && init)19810     static basic_json binary(typename binary_t::container_type&& init)
19811     {
19812         auto res = basic_json();
19813         res.m_type = value_t::binary;
19814         res.m_value = std::move(init);
19815         return res;
19816     }
19817 
19818     /// @brief explicitly create a binary array (with subtype)
19819     /// @sa https://json.nlohmann.me/api/basic_json/binary/
19820     JSON_HEDLEY_WARN_UNUSED_RESULT
binary(typename binary_t::container_type && init,typename binary_t::subtype_type subtype)19821     static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
19822     {
19823         auto res = basic_json();
19824         res.m_type = value_t::binary;
19825         res.m_value = binary_t(std::move(init), subtype);
19826         return res;
19827     }
19828 
19829     /// @brief explicitly create an array from an initializer list
19830     /// @sa https://json.nlohmann.me/api/basic_json/array/
19831     JSON_HEDLEY_WARN_UNUSED_RESULT
array(initializer_list_t init={})19832     static basic_json array(initializer_list_t init = {})
19833     {
19834         return basic_json(init, false, value_t::array);
19835     }
19836 
19837     /// @brief explicitly create an object from an initializer list
19838     /// @sa https://json.nlohmann.me/api/basic_json/object/
19839     JSON_HEDLEY_WARN_UNUSED_RESULT
object(initializer_list_t init={})19840     static basic_json object(initializer_list_t init = {})
19841     {
19842         return basic_json(init, false, value_t::object);
19843     }
19844 
19845     /// @brief construct an array with count copies of given value
19846     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
basic_json(size_type cnt,const basic_json & val)19847     basic_json(size_type cnt, const basic_json& val)
19848         : m_type(value_t::array)
19849     {
19850         m_value.array = create<array_t>(cnt, val);
19851         set_parents();
19852         assert_invariant();
19853     }
19854 
19855     /// @brief construct a JSON container given an iterator range
19856     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
19857     template < class InputIT, typename std::enable_if <
19858                    std::is_same<InputIT, typename basic_json_t::iterator>::value ||
19859                    std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
basic_json(InputIT first,InputIT last)19860     basic_json(InputIT first, InputIT last)
19861     {
19862         JSON_ASSERT(first.m_object != nullptr);
19863         JSON_ASSERT(last.m_object != nullptr);
19864 
19865         // make sure iterator fits the current value
19866         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
19867         {
19868             JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
19869         }
19870 
19871         // copy type from first iterator
19872         m_type = first.m_object->m_type;
19873 
19874         // check if iterator range is complete for primitive values
19875         switch (m_type)
19876         {
19877             case value_t::boolean:
19878             case value_t::number_float:
19879             case value_t::number_integer:
19880             case value_t::number_unsigned:
19881             case value_t::string:
19882             {
19883                 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
19884                                          || !last.m_it.primitive_iterator.is_end()))
19885                 {
19886                     JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
19887                 }
19888                 break;
19889             }
19890 
19891             case value_t::null:
19892             case value_t::object:
19893             case value_t::array:
19894             case value_t::binary:
19895             case value_t::discarded:
19896             default:
19897                 break;
19898         }
19899 
19900         switch (m_type)
19901         {
19902             case value_t::number_integer:
19903             {
19904                 m_value.number_integer = first.m_object->m_value.number_integer;
19905                 break;
19906             }
19907 
19908             case value_t::number_unsigned:
19909             {
19910                 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
19911                 break;
19912             }
19913 
19914             case value_t::number_float:
19915             {
19916                 m_value.number_float = first.m_object->m_value.number_float;
19917                 break;
19918             }
19919 
19920             case value_t::boolean:
19921             {
19922                 m_value.boolean = first.m_object->m_value.boolean;
19923                 break;
19924             }
19925 
19926             case value_t::string:
19927             {
19928                 m_value = *first.m_object->m_value.string;
19929                 break;
19930             }
19931 
19932             case value_t::object:
19933             {
19934                 m_value.object = create<object_t>(first.m_it.object_iterator,
19935                                                   last.m_it.object_iterator);
19936                 break;
19937             }
19938 
19939             case value_t::array:
19940             {
19941                 m_value.array = create<array_t>(first.m_it.array_iterator,
19942                                                 last.m_it.array_iterator);
19943                 break;
19944             }
19945 
19946             case value_t::binary:
19947             {
19948                 m_value = *first.m_object->m_value.binary;
19949                 break;
19950             }
19951 
19952             case value_t::null:
19953             case value_t::discarded:
19954             default:
19955                 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
19956         }
19957 
19958         set_parents();
19959         assert_invariant();
19960     }
19961 
19962 
19963     ///////////////////////////////////////
19964     // other constructors and destructor //
19965     ///////////////////////////////////////
19966 
19967     template<typename JsonRef,
19968              detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
19969                                  std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
basic_json(const JsonRef & ref)19970     basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
19971 
19972     /// @brief copy constructor
19973     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
basic_json(const basic_json & other)19974     basic_json(const basic_json& other)
19975         : m_type(other.m_type)
19976     {
19977         // check of passed value is valid
19978         other.assert_invariant();
19979 
19980         switch (m_type)
19981         {
19982             case value_t::object:
19983             {
19984                 m_value = *other.m_value.object;
19985                 break;
19986             }
19987 
19988             case value_t::array:
19989             {
19990                 m_value = *other.m_value.array;
19991                 break;
19992             }
19993 
19994             case value_t::string:
19995             {
19996                 m_value = *other.m_value.string;
19997                 break;
19998             }
19999 
20000             case value_t::boolean:
20001             {
20002                 m_value = other.m_value.boolean;
20003                 break;
20004             }
20005 
20006             case value_t::number_integer:
20007             {
20008                 m_value = other.m_value.number_integer;
20009                 break;
20010             }
20011 
20012             case value_t::number_unsigned:
20013             {
20014                 m_value = other.m_value.number_unsigned;
20015                 break;
20016             }
20017 
20018             case value_t::number_float:
20019             {
20020                 m_value = other.m_value.number_float;
20021                 break;
20022             }
20023 
20024             case value_t::binary:
20025             {
20026                 m_value = *other.m_value.binary;
20027                 break;
20028             }
20029 
20030             case value_t::null:
20031             case value_t::discarded:
20032             default:
20033                 break;
20034         }
20035 
20036         set_parents();
20037         assert_invariant();
20038     }
20039 
20040     /// @brief move constructor
20041     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
basic_json(basic_json && other)20042     basic_json(basic_json&& other) noexcept
20043         : m_type(std::move(other.m_type)),
20044           m_value(std::move(other.m_value))
20045     {
20046         // check that passed value is valid
20047         other.assert_invariant(false);
20048 
20049         // invalidate payload
20050         other.m_type = value_t::null;
20051         other.m_value = {};
20052 
20053         set_parents();
20054         assert_invariant();
20055     }
20056 
20057     /// @brief copy assignment
20058     /// @sa https://json.nlohmann.me/api/basic_json/operator=/
operator =(basic_json other)20059     basic_json& operator=(basic_json other) noexcept (
20060         std::is_nothrow_move_constructible<value_t>::value&&
20061         std::is_nothrow_move_assignable<value_t>::value&&
20062         std::is_nothrow_move_constructible<json_value>::value&&
20063         std::is_nothrow_move_assignable<json_value>::value
20064     )
20065     {
20066         // check that passed value is valid
20067         other.assert_invariant();
20068 
20069         using std::swap;
20070         swap(m_type, other.m_type);
20071         swap(m_value, other.m_value);
20072 
20073         set_parents();
20074         assert_invariant();
20075         return *this;
20076     }
20077 
20078     /// @brief destructor
20079     /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
~basic_json()20080     ~basic_json() noexcept
20081     {
20082         assert_invariant(false);
20083         m_value.destroy(m_type);
20084     }
20085 
20086     /// @}
20087 
20088   public:
20089     ///////////////////////
20090     // object inspection //
20091     ///////////////////////
20092 
20093     /// @name object inspection
20094     /// Functions to inspect the type of a JSON value.
20095     /// @{
20096 
20097     /// @brief serialization
20098     /// @sa https://json.nlohmann.me/api/basic_json/dump/
dump(const int indent=-1,const char indent_char=' ',const bool ensure_ascii=false,const error_handler_t error_handler=error_handler_t::strict) const20099     string_t dump(const int indent = -1,
20100                   const char indent_char = ' ',
20101                   const bool ensure_ascii = false,
20102                   const error_handler_t error_handler = error_handler_t::strict) const
20103     {
20104         string_t result;
20105         serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
20106 
20107         if (indent >= 0)
20108         {
20109             s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
20110         }
20111         else
20112         {
20113             s.dump(*this, false, ensure_ascii, 0);
20114         }
20115 
20116         return result;
20117     }
20118 
20119     /// @brief return the type of the JSON value (explicit)
20120     /// @sa https://json.nlohmann.me/api/basic_json/type/
type() const20121     constexpr value_t type() const noexcept
20122     {
20123         return m_type;
20124     }
20125 
20126     /// @brief return whether type is primitive
20127     /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
is_primitive() const20128     constexpr bool is_primitive() const noexcept
20129     {
20130         return is_null() || is_string() || is_boolean() || is_number() || is_binary();
20131     }
20132 
20133     /// @brief return whether type is structured
20134     /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
is_structured() const20135     constexpr bool is_structured() const noexcept
20136     {
20137         return is_array() || is_object();
20138     }
20139 
20140     /// @brief return whether value is null
20141     /// @sa https://json.nlohmann.me/api/basic_json/is_null/
is_null() const20142     constexpr bool is_null() const noexcept
20143     {
20144         return m_type == value_t::null;
20145     }
20146 
20147     /// @brief return whether value is a boolean
20148     /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
is_boolean() const20149     constexpr bool is_boolean() const noexcept
20150     {
20151         return m_type == value_t::boolean;
20152     }
20153 
20154     /// @brief return whether value is a number
20155     /// @sa https://json.nlohmann.me/api/basic_json/is_number/
is_number() const20156     constexpr bool is_number() const noexcept
20157     {
20158         return is_number_integer() || is_number_float();
20159     }
20160 
20161     /// @brief return whether value is an integer number
20162     /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
is_number_integer() const20163     constexpr bool is_number_integer() const noexcept
20164     {
20165         return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
20166     }
20167 
20168     /// @brief return whether value is an unsigned integer number
20169     /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
is_number_unsigned() const20170     constexpr bool is_number_unsigned() const noexcept
20171     {
20172         return m_type == value_t::number_unsigned;
20173     }
20174 
20175     /// @brief return whether value is a floating-point number
20176     /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
is_number_float() const20177     constexpr bool is_number_float() const noexcept
20178     {
20179         return m_type == value_t::number_float;
20180     }
20181 
20182     /// @brief return whether value is an object
20183     /// @sa https://json.nlohmann.me/api/basic_json/is_object/
is_object() const20184     constexpr bool is_object() const noexcept
20185     {
20186         return m_type == value_t::object;
20187     }
20188 
20189     /// @brief return whether value is an array
20190     /// @sa https://json.nlohmann.me/api/basic_json/is_array/
is_array() const20191     constexpr bool is_array() const noexcept
20192     {
20193         return m_type == value_t::array;
20194     }
20195 
20196     /// @brief return whether value is a string
20197     /// @sa https://json.nlohmann.me/api/basic_json/is_string/
is_string() const20198     constexpr bool is_string() const noexcept
20199     {
20200         return m_type == value_t::string;
20201     }
20202 
20203     /// @brief return whether value is a binary array
20204     /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
is_binary() const20205     constexpr bool is_binary() const noexcept
20206     {
20207         return m_type == value_t::binary;
20208     }
20209 
20210     /// @brief return whether value is discarded
20211     /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
is_discarded() const20212     constexpr bool is_discarded() const noexcept
20213     {
20214         return m_type == value_t::discarded;
20215     }
20216 
20217     /// @brief return the type of the JSON value (implicit)
20218     /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
operator value_t() const20219     constexpr operator value_t() const noexcept
20220     {
20221         return m_type;
20222     }
20223 
20224     /// @}
20225 
20226   private:
20227     //////////////////
20228     // value access //
20229     //////////////////
20230 
20231     /// get a boolean (explicit)
get_impl(boolean_t *) const20232     boolean_t get_impl(boolean_t* /*unused*/) const
20233     {
20234         if (JSON_HEDLEY_LIKELY(is_boolean()))
20235         {
20236             return m_value.boolean;
20237         }
20238 
20239         JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
20240     }
20241 
20242     /// get a pointer to the value (object)
get_impl_ptr(object_t *)20243     object_t* get_impl_ptr(object_t* /*unused*/) noexcept
20244     {
20245         return is_object() ? m_value.object : nullptr;
20246     }
20247 
20248     /// get a pointer to the value (object)
get_impl_ptr(const object_t *) const20249     constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
20250     {
20251         return is_object() ? m_value.object : nullptr;
20252     }
20253 
20254     /// get a pointer to the value (array)
get_impl_ptr(array_t *)20255     array_t* get_impl_ptr(array_t* /*unused*/) noexcept
20256     {
20257         return is_array() ? m_value.array : nullptr;
20258     }
20259 
20260     /// get a pointer to the value (array)
get_impl_ptr(const array_t *) const20261     constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
20262     {
20263         return is_array() ? m_value.array : nullptr;
20264     }
20265 
20266     /// get a pointer to the value (string)
get_impl_ptr(string_t *)20267     string_t* get_impl_ptr(string_t* /*unused*/) noexcept
20268     {
20269         return is_string() ? m_value.string : nullptr;
20270     }
20271 
20272     /// get a pointer to the value (string)
get_impl_ptr(const string_t *) const20273     constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
20274     {
20275         return is_string() ? m_value.string : nullptr;
20276     }
20277 
20278     /// get a pointer to the value (boolean)
get_impl_ptr(boolean_t *)20279     boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
20280     {
20281         return is_boolean() ? &m_value.boolean : nullptr;
20282     }
20283 
20284     /// get a pointer to the value (boolean)
get_impl_ptr(const boolean_t *) const20285     constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
20286     {
20287         return is_boolean() ? &m_value.boolean : nullptr;
20288     }
20289 
20290     /// get a pointer to the value (integer number)
get_impl_ptr(number_integer_t *)20291     number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
20292     {
20293         return is_number_integer() ? &m_value.number_integer : nullptr;
20294     }
20295 
20296     /// get a pointer to the value (integer number)
get_impl_ptr(const number_integer_t *) const20297     constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
20298     {
20299         return is_number_integer() ? &m_value.number_integer : nullptr;
20300     }
20301 
20302     /// get a pointer to the value (unsigned number)
get_impl_ptr(number_unsigned_t *)20303     number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
20304     {
20305         return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
20306     }
20307 
20308     /// get a pointer to the value (unsigned number)
get_impl_ptr(const number_unsigned_t *) const20309     constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
20310     {
20311         return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
20312     }
20313 
20314     /// get a pointer to the value (floating-point number)
get_impl_ptr(number_float_t *)20315     number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
20316     {
20317         return is_number_float() ? &m_value.number_float : nullptr;
20318     }
20319 
20320     /// get a pointer to the value (floating-point number)
get_impl_ptr(const number_float_t *) const20321     constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
20322     {
20323         return is_number_float() ? &m_value.number_float : nullptr;
20324     }
20325 
20326     /// get a pointer to the value (binary)
get_impl_ptr(binary_t *)20327     binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
20328     {
20329         return is_binary() ? m_value.binary : nullptr;
20330     }
20331 
20332     /// get a pointer to the value (binary)
get_impl_ptr(const binary_t *) const20333     constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
20334     {
20335         return is_binary() ? m_value.binary : nullptr;
20336     }
20337 
20338     /*!
20339     @brief helper function to implement get_ref()
20340 
20341     This function helps to implement get_ref() without code duplication for
20342     const and non-const overloads
20343 
20344     @tparam ThisType will be deduced as `basic_json` or `const basic_json`
20345 
20346     @throw type_error.303 if ReferenceType does not match underlying value
20347     type of the current JSON
20348     */
20349     template<typename ReferenceType, typename ThisType>
get_ref_impl(ThisType & obj)20350     static ReferenceType get_ref_impl(ThisType& obj)
20351     {
20352         // delegate the call to get_ptr<>()
20353         auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
20354 
20355         if (JSON_HEDLEY_LIKELY(ptr != nullptr))
20356         {
20357             return *ptr;
20358         }
20359 
20360         JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
20361     }
20362 
20363   public:
20364     /// @name value access
20365     /// Direct access to the stored value of a JSON value.
20366     /// @{
20367 
20368     /// @brief get a pointer value (implicit)
20369     /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
20370     template<typename PointerType, typename std::enable_if<
20371                  std::is_pointer<PointerType>::value, int>::type = 0>
get_ptr()20372     auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20373     {
20374         // delegate the call to get_impl_ptr<>()
20375         return get_impl_ptr(static_cast<PointerType>(nullptr));
20376     }
20377 
20378     /// @brief get a pointer value (implicit)
20379     /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
20380     template < typename PointerType, typename std::enable_if <
20381                    std::is_pointer<PointerType>::value&&
20382                    std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
get_ptr() const20383     constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20384     {
20385         // delegate the call to get_impl_ptr<>() const
20386         return get_impl_ptr(static_cast<PointerType>(nullptr));
20387     }
20388 
20389   private:
20390     /*!
20391     @brief get a value (explicit)
20392 
20393     Explicit type conversion between the JSON value and a compatible value
20394     which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
20395     and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
20396     The value is converted by calling the @ref json_serializer<ValueType>
20397     `from_json()` method.
20398 
20399     The function is equivalent to executing
20400     @code {.cpp}
20401     ValueType ret;
20402     JSONSerializer<ValueType>::from_json(*this, ret);
20403     return ret;
20404     @endcode
20405 
20406     This overloads is chosen if:
20407     - @a ValueType is not @ref basic_json,
20408     - @ref json_serializer<ValueType> has a `from_json()` method of the form
20409       `void from_json(const basic_json&, ValueType&)`, and
20410     - @ref json_serializer<ValueType> does not have a `from_json()` method of
20411       the form `ValueType from_json(const basic_json&)`
20412 
20413     @tparam ValueType the returned value type
20414 
20415     @return copy of the JSON value, converted to @a ValueType
20416 
20417     @throw what @ref json_serializer<ValueType> `from_json()` method throws
20418 
20419     @liveexample{The example below shows several conversions from JSON values
20420     to other types. There a few things to note: (1) Floating-point numbers can
20421     be converted to integers\, (2) A JSON array can be converted to a standard
20422     `std::vector<short>`\, (3) A JSON object can be converted to C++
20423     associative containers such as `std::unordered_map<std::string\,
20424     json>`.,get__ValueType_const}
20425 
20426     @since version 2.1.0
20427     */
20428     template < typename ValueType,
20429                detail::enable_if_t <
20430                    detail::is_default_constructible<ValueType>::value&&
20431                    detail::has_from_json<basic_json_t, ValueType>::value,
20432                    int > = 0 >
get_impl(detail::priority_tag<0>) const20433     ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
20434                 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
20435     {
20436         auto ret = ValueType();
20437         JSONSerializer<ValueType>::from_json(*this, ret);
20438         return ret;
20439     }
20440 
20441     /*!
20442     @brief get a value (explicit); special case
20443 
20444     Explicit type conversion between the JSON value and a compatible value
20445     which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
20446     and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
20447     The value is converted by calling the @ref json_serializer<ValueType>
20448     `from_json()` method.
20449 
20450     The function is equivalent to executing
20451     @code {.cpp}
20452     return JSONSerializer<ValueType>::from_json(*this);
20453     @endcode
20454 
20455     This overloads is chosen if:
20456     - @a ValueType is not @ref basic_json and
20457     - @ref json_serializer<ValueType> has a `from_json()` method of the form
20458       `ValueType from_json(const basic_json&)`
20459 
20460     @note If @ref json_serializer<ValueType> has both overloads of
20461     `from_json()`, this one is chosen.
20462 
20463     @tparam ValueType the returned value type
20464 
20465     @return copy of the JSON value, converted to @a ValueType
20466 
20467     @throw what @ref json_serializer<ValueType> `from_json()` method throws
20468 
20469     @since version 2.1.0
20470     */
20471     template < typename ValueType,
20472                detail::enable_if_t <
20473                    detail::has_non_default_from_json<basic_json_t, ValueType>::value,
20474                    int > = 0 >
get_impl(detail::priority_tag<1>) const20475     ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
20476                 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
20477     {
20478         return JSONSerializer<ValueType>::from_json(*this);
20479     }
20480 
20481     /*!
20482     @brief get special-case overload
20483 
20484     This overloads converts the current @ref basic_json in a different
20485     @ref basic_json type
20486 
20487     @tparam BasicJsonType == @ref basic_json
20488 
20489     @return a copy of *this, converted into @a BasicJsonType
20490 
20491     @complexity Depending on the implementation of the called `from_json()`
20492                 method.
20493 
20494     @since version 3.2.0
20495     */
20496     template < typename BasicJsonType,
20497                detail::enable_if_t <
20498                    detail::is_basic_json<BasicJsonType>::value,
20499                    int > = 0 >
get_impl(detail::priority_tag<2>) const20500     BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
20501     {
20502         return *this;
20503     }
20504 
20505     /*!
20506     @brief get special-case overload
20507 
20508     This overloads avoids a lot of template boilerplate, it can be seen as the
20509     identity method
20510 
20511     @tparam BasicJsonType == @ref basic_json
20512 
20513     @return a copy of *this
20514 
20515     @complexity Constant.
20516 
20517     @since version 2.1.0
20518     */
20519     template<typename BasicJsonType,
20520              detail::enable_if_t<
20521                  std::is_same<BasicJsonType, basic_json_t>::value,
20522                  int> = 0>
get_impl(detail::priority_tag<3>) const20523     basic_json get_impl(detail::priority_tag<3> /*unused*/) const
20524     {
20525         return *this;
20526     }
20527 
20528     /*!
20529     @brief get a pointer value (explicit)
20530     @copydoc get()
20531     */
20532     template<typename PointerType,
20533              detail::enable_if_t<
20534                  std::is_pointer<PointerType>::value,
20535                  int> = 0>
get_impl(detail::priority_tag<4>) const20536     constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
20537     -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
20538     {
20539         // delegate the call to get_ptr
20540         return get_ptr<PointerType>();
20541     }
20542 
20543   public:
20544     /*!
20545     @brief get a (pointer) value (explicit)
20546 
20547     Performs explicit type conversion between the JSON value and a compatible value if required.
20548 
20549     - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
20550     No copies are made.
20551 
20552     - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
20553     from the current @ref basic_json.
20554 
20555     - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
20556     method.
20557 
20558     @tparam ValueTypeCV the provided value type
20559     @tparam ValueType the returned value type
20560 
20561     @return copy of the JSON value, converted to @tparam ValueType if necessary
20562 
20563     @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
20564 
20565     @since version 2.1.0
20566     */
20567     template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
20568 #if defined(JSON_HAS_CPP_14)
20569     constexpr
20570 #endif
get() const20571     auto get() const noexcept(
20572     noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
20573     -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
20574     {
20575         // we cannot static_assert on ValueTypeCV being non-const, because
20576         // there is support for get<const basic_json_t>(), which is why we
20577         // still need the uncvref
20578         static_assert(!std::is_reference<ValueTypeCV>::value,
20579                       "get() cannot be used with reference types, you might want to use get_ref()");
20580         return get_impl<ValueType>(detail::priority_tag<4> {});
20581     }
20582 
20583     /*!
20584     @brief get a pointer value (explicit)
20585 
20586     Explicit pointer access to the internally stored JSON value. No copies are
20587     made.
20588 
20589     @warning The pointer becomes invalid if the underlying JSON object
20590     changes.
20591 
20592     @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
20593     object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
20594     @ref number_unsigned_t, or @ref number_float_t.
20595 
20596     @return pointer to the internally stored JSON value if the requested
20597     pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
20598 
20599     @complexity Constant.
20600 
20601     @liveexample{The example below shows how pointers to internal values of a
20602     JSON value can be requested. Note that no type conversions are made and a
20603     `nullptr` is returned if the value and the requested pointer type does not
20604     match.,get__PointerType}
20605 
20606     @sa see @ref get_ptr() for explicit pointer-member access
20607 
20608     @since version 1.0.0
20609     */
20610     template<typename PointerType, typename std::enable_if<
20611                  std::is_pointer<PointerType>::value, int>::type = 0>
get()20612     auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
20613     {
20614         // delegate the call to get_ptr
20615         return get_ptr<PointerType>();
20616     }
20617 
20618     /// @brief get a value (explicit)
20619     /// @sa https://json.nlohmann.me/api/basic_json/get_to/
20620     template < typename ValueType,
20621                detail::enable_if_t <
20622                    !detail::is_basic_json<ValueType>::value&&
20623                    detail::has_from_json<basic_json_t, ValueType>::value,
20624                    int > = 0 >
get_to(ValueType & v) const20625     ValueType & get_to(ValueType& v) const noexcept(noexcept(
20626                 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
20627     {
20628         JSONSerializer<ValueType>::from_json(*this, v);
20629         return v;
20630     }
20631 
20632     // specialization to allow calling get_to with a basic_json value
20633     // see https://github.com/nlohmann/json/issues/2175
20634     template<typename ValueType,
20635              detail::enable_if_t <
20636                  detail::is_basic_json<ValueType>::value,
20637                  int> = 0>
get_to(ValueType & v) const20638     ValueType & get_to(ValueType& v) const
20639     {
20640         v = *this;
20641         return v;
20642     }
20643 
20644     template <
20645         typename T, std::size_t N,
20646         typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
20647         detail::enable_if_t <
20648             detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
get_to(T (& v)[N]) const20649     Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
20650     noexcept(noexcept(JSONSerializer<Array>::from_json(
20651                           std::declval<const basic_json_t&>(), v)))
20652     {
20653         JSONSerializer<Array>::from_json(*this, v);
20654         return v;
20655     }
20656 
20657     /// @brief get a reference value (implicit)
20658     /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
20659     template<typename ReferenceType, typename std::enable_if<
20660                  std::is_reference<ReferenceType>::value, int>::type = 0>
get_ref()20661     ReferenceType get_ref()
20662     {
20663         // delegate call to get_ref_impl
20664         return get_ref_impl<ReferenceType>(*this);
20665     }
20666 
20667     /// @brief get a reference value (implicit)
20668     /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
20669     template < typename ReferenceType, typename std::enable_if <
20670                    std::is_reference<ReferenceType>::value&&
20671                    std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
get_ref() const20672     ReferenceType get_ref() const
20673     {
20674         // delegate call to get_ref_impl
20675         return get_ref_impl<ReferenceType>(*this);
20676     }
20677 
20678     /*!
20679     @brief get a value (implicit)
20680 
20681     Implicit type conversion between the JSON value and a compatible value.
20682     The call is realized by calling @ref get() const.
20683 
20684     @tparam ValueType non-pointer type compatible to the JSON value, for
20685     instance `int` for JSON integer numbers, `bool` for JSON booleans, or
20686     `std::vector` types for JSON arrays. The character type of @ref string_t
20687     as well as an initializer list of this type is excluded to avoid
20688     ambiguities as these types implicitly convert to `std::string`.
20689 
20690     @return copy of the JSON value, converted to type @a ValueType
20691 
20692     @throw type_error.302 in case passed type @a ValueType is incompatible
20693     to the JSON value type (e.g., the JSON value is of type boolean, but a
20694     string is requested); see example below
20695 
20696     @complexity Linear in the size of the JSON value.
20697 
20698     @liveexample{The example below shows several conversions from JSON values
20699     to other types. There a few things to note: (1) Floating-point numbers can
20700     be converted to integers\, (2) A JSON array can be converted to a standard
20701     `std::vector<short>`\, (3) A JSON object can be converted to C++
20702     associative containers such as `std::unordered_map<std::string\,
20703     json>`.,operator__ValueType}
20704 
20705     @since version 1.0.0
20706     */
20707     template < typename ValueType, typename std::enable_if <
20708                    detail::conjunction <
20709                        detail::negation<std::is_pointer<ValueType>>,
20710                        detail::negation<std::is_same<ValueType, std::nullptr_t>>,
20711                        detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
20712                                         detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
20713                                         detail::negation<detail::is_basic_json<ValueType>>,
20714                                         detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
20715 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
20716                                                 detail::negation<std::is_same<ValueType, std::string_view>>,
20717 #endif
20718 #if defined(JSON_HAS_CPP_17)
20719                                                 detail::negation<std::is_same<ValueType, std::any>>,
20720 #endif
20721                                                 detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
20722                                                 >::value, int >::type = 0 >
operator ValueType() const20723                                         JSON_EXPLICIT operator ValueType() const
20724     {
20725         // delegate the call to get<>() const
20726         return get<ValueType>();
20727     }
20728 
20729     /// @brief get a binary value
20730     /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
get_binary()20731     binary_t& get_binary()
20732     {
20733         if (!is_binary())
20734         {
20735             JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
20736         }
20737 
20738         return *get_ptr<binary_t*>();
20739     }
20740 
20741     /// @brief get a binary value
20742     /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
get_binary() const20743     const binary_t& get_binary() const
20744     {
20745         if (!is_binary())
20746         {
20747             JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
20748         }
20749 
20750         return *get_ptr<const binary_t*>();
20751     }
20752 
20753     /// @}
20754 
20755 
20756     ////////////////////
20757     // element access //
20758     ////////////////////
20759 
20760     /// @name element access
20761     /// Access to the JSON value.
20762     /// @{
20763 
20764     /// @brief access specified array element with bounds checking
20765     /// @sa https://json.nlohmann.me/api/basic_json/at/
at(size_type idx)20766     reference at(size_type idx)
20767     {
20768         // at only works for arrays
20769         if (JSON_HEDLEY_LIKELY(is_array()))
20770         {
20771             JSON_TRY
20772             {
20773                 return set_parent(m_value.array->at(idx));
20774             }
20775             JSON_CATCH (std::out_of_range&)
20776             {
20777                 // create better exception explanation
20778                 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
20779             }
20780         }
20781         else
20782         {
20783             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20784         }
20785     }
20786 
20787     /// @brief access specified array element with bounds checking
20788     /// @sa https://json.nlohmann.me/api/basic_json/at/
at(size_type idx) const20789     const_reference at(size_type idx) const
20790     {
20791         // at only works for arrays
20792         if (JSON_HEDLEY_LIKELY(is_array()))
20793         {
20794             JSON_TRY
20795             {
20796                 return m_value.array->at(idx);
20797             }
20798             JSON_CATCH (std::out_of_range&)
20799             {
20800                 // create better exception explanation
20801                 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
20802             }
20803         }
20804         else
20805         {
20806             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20807         }
20808     }
20809 
20810     /// @brief access specified object element with bounds checking
20811     /// @sa https://json.nlohmann.me/api/basic_json/at/
at(const typename object_t::key_type & key)20812     reference at(const typename object_t::key_type& key)
20813     {
20814         // at only works for objects
20815         if (JSON_HEDLEY_UNLIKELY(!is_object()))
20816         {
20817             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20818         }
20819 
20820         auto it = m_value.object->find(key);
20821         if (it == m_value.object->end())
20822         {
20823             JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
20824         }
20825         return set_parent(it->second);
20826     }
20827 
20828     /// @brief access specified object element with bounds checking
20829     /// @sa https://json.nlohmann.me/api/basic_json/at/
20830     template<class KeyType, detail::enable_if_t<
20831                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
at(KeyType && key)20832     reference at(KeyType && key)
20833     {
20834         // at only works for objects
20835         if (JSON_HEDLEY_UNLIKELY(!is_object()))
20836         {
20837             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20838         }
20839 
20840         auto it = m_value.object->find(std::forward<KeyType>(key));
20841         if (it == m_value.object->end())
20842         {
20843             JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
20844         }
20845         return set_parent(it->second);
20846     }
20847 
20848     /// @brief access specified object element with bounds checking
20849     /// @sa https://json.nlohmann.me/api/basic_json/at/
at(const typename object_t::key_type & key) const20850     const_reference at(const typename object_t::key_type& key) const
20851     {
20852         // at only works for objects
20853         if (JSON_HEDLEY_UNLIKELY(!is_object()))
20854         {
20855             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20856         }
20857 
20858         auto it = m_value.object->find(key);
20859         if (it == m_value.object->end())
20860         {
20861             JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
20862         }
20863         return it->second;
20864     }
20865 
20866     /// @brief access specified object element with bounds checking
20867     /// @sa https://json.nlohmann.me/api/basic_json/at/
20868     template<class KeyType, detail::enable_if_t<
20869                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
at(KeyType && key) const20870     const_reference at(KeyType && key) const
20871     {
20872         // at only works for objects
20873         if (JSON_HEDLEY_UNLIKELY(!is_object()))
20874         {
20875             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20876         }
20877 
20878         auto it = m_value.object->find(std::forward<KeyType>(key));
20879         if (it == m_value.object->end())
20880         {
20881             JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
20882         }
20883         return it->second;
20884     }
20885 
20886     /// @brief access specified array element
20887     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
operator [](size_type idx)20888     reference operator[](size_type idx)
20889     {
20890         // implicitly convert null value to an empty array
20891         if (is_null())
20892         {
20893             m_type = value_t::array;
20894             m_value.array = create<array_t>();
20895             assert_invariant();
20896         }
20897 
20898         // operator[] only works for arrays
20899         if (JSON_HEDLEY_LIKELY(is_array()))
20900         {
20901             // fill up array with null values if given idx is outside range
20902             if (idx >= m_value.array->size())
20903             {
20904 #if JSON_DIAGNOSTICS
20905                 // remember array size & capacity before resizing
20906                 const auto old_size = m_value.array->size();
20907                 const auto old_capacity = m_value.array->capacity();
20908 #endif
20909                 m_value.array->resize(idx + 1);
20910 
20911 #if JSON_DIAGNOSTICS
20912                 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
20913                 {
20914                     // capacity has changed: update all parents
20915                     set_parents();
20916                 }
20917                 else
20918                 {
20919                     // set parent for values added above
20920                     set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
20921                 }
20922 #endif
20923                 assert_invariant();
20924             }
20925 
20926             return m_value.array->operator[](idx);
20927         }
20928 
20929         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
20930     }
20931 
20932     /// @brief access specified array element
20933     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
operator [](size_type idx) const20934     const_reference operator[](size_type idx) const
20935     {
20936         // const operator[] only works for arrays
20937         if (JSON_HEDLEY_LIKELY(is_array()))
20938         {
20939             return m_value.array->operator[](idx);
20940         }
20941 
20942         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
20943     }
20944 
20945     /// @brief access specified object element
20946     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
operator [](typename object_t::key_type key)20947     reference operator[](typename object_t::key_type key)
20948     {
20949         // implicitly convert null value to an empty object
20950         if (is_null())
20951         {
20952             m_type = value_t::object;
20953             m_value.object = create<object_t>();
20954             assert_invariant();
20955         }
20956 
20957         // operator[] only works for objects
20958         if (JSON_HEDLEY_LIKELY(is_object()))
20959         {
20960             auto result = m_value.object->emplace(std::move(key), nullptr);
20961             return set_parent(result.first->second);
20962         }
20963 
20964         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
20965     }
20966 
20967     /// @brief access specified object element
20968     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
operator [](const typename object_t::key_type & key) const20969     const_reference operator[](const typename object_t::key_type& key) const
20970     {
20971         // const operator[] only works for objects
20972         if (JSON_HEDLEY_LIKELY(is_object()))
20973         {
20974             auto it = m_value.object->find(key);
20975             JSON_ASSERT(it != m_value.object->end());
20976             return it->second;
20977         }
20978 
20979         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
20980     }
20981 
20982     // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
20983     // (they seemingly cannot be constrained to resolve the ambiguity)
20984     template<typename T>
operator [](T * key)20985     reference operator[](T* key)
20986     {
20987         return operator[](typename object_t::key_type(key));
20988     }
20989 
20990     template<typename T>
operator [](T * key) const20991     const_reference operator[](T* key) const
20992     {
20993         return operator[](typename object_t::key_type(key));
20994     }
20995 
20996     /// @brief access specified object element
20997     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
20998     template<class KeyType, detail::enable_if_t<
20999                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
operator [](KeyType && key)21000     reference operator[](KeyType && key)
21001     {
21002         // implicitly convert null value to an empty object
21003         if (is_null())
21004         {
21005             m_type = value_t::object;
21006             m_value.object = create<object_t>();
21007             assert_invariant();
21008         }
21009 
21010         // operator[] only works for objects
21011         if (JSON_HEDLEY_LIKELY(is_object()))
21012         {
21013             auto result = m_value.object->emplace(std::forward<KeyType>(key), nullptr);
21014             return set_parent(result.first->second);
21015         }
21016 
21017         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21018     }
21019 
21020     /// @brief access specified object element
21021     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21022     template<class KeyType, detail::enable_if_t<
21023                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
operator [](KeyType && key) const21024     const_reference operator[](KeyType && key) const
21025     {
21026         // const operator[] only works for objects
21027         if (JSON_HEDLEY_LIKELY(is_object()))
21028         {
21029             auto it = m_value.object->find(std::forward<KeyType>(key));
21030             JSON_ASSERT(it != m_value.object->end());
21031             return it->second;
21032         }
21033 
21034         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21035     }
21036 
21037     /// @brief access specified object element with default value
21038     /// @sa https://json.nlohmann.me/api/basic_json/value/
21039     // this is the value(const typename object_t::key_type&) overload
21040     template < class KeyType, class ValueType, detail::enable_if_t <
21041                    std::is_same<KeyType, typename object_t::key_type>::value
21042                    && detail::is_getable<basic_json_t, ValueType>::value
21043                    && !std::is_same<value_t, ValueType>::value, int > = 0 >
value(const KeyType & key,ValueType && default_value) const21044     typename std::decay<ValueType>::type value(const KeyType& key, ValueType && default_value) const
21045     {
21046         // value only works for objects
21047         if (JSON_HEDLEY_LIKELY(is_object()))
21048         {
21049             // if key is found, return value and given default value otherwise
21050             const auto it = find(key);
21051             if (it != end())
21052             {
21053                 return it->template get<typename std::decay<ValueType>::type>();
21054             }
21055 
21056             return std::forward<ValueType>(default_value);
21057         }
21058 
21059         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21060     }
21061 
21062     /// @brief access specified object element with default value
21063     /// @sa https://json.nlohmann.me/api/basic_json/value/
21064     /// overload for a default value of type const char*
value(const typename object_t::key_type & key,const char * default_value) const21065     string_t value(const typename object_t::key_type& key, const char* default_value) const
21066     {
21067         return value(key, string_t(default_value));
21068     }
21069 
21070     // these two functions, in conjunction with value(const KeyType &, ValueType &&),
21071     // resolve an ambiguity that would otherwise occur between the json_pointer and
21072     // typename object_t::key_type & overloads
21073     template < class ValueType, detail::enable_if_t <
21074                    detail::is_getable<basic_json_t, ValueType>::value
21075                    && !std::is_same<value_t, ValueType>::value, int > = 0 >
value(const char * key,ValueType && default_value) const21076     typename std::decay<ValueType>::type value(const char* key, ValueType && default_value) const
21077     {
21078         return value(typename object_t::key_type(key), std::forward<ValueType>(default_value));
21079     }
21080 
value(const char * key,const char * default_value) const21081     string_t value(const char* key, const char* default_value) const
21082     {
21083         return value(typename object_t::key_type(key), string_t(default_value));
21084     }
21085 
21086     /// @brief access specified object element with default value
21087     /// @sa https://json.nlohmann.me/api/basic_json/value/
21088     /// using std::is_convertible in a std::enable_if will fail when using explicit conversions
21089     template < class KeyType, class ValueType, detail::enable_if_t <
21090                    detail::is_getable<basic_json_t, ValueType>::value
21091                    && !std::is_same<value_t, ValueType>::value
21092                    && detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
value(KeyType && key,ValueType && default_value) const21093     typename std::decay<ValueType>::type value(KeyType && key, ValueType && default_value) const
21094     {
21095         // value only works for objects
21096         if (JSON_HEDLEY_LIKELY(is_object()))
21097         {
21098             // if key is found, return value and given default value otherwise
21099             const auto it = find(std::forward<KeyType>(key));
21100             if (it != end())
21101             {
21102                 return it->template get<typename std::decay<ValueType>::type>();
21103             }
21104 
21105             return std::forward<ValueType>(default_value);
21106         }
21107 
21108         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21109     }
21110 
21111     /// @brief access specified object element with default value
21112     /// @sa https://json.nlohmann.me/api/basic_json/value/
21113     /// overload for a default value of type const char*
21114     template < class KeyType, detail::enable_if_t <
21115                    !detail::is_json_pointer<KeyType>::value, int > = 0 >
value(KeyType && key,const char * default_value) const21116     string_t value(KeyType && key, const char* default_value) const
21117     {
21118         return value(std::forward<KeyType>(key), string_t(default_value));
21119     }
21120 
21121     /// @brief access specified object element via JSON Pointer with default value
21122     /// @sa https://json.nlohmann.me/api/basic_json/value/
21123     template < class ValueType, detail::enable_if_t <
21124                    detail::is_getable<basic_json_t, ValueType>::value, int> = 0 >
value(const json_pointer & ptr,const ValueType & default_value) const21125     ValueType value(const json_pointer& ptr, const ValueType& default_value) const
21126     {
21127         // value only works for objects
21128         if (JSON_HEDLEY_LIKELY(is_object()))
21129         {
21130             // if pointer resolves a value, return it or use default value
21131             JSON_TRY
21132             {
21133                 return ptr.get_checked(this).template get<ValueType>();
21134             }
21135             JSON_INTERNAL_CATCH (out_of_range&)
21136             {
21137                 return default_value;
21138             }
21139         }
21140 
21141         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21142     }
21143 
21144     template < class ValueType, class BasicJsonType, detail::enable_if_t <
21145                    detail::is_getable<basic_json_t, ValueType>::value, int> = 0 >
21146     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
value(const::nlohmann::json_pointer<BasicJsonType> & ptr,const ValueType & default_value) const21147     ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
21148     {
21149         return value(ptr.convert(), default_value);
21150     }
21151 
21152     /// @brief access specified object element via JSON Pointer with default value
21153     /// @sa https://json.nlohmann.me/api/basic_json/value/
21154     /// overload for a default value of type const char*
21155     JSON_HEDLEY_NON_NULL(3)
value(const json_pointer & ptr,const char * default_value) const21156     string_t value(const json_pointer& ptr, const char* default_value) const
21157     {
21158         return value(ptr, string_t(default_value));
21159     }
21160 
21161     template<typename BasicJsonType>
21162     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21163     JSON_HEDLEY_NON_NULL(3)
value(const typename::nlohmann::json_pointer<BasicJsonType> & ptr,const char * default_value) const21164     string_t value(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr, const char* default_value) const
21165     {
21166         return value(ptr.convert(), default_value);
21167     }
21168 
21169     /// @brief access the first element
21170     /// @sa https://json.nlohmann.me/api/basic_json/front/
front()21171     reference front()
21172     {
21173         return *begin();
21174     }
21175 
21176     /// @brief access the first element
21177     /// @sa https://json.nlohmann.me/api/basic_json/front/
front() const21178     const_reference front() const
21179     {
21180         return *cbegin();
21181     }
21182 
21183     /// @brief access the last element
21184     /// @sa https://json.nlohmann.me/api/basic_json/back/
back()21185     reference back()
21186     {
21187         auto tmp = end();
21188         --tmp;
21189         return *tmp;
21190     }
21191 
21192     /// @brief access the last element
21193     /// @sa https://json.nlohmann.me/api/basic_json/back/
back() const21194     const_reference back() const
21195     {
21196         auto tmp = cend();
21197         --tmp;
21198         return *tmp;
21199     }
21200 
21201     /// @brief remove element given an iterator
21202     /// @sa https://json.nlohmann.me/api/basic_json/erase/
21203     template < class IteratorType, detail::enable_if_t <
21204                    std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21205                    std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
erase(IteratorType pos)21206     IteratorType erase(IteratorType pos)
21207     {
21208         // make sure iterator fits the current value
21209         if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
21210         {
21211             JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21212         }
21213 
21214         IteratorType result = end();
21215 
21216         switch (m_type)
21217         {
21218             case value_t::boolean:
21219             case value_t::number_float:
21220             case value_t::number_integer:
21221             case value_t::number_unsigned:
21222             case value_t::string:
21223             case value_t::binary:
21224             {
21225                 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
21226                 {
21227                     JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
21228                 }
21229 
21230                 if (is_string())
21231                 {
21232                     AllocatorType<string_t> alloc;
21233                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
21234                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
21235                     m_value.string = nullptr;
21236                 }
21237                 else if (is_binary())
21238                 {
21239                     AllocatorType<binary_t> alloc;
21240                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
21241                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
21242                     m_value.binary = nullptr;
21243                 }
21244 
21245                 m_type = value_t::null;
21246                 assert_invariant();
21247                 break;
21248             }
21249 
21250             case value_t::object:
21251             {
21252                 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
21253                 break;
21254             }
21255 
21256             case value_t::array:
21257             {
21258                 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
21259                 break;
21260             }
21261 
21262             case value_t::null:
21263             case value_t::discarded:
21264             default:
21265                 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21266         }
21267 
21268         return result;
21269     }
21270 
21271     /// @brief remove elements given an iterator range
21272     /// @sa https://json.nlohmann.me/api/basic_json/erase/
21273     template < class IteratorType, detail::enable_if_t <
21274                    std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21275                    std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
erase(IteratorType first,IteratorType last)21276     IteratorType erase(IteratorType first, IteratorType last)
21277     {
21278         // make sure iterator fits the current value
21279         if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
21280         {
21281             JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
21282         }
21283 
21284         IteratorType result = end();
21285 
21286         switch (m_type)
21287         {
21288             case value_t::boolean:
21289             case value_t::number_float:
21290             case value_t::number_integer:
21291             case value_t::number_unsigned:
21292             case value_t::string:
21293             case value_t::binary:
21294             {
21295                 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
21296                                        || !last.m_it.primitive_iterator.is_end()))
21297                 {
21298                     JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
21299                 }
21300 
21301                 if (is_string())
21302                 {
21303                     AllocatorType<string_t> alloc;
21304                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
21305                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
21306                     m_value.string = nullptr;
21307                 }
21308                 else if (is_binary())
21309                 {
21310                     AllocatorType<binary_t> alloc;
21311                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
21312                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
21313                     m_value.binary = nullptr;
21314                 }
21315 
21316                 m_type = value_t::null;
21317                 assert_invariant();
21318                 break;
21319             }
21320 
21321             case value_t::object:
21322             {
21323                 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
21324                                               last.m_it.object_iterator);
21325                 break;
21326             }
21327 
21328             case value_t::array:
21329             {
21330                 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
21331                                              last.m_it.array_iterator);
21332                 break;
21333             }
21334 
21335             case value_t::null:
21336             case value_t::discarded:
21337             default:
21338                 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21339         }
21340 
21341         return result;
21342     }
21343 
21344   private:
21345     template < typename KeyType, detail::enable_if_t <
21346                    detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
erase_internal(KeyType && key)21347     size_type erase_internal(KeyType && key)
21348     {
21349         // this erase only works for objects
21350         if (JSON_HEDLEY_UNLIKELY(!is_object()))
21351         {
21352             JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21353         }
21354 
21355         return m_value.object->erase(std::forward<KeyType>(key));
21356     }
21357 
21358     template < typename KeyType, detail::enable_if_t <
21359                    !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
erase_internal(KeyType && key)21360     size_type erase_internal(KeyType && key)
21361     {
21362         // this erase only works for objects
21363         if (JSON_HEDLEY_UNLIKELY(!is_object()))
21364         {
21365             JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21366         }
21367 
21368         const auto it = m_value.object->find(std::forward<KeyType>(key));
21369         if (it != m_value.object->end())
21370         {
21371             m_value.object->erase(it);
21372             return 1;
21373         }
21374         return 0;
21375     }
21376 
21377   public:
21378 
21379     /// @brief remove element from a JSON object given a key
21380     /// @sa https://json.nlohmann.me/api/basic_json/erase/
erase(const typename object_t::key_type & key)21381     size_type erase(const typename object_t::key_type& key)
21382     {
21383         // the indirection via erase_internal() is added to avoid making this
21384         // function a template and thus de-rank it during overload resolution
21385         return erase_internal(key);
21386     }
21387 
21388     /// @brief remove element from a JSON object given a key
21389     /// @sa https://json.nlohmann.me/api/basic_json/erase/
21390     template<class KeyType, detail::enable_if_t<
21391                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
erase(KeyType && key)21392     size_type erase(KeyType && key)
21393     {
21394         return erase_internal(std::forward<KeyType>(key));
21395     }
21396 
21397     /// @brief remove element from a JSON array given an index
21398     /// @sa https://json.nlohmann.me/api/basic_json/erase/
erase(const size_type idx)21399     void erase(const size_type idx)
21400     {
21401         // this erase only works for arrays
21402         if (JSON_HEDLEY_LIKELY(is_array()))
21403         {
21404             if (JSON_HEDLEY_UNLIKELY(idx >= size()))
21405             {
21406                 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21407             }
21408 
21409             m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
21410         }
21411         else
21412         {
21413             JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21414         }
21415     }
21416 
21417     /// @}
21418 
21419 
21420     ////////////
21421     // lookup //
21422     ////////////
21423 
21424     /// @name lookup
21425     /// @{
21426 
21427     /// @brief find an element in a JSON object
21428     /// @sa https://json.nlohmann.me/api/basic_json/find/
find(const typename object_t::key_type & key)21429     iterator find(const typename object_t::key_type& key)
21430     {
21431         auto result = end();
21432 
21433         if (is_object())
21434         {
21435             result.m_it.object_iterator = m_value.object->find(key);
21436         }
21437 
21438         return result;
21439     }
21440 
21441     /// @brief find an element in a JSON object
21442     /// @sa https://json.nlohmann.me/api/basic_json/find/
find(const typename object_t::key_type & key) const21443     const_iterator find(const typename object_t::key_type& key) const
21444     {
21445         auto result = cend();
21446 
21447         if (is_object())
21448         {
21449             result.m_it.object_iterator = m_value.object->find(key);
21450         }
21451 
21452         return result;
21453     }
21454 
21455     /// @brief find an element in a JSON object
21456     /// @sa https://json.nlohmann.me/api/basic_json/find/
21457     template<class KeyType, detail::enable_if_t<
21458                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
find(KeyType && key)21459     iterator find(KeyType && key)
21460     {
21461         auto result = end();
21462 
21463         if (is_object())
21464         {
21465             result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
21466         }
21467 
21468         return result;
21469     }
21470 
21471     /// @brief find an element in a JSON object
21472     /// @sa https://json.nlohmann.me/api/basic_json/find/
21473     template<class KeyType, detail::enable_if_t<
21474                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
find(KeyType && key) const21475     const_iterator find(KeyType && key) const
21476     {
21477         auto result = cend();
21478 
21479         if (is_object())
21480         {
21481             result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
21482         }
21483 
21484         return result;
21485     }
21486 
21487     /// @brief returns the number of occurrences of a key in a JSON object
21488     /// @sa https://json.nlohmann.me/api/basic_json/count/
count(const typename object_t::key_type & key) const21489     size_type count(const typename object_t::key_type& key) const
21490     {
21491         // return 0 for all nonobject types
21492         return is_object() ? m_value.object->count(key) : 0;
21493     }
21494 
21495     /// @brief returns the number of occurrences of a key in a JSON object
21496     /// @sa https://json.nlohmann.me/api/basic_json/count/
21497     template<class KeyType, detail::enable_if_t<
21498                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
count(KeyType && key) const21499     size_type count(KeyType && key) const
21500     {
21501         // return 0 for all nonobject types
21502         return is_object() ? m_value.object->count(std::forward<KeyType>(key)) : 0;
21503     }
21504 
21505     /// @brief check the existence of an element in a JSON object
21506     /// @sa https://json.nlohmann.me/api/basic_json/contains/
contains(const typename object_t::key_type & key) const21507     bool contains(const typename object_t::key_type& key) const
21508     {
21509         return is_object() && m_value.object->find(key) != m_value.object->end();
21510     }
21511 
21512     /// @brief check the existence of an element in a JSON object
21513     /// @sa https://json.nlohmann.me/api/basic_json/contains/
21514     template<class KeyType, detail::enable_if_t<
21515                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
contains(KeyType && key) const21516     bool contains(KeyType && key) const
21517     {
21518         return is_object() && m_value.object->find(std::forward<KeyType>(key)) != m_value.object->end();
21519     }
21520 
21521     /// @brief check the existence of an element in a JSON object given a JSON pointer
21522     /// @sa https://json.nlohmann.me/api/basic_json/contains/
contains(const json_pointer & ptr) const21523     bool contains(const json_pointer& ptr) const
21524     {
21525         return ptr.contains(this);
21526     }
21527 
21528     template<typename BasicJsonType>
21529     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
contains(const typename::nlohmann::json_pointer<BasicJsonType> ptr) const21530     bool contains(const typename ::nlohmann::json_pointer<BasicJsonType> ptr) const
21531     {
21532         return ptr.contains(this);
21533     }
21534 
21535     /// @}
21536 
21537 
21538     ///////////////
21539     // iterators //
21540     ///////////////
21541 
21542     /// @name iterators
21543     /// @{
21544 
21545     /// @brief returns an iterator to the first element
21546     /// @sa https://json.nlohmann.me/api/basic_json/begin/
begin()21547     iterator begin() noexcept
21548     {
21549         iterator result(this);
21550         result.set_begin();
21551         return result;
21552     }
21553 
21554     /// @brief returns an iterator to the first element
21555     /// @sa https://json.nlohmann.me/api/basic_json/begin/
begin() const21556     const_iterator begin() const noexcept
21557     {
21558         return cbegin();
21559     }
21560 
21561     /// @brief returns a const iterator to the first element
21562     /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
cbegin() const21563     const_iterator cbegin() const noexcept
21564     {
21565         const_iterator result(this);
21566         result.set_begin();
21567         return result;
21568     }
21569 
21570     /// @brief returns an iterator to one past the last element
21571     /// @sa https://json.nlohmann.me/api/basic_json/end/
end()21572     iterator end() noexcept
21573     {
21574         iterator result(this);
21575         result.set_end();
21576         return result;
21577     }
21578 
21579     /// @brief returns an iterator to one past the last element
21580     /// @sa https://json.nlohmann.me/api/basic_json/end/
end() const21581     const_iterator end() const noexcept
21582     {
21583         return cend();
21584     }
21585 
21586     /// @brief returns an iterator to one past the last element
21587     /// @sa https://json.nlohmann.me/api/basic_json/cend/
cend() const21588     const_iterator cend() const noexcept
21589     {
21590         const_iterator result(this);
21591         result.set_end();
21592         return result;
21593     }
21594 
21595     /// @brief returns an iterator to the reverse-beginning
21596     /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
rbegin()21597     reverse_iterator rbegin() noexcept
21598     {
21599         return reverse_iterator(end());
21600     }
21601 
21602     /// @brief returns an iterator to the reverse-beginning
21603     /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
rbegin() const21604     const_reverse_iterator rbegin() const noexcept
21605     {
21606         return crbegin();
21607     }
21608 
21609     /// @brief returns an iterator to the reverse-end
21610     /// @sa https://json.nlohmann.me/api/basic_json/rend/
rend()21611     reverse_iterator rend() noexcept
21612     {
21613         return reverse_iterator(begin());
21614     }
21615 
21616     /// @brief returns an iterator to the reverse-end
21617     /// @sa https://json.nlohmann.me/api/basic_json/rend/
rend() const21618     const_reverse_iterator rend() const noexcept
21619     {
21620         return crend();
21621     }
21622 
21623     /// @brief returns a const reverse iterator to the last element
21624     /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
crbegin() const21625     const_reverse_iterator crbegin() const noexcept
21626     {
21627         return const_reverse_iterator(cend());
21628     }
21629 
21630     /// @brief returns a const reverse iterator to one before the first
21631     /// @sa https://json.nlohmann.me/api/basic_json/crend/
crend() const21632     const_reverse_iterator crend() const noexcept
21633     {
21634         return const_reverse_iterator(cbegin());
21635     }
21636 
21637   public:
21638     /// @brief wrapper to access iterator member functions in range-based for
21639     /// @sa https://json.nlohmann.me/api/basic_json/items/
21640     /// @deprecated This function is deprecated since 3.1.0 and will be removed in
21641     ///             version 4.0.0 of the library. Please use @ref items() instead;
21642     ///             that is, replace `json::iterator_wrapper(j)` with `j.items()`.
items()21643     JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
21644     static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
21645     {
21646         return ref.items();
21647     }
21648 
21649     /// @brief wrapper to access iterator member functions in range-based for
21650     /// @sa https://json.nlohmann.me/api/basic_json/items/
21651     /// @deprecated This function is deprecated since 3.1.0 and will be removed in
21652     ///         version 4.0.0 of the library. Please use @ref items() instead;
21653     ///         that is, replace `json::iterator_wrapper(j)` with `j.items()`.
items()21654     JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
21655     static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
21656     {
21657         return ref.items();
21658     }
21659 
21660     /// @brief helper to access iterator member functions in range-based for
21661     /// @sa https://json.nlohmann.me/api/basic_json/items/
items()21662     iteration_proxy<iterator> items() noexcept
21663     {
21664         return iteration_proxy<iterator>(*this);
21665     }
21666 
21667     /// @brief helper to access iterator member functions in range-based for
21668     /// @sa https://json.nlohmann.me/api/basic_json/items/
items() const21669     iteration_proxy<const_iterator> items() const noexcept
21670     {
21671         return iteration_proxy<const_iterator>(*this);
21672     }
21673 
21674     /// @}
21675 
21676 
21677     //////////////
21678     // capacity //
21679     //////////////
21680 
21681     /// @name capacity
21682     /// @{
21683 
21684     /// @brief checks whether the container is empty.
21685     /// @sa https://json.nlohmann.me/api/basic_json/empty/
empty() const21686     bool empty() const noexcept
21687     {
21688         switch (m_type)
21689         {
21690             case value_t::null:
21691             {
21692                 // null values are empty
21693                 return true;
21694             }
21695 
21696             case value_t::array:
21697             {
21698                 // delegate call to array_t::empty()
21699                 return m_value.array->empty();
21700             }
21701 
21702             case value_t::object:
21703             {
21704                 // delegate call to object_t::empty()
21705                 return m_value.object->empty();
21706             }
21707 
21708             case value_t::string:
21709             case value_t::boolean:
21710             case value_t::number_integer:
21711             case value_t::number_unsigned:
21712             case value_t::number_float:
21713             case value_t::binary:
21714             case value_t::discarded:
21715             default:
21716             {
21717                 // all other types are nonempty
21718                 return false;
21719             }
21720         }
21721     }
21722 
21723     /// @brief returns the number of elements
21724     /// @sa https://json.nlohmann.me/api/basic_json/size/
size() const21725     size_type size() const noexcept
21726     {
21727         switch (m_type)
21728         {
21729             case value_t::null:
21730             {
21731                 // null values are empty
21732                 return 0;
21733             }
21734 
21735             case value_t::array:
21736             {
21737                 // delegate call to array_t::size()
21738                 return m_value.array->size();
21739             }
21740 
21741             case value_t::object:
21742             {
21743                 // delegate call to object_t::size()
21744                 return m_value.object->size();
21745             }
21746 
21747             case value_t::string:
21748             case value_t::boolean:
21749             case value_t::number_integer:
21750             case value_t::number_unsigned:
21751             case value_t::number_float:
21752             case value_t::binary:
21753             case value_t::discarded:
21754             default:
21755             {
21756                 // all other types have size 1
21757                 return 1;
21758             }
21759         }
21760     }
21761 
21762     /// @brief returns the maximum possible number of elements
21763     /// @sa https://json.nlohmann.me/api/basic_json/max_size/
max_size() const21764     size_type max_size() const noexcept
21765     {
21766         switch (m_type)
21767         {
21768             case value_t::array:
21769             {
21770                 // delegate call to array_t::max_size()
21771                 return m_value.array->max_size();
21772             }
21773 
21774             case value_t::object:
21775             {
21776                 // delegate call to object_t::max_size()
21777                 return m_value.object->max_size();
21778             }
21779 
21780             case value_t::null:
21781             case value_t::string:
21782             case value_t::boolean:
21783             case value_t::number_integer:
21784             case value_t::number_unsigned:
21785             case value_t::number_float:
21786             case value_t::binary:
21787             case value_t::discarded:
21788             default:
21789             {
21790                 // all other types have max_size() == size()
21791                 return size();
21792             }
21793         }
21794     }
21795 
21796     /// @}
21797 
21798 
21799     ///////////////
21800     // modifiers //
21801     ///////////////
21802 
21803     /// @name modifiers
21804     /// @{
21805 
21806     /// @brief clears the contents
21807     /// @sa https://json.nlohmann.me/api/basic_json/clear/
clear()21808     void clear() noexcept
21809     {
21810         switch (m_type)
21811         {
21812             case value_t::number_integer:
21813             {
21814                 m_value.number_integer = 0;
21815                 break;
21816             }
21817 
21818             case value_t::number_unsigned:
21819             {
21820                 m_value.number_unsigned = 0;
21821                 break;
21822             }
21823 
21824             case value_t::number_float:
21825             {
21826                 m_value.number_float = 0.0;
21827                 break;
21828             }
21829 
21830             case value_t::boolean:
21831             {
21832                 m_value.boolean = false;
21833                 break;
21834             }
21835 
21836             case value_t::string:
21837             {
21838                 m_value.string->clear();
21839                 break;
21840             }
21841 
21842             case value_t::binary:
21843             {
21844                 m_value.binary->clear();
21845                 break;
21846             }
21847 
21848             case value_t::array:
21849             {
21850                 m_value.array->clear();
21851                 break;
21852             }
21853 
21854             case value_t::object:
21855             {
21856                 m_value.object->clear();
21857                 break;
21858             }
21859 
21860             case value_t::null:
21861             case value_t::discarded:
21862             default:
21863                 break;
21864         }
21865     }
21866 
21867     /// @brief add an object to an array
21868     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
push_back(basic_json && val)21869     void push_back(basic_json&& val)
21870     {
21871         // push_back only works for null objects or arrays
21872         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
21873         {
21874             JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
21875         }
21876 
21877         // transform null object into an array
21878         if (is_null())
21879         {
21880             m_type = value_t::array;
21881             m_value = value_t::array;
21882             assert_invariant();
21883         }
21884 
21885         // add element to array (move semantics)
21886         const auto old_capacity = m_value.array->capacity();
21887         m_value.array->push_back(std::move(val));
21888         set_parent(m_value.array->back(), old_capacity);
21889         // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
21890     }
21891 
21892     /// @brief add an object to an array
21893     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
operator +=(basic_json && val)21894     reference operator+=(basic_json&& val)
21895     {
21896         push_back(std::move(val));
21897         return *this;
21898     }
21899 
21900     /// @brief add an object to an array
21901     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
push_back(const basic_json & val)21902     void push_back(const basic_json& val)
21903     {
21904         // push_back only works for null objects or arrays
21905         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
21906         {
21907             JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
21908         }
21909 
21910         // transform null object into an array
21911         if (is_null())
21912         {
21913             m_type = value_t::array;
21914             m_value = value_t::array;
21915             assert_invariant();
21916         }
21917 
21918         // add element to array
21919         const auto old_capacity = m_value.array->capacity();
21920         m_value.array->push_back(val);
21921         set_parent(m_value.array->back(), old_capacity);
21922     }
21923 
21924     /// @brief add an object to an array
21925     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
operator +=(const basic_json & val)21926     reference operator+=(const basic_json& val)
21927     {
21928         push_back(val);
21929         return *this;
21930     }
21931 
21932     /// @brief add an object to an object
21933     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
push_back(const typename object_t::value_type & val)21934     void push_back(const typename object_t::value_type& val)
21935     {
21936         // push_back only works for null objects or objects
21937         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
21938         {
21939             JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
21940         }
21941 
21942         // transform null object into an object
21943         if (is_null())
21944         {
21945             m_type = value_t::object;
21946             m_value = value_t::object;
21947             assert_invariant();
21948         }
21949 
21950         // add element to object
21951         auto res = m_value.object->insert(val);
21952         set_parent(res.first->second);
21953     }
21954 
21955     /// @brief add an object to an object
21956     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
operator +=(const typename object_t::value_type & val)21957     reference operator+=(const typename object_t::value_type& val)
21958     {
21959         push_back(val);
21960         return *this;
21961     }
21962 
21963     /// @brief add an object to an object
21964     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
push_back(initializer_list_t init)21965     void push_back(initializer_list_t init)
21966     {
21967         if (is_object() && init.size() == 2 && (*init.begin())->is_string())
21968         {
21969             basic_json&& key = init.begin()->moved_or_copied();
21970             push_back(typename object_t::value_type(
21971                           std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
21972         }
21973         else
21974         {
21975             push_back(basic_json(init));
21976         }
21977     }
21978 
21979     /// @brief add an object to an object
21980     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
operator +=(initializer_list_t init)21981     reference operator+=(initializer_list_t init)
21982     {
21983         push_back(init);
21984         return *this;
21985     }
21986 
21987     /// @brief add an object to an array
21988     /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
21989     template<class... Args>
emplace_back(Args &&...args)21990     reference emplace_back(Args&& ... args)
21991     {
21992         // emplace_back only works for null objects or arrays
21993         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
21994         {
21995             JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
21996         }
21997 
21998         // transform null object into an array
21999         if (is_null())
22000         {
22001             m_type = value_t::array;
22002             m_value = value_t::array;
22003             assert_invariant();
22004         }
22005 
22006         // add element to array (perfect forwarding)
22007         const auto old_capacity = m_value.array->capacity();
22008         m_value.array->emplace_back(std::forward<Args>(args)...);
22009         return set_parent(m_value.array->back(), old_capacity);
22010     }
22011 
22012     /// @brief add an object to an object if key does not exist
22013     /// @sa https://json.nlohmann.me/api/basic_json/emplace/
22014     template<class... Args>
emplace(Args &&...args)22015     std::pair<iterator, bool> emplace(Args&& ... args)
22016     {
22017         // emplace only works for null objects or arrays
22018         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22019         {
22020             JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
22021         }
22022 
22023         // transform null object into an object
22024         if (is_null())
22025         {
22026             m_type = value_t::object;
22027             m_value = value_t::object;
22028             assert_invariant();
22029         }
22030 
22031         // add element to array (perfect forwarding)
22032         auto res = m_value.object->emplace(std::forward<Args>(args)...);
22033         set_parent(res.first->second);
22034 
22035         // create result iterator and set iterator to the result of emplace
22036         auto it = begin();
22037         it.m_it.object_iterator = res.first;
22038 
22039         // return pair of iterator and boolean
22040         return {it, res.second};
22041     }
22042 
22043     /// Helper for insertion of an iterator
22044     /// @note: This uses std::distance to support GCC 4.8,
22045     ///        see https://github.com/nlohmann/json/pull/1257
22046     template<typename... Args>
insert_iterator(const_iterator pos,Args &&...args)22047     iterator insert_iterator(const_iterator pos, Args&& ... args)
22048     {
22049         iterator result(this);
22050         JSON_ASSERT(m_value.array != nullptr);
22051 
22052         auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
22053         m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
22054         result.m_it.array_iterator = m_value.array->begin() + insert_pos;
22055 
22056         // This could have been written as:
22057         // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
22058         // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
22059 
22060         set_parents();
22061         return result;
22062     }
22063 
22064     /// @brief inserts element into array
22065     /// @sa https://json.nlohmann.me/api/basic_json/insert/
insert(const_iterator pos,const basic_json & val)22066     iterator insert(const_iterator pos, const basic_json& val)
22067     {
22068         // insert only works for arrays
22069         if (JSON_HEDLEY_LIKELY(is_array()))
22070         {
22071             // check if iterator pos fits to this JSON value
22072             if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22073             {
22074                 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22075             }
22076 
22077             // insert to array and return iterator
22078             return insert_iterator(pos, val);
22079         }
22080 
22081         JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22082     }
22083 
22084     /// @brief inserts element into array
22085     /// @sa https://json.nlohmann.me/api/basic_json/insert/
insert(const_iterator pos,basic_json && val)22086     iterator insert(const_iterator pos, basic_json&& val)
22087     {
22088         return insert(pos, val);
22089     }
22090 
22091     /// @brief inserts copies of element into array
22092     /// @sa https://json.nlohmann.me/api/basic_json/insert/
insert(const_iterator pos,size_type cnt,const basic_json & val)22093     iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
22094     {
22095         // insert only works for arrays
22096         if (JSON_HEDLEY_LIKELY(is_array()))
22097         {
22098             // check if iterator pos fits to this JSON value
22099             if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22100             {
22101                 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22102             }
22103 
22104             // insert to array and return iterator
22105             return insert_iterator(pos, cnt, val);
22106         }
22107 
22108         JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22109     }
22110 
22111     /// @brief inserts range of elements into array
22112     /// @sa https://json.nlohmann.me/api/basic_json/insert/
insert(const_iterator pos,const_iterator first,const_iterator last)22113     iterator insert(const_iterator pos, const_iterator first, const_iterator last)
22114     {
22115         // insert only works for arrays
22116         if (JSON_HEDLEY_UNLIKELY(!is_array()))
22117         {
22118             JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22119         }
22120 
22121         // check if iterator pos fits to this JSON value
22122         if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22123         {
22124             JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22125         }
22126 
22127         // check if range iterators belong to the same JSON object
22128         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22129         {
22130             JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22131         }
22132 
22133         if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
22134         {
22135             JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
22136         }
22137 
22138         // insert to array and return iterator
22139         return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
22140     }
22141 
22142     /// @brief inserts elements from initializer list into array
22143     /// @sa https://json.nlohmann.me/api/basic_json/insert/
insert(const_iterator pos,initializer_list_t ilist)22144     iterator insert(const_iterator pos, initializer_list_t ilist)
22145     {
22146         // insert only works for arrays
22147         if (JSON_HEDLEY_UNLIKELY(!is_array()))
22148         {
22149             JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22150         }
22151 
22152         // check if iterator pos fits to this JSON value
22153         if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22154         {
22155             JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22156         }
22157 
22158         // insert to array and return iterator
22159         return insert_iterator(pos, ilist.begin(), ilist.end());
22160     }
22161 
22162     /// @brief inserts range of elements into object
22163     /// @sa https://json.nlohmann.me/api/basic_json/insert/
insert(const_iterator first,const_iterator last)22164     void insert(const_iterator first, const_iterator last)
22165     {
22166         // insert only works for objects
22167         if (JSON_HEDLEY_UNLIKELY(!is_object()))
22168         {
22169             JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22170         }
22171 
22172         // check if range iterators belong to the same JSON object
22173         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22174         {
22175             JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22176         }
22177 
22178         // passed iterators must belong to objects
22179         if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22180         {
22181             JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
22182         }
22183 
22184         m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
22185     }
22186 
22187     /// @brief updates a JSON object from another object, overwriting existing keys
22188     /// @sa https://json.nlohmann.me/api/basic_json/update/
update(const_reference j,bool merge_objects=false)22189     void update(const_reference j, bool merge_objects = false)
22190     {
22191         update(j.begin(), j.end(), merge_objects);
22192     }
22193 
22194     /// @brief updates a JSON object from another object, overwriting existing keys
22195     /// @sa https://json.nlohmann.me/api/basic_json/update/
update(const_iterator first,const_iterator last,bool merge_objects=false)22196     void update(const_iterator first, const_iterator last, bool merge_objects = false)
22197     {
22198         // implicitly convert null value to an empty object
22199         if (is_null())
22200         {
22201             m_type = value_t::object;
22202             m_value.object = create<object_t>();
22203             assert_invariant();
22204         }
22205 
22206         if (JSON_HEDLEY_UNLIKELY(!is_object()))
22207         {
22208             JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
22209         }
22210 
22211         // check if range iterators belong to the same JSON object
22212         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22213         {
22214             JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22215         }
22216 
22217         // passed iterators must belong to objects
22218         if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22219         {
22220             JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
22221         }
22222 
22223         for (auto it = first; it != last; ++it)
22224         {
22225             if (merge_objects && it.value().is_object())
22226             {
22227                 auto it2 = m_value.object->find(it.key());
22228                 if (it2 != m_value.object->end())
22229                 {
22230                     it2->second.update(it.value(), true);
22231                     continue;
22232                 }
22233             }
22234             m_value.object->operator[](it.key()) = it.value();
22235 #if JSON_DIAGNOSTICS
22236             m_value.object->operator[](it.key()).m_parent = this;
22237 #endif
22238         }
22239     }
22240 
22241     /// @brief exchanges the values
22242     /// @sa https://json.nlohmann.me/api/basic_json/swap/
swap(reference other)22243     void swap(reference other) noexcept (
22244         std::is_nothrow_move_constructible<value_t>::value&&
22245         std::is_nothrow_move_assignable<value_t>::value&&
22246         std::is_nothrow_move_constructible<json_value>::value&&
22247         std::is_nothrow_move_assignable<json_value>::value
22248     )
22249     {
22250         std::swap(m_type, other.m_type);
22251         std::swap(m_value, other.m_value);
22252 
22253         set_parents();
22254         other.set_parents();
22255         assert_invariant();
22256     }
22257 
22258     /// @brief exchanges the values
22259     /// @sa https://json.nlohmann.me/api/basic_json/swap/
swap(reference left,reference right)22260     friend void swap(reference left, reference right) noexcept (
22261         std::is_nothrow_move_constructible<value_t>::value&&
22262         std::is_nothrow_move_assignable<value_t>::value&&
22263         std::is_nothrow_move_constructible<json_value>::value&&
22264         std::is_nothrow_move_assignable<json_value>::value
22265     )
22266     {
22267         left.swap(right);
22268     }
22269 
22270     /// @brief exchanges the values
22271     /// @sa https://json.nlohmann.me/api/basic_json/swap/
swap(array_t & other)22272     void swap(array_t& other) // NOLINT(bugprone-exception-escape)
22273     {
22274         // swap only works for arrays
22275         if (JSON_HEDLEY_LIKELY(is_array()))
22276         {
22277             std::swap(*(m_value.array), other);
22278         }
22279         else
22280         {
22281             JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this));
22282         }
22283     }
22284 
22285     /// @brief exchanges the values
22286     /// @sa https://json.nlohmann.me/api/basic_json/swap/
swap(object_t & other)22287     void swap(object_t& other) // NOLINT(bugprone-exception-escape)
22288     {
22289         // swap only works for objects
22290         if (JSON_HEDLEY_LIKELY(is_object()))
22291         {
22292             std::swap(*(m_value.object), other);
22293         }
22294         else
22295         {
22296             JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this));
22297         }
22298     }
22299 
22300     /// @brief exchanges the values
22301     /// @sa https://json.nlohmann.me/api/basic_json/swap/
swap(string_t & other)22302     void swap(string_t& other) // NOLINT(bugprone-exception-escape)
22303     {
22304         // swap only works for strings
22305         if (JSON_HEDLEY_LIKELY(is_string()))
22306         {
22307             std::swap(*(m_value.string), other);
22308         }
22309         else
22310         {
22311             JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this));
22312         }
22313     }
22314 
22315     /// @brief exchanges the values
22316     /// @sa https://json.nlohmann.me/api/basic_json/swap/
swap(binary_t & other)22317     void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
22318     {
22319         // swap only works for strings
22320         if (JSON_HEDLEY_LIKELY(is_binary()))
22321         {
22322             std::swap(*(m_value.binary), other);
22323         }
22324         else
22325         {
22326             JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this));
22327         }
22328     }
22329 
22330     /// @brief exchanges the values
22331     /// @sa https://json.nlohmann.me/api/basic_json/swap/
swap(typename binary_t::container_type & other)22332     void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
22333     {
22334         // swap only works for strings
22335         if (JSON_HEDLEY_LIKELY(is_binary()))
22336         {
22337             std::swap(*(m_value.binary), other);
22338         }
22339         else
22340         {
22341             JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this));
22342         }
22343     }
22344 
22345     /// @}
22346 
22347     //////////////////////////////////////////
22348     // lexicographical comparison operators //
22349     //////////////////////////////////////////
22350 
22351     /// @name lexicographical comparison operators
22352     /// @{
22353 
22354     // note parentheses around operands are necessary; see
22355     // https://github.com/nlohmann/json/issues/1530
22356 #define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)                       \
22357     const auto lhs_type = lhs.type();                                                                    \
22358     const auto rhs_type = rhs.type();                                                                    \
22359     \
22360     if (lhs_type == rhs_type) /* NOLINT(readability/braces) */                                           \
22361     {                                                                                                    \
22362         switch (lhs_type)                                                                                \
22363         {                                                                                                \
22364             case value_t::array:                                                                         \
22365                 return (*lhs.m_value.array) op (*rhs.m_value.array);                                     \
22366                 \
22367             case value_t::object:                                                                        \
22368                 return (*lhs.m_value.object) op (*rhs.m_value.object);                                   \
22369                 \
22370             case value_t::null:                                                                          \
22371                 return (null_result);                                                                    \
22372                 \
22373             case value_t::string:                                                                        \
22374                 return (*lhs.m_value.string) op (*rhs.m_value.string);                                   \
22375                 \
22376             case value_t::boolean:                                                                       \
22377                 return (lhs.m_value.boolean) op (rhs.m_value.boolean);                                   \
22378                 \
22379             case value_t::number_integer:                                                                \
22380                 return (lhs.m_value.number_integer) op (rhs.m_value.number_integer);                     \
22381                 \
22382             case value_t::number_unsigned:                                                               \
22383                 return (lhs.m_value.number_unsigned) op (rhs.m_value.number_unsigned);                   \
22384                 \
22385             case value_t::number_float:                                                                  \
22386                 return (lhs.m_value.number_float) op (rhs.m_value.number_float);                         \
22387                 \
22388             case value_t::binary:                                                                        \
22389                 return (*lhs.m_value.binary) op (*rhs.m_value.binary);                                   \
22390                 \
22391             case value_t::discarded:                                                                     \
22392             default:                                                                                     \
22393                 return (unordered_result);                                                               \
22394         }                                                                                                \
22395     }                                                                                                    \
22396     else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)                   \
22397     {                                                                                                    \
22398         return static_cast<number_float_t>(lhs.m_value.number_integer) op rhs.m_value.number_float;      \
22399     }                                                                                                    \
22400     else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)                   \
22401     {                                                                                                    \
22402         return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_integer);      \
22403     }                                                                                                    \
22404     else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)                  \
22405     {                                                                                                    \
22406         return static_cast<number_float_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_float;     \
22407     }                                                                                                    \
22408     else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)                  \
22409     {                                                                                                    \
22410         return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_unsigned);     \
22411     }                                                                                                    \
22412     else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)                \
22413     {                                                                                                    \
22414         return static_cast<number_integer_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_integer; \
22415     }                                                                                                    \
22416     else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)                \
22417     {                                                                                                    \
22418         return lhs.m_value.number_integer op static_cast<number_integer_t>(rhs.m_value.number_unsigned); \
22419     }                                                                                                    \
22420     else if(compares_unordered(lhs, rhs))\
22421     {\
22422         return (unordered_result);\
22423     }\
22424     \
22425     return (default_result);
22426 
22427   JSON_PRIVATE_UNLESS_TESTED:
22428     // returns true if:
22429     // - any operand is NaN and the other operand is of number type
22430     // - any operand is discarded
22431     // in legacy mode, discarded values are considered ordered if
22432     // an operation is computed as an odd number of inverses of others
22433     static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
22434     {
22435         if ((lhs.is_number_float() && std::isnan(lhs.m_value.number_float) && rhs.is_number())
22436                 || (rhs.is_number_float() && std::isnan(rhs.m_value.number_float) && lhs.is_number()))
22437         {
22438             return true;
22439         }
22440 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22441         return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
22442 #else
22443         static_cast<void>(inverse);
22444         return lhs.is_discarded() || rhs.is_discarded();
22445 #endif
22446     }
22447 
22448   private:
compares_unordered(const_reference rhs,bool inverse=false) const22449     bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
22450     {
22451         return compares_unordered(*this, rhs, inverse);
22452     }
22453 
22454   public:
22455 #if JSON_HAS_THREE_WAY_COMPARISON
22456     /// @brief comparison: equal
22457     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
operator ==(const_reference rhs) const22458     bool operator==(const_reference rhs) const noexcept
22459     {
22460 #ifdef __GNUC__
22461 #pragma GCC diagnostic push
22462 #pragma GCC diagnostic ignored "-Wfloat-equal"
22463 #endif
22464         const_reference lhs = *this;
22465         JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
22466 #ifdef __GNUC__
22467 #pragma GCC diagnostic pop
22468 #endif
22469     }
22470 
22471     /// @brief comparison: equal
22472     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
22473     template<typename ScalarType>
22474     requires std::is_scalar_v<ScalarType>
operator ==(ScalarType rhs) const22475     bool operator==(ScalarType rhs) const noexcept
22476     {
22477         return *this == basic_json(rhs);
22478     }
22479 
22480     /// @brief comparison: not equal
22481     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
operator !=(const_reference rhs) const22482     bool operator!=(const_reference rhs) const noexcept
22483     {
22484         if (compares_unordered(rhs, true))
22485         {
22486             return false;
22487         }
22488         return !operator==(rhs);
22489     }
22490 
22491     /// @brief comparison: 3-way
22492     /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
operator <=>(const_reference rhs) const22493     std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
22494     {
22495         const_reference lhs = *this;
22496         // default_result is used if we cannot compare values. In that case,
22497         // we compare types.
22498         JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
22499                                 std::partial_ordering::equivalent,
22500                                 std::partial_ordering::unordered,
22501                                 lhs_type <=> rhs_type) // *NOPAD*
22502     }
22503 
22504     /// @brief comparison: 3-way
22505     /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
22506     template<typename ScalarType>
22507     requires std::is_scalar_v<ScalarType>
operator <=>(ScalarType rhs) const22508     std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
22509     {
22510         return *this <=> basic_json(rhs); // *NOPAD*
22511     }
22512 
22513 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22514     // all operators that are computed as an odd number of inverses of others
22515     // need to be overloaded to emulate the legacy comparison behavior
22516 
22517     /// @brief comparison: less than or equal
22518     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
22519     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
operator <=(const_reference rhs) const22520     bool operator<=(const_reference rhs) const noexcept
22521     {
22522         if (compares_unordered(rhs, true))
22523         {
22524             return false;
22525         }
22526         return !(rhs < *this);
22527     }
22528 
22529     /// @brief comparison: less than or equal
22530     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
22531     template<typename ScalarType>
22532     requires std::is_scalar_v<ScalarType>
operator <=(ScalarType rhs) const22533     bool operator<=(ScalarType rhs) const noexcept
22534     {
22535         return *this <= basic_json(rhs);
22536     }
22537 
22538     /// @brief comparison: greater than or equal
22539     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
22540     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
operator >=(const_reference rhs) const22541     bool operator>=(const_reference rhs) const noexcept
22542     {
22543         if (compares_unordered(rhs, true))
22544         {
22545             return false;
22546         }
22547         return !(*this < rhs);
22548     }
22549 
22550     /// @brief comparison: greater than or equal
22551     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
22552     template<typename ScalarType>
22553     requires std::is_scalar_v<ScalarType>
operator >=(ScalarType rhs) const22554     bool operator>=(ScalarType rhs) const noexcept
22555     {
22556         return *this >= basic_json(rhs);
22557     }
22558 #endif
22559 #else
22560     /// @brief comparison: equal
22561     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
22562     friend bool operator==(const_reference lhs, const_reference rhs) noexcept
22563     {
22564 #ifdef __GNUC__
22565 #pragma GCC diagnostic push
22566 #pragma GCC diagnostic ignored "-Wfloat-equal"
22567 #endif
22568         JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
22569 #ifdef __GNUC__
22570 #pragma GCC diagnostic pop
22571 #endif
22572     }
22573 
22574     /// @brief comparison: equal
22575     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
22576     template<typename ScalarType, typename std::enable_if<
22577                  std::is_scalar<ScalarType>::value, int>::type = 0>
22578     friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
22579     {
22580         return lhs == basic_json(rhs);
22581     }
22582 
22583     /// @brief comparison: equal
22584     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
22585     template<typename ScalarType, typename std::enable_if<
22586                  std::is_scalar<ScalarType>::value, int>::type = 0>
22587     friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
22588     {
22589         return basic_json(lhs) == rhs;
22590     }
22591 
22592     /// @brief comparison: not equal
22593     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
22594     friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
22595     {
22596         if (compares_unordered(lhs, rhs, true))
22597         {
22598             return false;
22599         }
22600         return !(lhs == rhs);
22601     }
22602 
22603     /// @brief comparison: not equal
22604     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
22605     template<typename ScalarType, typename std::enable_if<
22606                  std::is_scalar<ScalarType>::value, int>::type = 0>
22607     friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
22608     {
22609         return lhs != basic_json(rhs);
22610     }
22611 
22612     /// @brief comparison: not equal
22613     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
22614     template<typename ScalarType, typename std::enable_if<
22615                  std::is_scalar<ScalarType>::value, int>::type = 0>
22616     friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
22617     {
22618         return basic_json(lhs) != rhs;
22619     }
22620 
22621     /// @brief comparison: less than
22622     /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
22623     friend bool operator<(const_reference lhs, const_reference rhs) noexcept
22624     {
22625         // default_result is used if we cannot compare values. In that case,
22626         // we compare types. Note we have to call the operator explicitly,
22627         // because MSVC has problems otherwise.
22628         JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
22629     }
22630 
22631     /// @brief comparison: less than
22632     /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
22633     template<typename ScalarType, typename std::enable_if<
22634                  std::is_scalar<ScalarType>::value, int>::type = 0>
22635     friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
22636     {
22637         return lhs < basic_json(rhs);
22638     }
22639 
22640     /// @brief comparison: less than
22641     /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
22642     template<typename ScalarType, typename std::enable_if<
22643                  std::is_scalar<ScalarType>::value, int>::type = 0>
22644     friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
22645     {
22646         return basic_json(lhs) < rhs;
22647     }
22648 
22649     /// @brief comparison: less than or equal
22650     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
22651     friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
22652     {
22653         if (compares_unordered(lhs, rhs, true))
22654         {
22655             return false;
22656         }
22657         return !(rhs < lhs);
22658     }
22659 
22660     /// @brief comparison: less than or equal
22661     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
22662     template<typename ScalarType, typename std::enable_if<
22663                  std::is_scalar<ScalarType>::value, int>::type = 0>
22664     friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
22665     {
22666         return lhs <= basic_json(rhs);
22667     }
22668 
22669     /// @brief comparison: less than or equal
22670     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
22671     template<typename ScalarType, typename std::enable_if<
22672                  std::is_scalar<ScalarType>::value, int>::type = 0>
22673     friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
22674     {
22675         return basic_json(lhs) <= rhs;
22676     }
22677 
22678     /// @brief comparison: greater than
22679     /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
22680     friend bool operator>(const_reference lhs, const_reference rhs) noexcept
22681     {
22682         // double inverse
22683         if (compares_unordered(lhs, rhs))
22684         {
22685             return false;
22686         }
22687         return !(lhs <= rhs);
22688     }
22689 
22690     /// @brief comparison: greater than
22691     /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
22692     template<typename ScalarType, typename std::enable_if<
22693                  std::is_scalar<ScalarType>::value, int>::type = 0>
22694     friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
22695     {
22696         return lhs > basic_json(rhs);
22697     }
22698 
22699     /// @brief comparison: greater than
22700     /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
22701     template<typename ScalarType, typename std::enable_if<
22702                  std::is_scalar<ScalarType>::value, int>::type = 0>
22703     friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
22704     {
22705         return basic_json(lhs) > rhs;
22706     }
22707 
22708     /// @brief comparison: greater than or equal
22709     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
22710     friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
22711     {
22712         if (compares_unordered(lhs, rhs, true))
22713         {
22714             return false;
22715         }
22716         return !(lhs < rhs);
22717     }
22718 
22719     /// @brief comparison: greater than or equal
22720     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
22721     template<typename ScalarType, typename std::enable_if<
22722                  std::is_scalar<ScalarType>::value, int>::type = 0>
22723     friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
22724     {
22725         return lhs >= basic_json(rhs);
22726     }
22727 
22728     /// @brief comparison: greater than or equal
22729     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
22730     template<typename ScalarType, typename std::enable_if<
22731                  std::is_scalar<ScalarType>::value, int>::type = 0>
22732     friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
22733     {
22734         return basic_json(lhs) >= rhs;
22735     }
22736 #endif
22737 
22738 #undef JSON_IMPLEMENT_OPERATOR
22739 
22740     /// @}
22741 
22742     ///////////////////
22743     // serialization //
22744     ///////////////////
22745 
22746     /// @name serialization
22747     /// @{
22748 #ifndef JSON_NO_IO
22749     /// @brief serialize to stream
22750     /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
operator <<(std::ostream & o,const basic_json & j)22751     friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
22752     {
22753         // read width member and use it as indentation parameter if nonzero
22754         const bool pretty_print = o.width() > 0;
22755         const auto indentation = pretty_print ? o.width() : 0;
22756 
22757         // reset width to 0 for subsequent calls to this stream
22758         o.width(0);
22759 
22760         // do the actual serialization
22761         serializer s(detail::output_adapter<char>(o), o.fill());
22762         s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
22763         return o;
22764     }
22765 
22766     /// @brief serialize to stream
22767     /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
22768     /// @deprecated This function is deprecated since 3.0.0 and will be removed in
22769     ///             version 4.0.0 of the library. Please use
22770     ///             operator<<(std::ostream&, const basic_json&) instead; that is,
22771     ///             replace calls like `j >> o;` with `o << j;`.
22772     JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
operator >>(const basic_json & j,std::ostream & o)22773     friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
22774     {
22775         return o << j;
22776     }
22777 #endif  // JSON_NO_IO
22778     /// @}
22779 
22780 
22781     /////////////////////
22782     // deserialization //
22783     /////////////////////
22784 
22785     /// @name deserialization
22786     /// @{
22787 
22788     /// @brief deserialize from a compatible input
22789     /// @sa https://json.nlohmann.me/api/basic_json/parse/
22790     template<typename InputType>
22791     JSON_HEDLEY_WARN_UNUSED_RESULT
parse(InputType && i,const parser_callback_t cb=nullptr,const bool allow_exceptions=true,const bool ignore_comments=false)22792     static basic_json parse(InputType&& i,
22793                             const parser_callback_t cb = nullptr,
22794                             const bool allow_exceptions = true,
22795                             const bool ignore_comments = false)
22796     {
22797         basic_json result;
22798         parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
22799         return result;
22800     }
22801 
22802     /// @brief deserialize from a pair of character iterators
22803     /// @sa https://json.nlohmann.me/api/basic_json/parse/
22804     template<typename IteratorType>
22805     JSON_HEDLEY_WARN_UNUSED_RESULT
parse(IteratorType first,IteratorType last,const parser_callback_t cb=nullptr,const bool allow_exceptions=true,const bool ignore_comments=false)22806     static basic_json parse(IteratorType first,
22807                             IteratorType last,
22808                             const parser_callback_t cb = nullptr,
22809                             const bool allow_exceptions = true,
22810                             const bool ignore_comments = false)
22811     {
22812         basic_json result;
22813         parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
22814         return result;
22815     }
22816 
22817     JSON_HEDLEY_WARN_UNUSED_RESULT
22818     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
parse(detail::span_input_adapter && i,const parser_callback_t cb=nullptr,const bool allow_exceptions=true,const bool ignore_comments=false)22819     static basic_json parse(detail::span_input_adapter&& i,
22820                             const parser_callback_t cb = nullptr,
22821                             const bool allow_exceptions = true,
22822                             const bool ignore_comments = false)
22823     {
22824         basic_json result;
22825         parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
22826         return result;
22827     }
22828 
22829     /// @brief check if the input is valid JSON
22830     /// @sa https://json.nlohmann.me/api/basic_json/accept/
22831     template<typename InputType>
accept(InputType && i,const bool ignore_comments=false)22832     static bool accept(InputType&& i,
22833                        const bool ignore_comments = false)
22834     {
22835         return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
22836     }
22837 
22838     /// @brief check if the input is valid JSON
22839     /// @sa https://json.nlohmann.me/api/basic_json/accept/
22840     template<typename IteratorType>
accept(IteratorType first,IteratorType last,const bool ignore_comments=false)22841     static bool accept(IteratorType first, IteratorType last,
22842                        const bool ignore_comments = false)
22843     {
22844         return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
22845     }
22846 
22847     JSON_HEDLEY_WARN_UNUSED_RESULT
22848     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
accept(detail::span_input_adapter && i,const bool ignore_comments=false)22849     static bool accept(detail::span_input_adapter&& i,
22850                        const bool ignore_comments = false)
22851     {
22852         return parser(i.get(), nullptr, false, ignore_comments).accept(true);
22853     }
22854 
22855     /// @brief generate SAX events
22856     /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
22857     template <typename InputType, typename SAX>
22858     JSON_HEDLEY_NON_NULL(2)
sax_parse(InputType && i,SAX * sax,input_format_t format=input_format_t::json,const bool strict=true,const bool ignore_comments=false)22859     static bool sax_parse(InputType&& i, SAX* sax,
22860                           input_format_t format = input_format_t::json,
22861                           const bool strict = true,
22862                           const bool ignore_comments = false)
22863     {
22864         auto ia = detail::input_adapter(std::forward<InputType>(i));
22865         return format == input_format_t::json
22866                ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
22867                : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
22868     }
22869 
22870     /// @brief generate SAX events
22871     /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
22872     template<class IteratorType, class SAX>
22873     JSON_HEDLEY_NON_NULL(3)
sax_parse(IteratorType first,IteratorType last,SAX * sax,input_format_t format=input_format_t::json,const bool strict=true,const bool ignore_comments=false)22874     static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
22875                           input_format_t format = input_format_t::json,
22876                           const bool strict = true,
22877                           const bool ignore_comments = false)
22878     {
22879         auto ia = detail::input_adapter(std::move(first), std::move(last));
22880         return format == input_format_t::json
22881                ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
22882                : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
22883     }
22884 
22885     /// @brief generate SAX events
22886     /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
22887     /// @deprecated This function is deprecated since 3.8.0 and will be removed in
22888     ///             version 4.0.0 of the library. Please use
22889     ///             sax_parse(ptr, ptr + len) instead.
22890     template <typename SAX>
22891     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
22892     JSON_HEDLEY_NON_NULL(2)
sax_parse(detail::span_input_adapter && i,SAX * sax,input_format_t format=input_format_t::json,const bool strict=true,const bool ignore_comments=false)22893     static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
22894                           input_format_t format = input_format_t::json,
22895                           const bool strict = true,
22896                           const bool ignore_comments = false)
22897     {
22898         auto ia = i.get();
22899         return format == input_format_t::json
22900                // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
22901                ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
22902                // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
22903                : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
22904     }
22905 #ifndef JSON_NO_IO
22906     /// @brief deserialize from stream
22907     /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
22908     /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
22909     ///             version 4.0.0 of the library. Please use
22910     ///             operator>>(std::istream&, basic_json&) instead; that is,
22911     ///             replace calls like `j << i;` with `i >> j;`.
22912     JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
operator <<(basic_json & j,std::istream & i)22913     friend std::istream& operator<<(basic_json& j, std::istream& i)
22914     {
22915         return operator>>(i, j);
22916     }
22917 
22918     /// @brief deserialize from stream
22919     /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
operator >>(std::istream & i,basic_json & j)22920     friend std::istream& operator>>(std::istream& i, basic_json& j)
22921     {
22922         parser(detail::input_adapter(i)).parse(false, j);
22923         return i;
22924     }
22925 #endif  // JSON_NO_IO
22926     /// @}
22927 
22928     ///////////////////////////
22929     // convenience functions //
22930     ///////////////////////////
22931 
22932     /// @brief return the type as string
22933     /// @sa https://json.nlohmann.me/api/basic_json/type_name/
22934     JSON_HEDLEY_RETURNS_NON_NULL
type_name() const22935     const char* type_name() const noexcept
22936     {
22937         switch (m_type)
22938         {
22939             case value_t::null:
22940                 return "null";
22941             case value_t::object:
22942                 return "object";
22943             case value_t::array:
22944                 return "array";
22945             case value_t::string:
22946                 return "string";
22947             case value_t::boolean:
22948                 return "boolean";
22949             case value_t::binary:
22950                 return "binary";
22951             case value_t::discarded:
22952                 return "discarded";
22953             case value_t::number_integer:
22954             case value_t::number_unsigned:
22955             case value_t::number_float:
22956             default:
22957                 return "number";
22958         }
22959     }
22960 
22961 
22962   JSON_PRIVATE_UNLESS_TESTED:
22963     //////////////////////
22964     // member variables //
22965     //////////////////////
22966 
22967     /// the type of the current element
22968     value_t m_type = value_t::null;
22969 
22970     /// the value of the current element
22971     json_value m_value = {};
22972 
22973 #if JSON_DIAGNOSTICS
22974     /// a pointer to a parent value (for debugging purposes)
22975     basic_json* m_parent = nullptr;
22976 #endif
22977 
22978     //////////////////////////////////////////
22979     // binary serialization/deserialization //
22980     //////////////////////////////////////////
22981 
22982     /// @name binary serialization/deserialization support
22983     /// @{
22984 
22985   public:
22986     /// @brief create a CBOR serialization of a given JSON value
22987     /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
to_cbor(const basic_json & j)22988     static std::vector<std::uint8_t> to_cbor(const basic_json& j)
22989     {
22990         std::vector<std::uint8_t> result;
22991         to_cbor(j, result);
22992         return result;
22993     }
22994 
22995     /// @brief create a CBOR serialization of a given JSON value
22996     /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
to_cbor(const basic_json & j,detail::output_adapter<std::uint8_t> o)22997     static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
22998     {
22999         binary_writer<std::uint8_t>(o).write_cbor(j);
23000     }
23001 
23002     /// @brief create a CBOR serialization of a given JSON value
23003     /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
to_cbor(const basic_json & j,detail::output_adapter<char> o)23004     static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
23005     {
23006         binary_writer<char>(o).write_cbor(j);
23007     }
23008 
23009     /// @brief create a MessagePack serialization of a given JSON value
23010     /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
to_msgpack(const basic_json & j)23011     static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
23012     {
23013         std::vector<std::uint8_t> result;
23014         to_msgpack(j, result);
23015         return result;
23016     }
23017 
23018     /// @brief create a MessagePack serialization of a given JSON value
23019     /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
to_msgpack(const basic_json & j,detail::output_adapter<std::uint8_t> o)23020     static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23021     {
23022         binary_writer<std::uint8_t>(o).write_msgpack(j);
23023     }
23024 
23025     /// @brief create a MessagePack serialization of a given JSON value
23026     /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
to_msgpack(const basic_json & j,detail::output_adapter<char> o)23027     static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
23028     {
23029         binary_writer<char>(o).write_msgpack(j);
23030     }
23031 
23032     /// @brief create a UBJSON serialization of a given JSON value
23033     /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
to_ubjson(const basic_json & j,const bool use_size=false,const bool use_type=false)23034     static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
23035             const bool use_size = false,
23036             const bool use_type = false)
23037     {
23038         std::vector<std::uint8_t> result;
23039         to_ubjson(j, result, use_size, use_type);
23040         return result;
23041     }
23042 
23043     /// @brief create a UBJSON serialization of a given JSON value
23044     /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
to_ubjson(const basic_json & j,detail::output_adapter<std::uint8_t> o,const bool use_size=false,const bool use_type=false)23045     static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
23046                           const bool use_size = false, const bool use_type = false)
23047     {
23048         binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
23049     }
23050 
23051     /// @brief create a UBJSON serialization of a given JSON value
23052     /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
to_ubjson(const basic_json & j,detail::output_adapter<char> o,const bool use_size=false,const bool use_type=false)23053     static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
23054                           const bool use_size = false, const bool use_type = false)
23055     {
23056         binary_writer<char>(o).write_ubjson(j, use_size, use_type);
23057     }
23058 
23059     /// @brief create a BJData serialization of a given JSON value
23060     /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
to_bjdata(const basic_json & j,const bool use_size=false,const bool use_type=false)23061     static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
23062             const bool use_size = false,
23063             const bool use_type = false)
23064     {
23065         std::vector<std::uint8_t> result;
23066         to_bjdata(j, result, use_size, use_type);
23067         return result;
23068     }
23069 
23070     /// @brief create a BJData serialization of a given JSON value
23071     /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
to_bjdata(const basic_json & j,detail::output_adapter<std::uint8_t> o,const bool use_size=false,const bool use_type=false)23072     static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
23073                           const bool use_size = false, const bool use_type = false)
23074     {
23075         binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
23076     }
23077 
23078     /// @brief create a BJData serialization of a given JSON value
23079     /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
to_bjdata(const basic_json & j,detail::output_adapter<char> o,const bool use_size=false,const bool use_type=false)23080     static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
23081                           const bool use_size = false, const bool use_type = false)
23082     {
23083         binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
23084     }
23085 
23086     /// @brief create a BSON serialization of a given JSON value
23087     /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
to_bson(const basic_json & j)23088     static std::vector<std::uint8_t> to_bson(const basic_json& j)
23089     {
23090         std::vector<std::uint8_t> result;
23091         to_bson(j, result);
23092         return result;
23093     }
23094 
23095     /// @brief create a BSON serialization of a given JSON value
23096     /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
to_bson(const basic_json & j,detail::output_adapter<std::uint8_t> o)23097     static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23098     {
23099         binary_writer<std::uint8_t>(o).write_bson(j);
23100     }
23101 
23102     /// @brief create a BSON serialization of a given JSON value
23103     /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
to_bson(const basic_json & j,detail::output_adapter<char> o)23104     static void to_bson(const basic_json& j, detail::output_adapter<char> o)
23105     {
23106         binary_writer<char>(o).write_bson(j);
23107     }
23108 
23109     /// @brief create a JSON value from an input in CBOR format
23110     /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
23111     template<typename InputType>
23112     JSON_HEDLEY_WARN_UNUSED_RESULT
from_cbor(InputType && i,const bool strict=true,const bool allow_exceptions=true,const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)23113     static basic_json from_cbor(InputType&& i,
23114                                 const bool strict = true,
23115                                 const bool allow_exceptions = true,
23116                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23117     {
23118         basic_json result;
23119         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23120         auto ia = detail::input_adapter(std::forward<InputType>(i));
23121         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23122         return res ? result : basic_json(value_t::discarded);
23123     }
23124 
23125     /// @brief create a JSON value from an input in CBOR format
23126     /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
23127     template<typename IteratorType>
23128     JSON_HEDLEY_WARN_UNUSED_RESULT
from_cbor(IteratorType first,IteratorType last,const bool strict=true,const bool allow_exceptions=true,const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)23129     static basic_json from_cbor(IteratorType first, IteratorType last,
23130                                 const bool strict = true,
23131                                 const bool allow_exceptions = true,
23132                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23133     {
23134         basic_json result;
23135         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23136         auto ia = detail::input_adapter(std::move(first), std::move(last));
23137         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23138         return res ? result : basic_json(value_t::discarded);
23139     }
23140 
23141     template<typename T>
23142     JSON_HEDLEY_WARN_UNUSED_RESULT
23143     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
from_cbor(const T * ptr,std::size_t len,const bool strict=true,const bool allow_exceptions=true,const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)23144     static basic_json from_cbor(const T* ptr, std::size_t len,
23145                                 const bool strict = true,
23146                                 const bool allow_exceptions = true,
23147                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23148     {
23149         return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
23150     }
23151 
23152 
23153     JSON_HEDLEY_WARN_UNUSED_RESULT
23154     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
from_cbor(detail::span_input_adapter && i,const bool strict=true,const bool allow_exceptions=true,const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)23155     static basic_json from_cbor(detail::span_input_adapter&& i,
23156                                 const bool strict = true,
23157                                 const bool allow_exceptions = true,
23158                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23159     {
23160         basic_json result;
23161         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23162         auto ia = i.get();
23163         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23164         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23165         return res ? result : basic_json(value_t::discarded);
23166     }
23167 
23168     /// @brief create a JSON value from an input in MessagePack format
23169     /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
23170     template<typename InputType>
23171     JSON_HEDLEY_WARN_UNUSED_RESULT
from_msgpack(InputType && i,const bool strict=true,const bool allow_exceptions=true)23172     static basic_json from_msgpack(InputType&& i,
23173                                    const bool strict = true,
23174                                    const bool allow_exceptions = true)
23175     {
23176         basic_json result;
23177         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23178         auto ia = detail::input_adapter(std::forward<InputType>(i));
23179         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23180         return res ? result : basic_json(value_t::discarded);
23181     }
23182 
23183     /// @brief create a JSON value from an input in MessagePack format
23184     /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
23185     template<typename IteratorType>
23186     JSON_HEDLEY_WARN_UNUSED_RESULT
from_msgpack(IteratorType first,IteratorType last,const bool strict=true,const bool allow_exceptions=true)23187     static basic_json from_msgpack(IteratorType first, IteratorType last,
23188                                    const bool strict = true,
23189                                    const bool allow_exceptions = true)
23190     {
23191         basic_json result;
23192         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23193         auto ia = detail::input_adapter(std::move(first), std::move(last));
23194         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23195         return res ? result : basic_json(value_t::discarded);
23196     }
23197 
23198     template<typename T>
23199     JSON_HEDLEY_WARN_UNUSED_RESULT
23200     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
from_msgpack(const T * ptr,std::size_t len,const bool strict=true,const bool allow_exceptions=true)23201     static basic_json from_msgpack(const T* ptr, std::size_t len,
23202                                    const bool strict = true,
23203                                    const bool allow_exceptions = true)
23204     {
23205         return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
23206     }
23207 
23208     JSON_HEDLEY_WARN_UNUSED_RESULT
23209     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
from_msgpack(detail::span_input_adapter && i,const bool strict=true,const bool allow_exceptions=true)23210     static basic_json from_msgpack(detail::span_input_adapter&& i,
23211                                    const bool strict = true,
23212                                    const bool allow_exceptions = true)
23213     {
23214         basic_json result;
23215         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23216         auto ia = i.get();
23217         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23218         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23219         return res ? result : basic_json(value_t::discarded);
23220     }
23221 
23222     /// @brief create a JSON value from an input in UBJSON format
23223     /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
23224     template<typename InputType>
23225     JSON_HEDLEY_WARN_UNUSED_RESULT
from_ubjson(InputType && i,const bool strict=true,const bool allow_exceptions=true)23226     static basic_json from_ubjson(InputType&& i,
23227                                   const bool strict = true,
23228                                   const bool allow_exceptions = true)
23229     {
23230         basic_json result;
23231         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23232         auto ia = detail::input_adapter(std::forward<InputType>(i));
23233         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23234         return res ? result : basic_json(value_t::discarded);
23235     }
23236 
23237     /// @brief create a JSON value from an input in UBJSON format
23238     /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
23239     template<typename IteratorType>
23240     JSON_HEDLEY_WARN_UNUSED_RESULT
from_ubjson(IteratorType first,IteratorType last,const bool strict=true,const bool allow_exceptions=true)23241     static basic_json from_ubjson(IteratorType first, IteratorType last,
23242                                   const bool strict = true,
23243                                   const bool allow_exceptions = true)
23244     {
23245         basic_json result;
23246         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23247         auto ia = detail::input_adapter(std::move(first), std::move(last));
23248         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23249         return res ? result : basic_json(value_t::discarded);
23250     }
23251 
23252     template<typename T>
23253     JSON_HEDLEY_WARN_UNUSED_RESULT
23254     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
from_ubjson(const T * ptr,std::size_t len,const bool strict=true,const bool allow_exceptions=true)23255     static basic_json from_ubjson(const T* ptr, std::size_t len,
23256                                   const bool strict = true,
23257                                   const bool allow_exceptions = true)
23258     {
23259         return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
23260     }
23261 
23262     JSON_HEDLEY_WARN_UNUSED_RESULT
23263     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
from_ubjson(detail::span_input_adapter && i,const bool strict=true,const bool allow_exceptions=true)23264     static basic_json from_ubjson(detail::span_input_adapter&& i,
23265                                   const bool strict = true,
23266                                   const bool allow_exceptions = true)
23267     {
23268         basic_json result;
23269         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23270         auto ia = i.get();
23271         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23272         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23273         return res ? result : basic_json(value_t::discarded);
23274     }
23275 
23276 
23277     /// @brief create a JSON value from an input in BJData format
23278     /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
23279     template<typename InputType>
23280     JSON_HEDLEY_WARN_UNUSED_RESULT
from_bjdata(InputType && i,const bool strict=true,const bool allow_exceptions=true)23281     static basic_json from_bjdata(InputType&& i,
23282                                   const bool strict = true,
23283                                   const bool allow_exceptions = true)
23284     {
23285         basic_json result;
23286         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23287         auto ia = detail::input_adapter(std::forward<InputType>(i));
23288         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23289         return res ? result : basic_json(value_t::discarded);
23290     }
23291 
23292     /// @brief create a JSON value from an input in BJData format
23293     /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
23294     template<typename IteratorType>
23295     JSON_HEDLEY_WARN_UNUSED_RESULT
from_bjdata(IteratorType first,IteratorType last,const bool strict=true,const bool allow_exceptions=true)23296     static basic_json from_bjdata(IteratorType first, IteratorType last,
23297                                   const bool strict = true,
23298                                   const bool allow_exceptions = true)
23299     {
23300         basic_json result;
23301         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23302         auto ia = detail::input_adapter(std::move(first), std::move(last));
23303         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23304         return res ? result : basic_json(value_t::discarded);
23305     }
23306 
23307     /// @brief create a JSON value from an input in BSON format
23308     /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
23309     template<typename InputType>
23310     JSON_HEDLEY_WARN_UNUSED_RESULT
from_bson(InputType && i,const bool strict=true,const bool allow_exceptions=true)23311     static basic_json from_bson(InputType&& i,
23312                                 const bool strict = true,
23313                                 const bool allow_exceptions = true)
23314     {
23315         basic_json result;
23316         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23317         auto ia = detail::input_adapter(std::forward<InputType>(i));
23318         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23319         return res ? result : basic_json(value_t::discarded);
23320     }
23321 
23322     /// @brief create a JSON value from an input in BSON format
23323     /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
23324     template<typename IteratorType>
23325     JSON_HEDLEY_WARN_UNUSED_RESULT
from_bson(IteratorType first,IteratorType last,const bool strict=true,const bool allow_exceptions=true)23326     static basic_json from_bson(IteratorType first, IteratorType last,
23327                                 const bool strict = true,
23328                                 const bool allow_exceptions = true)
23329     {
23330         basic_json result;
23331         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23332         auto ia = detail::input_adapter(std::move(first), std::move(last));
23333         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23334         return res ? result : basic_json(value_t::discarded);
23335     }
23336 
23337     template<typename T>
23338     JSON_HEDLEY_WARN_UNUSED_RESULT
23339     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
from_bson(const T * ptr,std::size_t len,const bool strict=true,const bool allow_exceptions=true)23340     static basic_json from_bson(const T* ptr, std::size_t len,
23341                                 const bool strict = true,
23342                                 const bool allow_exceptions = true)
23343     {
23344         return from_bson(ptr, ptr + len, strict, allow_exceptions);
23345     }
23346 
23347     JSON_HEDLEY_WARN_UNUSED_RESULT
23348     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
from_bson(detail::span_input_adapter && i,const bool strict=true,const bool allow_exceptions=true)23349     static basic_json from_bson(detail::span_input_adapter&& i,
23350                                 const bool strict = true,
23351                                 const bool allow_exceptions = true)
23352     {
23353         basic_json result;
23354         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23355         auto ia = i.get();
23356         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23357         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23358         return res ? result : basic_json(value_t::discarded);
23359     }
23360     /// @}
23361 
23362     //////////////////////////
23363     // JSON Pointer support //
23364     //////////////////////////
23365 
23366     /// @name JSON Pointer functions
23367     /// @{
23368 
23369     /// @brief access specified element via JSON Pointer
23370     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
operator [](const json_pointer & ptr)23371     reference operator[](const json_pointer& ptr)
23372     {
23373         return ptr.get_unchecked(this);
23374     }
23375 
23376     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23377     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
operator [](const::nlohmann::json_pointer<BasicJsonType> & ptr)23378     reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23379     {
23380         return ptr.get_unchecked(this);
23381     }
23382 
23383     /// @brief access specified element via JSON Pointer
23384     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
operator [](const json_pointer & ptr) const23385     const_reference operator[](const json_pointer& ptr) const
23386     {
23387         return ptr.get_unchecked(this);
23388     }
23389 
23390     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23391     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
operator [](const::nlohmann::json_pointer<BasicJsonType> & ptr) const23392     const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23393     {
23394         return ptr.get_unchecked(this);
23395     }
23396 
23397     /// @brief access specified element via JSON Pointer
23398     /// @sa https://json.nlohmann.me/api/basic_json/at/
at(const json_pointer & ptr)23399     reference at(const json_pointer& ptr)
23400     {
23401         return ptr.get_checked(this);
23402     }
23403 
23404     template<typename BasicJsonType>
23405     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
at(const::nlohmann::json_pointer<BasicJsonType> & ptr)23406     reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23407     {
23408         return ptr.get_checked(this);
23409     }
23410 
23411     /// @brief access specified element via JSON Pointer
23412     /// @sa https://json.nlohmann.me/api/basic_json/at/
at(const json_pointer & ptr) const23413     const_reference at(const json_pointer& ptr) const
23414     {
23415         return ptr.get_checked(this);
23416     }
23417 
23418     template<typename BasicJsonType>
23419     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
at(const::nlohmann::json_pointer<BasicJsonType> & ptr) const23420     const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23421     {
23422         return ptr.get_checked(this);
23423     }
23424 
23425     /// @brief return flattened JSON value
23426     /// @sa https://json.nlohmann.me/api/basic_json/flatten/
flatten() const23427     basic_json flatten() const
23428     {
23429         basic_json result(value_t::object);
23430         json_pointer::flatten("", *this, result);
23431         return result;
23432     }
23433 
23434     /// @brief unflatten a previously flattened JSON value
23435     /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
unflatten() const23436     basic_json unflatten() const
23437     {
23438         return json_pointer::unflatten(*this);
23439     }
23440 
23441     /// @}
23442 
23443     //////////////////////////
23444     // JSON Patch functions //
23445     //////////////////////////
23446 
23447     /// @name JSON Patch functions
23448     /// @{
23449 
23450     /// @brief applies a JSON patch in-place without copying the object
23451     /// @sa https://json.nlohmann.me/api/basic_json/patch/
patch_inplace(const basic_json & json_patch)23452     void patch_inplace(const basic_json& json_patch)
23453     {
23454         basic_json& result = *this;
23455         // the valid JSON Patch operations
23456         enum class patch_operations {add, remove, replace, move, copy, test, invalid};
23457 
23458         const auto get_op = [](const std::string & op)
23459         {
23460             if (op == "add")
23461             {
23462                 return patch_operations::add;
23463             }
23464             if (op == "remove")
23465             {
23466                 return patch_operations::remove;
23467             }
23468             if (op == "replace")
23469             {
23470                 return patch_operations::replace;
23471             }
23472             if (op == "move")
23473             {
23474                 return patch_operations::move;
23475             }
23476             if (op == "copy")
23477             {
23478                 return patch_operations::copy;
23479             }
23480             if (op == "test")
23481             {
23482                 return patch_operations::test;
23483             }
23484 
23485             return patch_operations::invalid;
23486         };
23487 
23488         // wrapper for "add" operation; add value at ptr
23489         const auto operation_add = [&result](json_pointer & ptr, basic_json val)
23490         {
23491             // adding to the root of the target document means replacing it
23492             if (ptr.empty())
23493             {
23494                 result = val;
23495                 return;
23496             }
23497 
23498             // make sure the top element of the pointer exists
23499             json_pointer top_pointer = ptr.top();
23500             if (top_pointer != ptr)
23501             {
23502                 result.at(top_pointer);
23503             }
23504 
23505             // get reference to parent of JSON pointer ptr
23506             const auto last_path = ptr.back();
23507             ptr.pop_back();
23508             basic_json& parent = result[ptr];
23509 
23510             switch (parent.m_type)
23511             {
23512                 case value_t::null:
23513                 case value_t::object:
23514                 {
23515                     // use operator[] to add value
23516                     parent[last_path] = val;
23517                     break;
23518                 }
23519 
23520                 case value_t::array:
23521                 {
23522                     if (last_path == "-")
23523                     {
23524                         // special case: append to back
23525                         parent.push_back(val);
23526                     }
23527                     else
23528                     {
23529                         const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
23530                         if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
23531                         {
23532                             // avoid undefined behavior
23533                             JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
23534                         }
23535 
23536                         // default case: insert add offset
23537                         parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
23538                     }
23539                     break;
23540                 }
23541 
23542                 // if there exists a parent it cannot be primitive
23543                 case value_t::string: // LCOV_EXCL_LINE
23544                 case value_t::boolean: // LCOV_EXCL_LINE
23545                 case value_t::number_integer: // LCOV_EXCL_LINE
23546                 case value_t::number_unsigned: // LCOV_EXCL_LINE
23547                 case value_t::number_float: // LCOV_EXCL_LINE
23548                 case value_t::binary: // LCOV_EXCL_LINE
23549                 case value_t::discarded: // LCOV_EXCL_LINE
23550                 default:            // LCOV_EXCL_LINE
23551                     JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
23552             }
23553         };
23554 
23555         // wrapper for "remove" operation; remove value at ptr
23556         const auto operation_remove = [this, &result](json_pointer & ptr)
23557         {
23558             // get reference to parent of JSON pointer ptr
23559             const auto last_path = ptr.back();
23560             ptr.pop_back();
23561             basic_json& parent = result.at(ptr);
23562 
23563             // remove child
23564             if (parent.is_object())
23565             {
23566                 // perform range check
23567                 auto it = parent.find(last_path);
23568                 if (JSON_HEDLEY_LIKELY(it != parent.end()))
23569                 {
23570                     parent.erase(it);
23571                 }
23572                 else
23573                 {
23574                     JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
23575                 }
23576             }
23577             else if (parent.is_array())
23578             {
23579                 // note erase performs range check
23580                 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
23581             }
23582         };
23583 
23584         // type check: top level value must be an array
23585         if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
23586         {
23587             JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
23588         }
23589 
23590         // iterate and apply the operations
23591         for (const auto& val : json_patch)
23592         {
23593             // wrapper to get a value for an operation
23594             const auto get_value = [&val](const std::string & op,
23595                                           const std::string & member,
23596                                           bool string_type) -> basic_json &
23597             {
23598                 // find value
23599                 auto it = val.m_value.object->find(member);
23600 
23601                 // context-sensitive error message
23602                 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
23603 
23604                 // check if desired value is present
23605                 if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
23606                 {
23607                     // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
23608                     JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
23609                 }
23610 
23611                 // check if result is of type string
23612                 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
23613                 {
23614                     // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
23615                     JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
23616                 }
23617 
23618                 // no error: return value
23619                 return it->second;
23620             };
23621 
23622             // type check: every element of the array must be an object
23623             if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
23624             {
23625                 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
23626             }
23627 
23628             // collect mandatory members
23629             const auto op = get_value("op", "op", true).template get<std::string>();
23630             const auto path = get_value(op, "path", true).template get<std::string>();
23631             json_pointer ptr(path);
23632 
23633             switch (get_op(op))
23634             {
23635                 case patch_operations::add:
23636                 {
23637                     operation_add(ptr, get_value("add", "value", false));
23638                     break;
23639                 }
23640 
23641                 case patch_operations::remove:
23642                 {
23643                     operation_remove(ptr);
23644                     break;
23645                 }
23646 
23647                 case patch_operations::replace:
23648                 {
23649                     // the "path" location must exist - use at()
23650                     result.at(ptr) = get_value("replace", "value", false);
23651                     break;
23652                 }
23653 
23654                 case patch_operations::move:
23655                 {
23656                     const auto from_path = get_value("move", "from", true).template get<std::string>();
23657                     json_pointer from_ptr(from_path);
23658 
23659                     // the "from" location must exist - use at()
23660                     basic_json v = result.at(from_ptr);
23661 
23662                     // The move operation is functionally identical to a
23663                     // "remove" operation on the "from" location, followed
23664                     // immediately by an "add" operation at the target
23665                     // location with the value that was just removed.
23666                     operation_remove(from_ptr);
23667                     operation_add(ptr, v);
23668                     break;
23669                 }
23670 
23671                 case patch_operations::copy:
23672                 {
23673                     const auto from_path = get_value("copy", "from", true).template get<std::string>();
23674                     const json_pointer from_ptr(from_path);
23675 
23676                     // the "from" location must exist - use at()
23677                     basic_json v = result.at(from_ptr);
23678 
23679                     // The copy is functionally identical to an "add"
23680                     // operation at the target location using the value
23681                     // specified in the "from" member.
23682                     operation_add(ptr, v);
23683                     break;
23684                 }
23685 
23686                 case patch_operations::test:
23687                 {
23688                     bool success = false;
23689                     JSON_TRY
23690                     {
23691                         // check if "value" matches the one at "path"
23692                         // the "path" location must exist - use at()
23693                         success = (result.at(ptr) == get_value("test", "value", false));
23694                     }
23695                     JSON_INTERNAL_CATCH (out_of_range&)
23696                     {
23697                         // ignore out of range errors: success remains false
23698                     }
23699 
23700                     // throw an exception if test fails
23701                     if (JSON_HEDLEY_UNLIKELY(!success))
23702                     {
23703                         JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
23704                     }
23705 
23706                     break;
23707                 }
23708 
23709                 case patch_operations::invalid:
23710                 default:
23711                 {
23712                     // op must be "add", "remove", "replace", "move", "copy", or
23713                     // "test"
23714                     JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
23715                 }
23716             }
23717         }
23718     }
23719 
23720     /// @brief applies a JSON patch to a copy of the current object
23721     /// @sa https://json.nlohmann.me/api/basic_json/patch/
patch(const basic_json & json_patch) const23722     basic_json patch(const basic_json& json_patch) const
23723     {
23724         basic_json result = *this;
23725         result.patch_inplace(json_patch);
23726         return result;
23727     }
23728 
23729     /// @brief creates a diff as a JSON patch
23730     /// @sa https://json.nlohmann.me/api/basic_json/diff/
23731     JSON_HEDLEY_WARN_UNUSED_RESULT
diff(const basic_json & source,const basic_json & target,const std::string & path="")23732     static basic_json diff(const basic_json& source, const basic_json& target,
23733                            const std::string& path = "")
23734     {
23735         // the patch
23736         basic_json result(value_t::array);
23737 
23738         // if the values are the same, return empty patch
23739         if (source == target)
23740         {
23741             return result;
23742         }
23743 
23744         if (source.type() != target.type())
23745         {
23746             // different types: replace value
23747             result.push_back(
23748             {
23749                 {"op", "replace"}, {"path", path}, {"value", target}
23750             });
23751             return result;
23752         }
23753 
23754         switch (source.type())
23755         {
23756             case value_t::array:
23757             {
23758                 // first pass: traverse common elements
23759                 std::size_t i = 0;
23760                 while (i < source.size() && i < target.size())
23761                 {
23762                     // recursive call to compare array values at index i
23763                     auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
23764                     result.insert(result.end(), temp_diff.begin(), temp_diff.end());
23765                     ++i;
23766                 }
23767 
23768                 // We now reached the end of at least one array
23769                 // in a second pass, traverse the remaining elements
23770 
23771                 // remove my remaining elements
23772                 const auto end_index = static_cast<difference_type>(result.size());
23773                 while (i < source.size())
23774                 {
23775                     // add operations in reverse order to avoid invalid
23776                     // indices
23777                     result.insert(result.begin() + end_index, object(
23778                     {
23779                         {"op", "remove"},
23780                         {"path", detail::concat(path, '/', std::to_string(i))}
23781                     }));
23782                     ++i;
23783                 }
23784 
23785                 // add other remaining elements
23786                 while (i < target.size())
23787                 {
23788                     result.push_back(
23789                     {
23790                         {"op", "add"},
23791                         {"path", detail::concat(path, "/-")},
23792                         {"value", target[i]}
23793                     });
23794                     ++i;
23795                 }
23796 
23797                 break;
23798             }
23799 
23800             case value_t::object:
23801             {
23802                 // first pass: traverse this object's elements
23803                 for (auto it = source.cbegin(); it != source.cend(); ++it)
23804                 {
23805                     // escape the key name to be used in a JSON patch
23806                     const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
23807 
23808                     if (target.find(it.key()) != target.end())
23809                     {
23810                         // recursive call to compare object values at key it
23811                         auto temp_diff = diff(it.value(), target[it.key()], path_key);
23812                         result.insert(result.end(), temp_diff.begin(), temp_diff.end());
23813                     }
23814                     else
23815                     {
23816                         // found a key that is not in o -> remove it
23817                         result.push_back(object(
23818                         {
23819                             {"op", "remove"}, {"path", path_key}
23820                         }));
23821                     }
23822                 }
23823 
23824                 // second pass: traverse other object's elements
23825                 for (auto it = target.cbegin(); it != target.cend(); ++it)
23826                 {
23827                     if (source.find(it.key()) == source.end())
23828                     {
23829                         // found a key that is not in this -> add it
23830                         const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
23831                         result.push_back(
23832                         {
23833                             {"op", "add"}, {"path", path_key},
23834                             {"value", it.value()}
23835                         });
23836                     }
23837                 }
23838 
23839                 break;
23840             }
23841 
23842             case value_t::null:
23843             case value_t::string:
23844             case value_t::boolean:
23845             case value_t::number_integer:
23846             case value_t::number_unsigned:
23847             case value_t::number_float:
23848             case value_t::binary:
23849             case value_t::discarded:
23850             default:
23851             {
23852                 // both primitive type: replace value
23853                 result.push_back(
23854                 {
23855                     {"op", "replace"}, {"path", path}, {"value", target}
23856                 });
23857                 break;
23858             }
23859         }
23860 
23861         return result;
23862     }
23863     /// @}
23864 
23865     ////////////////////////////////
23866     // JSON Merge Patch functions //
23867     ////////////////////////////////
23868 
23869     /// @name JSON Merge Patch functions
23870     /// @{
23871 
23872     /// @brief applies a JSON Merge Patch
23873     /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
merge_patch(const basic_json & apply_patch)23874     void merge_patch(const basic_json& apply_patch)
23875     {
23876         if (apply_patch.is_object())
23877         {
23878             if (!is_object())
23879             {
23880                 *this = object();
23881             }
23882             for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
23883             {
23884                 if (it.value().is_null())
23885                 {
23886                     erase(it.key());
23887                 }
23888                 else
23889                 {
23890                     operator[](it.key()).merge_patch(it.value());
23891                 }
23892             }
23893         }
23894         else
23895         {
23896             *this = apply_patch;
23897         }
23898     }
23899 
23900     /// @}
23901 };
23902 
23903 /// @brief user-defined to_string function for JSON values
23904 /// @sa https://json.nlohmann.me/api/basic_json/to_string/
23905 NLOHMANN_BASIC_JSON_TPL_DECLARATION
to_string(const NLOHMANN_BASIC_JSON_TPL & j)23906 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
23907 {
23908     return j.dump();
23909 }
23910 
23911 } // namespace nlohmann
23912 
23913 ///////////////////////
23914 // nonmember support //
23915 ///////////////////////
23916 
23917 namespace std // NOLINT(cert-dcl58-cpp)
23918 {
23919 
23920 /// @brief hash value for JSON objects
23921 /// @sa https://json.nlohmann.me/api/basic_json/std_hash/
23922 NLOHMANN_BASIC_JSON_TPL_DECLARATION
23923 struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL>
23924 {
operator ()std::hash23925     std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
23926     {
23927         return nlohmann::detail::hash(j);
23928     }
23929 };
23930 
23931 // specialization for std::less<value_t>
23932 template<>
23933 struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
23934 {
23935     /*!
23936     @brief compare two value_t enum values
23937     @since version 3.0.0
23938     */
operator ()std::less23939     bool operator()(::nlohmann::detail::value_t lhs,
23940                     ::nlohmann::detail::value_t rhs) const noexcept
23941     {
23942 #if JSON_HAS_THREE_WAY_COMPARISON
23943         return std::is_lt(lhs <=> rhs); // *NOPAD*
23944 #else
23945         return ::nlohmann::detail::operator<(lhs, rhs);
23946 #endif
23947     }
23948 };
23949 
23950 // C++20 prohibit function specialization in the std namespace.
23951 #ifndef JSON_HAS_CPP_20
23952 
23953 /// @brief exchanges the values of two JSON objects
23954 /// @sa https://json.nlohmann.me/api/basic_json/std_swap/
23955 NLOHMANN_BASIC_JSON_TPL_DECLARATION
swap(nlohmann::NLOHMANN_BASIC_JSON_TPL & j1,nlohmann::NLOHMANN_BASIC_JSON_TPL & j2)23956 inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept(  // NOLINT(readability-inconsistent-declaration-parameter-name)
23957     is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&&                          // NOLINT(misc-redundant-expression)
23958     is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
23959 {
23960     j1.swap(j2);
23961 }
23962 
23963 #endif
23964 
23965 } // namespace std
23966 
23967 /// @brief user-defined string literal for JSON values
23968 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
23969 JSON_HEDLEY_NON_NULL(1)
operator ""_json(const char * s,std::size_t n)23970 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
23971 {
23972     return nlohmann::json::parse(s, s + n);
23973 }
23974 
23975 /// @brief user-defined string literal for JSON pointer
23976 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
23977 JSON_HEDLEY_NON_NULL(1)
operator ""_json_pointer(const char * s,std::size_t n)23978 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
23979 {
23980     return nlohmann::json::json_pointer(std::string(s, n));
23981 }
23982 
23983 // #include <nlohmann/detail/macro_unscope.hpp>
23984 //     __ _____ _____ _____
23985 //  __|  |   __|     |   | |  JSON for Modern C++
23986 // |  |  |__   |  |  | | | |  version 3.10.5
23987 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
23988 //
23989 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
23990 // SPDX-License-Identifier: MIT
23991 
23992 
23993 
23994 // restore clang diagnostic settings
23995 #if defined(__clang__)
23996     #pragma clang diagnostic pop
23997 #endif
23998 
23999 // clean up
24000 #undef JSON_ASSERT
24001 #undef JSON_INTERNAL_CATCH
24002 #undef JSON_THROW
24003 #undef JSON_PRIVATE_UNLESS_TESTED
24004 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
24005 #undef NLOHMANN_BASIC_JSON_TPL
24006 #undef JSON_EXPLICIT
24007 #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
24008 #undef JSON_INLINE_VARIABLE
24009 #undef JSON_NO_UNIQUE_ADDRESS
24010 #undef JSON_DISABLE_ENUM_SERIALIZATION
24011 
24012 #ifndef JSON_TEST_KEEP_MACROS
24013     #undef JSON_CATCH
24014     #undef JSON_TRY
24015     #undef JSON_HAS_CPP_11
24016     #undef JSON_HAS_CPP_14
24017     #undef JSON_HAS_CPP_17
24018     #undef JSON_HAS_CPP_20
24019     #undef JSON_HAS_FILESYSTEM
24020     #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
24021     #undef JSON_HAS_THREE_WAY_COMPARISON
24022     #undef JSON_HAS_RANGES
24023     #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
24024 #endif
24025 
24026 // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
24027 //     __ _____ _____ _____
24028 //  __|  |   __|     |   | |  JSON for Modern C++
24029 // |  |  |__   |  |  | | | |  version 3.10.5
24030 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
24031 //
24032 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
24033 // SPDX-License-Identifier: MIT
24034 
24035 
24036 
24037 #undef JSON_HEDLEY_ALWAYS_INLINE
24038 #undef JSON_HEDLEY_ARM_VERSION
24039 #undef JSON_HEDLEY_ARM_VERSION_CHECK
24040 #undef JSON_HEDLEY_ARRAY_PARAM
24041 #undef JSON_HEDLEY_ASSUME
24042 #undef JSON_HEDLEY_BEGIN_C_DECLS
24043 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
24044 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
24045 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
24046 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
24047 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
24048 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
24049 #undef JSON_HEDLEY_CLANG_HAS_WARNING
24050 #undef JSON_HEDLEY_COMPCERT_VERSION
24051 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
24052 #undef JSON_HEDLEY_CONCAT
24053 #undef JSON_HEDLEY_CONCAT3
24054 #undef JSON_HEDLEY_CONCAT3_EX
24055 #undef JSON_HEDLEY_CONCAT_EX
24056 #undef JSON_HEDLEY_CONST
24057 #undef JSON_HEDLEY_CONSTEXPR
24058 #undef JSON_HEDLEY_CONST_CAST
24059 #undef JSON_HEDLEY_CPP_CAST
24060 #undef JSON_HEDLEY_CRAY_VERSION
24061 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
24062 #undef JSON_HEDLEY_C_DECL
24063 #undef JSON_HEDLEY_DEPRECATED
24064 #undef JSON_HEDLEY_DEPRECATED_FOR
24065 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
24066 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
24067 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
24068 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
24069 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
24070 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
24071 #undef JSON_HEDLEY_DIAGNOSTIC_POP
24072 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
24073 #undef JSON_HEDLEY_DMC_VERSION
24074 #undef JSON_HEDLEY_DMC_VERSION_CHECK
24075 #undef JSON_HEDLEY_EMPTY_BASES
24076 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
24077 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
24078 #undef JSON_HEDLEY_END_C_DECLS
24079 #undef JSON_HEDLEY_FLAGS
24080 #undef JSON_HEDLEY_FLAGS_CAST
24081 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
24082 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
24083 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
24084 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
24085 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
24086 #undef JSON_HEDLEY_GCC_HAS_FEATURE
24087 #undef JSON_HEDLEY_GCC_HAS_WARNING
24088 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
24089 #undef JSON_HEDLEY_GCC_VERSION
24090 #undef JSON_HEDLEY_GCC_VERSION_CHECK
24091 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
24092 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
24093 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
24094 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
24095 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
24096 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
24097 #undef JSON_HEDLEY_GNUC_HAS_WARNING
24098 #undef JSON_HEDLEY_GNUC_VERSION
24099 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
24100 #undef JSON_HEDLEY_HAS_ATTRIBUTE
24101 #undef JSON_HEDLEY_HAS_BUILTIN
24102 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
24103 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
24104 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
24105 #undef JSON_HEDLEY_HAS_EXTENSION
24106 #undef JSON_HEDLEY_HAS_FEATURE
24107 #undef JSON_HEDLEY_HAS_WARNING
24108 #undef JSON_HEDLEY_IAR_VERSION
24109 #undef JSON_HEDLEY_IAR_VERSION_CHECK
24110 #undef JSON_HEDLEY_IBM_VERSION
24111 #undef JSON_HEDLEY_IBM_VERSION_CHECK
24112 #undef JSON_HEDLEY_IMPORT
24113 #undef JSON_HEDLEY_INLINE
24114 #undef JSON_HEDLEY_INTEL_CL_VERSION
24115 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
24116 #undef JSON_HEDLEY_INTEL_VERSION
24117 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
24118 #undef JSON_HEDLEY_IS_CONSTANT
24119 #undef JSON_HEDLEY_IS_CONSTEXPR_
24120 #undef JSON_HEDLEY_LIKELY
24121 #undef JSON_HEDLEY_MALLOC
24122 #undef JSON_HEDLEY_MCST_LCC_VERSION
24123 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
24124 #undef JSON_HEDLEY_MESSAGE
24125 #undef JSON_HEDLEY_MSVC_VERSION
24126 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
24127 #undef JSON_HEDLEY_NEVER_INLINE
24128 #undef JSON_HEDLEY_NON_NULL
24129 #undef JSON_HEDLEY_NO_ESCAPE
24130 #undef JSON_HEDLEY_NO_RETURN
24131 #undef JSON_HEDLEY_NO_THROW
24132 #undef JSON_HEDLEY_NULL
24133 #undef JSON_HEDLEY_PELLES_VERSION
24134 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
24135 #undef JSON_HEDLEY_PGI_VERSION
24136 #undef JSON_HEDLEY_PGI_VERSION_CHECK
24137 #undef JSON_HEDLEY_PREDICT
24138 #undef JSON_HEDLEY_PRINTF_FORMAT
24139 #undef JSON_HEDLEY_PRIVATE
24140 #undef JSON_HEDLEY_PUBLIC
24141 #undef JSON_HEDLEY_PURE
24142 #undef JSON_HEDLEY_REINTERPRET_CAST
24143 #undef JSON_HEDLEY_REQUIRE
24144 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
24145 #undef JSON_HEDLEY_REQUIRE_MSG
24146 #undef JSON_HEDLEY_RESTRICT
24147 #undef JSON_HEDLEY_RETURNS_NON_NULL
24148 #undef JSON_HEDLEY_SENTINEL
24149 #undef JSON_HEDLEY_STATIC_ASSERT
24150 #undef JSON_HEDLEY_STATIC_CAST
24151 #undef JSON_HEDLEY_STRINGIFY
24152 #undef JSON_HEDLEY_STRINGIFY_EX
24153 #undef JSON_HEDLEY_SUNPRO_VERSION
24154 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
24155 #undef JSON_HEDLEY_TINYC_VERSION
24156 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
24157 #undef JSON_HEDLEY_TI_ARMCL_VERSION
24158 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
24159 #undef JSON_HEDLEY_TI_CL2000_VERSION
24160 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
24161 #undef JSON_HEDLEY_TI_CL430_VERSION
24162 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
24163 #undef JSON_HEDLEY_TI_CL6X_VERSION
24164 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
24165 #undef JSON_HEDLEY_TI_CL7X_VERSION
24166 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
24167 #undef JSON_HEDLEY_TI_CLPRU_VERSION
24168 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
24169 #undef JSON_HEDLEY_TI_VERSION
24170 #undef JSON_HEDLEY_TI_VERSION_CHECK
24171 #undef JSON_HEDLEY_UNAVAILABLE
24172 #undef JSON_HEDLEY_UNLIKELY
24173 #undef JSON_HEDLEY_UNPREDICTABLE
24174 #undef JSON_HEDLEY_UNREACHABLE
24175 #undef JSON_HEDLEY_UNREACHABLE_RETURN
24176 #undef JSON_HEDLEY_VERSION
24177 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
24178 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
24179 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
24180 #undef JSON_HEDLEY_VERSION_ENCODE
24181 #undef JSON_HEDLEY_WARNING
24182 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
24183 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
24184 #undef JSON_HEDLEY_FALL_THROUGH
24185 
24186 
24187 
24188 #endif  // INCLUDE_NLOHMANN_JSON_HPP_
24189