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 (¤t->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