Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/nlohmann/include/json.hpp
2 views
1
// __ _____ _____ _____
2
// __| | __| | | | JSON for Modern C++
3
// | | |__ | | | | | | version 3.11.3
4
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5
//
6
// SPDX-FileCopyrightText: 2013-2023 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
#include <algorithm> // all_of, find, for_each
22
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
23
#include <functional> // hash, less
24
#include <initializer_list> // initializer_list
25
#ifndef JSON_NO_IO
26
#include <iosfwd> // istream, ostream
27
#endif // JSON_NO_IO
28
#include <iterator> // random_access_iterator_tag
29
#include <memory> // unique_ptr
30
#include <string> // string, stoi, to_string
31
#include <utility> // declval, forward, move, pair, swap
32
#include <vector> // vector
33
34
// #include <nlohmann/adl_serializer.hpp>
35
// __ _____ _____ _____
36
// __| | __| | | | JSON for Modern C++
37
// | | |__ | | | | | | version 3.11.3
38
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
39
//
40
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
41
// SPDX-License-Identifier: MIT
42
43
44
45
#include <utility>
46
47
// #include <nlohmann/detail/abi_macros.hpp>
48
// __ _____ _____ _____
49
// __| | __| | | | JSON for Modern C++
50
// | | |__ | | | | | | version 3.11.3
51
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
52
//
53
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
54
// SPDX-License-Identifier: MIT
55
56
57
58
// This file contains all macro definitions affecting or depending on the ABI
59
60
#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
61
#if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
62
#if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3
63
#warning "Already included a different version of the library!"
64
#endif
65
#endif
66
#endif
67
68
#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
69
#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
70
#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum)
71
72
#ifndef JSON_DIAGNOSTICS
73
#define JSON_DIAGNOSTICS 0
74
#endif
75
76
#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
77
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
78
#endif
79
80
#if JSON_DIAGNOSTICS
81
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
82
#else
83
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
84
#endif
85
86
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
87
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
88
#else
89
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
90
#endif
91
92
#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
93
#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
94
#endif
95
96
// Construct the namespace ABI tags component
97
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
98
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
99
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
100
101
#define NLOHMANN_JSON_ABI_TAGS \
102
NLOHMANN_JSON_ABI_TAGS_CONCAT( \
103
NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
104
NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
105
106
// Construct the namespace version component
107
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
108
_v ## major ## _ ## minor ## _ ## patch
109
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
110
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
111
112
#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
113
#define NLOHMANN_JSON_NAMESPACE_VERSION
114
#else
115
#define NLOHMANN_JSON_NAMESPACE_VERSION \
116
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
117
NLOHMANN_JSON_VERSION_MINOR, \
118
NLOHMANN_JSON_VERSION_PATCH)
119
#endif
120
121
// Combine namespace components
122
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
123
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
124
NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
125
126
#ifndef NLOHMANN_JSON_NAMESPACE
127
#define NLOHMANN_JSON_NAMESPACE \
128
nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
129
NLOHMANN_JSON_ABI_TAGS, \
130
NLOHMANN_JSON_NAMESPACE_VERSION)
131
#endif
132
133
#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
134
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
135
namespace nlohmann \
136
{ \
137
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
138
NLOHMANN_JSON_ABI_TAGS, \
139
NLOHMANN_JSON_NAMESPACE_VERSION) \
140
{
141
#endif
142
143
#ifndef NLOHMANN_JSON_NAMESPACE_END
144
#define NLOHMANN_JSON_NAMESPACE_END \
145
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
146
} // namespace nlohmann
147
#endif
148
149
// #include <nlohmann/detail/conversions/from_json.hpp>
150
// __ _____ _____ _____
151
// __| | __| | | | JSON for Modern C++
152
// | | |__ | | | | | | version 3.11.3
153
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
154
//
155
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
156
// SPDX-License-Identifier: MIT
157
158
159
160
#include <algorithm> // transform
161
#include <array> // array
162
#include <forward_list> // forward_list
163
#include <iterator> // inserter, front_inserter, end
164
#include <map> // map
165
#include <string> // string
166
#include <tuple> // tuple, make_tuple
167
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
168
#include <unordered_map> // unordered_map
169
#include <utility> // pair, declval
170
#include <valarray> // valarray
171
172
// #include <nlohmann/detail/exceptions.hpp>
173
// __ _____ _____ _____
174
// __| | __| | | | JSON for Modern C++
175
// | | |__ | | | | | | version 3.11.3
176
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
177
//
178
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
179
// SPDX-License-Identifier: MIT
180
181
182
183
#include <cstddef> // nullptr_t
184
#include <exception> // exception
185
#if JSON_DIAGNOSTICS
186
#include <numeric> // accumulate
187
#endif
188
#include <stdexcept> // runtime_error
189
#include <string> // to_string
190
#include <vector> // vector
191
192
// #include <nlohmann/detail/value_t.hpp>
193
// __ _____ _____ _____
194
// __| | __| | | | JSON for Modern C++
195
// | | |__ | | | | | | version 3.11.3
196
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
197
//
198
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
199
// SPDX-License-Identifier: MIT
200
201
202
203
#include <array> // array
204
#include <cstddef> // size_t
205
#include <cstdint> // uint8_t
206
#include <string> // string
207
208
// #include <nlohmann/detail/macro_scope.hpp>
209
// __ _____ _____ _____
210
// __| | __| | | | JSON for Modern C++
211
// | | |__ | | | | | | version 3.11.3
212
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
213
//
214
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
215
// SPDX-License-Identifier: MIT
216
217
218
219
#include <utility> // declval, pair
220
// #include <nlohmann/detail/meta/detected.hpp>
221
// __ _____ _____ _____
222
// __| | __| | | | JSON for Modern C++
223
// | | |__ | | | | | | version 3.11.3
224
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
225
//
226
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
227
// SPDX-License-Identifier: MIT
228
229
230
231
#include <type_traits>
232
233
// #include <nlohmann/detail/meta/void_t.hpp>
234
// __ _____ _____ _____
235
// __| | __| | | | JSON for Modern C++
236
// | | |__ | | | | | | version 3.11.3
237
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
238
//
239
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
240
// SPDX-License-Identifier: MIT
241
242
243
244
// #include <nlohmann/detail/abi_macros.hpp>
245
246
247
NLOHMANN_JSON_NAMESPACE_BEGIN
248
namespace detail
249
{
250
251
template<typename ...Ts> struct make_void
252
{
253
using type = void;
254
};
255
template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
256
257
} // namespace detail
258
NLOHMANN_JSON_NAMESPACE_END
259
260
261
NLOHMANN_JSON_NAMESPACE_BEGIN
262
namespace detail
263
{
264
265
// https://en.cppreference.com/w/cpp/experimental/is_detected
266
struct nonesuch
267
{
268
nonesuch() = delete;
269
~nonesuch() = delete;
270
nonesuch(nonesuch const&) = delete;
271
nonesuch(nonesuch const&&) = delete;
272
void operator=(nonesuch const&) = delete;
273
void operator=(nonesuch&&) = delete;
274
};
275
276
template<class Default,
277
class AlwaysVoid,
278
template<class...> class Op,
279
class... Args>
280
struct detector
281
{
282
using value_t = std::false_type;
283
using type = Default;
284
};
285
286
template<class Default, template<class...> class Op, class... Args>
287
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
288
{
289
using value_t = std::true_type;
290
using type = Op<Args...>;
291
};
292
293
template<template<class...> class Op, class... Args>
294
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
295
296
template<template<class...> class Op, class... Args>
297
struct is_detected_lazy : is_detected<Op, Args...> { };
298
299
template<template<class...> class Op, class... Args>
300
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
301
302
template<class Default, template<class...> class Op, class... Args>
303
using detected_or = detector<Default, void, Op, Args...>;
304
305
template<class Default, template<class...> class Op, class... Args>
306
using detected_or_t = typename detected_or<Default, Op, Args...>::type;
307
308
template<class Expected, template<class...> class Op, class... Args>
309
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
310
311
template<class To, template<class...> class Op, class... Args>
312
using is_detected_convertible =
313
std::is_convertible<detected_t<Op, Args...>, To>;
314
315
} // namespace detail
316
NLOHMANN_JSON_NAMESPACE_END
317
318
// #include <nlohmann/thirdparty/hedley/hedley.hpp>
319
320
321
// __ _____ _____ _____
322
// __| | __| | | | JSON for Modern C++
323
// | | |__ | | | | | | version 3.11.3
324
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
325
//
326
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
327
// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <[email protected]>
328
// SPDX-License-Identifier: MIT
329
330
/* Hedley - https://nemequ.github.io/hedley
331
* Created by Evan Nemerson <[email protected]>
332
*/
333
334
#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
335
#if defined(JSON_HEDLEY_VERSION)
336
#undef JSON_HEDLEY_VERSION
337
#endif
338
#define JSON_HEDLEY_VERSION 15
339
340
#if defined(JSON_HEDLEY_STRINGIFY_EX)
341
#undef JSON_HEDLEY_STRINGIFY_EX
342
#endif
343
#define JSON_HEDLEY_STRINGIFY_EX(x) #x
344
345
#if defined(JSON_HEDLEY_STRINGIFY)
346
#undef JSON_HEDLEY_STRINGIFY
347
#endif
348
#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
349
350
#if defined(JSON_HEDLEY_CONCAT_EX)
351
#undef JSON_HEDLEY_CONCAT_EX
352
#endif
353
#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
354
355
#if defined(JSON_HEDLEY_CONCAT)
356
#undef JSON_HEDLEY_CONCAT
357
#endif
358
#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
359
360
#if defined(JSON_HEDLEY_CONCAT3_EX)
361
#undef JSON_HEDLEY_CONCAT3_EX
362
#endif
363
#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
364
365
#if defined(JSON_HEDLEY_CONCAT3)
366
#undef JSON_HEDLEY_CONCAT3
367
#endif
368
#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
369
370
#if defined(JSON_HEDLEY_VERSION_ENCODE)
371
#undef JSON_HEDLEY_VERSION_ENCODE
372
#endif
373
#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
374
375
#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
376
#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
377
#endif
378
#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
379
380
#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
381
#undef JSON_HEDLEY_VERSION_DECODE_MINOR
382
#endif
383
#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
384
385
#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
386
#undef JSON_HEDLEY_VERSION_DECODE_REVISION
387
#endif
388
#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
389
390
#if defined(JSON_HEDLEY_GNUC_VERSION)
391
#undef JSON_HEDLEY_GNUC_VERSION
392
#endif
393
#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
394
#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
395
#elif defined(__GNUC__)
396
#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
397
#endif
398
399
#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
400
#undef JSON_HEDLEY_GNUC_VERSION_CHECK
401
#endif
402
#if defined(JSON_HEDLEY_GNUC_VERSION)
403
#define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
404
#else
405
#define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
406
#endif
407
408
#if defined(JSON_HEDLEY_MSVC_VERSION)
409
#undef JSON_HEDLEY_MSVC_VERSION
410
#endif
411
#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
412
#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
413
#elif defined(_MSC_FULL_VER) && !defined(__ICL)
414
#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
415
#elif defined(_MSC_VER) && !defined(__ICL)
416
#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
417
#endif
418
419
#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
420
#undef JSON_HEDLEY_MSVC_VERSION_CHECK
421
#endif
422
#if !defined(JSON_HEDLEY_MSVC_VERSION)
423
#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
424
#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
425
#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
426
#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
427
#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
428
#else
429
#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
430
#endif
431
432
#if defined(JSON_HEDLEY_INTEL_VERSION)
433
#undef JSON_HEDLEY_INTEL_VERSION
434
#endif
435
#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
436
#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
437
#elif defined(__INTEL_COMPILER) && !defined(__ICL)
438
#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
439
#endif
440
441
#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
442
#undef JSON_HEDLEY_INTEL_VERSION_CHECK
443
#endif
444
#if defined(JSON_HEDLEY_INTEL_VERSION)
445
#define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
446
#else
447
#define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
448
#endif
449
450
#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
451
#undef JSON_HEDLEY_INTEL_CL_VERSION
452
#endif
453
#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
454
#define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
455
#endif
456
457
#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
458
#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
459
#endif
460
#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
461
#define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
462
#else
463
#define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
464
#endif
465
466
#if defined(JSON_HEDLEY_PGI_VERSION)
467
#undef JSON_HEDLEY_PGI_VERSION
468
#endif
469
#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
470
#define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
471
#endif
472
473
#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
474
#undef JSON_HEDLEY_PGI_VERSION_CHECK
475
#endif
476
#if defined(JSON_HEDLEY_PGI_VERSION)
477
#define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
478
#else
479
#define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
480
#endif
481
482
#if defined(JSON_HEDLEY_SUNPRO_VERSION)
483
#undef JSON_HEDLEY_SUNPRO_VERSION
484
#endif
485
#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
486
#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)
487
#elif defined(__SUNPRO_C)
488
#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
489
#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
490
#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)
491
#elif defined(__SUNPRO_CC)
492
#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
493
#endif
494
495
#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
496
#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
497
#endif
498
#if defined(JSON_HEDLEY_SUNPRO_VERSION)
499
#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
500
#else
501
#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
502
#endif
503
504
#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
505
#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
506
#endif
507
#if defined(__EMSCRIPTEN__)
508
#define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
509
#endif
510
511
#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
512
#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
513
#endif
514
#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
515
#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
516
#else
517
#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
518
#endif
519
520
#if defined(JSON_HEDLEY_ARM_VERSION)
521
#undef JSON_HEDLEY_ARM_VERSION
522
#endif
523
#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
524
#define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
525
#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
526
#define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
527
#endif
528
529
#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
530
#undef JSON_HEDLEY_ARM_VERSION_CHECK
531
#endif
532
#if defined(JSON_HEDLEY_ARM_VERSION)
533
#define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
534
#else
535
#define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
536
#endif
537
538
#if defined(JSON_HEDLEY_IBM_VERSION)
539
#undef JSON_HEDLEY_IBM_VERSION
540
#endif
541
#if defined(__ibmxl__)
542
#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
543
#elif defined(__xlC__) && defined(__xlC_ver__)
544
#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
545
#elif defined(__xlC__)
546
#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
547
#endif
548
549
#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
550
#undef JSON_HEDLEY_IBM_VERSION_CHECK
551
#endif
552
#if defined(JSON_HEDLEY_IBM_VERSION)
553
#define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
554
#else
555
#define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
556
#endif
557
558
#if defined(JSON_HEDLEY_TI_VERSION)
559
#undef JSON_HEDLEY_TI_VERSION
560
#endif
561
#if \
562
defined(__TI_COMPILER_VERSION__) && \
563
( \
564
defined(__TMS470__) || defined(__TI_ARM__) || \
565
defined(__MSP430__) || \
566
defined(__TMS320C2000__) \
567
)
568
#if (__TI_COMPILER_VERSION__ >= 16000000)
569
#define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
570
#endif
571
#endif
572
573
#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
574
#undef JSON_HEDLEY_TI_VERSION_CHECK
575
#endif
576
#if defined(JSON_HEDLEY_TI_VERSION)
577
#define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
578
#else
579
#define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
580
#endif
581
582
#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
583
#undef JSON_HEDLEY_TI_CL2000_VERSION
584
#endif
585
#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
586
#define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
587
#endif
588
589
#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
590
#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
591
#endif
592
#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
593
#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
594
#else
595
#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
596
#endif
597
598
#if defined(JSON_HEDLEY_TI_CL430_VERSION)
599
#undef JSON_HEDLEY_TI_CL430_VERSION
600
#endif
601
#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
602
#define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
603
#endif
604
605
#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
606
#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
607
#endif
608
#if defined(JSON_HEDLEY_TI_CL430_VERSION)
609
#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
610
#else
611
#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
612
#endif
613
614
#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
615
#undef JSON_HEDLEY_TI_ARMCL_VERSION
616
#endif
617
#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
618
#define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
619
#endif
620
621
#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
622
#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
623
#endif
624
#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
625
#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
626
#else
627
#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
628
#endif
629
630
#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
631
#undef JSON_HEDLEY_TI_CL6X_VERSION
632
#endif
633
#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
634
#define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
635
#endif
636
637
#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
638
#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
639
#endif
640
#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
641
#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
642
#else
643
#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
644
#endif
645
646
#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
647
#undef JSON_HEDLEY_TI_CL7X_VERSION
648
#endif
649
#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
650
#define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
651
#endif
652
653
#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
654
#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
655
#endif
656
#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
657
#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
658
#else
659
#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
660
#endif
661
662
#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
663
#undef JSON_HEDLEY_TI_CLPRU_VERSION
664
#endif
665
#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
666
#define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
667
#endif
668
669
#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
670
#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
671
#endif
672
#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
673
#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
674
#else
675
#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
676
#endif
677
678
#if defined(JSON_HEDLEY_CRAY_VERSION)
679
#undef JSON_HEDLEY_CRAY_VERSION
680
#endif
681
#if defined(_CRAYC)
682
#if defined(_RELEASE_PATCHLEVEL)
683
#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
684
#else
685
#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
686
#endif
687
#endif
688
689
#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
690
#undef JSON_HEDLEY_CRAY_VERSION_CHECK
691
#endif
692
#if defined(JSON_HEDLEY_CRAY_VERSION)
693
#define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
694
#else
695
#define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
696
#endif
697
698
#if defined(JSON_HEDLEY_IAR_VERSION)
699
#undef JSON_HEDLEY_IAR_VERSION
700
#endif
701
#if defined(__IAR_SYSTEMS_ICC__)
702
#if __VER__ > 1000
703
#define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
704
#else
705
#define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
706
#endif
707
#endif
708
709
#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
710
#undef JSON_HEDLEY_IAR_VERSION_CHECK
711
#endif
712
#if defined(JSON_HEDLEY_IAR_VERSION)
713
#define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
714
#else
715
#define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
716
#endif
717
718
#if defined(JSON_HEDLEY_TINYC_VERSION)
719
#undef JSON_HEDLEY_TINYC_VERSION
720
#endif
721
#if defined(__TINYC__)
722
#define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
723
#endif
724
725
#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
726
#undef JSON_HEDLEY_TINYC_VERSION_CHECK
727
#endif
728
#if defined(JSON_HEDLEY_TINYC_VERSION)
729
#define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
730
#else
731
#define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
732
#endif
733
734
#if defined(JSON_HEDLEY_DMC_VERSION)
735
#undef JSON_HEDLEY_DMC_VERSION
736
#endif
737
#if defined(__DMC__)
738
#define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
739
#endif
740
741
#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
742
#undef JSON_HEDLEY_DMC_VERSION_CHECK
743
#endif
744
#if defined(JSON_HEDLEY_DMC_VERSION)
745
#define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
746
#else
747
#define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
748
#endif
749
750
#if defined(JSON_HEDLEY_COMPCERT_VERSION)
751
#undef JSON_HEDLEY_COMPCERT_VERSION
752
#endif
753
#if defined(__COMPCERT_VERSION__)
754
#define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
755
#endif
756
757
#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
758
#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
759
#endif
760
#if defined(JSON_HEDLEY_COMPCERT_VERSION)
761
#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
762
#else
763
#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
764
#endif
765
766
#if defined(JSON_HEDLEY_PELLES_VERSION)
767
#undef JSON_HEDLEY_PELLES_VERSION
768
#endif
769
#if defined(__POCC__)
770
#define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
771
#endif
772
773
#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
774
#undef JSON_HEDLEY_PELLES_VERSION_CHECK
775
#endif
776
#if defined(JSON_HEDLEY_PELLES_VERSION)
777
#define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
778
#else
779
#define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
780
#endif
781
782
#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
783
#undef JSON_HEDLEY_MCST_LCC_VERSION
784
#endif
785
#if defined(__LCC__) && defined(__LCC_MINOR__)
786
#define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
787
#endif
788
789
#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
790
#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
791
#endif
792
#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
793
#define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
794
#else
795
#define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
796
#endif
797
798
#if defined(JSON_HEDLEY_GCC_VERSION)
799
#undef JSON_HEDLEY_GCC_VERSION
800
#endif
801
#if \
802
defined(JSON_HEDLEY_GNUC_VERSION) && \
803
!defined(__clang__) && \
804
!defined(JSON_HEDLEY_INTEL_VERSION) && \
805
!defined(JSON_HEDLEY_PGI_VERSION) && \
806
!defined(JSON_HEDLEY_ARM_VERSION) && \
807
!defined(JSON_HEDLEY_CRAY_VERSION) && \
808
!defined(JSON_HEDLEY_TI_VERSION) && \
809
!defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
810
!defined(JSON_HEDLEY_TI_CL430_VERSION) && \
811
!defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
812
!defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
813
!defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
814
!defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
815
!defined(__COMPCERT__) && \
816
!defined(JSON_HEDLEY_MCST_LCC_VERSION)
817
#define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
818
#endif
819
820
#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
821
#undef JSON_HEDLEY_GCC_VERSION_CHECK
822
#endif
823
#if defined(JSON_HEDLEY_GCC_VERSION)
824
#define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
825
#else
826
#define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
827
#endif
828
829
#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
830
#undef JSON_HEDLEY_HAS_ATTRIBUTE
831
#endif
832
#if \
833
defined(__has_attribute) && \
834
( \
835
(!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
836
)
837
# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
838
#else
839
# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
840
#endif
841
842
#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
843
#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
844
#endif
845
#if defined(__has_attribute)
846
#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
847
#else
848
#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
849
#endif
850
851
#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
852
#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
853
#endif
854
#if defined(__has_attribute)
855
#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
856
#else
857
#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
858
#endif
859
860
#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
861
#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
862
#endif
863
#if \
864
defined(__has_cpp_attribute) && \
865
defined(__cplusplus) && \
866
(!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
867
#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
868
#else
869
#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
870
#endif
871
872
#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
873
#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
874
#endif
875
#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
876
#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
877
#elif \
878
!defined(JSON_HEDLEY_PGI_VERSION) && \
879
!defined(JSON_HEDLEY_IAR_VERSION) && \
880
(!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
881
(!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
882
#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
883
#else
884
#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
885
#endif
886
887
#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
888
#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
889
#endif
890
#if defined(__has_cpp_attribute) && defined(__cplusplus)
891
#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
892
#else
893
#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
894
#endif
895
896
#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
897
#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
898
#endif
899
#if defined(__has_cpp_attribute) && defined(__cplusplus)
900
#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
901
#else
902
#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
903
#endif
904
905
#if defined(JSON_HEDLEY_HAS_BUILTIN)
906
#undef JSON_HEDLEY_HAS_BUILTIN
907
#endif
908
#if defined(__has_builtin)
909
#define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
910
#else
911
#define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
912
#endif
913
914
#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
915
#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
916
#endif
917
#if defined(__has_builtin)
918
#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
919
#else
920
#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
921
#endif
922
923
#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
924
#undef JSON_HEDLEY_GCC_HAS_BUILTIN
925
#endif
926
#if defined(__has_builtin)
927
#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
928
#else
929
#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
930
#endif
931
932
#if defined(JSON_HEDLEY_HAS_FEATURE)
933
#undef JSON_HEDLEY_HAS_FEATURE
934
#endif
935
#if defined(__has_feature)
936
#define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
937
#else
938
#define JSON_HEDLEY_HAS_FEATURE(feature) (0)
939
#endif
940
941
#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
942
#undef JSON_HEDLEY_GNUC_HAS_FEATURE
943
#endif
944
#if defined(__has_feature)
945
#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
946
#else
947
#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
948
#endif
949
950
#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
951
#undef JSON_HEDLEY_GCC_HAS_FEATURE
952
#endif
953
#if defined(__has_feature)
954
#define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
955
#else
956
#define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
957
#endif
958
959
#if defined(JSON_HEDLEY_HAS_EXTENSION)
960
#undef JSON_HEDLEY_HAS_EXTENSION
961
#endif
962
#if defined(__has_extension)
963
#define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
964
#else
965
#define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
966
#endif
967
968
#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
969
#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
970
#endif
971
#if defined(__has_extension)
972
#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
973
#else
974
#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
975
#endif
976
977
#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
978
#undef JSON_HEDLEY_GCC_HAS_EXTENSION
979
#endif
980
#if defined(__has_extension)
981
#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
982
#else
983
#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
984
#endif
985
986
#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
987
#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
988
#endif
989
#if defined(__has_declspec_attribute)
990
#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
991
#else
992
#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
993
#endif
994
995
#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
996
#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
997
#endif
998
#if defined(__has_declspec_attribute)
999
#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1000
#else
1001
#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1002
#endif
1003
1004
#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1005
#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1006
#endif
1007
#if defined(__has_declspec_attribute)
1008
#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1009
#else
1010
#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1011
#endif
1012
1013
#if defined(JSON_HEDLEY_HAS_WARNING)
1014
#undef JSON_HEDLEY_HAS_WARNING
1015
#endif
1016
#if defined(__has_warning)
1017
#define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1018
#else
1019
#define JSON_HEDLEY_HAS_WARNING(warning) (0)
1020
#endif
1021
1022
#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1023
#undef JSON_HEDLEY_GNUC_HAS_WARNING
1024
#endif
1025
#if defined(__has_warning)
1026
#define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1027
#else
1028
#define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1029
#endif
1030
1031
#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1032
#undef JSON_HEDLEY_GCC_HAS_WARNING
1033
#endif
1034
#if defined(__has_warning)
1035
#define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1036
#else
1037
#define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1038
#endif
1039
1040
#if \
1041
(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1042
defined(__clang__) || \
1043
JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1044
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1045
JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1046
JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1047
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1048
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1049
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1050
JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1051
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1052
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1053
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1054
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1055
JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1056
JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1057
JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1058
(JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1059
#define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1060
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1061
#define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1062
#else
1063
#define JSON_HEDLEY_PRAGMA(value)
1064
#endif
1065
1066
#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1067
#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1068
#endif
1069
#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1070
#undef JSON_HEDLEY_DIAGNOSTIC_POP
1071
#endif
1072
#if defined(__clang__)
1073
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1074
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1075
#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1076
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1077
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1078
#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1079
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1080
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1081
#elif \
1082
JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1083
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1084
#define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1085
#define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1086
#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1087
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1088
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1089
#elif \
1090
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1091
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1092
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1093
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1094
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1095
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1096
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1097
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1098
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1099
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1100
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1101
#else
1102
#define JSON_HEDLEY_DIAGNOSTIC_PUSH
1103
#define JSON_HEDLEY_DIAGNOSTIC_POP
1104
#endif
1105
1106
/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1107
HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1108
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1109
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1110
#endif
1111
#if defined(__cplusplus)
1112
# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1113
# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1114
# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1115
# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1116
JSON_HEDLEY_DIAGNOSTIC_PUSH \
1117
_Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1118
_Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1119
_Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1120
xpr \
1121
JSON_HEDLEY_DIAGNOSTIC_POP
1122
# else
1123
# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1124
JSON_HEDLEY_DIAGNOSTIC_PUSH \
1125
_Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1126
_Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1127
xpr \
1128
JSON_HEDLEY_DIAGNOSTIC_POP
1129
# endif
1130
# else
1131
# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1132
JSON_HEDLEY_DIAGNOSTIC_PUSH \
1133
_Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1134
xpr \
1135
JSON_HEDLEY_DIAGNOSTIC_POP
1136
# endif
1137
# endif
1138
#endif
1139
#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1140
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1141
#endif
1142
1143
#if defined(JSON_HEDLEY_CONST_CAST)
1144
#undef JSON_HEDLEY_CONST_CAST
1145
#endif
1146
#if defined(__cplusplus)
1147
# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1148
#elif \
1149
JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1150
JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1151
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1152
# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1153
JSON_HEDLEY_DIAGNOSTIC_PUSH \
1154
JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1155
((T) (expr)); \
1156
JSON_HEDLEY_DIAGNOSTIC_POP \
1157
}))
1158
#else
1159
# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1160
#endif
1161
1162
#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1163
#undef JSON_HEDLEY_REINTERPRET_CAST
1164
#endif
1165
#if defined(__cplusplus)
1166
#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1167
#else
1168
#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1169
#endif
1170
1171
#if defined(JSON_HEDLEY_STATIC_CAST)
1172
#undef JSON_HEDLEY_STATIC_CAST
1173
#endif
1174
#if defined(__cplusplus)
1175
#define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1176
#else
1177
#define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1178
#endif
1179
1180
#if defined(JSON_HEDLEY_CPP_CAST)
1181
#undef JSON_HEDLEY_CPP_CAST
1182
#endif
1183
#if defined(__cplusplus)
1184
# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1185
# define JSON_HEDLEY_CPP_CAST(T, expr) \
1186
JSON_HEDLEY_DIAGNOSTIC_PUSH \
1187
_Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1188
((T) (expr)) \
1189
JSON_HEDLEY_DIAGNOSTIC_POP
1190
# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1191
# define JSON_HEDLEY_CPP_CAST(T, expr) \
1192
JSON_HEDLEY_DIAGNOSTIC_PUSH \
1193
_Pragma("diag_suppress=Pe137") \
1194
JSON_HEDLEY_DIAGNOSTIC_POP
1195
# else
1196
# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1197
# endif
1198
#else
1199
# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1200
#endif
1201
1202
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1203
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1204
#endif
1205
#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1206
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1207
#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1208
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1209
#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1210
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1211
#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1212
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1213
#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1214
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1215
#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1216
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1217
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1218
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1219
#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1220
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1221
#elif \
1222
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1223
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1224
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1225
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1226
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1227
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1228
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1229
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1230
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1231
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1232
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1233
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1234
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1235
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1236
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1237
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1238
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1239
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1240
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1241
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1242
#else
1243
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1244
#endif
1245
1246
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1247
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1248
#endif
1249
#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1250
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1251
#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1252
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1253
#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1254
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1255
#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1256
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1257
#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1258
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1259
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1260
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1261
#elif \
1262
JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1263
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1264
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1265
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1266
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1267
#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1268
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1269
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1270
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1271
#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1272
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1273
#else
1274
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1275
#endif
1276
1277
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1278
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1279
#endif
1280
#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1281
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1282
#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1283
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1284
#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1285
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1286
#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1287
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1288
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1289
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1290
#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1291
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1292
#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1293
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1294
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1295
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1296
#elif \
1297
JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1298
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1299
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1300
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1301
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1302
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1303
#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1304
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1305
#else
1306
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1307
#endif
1308
1309
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1310
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1311
#endif
1312
#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1313
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1314
#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1315
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1316
#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1317
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1318
#else
1319
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1320
#endif
1321
1322
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1323
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1324
#endif
1325
#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1326
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1327
#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1328
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1329
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1330
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1331
#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1332
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1333
#else
1334
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1335
#endif
1336
1337
#if defined(JSON_HEDLEY_DEPRECATED)
1338
#undef JSON_HEDLEY_DEPRECATED
1339
#endif
1340
#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1341
#undef JSON_HEDLEY_DEPRECATED_FOR
1342
#endif
1343
#if \
1344
JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1345
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1346
#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1347
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1348
#elif \
1349
(JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1350
JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1351
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1352
JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1353
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1354
JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1355
JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1356
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1357
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1358
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1359
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1360
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1361
#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1362
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1363
#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1364
#define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1365
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1366
#elif \
1367
JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1368
JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1369
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1370
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1371
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1372
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1373
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1374
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1375
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1376
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1377
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1378
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1379
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1380
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1381
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1382
JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1383
#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1384
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1385
#elif \
1386
JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1387
JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1388
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1389
#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1390
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1391
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1392
#define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1393
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1394
#else
1395
#define JSON_HEDLEY_DEPRECATED(since)
1396
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1397
#endif
1398
1399
#if defined(JSON_HEDLEY_UNAVAILABLE)
1400
#undef JSON_HEDLEY_UNAVAILABLE
1401
#endif
1402
#if \
1403
JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1404
JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1405
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1406
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1407
#define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1408
#else
1409
#define JSON_HEDLEY_UNAVAILABLE(available_since)
1410
#endif
1411
1412
#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1413
#undef JSON_HEDLEY_WARN_UNUSED_RESULT
1414
#endif
1415
#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1416
#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1417
#endif
1418
#if \
1419
JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1420
JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1421
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1422
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1423
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1424
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1425
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1426
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1427
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1428
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1429
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1430
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1431
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1432
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1433
(JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1434
JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1435
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1436
#define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1437
#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1438
#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1439
#define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1440
#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1441
#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1442
#define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1443
#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1444
#elif defined(_Check_return_) /* SAL */
1445
#define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1446
#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1447
#else
1448
#define JSON_HEDLEY_WARN_UNUSED_RESULT
1449
#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1450
#endif
1451
1452
#if defined(JSON_HEDLEY_SENTINEL)
1453
#undef JSON_HEDLEY_SENTINEL
1454
#endif
1455
#if \
1456
JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1457
JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1458
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1459
JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1460
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1461
#define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1462
#else
1463
#define JSON_HEDLEY_SENTINEL(position)
1464
#endif
1465
1466
#if defined(JSON_HEDLEY_NO_RETURN)
1467
#undef JSON_HEDLEY_NO_RETURN
1468
#endif
1469
#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1470
#define JSON_HEDLEY_NO_RETURN __noreturn
1471
#elif \
1472
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1473
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1474
#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1475
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1476
#define JSON_HEDLEY_NO_RETURN _Noreturn
1477
#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1478
#define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1479
#elif \
1480
JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1481
JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1482
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1483
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1484
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1485
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1486
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1487
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1488
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1489
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1490
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1491
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1492
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1493
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1494
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1495
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1496
JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1497
#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1498
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1499
#define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1500
#elif \
1501
JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1502
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1503
#define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1504
#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1505
#define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1506
#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1507
#define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1508
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1509
#define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1510
#else
1511
#define JSON_HEDLEY_NO_RETURN
1512
#endif
1513
1514
#if defined(JSON_HEDLEY_NO_ESCAPE)
1515
#undef JSON_HEDLEY_NO_ESCAPE
1516
#endif
1517
#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1518
#define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1519
#else
1520
#define JSON_HEDLEY_NO_ESCAPE
1521
#endif
1522
1523
#if defined(JSON_HEDLEY_UNREACHABLE)
1524
#undef JSON_HEDLEY_UNREACHABLE
1525
#endif
1526
#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1527
#undef JSON_HEDLEY_UNREACHABLE_RETURN
1528
#endif
1529
#if defined(JSON_HEDLEY_ASSUME)
1530
#undef JSON_HEDLEY_ASSUME
1531
#endif
1532
#if \
1533
JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1534
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1535
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1536
#define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1537
#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1538
#define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1539
#elif \
1540
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1541
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1542
#if defined(__cplusplus)
1543
#define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1544
#else
1545
#define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1546
#endif
1547
#endif
1548
#if \
1549
(JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1550
JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1551
JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1552
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1553
JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1554
JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1555
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1556
#define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1557
#elif defined(JSON_HEDLEY_ASSUME)
1558
#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1559
#endif
1560
#if !defined(JSON_HEDLEY_ASSUME)
1561
#if defined(JSON_HEDLEY_UNREACHABLE)
1562
#define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1563
#else
1564
#define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1565
#endif
1566
#endif
1567
#if defined(JSON_HEDLEY_UNREACHABLE)
1568
#if \
1569
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1570
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1571
#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1572
#else
1573
#define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1574
#endif
1575
#else
1576
#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1577
#endif
1578
#if !defined(JSON_HEDLEY_UNREACHABLE)
1579
#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1580
#endif
1581
1582
JSON_HEDLEY_DIAGNOSTIC_PUSH
1583
#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1584
#pragma clang diagnostic ignored "-Wpedantic"
1585
#endif
1586
#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1587
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1588
#endif
1589
#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1590
#if defined(__clang__)
1591
#pragma clang diagnostic ignored "-Wvariadic-macros"
1592
#elif defined(JSON_HEDLEY_GCC_VERSION)
1593
#pragma GCC diagnostic ignored "-Wvariadic-macros"
1594
#endif
1595
#endif
1596
#if defined(JSON_HEDLEY_NON_NULL)
1597
#undef JSON_HEDLEY_NON_NULL
1598
#endif
1599
#if \
1600
JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1601
JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1602
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1603
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1604
#define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1605
#else
1606
#define JSON_HEDLEY_NON_NULL(...)
1607
#endif
1608
JSON_HEDLEY_DIAGNOSTIC_POP
1609
1610
#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1611
#undef JSON_HEDLEY_PRINTF_FORMAT
1612
#endif
1613
#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1614
#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1615
#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1616
#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1617
#elif \
1618
JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1619
JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1620
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1621
JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1622
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1623
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1624
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1625
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1626
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1627
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1628
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1629
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1630
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1631
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1632
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1633
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1634
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1635
#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1636
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1637
#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1638
#else
1639
#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1640
#endif
1641
1642
#if defined(JSON_HEDLEY_CONSTEXPR)
1643
#undef JSON_HEDLEY_CONSTEXPR
1644
#endif
1645
#if defined(__cplusplus)
1646
#if __cplusplus >= 201103L
1647
#define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1648
#endif
1649
#endif
1650
#if !defined(JSON_HEDLEY_CONSTEXPR)
1651
#define JSON_HEDLEY_CONSTEXPR
1652
#endif
1653
1654
#if defined(JSON_HEDLEY_PREDICT)
1655
#undef JSON_HEDLEY_PREDICT
1656
#endif
1657
#if defined(JSON_HEDLEY_LIKELY)
1658
#undef JSON_HEDLEY_LIKELY
1659
#endif
1660
#if defined(JSON_HEDLEY_UNLIKELY)
1661
#undef JSON_HEDLEY_UNLIKELY
1662
#endif
1663
#if defined(JSON_HEDLEY_UNPREDICTABLE)
1664
#undef JSON_HEDLEY_UNPREDICTABLE
1665
#endif
1666
#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1667
#define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1668
#endif
1669
#if \
1670
(JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1671
JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1672
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1673
# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1674
# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1675
# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1676
# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1677
# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1678
#elif \
1679
(JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1680
JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1681
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1682
(JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1683
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1684
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1685
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1686
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1687
JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1688
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1689
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1690
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1691
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1692
JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1693
JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1694
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1695
# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1696
(((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1697
# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1698
(__extension__ ({ \
1699
double hedley_probability_ = (probability); \
1700
((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1701
}))
1702
# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1703
(__extension__ ({ \
1704
double hedley_probability_ = (probability); \
1705
((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1706
}))
1707
# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1708
# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1709
#else
1710
# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1711
# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1712
# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1713
# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1714
# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1715
#endif
1716
#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1717
#define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1718
#endif
1719
1720
#if defined(JSON_HEDLEY_MALLOC)
1721
#undef JSON_HEDLEY_MALLOC
1722
#endif
1723
#if \
1724
JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1725
JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1726
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1727
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1728
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1729
JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1730
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1731
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1732
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1733
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1734
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1735
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1736
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1737
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1738
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1739
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1740
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1741
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1742
#define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1743
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1744
#define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1745
#elif \
1746
JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1747
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1748
#define JSON_HEDLEY_MALLOC __declspec(restrict)
1749
#else
1750
#define JSON_HEDLEY_MALLOC
1751
#endif
1752
1753
#if defined(JSON_HEDLEY_PURE)
1754
#undef JSON_HEDLEY_PURE
1755
#endif
1756
#if \
1757
JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1758
JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1759
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1760
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1761
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1762
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1763
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1764
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1765
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1766
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1767
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1768
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1769
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1770
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1771
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1772
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1773
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1774
JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1775
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1776
# define JSON_HEDLEY_PURE __attribute__((__pure__))
1777
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1778
# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1779
#elif defined(__cplusplus) && \
1780
( \
1781
JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1782
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1783
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1784
)
1785
# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1786
#else
1787
# define JSON_HEDLEY_PURE
1788
#endif
1789
1790
#if defined(JSON_HEDLEY_CONST)
1791
#undef JSON_HEDLEY_CONST
1792
#endif
1793
#if \
1794
JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1795
JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1796
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1797
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1798
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1799
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1800
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1801
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1802
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1803
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1804
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1805
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1806
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1807
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1808
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1809
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1810
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1811
JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1812
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1813
#define JSON_HEDLEY_CONST __attribute__((__const__))
1814
#elif \
1815
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1816
#define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1817
#else
1818
#define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1819
#endif
1820
1821
#if defined(JSON_HEDLEY_RESTRICT)
1822
#undef JSON_HEDLEY_RESTRICT
1823
#endif
1824
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1825
#define JSON_HEDLEY_RESTRICT restrict
1826
#elif \
1827
JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1828
JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1829
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1830
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1831
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1832
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1833
JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1834
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1835
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1836
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1837
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1838
(JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1839
JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1840
defined(__clang__) || \
1841
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1842
#define JSON_HEDLEY_RESTRICT __restrict
1843
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1844
#define JSON_HEDLEY_RESTRICT _Restrict
1845
#else
1846
#define JSON_HEDLEY_RESTRICT
1847
#endif
1848
1849
#if defined(JSON_HEDLEY_INLINE)
1850
#undef JSON_HEDLEY_INLINE
1851
#endif
1852
#if \
1853
(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1854
(defined(__cplusplus) && (__cplusplus >= 199711L))
1855
#define JSON_HEDLEY_INLINE inline
1856
#elif \
1857
defined(JSON_HEDLEY_GCC_VERSION) || \
1858
JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1859
#define JSON_HEDLEY_INLINE __inline__
1860
#elif \
1861
JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1862
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1863
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1864
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1865
JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1866
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1867
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1868
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1869
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1870
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1871
#define JSON_HEDLEY_INLINE __inline
1872
#else
1873
#define JSON_HEDLEY_INLINE
1874
#endif
1875
1876
#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1877
#undef JSON_HEDLEY_ALWAYS_INLINE
1878
#endif
1879
#if \
1880
JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1881
JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1882
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1883
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1884
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1885
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1886
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1887
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1888
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1889
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1890
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1891
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1892
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1893
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1894
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1895
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1896
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1897
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1898
JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1899
# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1900
#elif \
1901
JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1902
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1903
# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1904
#elif defined(__cplusplus) && \
1905
( \
1906
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1907
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1908
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1909
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1910
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1911
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1912
)
1913
# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1914
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1915
# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1916
#else
1917
# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1918
#endif
1919
1920
#if defined(JSON_HEDLEY_NEVER_INLINE)
1921
#undef JSON_HEDLEY_NEVER_INLINE
1922
#endif
1923
#if \
1924
JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1925
JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1926
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1927
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1928
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1929
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1930
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1931
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1932
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1933
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1934
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1935
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1936
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1937
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1938
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1939
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1940
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1941
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1942
JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1943
#define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1944
#elif \
1945
JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1946
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1947
#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1948
#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1949
#define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1950
#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1951
#define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1952
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1953
#define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1954
#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1955
#define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1956
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1957
#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1958
#else
1959
#define JSON_HEDLEY_NEVER_INLINE
1960
#endif
1961
1962
#if defined(JSON_HEDLEY_PRIVATE)
1963
#undef JSON_HEDLEY_PRIVATE
1964
#endif
1965
#if defined(JSON_HEDLEY_PUBLIC)
1966
#undef JSON_HEDLEY_PUBLIC
1967
#endif
1968
#if defined(JSON_HEDLEY_IMPORT)
1969
#undef JSON_HEDLEY_IMPORT
1970
#endif
1971
#if defined(_WIN32) || defined(__CYGWIN__)
1972
# define JSON_HEDLEY_PRIVATE
1973
# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1974
# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1975
#else
1976
# if \
1977
JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1978
JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1979
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1980
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1981
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1982
JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1983
( \
1984
defined(__TI_EABI__) && \
1985
( \
1986
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1987
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1988
) \
1989
) || \
1990
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1991
# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1992
# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1993
# else
1994
# define JSON_HEDLEY_PRIVATE
1995
# define JSON_HEDLEY_PUBLIC
1996
# endif
1997
# define JSON_HEDLEY_IMPORT extern
1998
#endif
1999
2000
#if defined(JSON_HEDLEY_NO_THROW)
2001
#undef JSON_HEDLEY_NO_THROW
2002
#endif
2003
#if \
2004
JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2005
JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2006
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2007
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2008
#define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2009
#elif \
2010
JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2011
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2012
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2013
#define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2014
#else
2015
#define JSON_HEDLEY_NO_THROW
2016
#endif
2017
2018
#if defined(JSON_HEDLEY_FALL_THROUGH)
2019
#undef JSON_HEDLEY_FALL_THROUGH
2020
#endif
2021
#if \
2022
JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2023
JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2024
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2025
#define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2026
#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2027
#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2028
#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2029
#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2030
#elif defined(__fallthrough) /* SAL */
2031
#define JSON_HEDLEY_FALL_THROUGH __fallthrough
2032
#else
2033
#define JSON_HEDLEY_FALL_THROUGH
2034
#endif
2035
2036
#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2037
#undef JSON_HEDLEY_RETURNS_NON_NULL
2038
#endif
2039
#if \
2040
JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2041
JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2042
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2043
#define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2044
#elif defined(_Ret_notnull_) /* SAL */
2045
#define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2046
#else
2047
#define JSON_HEDLEY_RETURNS_NON_NULL
2048
#endif
2049
2050
#if defined(JSON_HEDLEY_ARRAY_PARAM)
2051
#undef JSON_HEDLEY_ARRAY_PARAM
2052
#endif
2053
#if \
2054
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2055
!defined(__STDC_NO_VLA__) && \
2056
!defined(__cplusplus) && \
2057
!defined(JSON_HEDLEY_PGI_VERSION) && \
2058
!defined(JSON_HEDLEY_TINYC_VERSION)
2059
#define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2060
#else
2061
#define JSON_HEDLEY_ARRAY_PARAM(name)
2062
#endif
2063
2064
#if defined(JSON_HEDLEY_IS_CONSTANT)
2065
#undef JSON_HEDLEY_IS_CONSTANT
2066
#endif
2067
#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2068
#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2069
#endif
2070
/* JSON_HEDLEY_IS_CONSTEXPR_ is for
2071
HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2072
#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2073
#undef JSON_HEDLEY_IS_CONSTEXPR_
2074
#endif
2075
#if \
2076
JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2077
JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2078
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2079
JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2080
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2081
JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2082
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2083
(JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2084
JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2085
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2086
#define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2087
#endif
2088
#if !defined(__cplusplus)
2089
# if \
2090
JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2091
JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2092
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2093
JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2094
JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2095
JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2096
JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2097
#if defined(__INTPTR_TYPE__)
2098
#define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2099
#else
2100
#include <stdint.h>
2101
#define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2102
#endif
2103
# elif \
2104
( \
2105
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2106
!defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2107
!defined(JSON_HEDLEY_PGI_VERSION) && \
2108
!defined(JSON_HEDLEY_IAR_VERSION)) || \
2109
(JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2110
JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2111
JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2112
JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2113
JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2114
#if defined(__INTPTR_TYPE__)
2115
#define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2116
#else
2117
#include <stdint.h>
2118
#define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2119
#endif
2120
# elif \
2121
defined(JSON_HEDLEY_GCC_VERSION) || \
2122
defined(JSON_HEDLEY_INTEL_VERSION) || \
2123
defined(JSON_HEDLEY_TINYC_VERSION) || \
2124
defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2125
JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2126
defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2127
defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2128
defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2129
defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2130
defined(__clang__)
2131
# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2132
sizeof(void) != \
2133
sizeof(*( \
2134
1 ? \
2135
((void*) ((expr) * 0L) ) : \
2136
((struct { char v[sizeof(void) * 2]; } *) 1) \
2137
) \
2138
) \
2139
)
2140
# endif
2141
#endif
2142
#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2143
#if !defined(JSON_HEDLEY_IS_CONSTANT)
2144
#define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2145
#endif
2146
#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2147
#else
2148
#if !defined(JSON_HEDLEY_IS_CONSTANT)
2149
#define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2150
#endif
2151
#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2152
#endif
2153
2154
#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2155
#undef JSON_HEDLEY_BEGIN_C_DECLS
2156
#endif
2157
#if defined(JSON_HEDLEY_END_C_DECLS)
2158
#undef JSON_HEDLEY_END_C_DECLS
2159
#endif
2160
#if defined(JSON_HEDLEY_C_DECL)
2161
#undef JSON_HEDLEY_C_DECL
2162
#endif
2163
#if defined(__cplusplus)
2164
#define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2165
#define JSON_HEDLEY_END_C_DECLS }
2166
#define JSON_HEDLEY_C_DECL extern "C"
2167
#else
2168
#define JSON_HEDLEY_BEGIN_C_DECLS
2169
#define JSON_HEDLEY_END_C_DECLS
2170
#define JSON_HEDLEY_C_DECL
2171
#endif
2172
2173
#if defined(JSON_HEDLEY_STATIC_ASSERT)
2174
#undef JSON_HEDLEY_STATIC_ASSERT
2175
#endif
2176
#if \
2177
!defined(__cplusplus) && ( \
2178
(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2179
(JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2180
JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2181
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2182
defined(_Static_assert) \
2183
)
2184
# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2185
#elif \
2186
(defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2187
JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2188
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2189
# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2190
#else
2191
# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2192
#endif
2193
2194
#if defined(JSON_HEDLEY_NULL)
2195
#undef JSON_HEDLEY_NULL
2196
#endif
2197
#if defined(__cplusplus)
2198
#if __cplusplus >= 201103L
2199
#define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2200
#elif defined(NULL)
2201
#define JSON_HEDLEY_NULL NULL
2202
#else
2203
#define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2204
#endif
2205
#elif defined(NULL)
2206
#define JSON_HEDLEY_NULL NULL
2207
#else
2208
#define JSON_HEDLEY_NULL ((void*) 0)
2209
#endif
2210
2211
#if defined(JSON_HEDLEY_MESSAGE)
2212
#undef JSON_HEDLEY_MESSAGE
2213
#endif
2214
#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2215
# define JSON_HEDLEY_MESSAGE(msg) \
2216
JSON_HEDLEY_DIAGNOSTIC_PUSH \
2217
JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2218
JSON_HEDLEY_PRAGMA(message msg) \
2219
JSON_HEDLEY_DIAGNOSTIC_POP
2220
#elif \
2221
JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2222
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2223
# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2224
#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2225
# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2226
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2227
# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2228
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2229
# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2230
#else
2231
# define JSON_HEDLEY_MESSAGE(msg)
2232
#endif
2233
2234
#if defined(JSON_HEDLEY_WARNING)
2235
#undef JSON_HEDLEY_WARNING
2236
#endif
2237
#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2238
# define JSON_HEDLEY_WARNING(msg) \
2239
JSON_HEDLEY_DIAGNOSTIC_PUSH \
2240
JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2241
JSON_HEDLEY_PRAGMA(clang warning msg) \
2242
JSON_HEDLEY_DIAGNOSTIC_POP
2243
#elif \
2244
JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2245
JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2246
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2247
# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2248
#elif \
2249
JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2250
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2251
# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2252
#else
2253
# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2254
#endif
2255
2256
#if defined(JSON_HEDLEY_REQUIRE)
2257
#undef JSON_HEDLEY_REQUIRE
2258
#endif
2259
#if defined(JSON_HEDLEY_REQUIRE_MSG)
2260
#undef JSON_HEDLEY_REQUIRE_MSG
2261
#endif
2262
#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2263
# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2264
# define JSON_HEDLEY_REQUIRE(expr) \
2265
JSON_HEDLEY_DIAGNOSTIC_PUSH \
2266
_Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2267
__attribute__((diagnose_if(!(expr), #expr, "error"))) \
2268
JSON_HEDLEY_DIAGNOSTIC_POP
2269
# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2270
JSON_HEDLEY_DIAGNOSTIC_PUSH \
2271
_Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2272
__attribute__((diagnose_if(!(expr), msg, "error"))) \
2273
JSON_HEDLEY_DIAGNOSTIC_POP
2274
# else
2275
# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2276
# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2277
# endif
2278
#else
2279
# define JSON_HEDLEY_REQUIRE(expr)
2280
# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2281
#endif
2282
2283
#if defined(JSON_HEDLEY_FLAGS)
2284
#undef JSON_HEDLEY_FLAGS
2285
#endif
2286
#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2287
#define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2288
#else
2289
#define JSON_HEDLEY_FLAGS
2290
#endif
2291
2292
#if defined(JSON_HEDLEY_FLAGS_CAST)
2293
#undef JSON_HEDLEY_FLAGS_CAST
2294
#endif
2295
#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2296
# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2297
JSON_HEDLEY_DIAGNOSTIC_PUSH \
2298
_Pragma("warning(disable:188)") \
2299
((T) (expr)); \
2300
JSON_HEDLEY_DIAGNOSTIC_POP \
2301
}))
2302
#else
2303
# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2304
#endif
2305
2306
#if defined(JSON_HEDLEY_EMPTY_BASES)
2307
#undef JSON_HEDLEY_EMPTY_BASES
2308
#endif
2309
#if \
2310
(JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2311
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2312
#define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2313
#else
2314
#define JSON_HEDLEY_EMPTY_BASES
2315
#endif
2316
2317
/* Remaining macros are deprecated. */
2318
2319
#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2320
#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2321
#endif
2322
#if defined(__clang__)
2323
#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2324
#else
2325
#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2326
#endif
2327
2328
#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2329
#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2330
#endif
2331
#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2332
2333
#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2334
#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2335
#endif
2336
#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2337
2338
#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2339
#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2340
#endif
2341
#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2342
2343
#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2344
#undef JSON_HEDLEY_CLANG_HAS_FEATURE
2345
#endif
2346
#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2347
2348
#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2349
#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2350
#endif
2351
#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2352
2353
#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2354
#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2355
#endif
2356
#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2357
2358
#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2359
#undef JSON_HEDLEY_CLANG_HAS_WARNING
2360
#endif
2361
#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2362
2363
#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2364
2365
2366
// This file contains all internal macro definitions (except those affecting ABI)
2367
// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2368
2369
// #include <nlohmann/detail/abi_macros.hpp>
2370
2371
2372
// exclude unsupported compilers
2373
#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2374
#if defined(__clang__)
2375
#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2376
#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2377
#endif
2378
#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2379
#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2380
#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2381
#endif
2382
#endif
2383
#endif
2384
2385
// C++ language standard detection
2386
// if the user manually specified the used c++ version this is skipped
2387
#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2388
#if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2389
#define JSON_HAS_CPP_20
2390
#define JSON_HAS_CPP_17
2391
#define JSON_HAS_CPP_14
2392
#elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2393
#define JSON_HAS_CPP_17
2394
#define JSON_HAS_CPP_14
2395
#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2396
#define JSON_HAS_CPP_14
2397
#endif
2398
// the cpp 11 flag is always specified because it is the minimal required version
2399
#define JSON_HAS_CPP_11
2400
#endif
2401
2402
#ifdef __has_include
2403
#if __has_include(<version>)
2404
#include <version>
2405
#endif
2406
#endif
2407
2408
#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2409
#ifdef JSON_HAS_CPP_17
2410
#if defined(__cpp_lib_filesystem)
2411
#define JSON_HAS_FILESYSTEM 1
2412
#elif defined(__cpp_lib_experimental_filesystem)
2413
#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2414
#elif !defined(__has_include)
2415
#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2416
#elif __has_include(<filesystem>)
2417
#define JSON_HAS_FILESYSTEM 1
2418
#elif __has_include(<experimental/filesystem>)
2419
#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2420
#endif
2421
2422
// std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2423
#if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2424
#undef JSON_HAS_FILESYSTEM
2425
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2426
#endif
2427
2428
// no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2429
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2430
#undef JSON_HAS_FILESYSTEM
2431
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2432
#endif
2433
2434
// no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2435
#if defined(__clang_major__) && __clang_major__ < 7
2436
#undef JSON_HAS_FILESYSTEM
2437
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2438
#endif
2439
2440
// no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2441
#if defined(_MSC_VER) && _MSC_VER < 1914
2442
#undef JSON_HAS_FILESYSTEM
2443
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2444
#endif
2445
2446
// no filesystem support before iOS 13
2447
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2448
#undef JSON_HAS_FILESYSTEM
2449
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2450
#endif
2451
2452
// no filesystem support before macOS Catalina
2453
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2454
#undef JSON_HAS_FILESYSTEM
2455
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2456
#endif
2457
#endif
2458
#endif
2459
2460
#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2461
#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2462
#endif
2463
2464
#ifndef JSON_HAS_FILESYSTEM
2465
#define JSON_HAS_FILESYSTEM 0
2466
#endif
2467
2468
#ifndef JSON_HAS_THREE_WAY_COMPARISON
2469
#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2470
&& defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2471
#define JSON_HAS_THREE_WAY_COMPARISON 1
2472
#else
2473
#define JSON_HAS_THREE_WAY_COMPARISON 0
2474
#endif
2475
#endif
2476
2477
#ifndef JSON_HAS_RANGES
2478
// ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
2479
#if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2480
#define JSON_HAS_RANGES 0
2481
#elif defined(__cpp_lib_ranges)
2482
#define JSON_HAS_RANGES 1
2483
#else
2484
#define JSON_HAS_RANGES 0
2485
#endif
2486
#endif
2487
2488
#ifndef JSON_HAS_STATIC_RTTI
2489
#if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2490
#define JSON_HAS_STATIC_RTTI 1
2491
#else
2492
#define JSON_HAS_STATIC_RTTI 0
2493
#endif
2494
#endif
2495
2496
#ifdef JSON_HAS_CPP_17
2497
#define JSON_INLINE_VARIABLE inline
2498
#else
2499
#define JSON_INLINE_VARIABLE
2500
#endif
2501
2502
#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2503
#define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2504
#else
2505
#define JSON_NO_UNIQUE_ADDRESS
2506
#endif
2507
2508
// disable documentation warnings on clang
2509
#if defined(__clang__)
2510
#pragma clang diagnostic push
2511
#pragma clang diagnostic ignored "-Wdocumentation"
2512
#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2513
#endif
2514
2515
// allow disabling exceptions
2516
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2517
#define JSON_THROW(exception) throw exception
2518
#define JSON_TRY try
2519
#define JSON_CATCH(exception) catch(exception)
2520
#define JSON_INTERNAL_CATCH(exception) catch(exception)
2521
#else
2522
#include <cstdlib>
2523
#define JSON_THROW(exception) std::abort()
2524
#define JSON_TRY if(true)
2525
#define JSON_CATCH(exception) if(false)
2526
#define JSON_INTERNAL_CATCH(exception) if(false)
2527
#endif
2528
2529
// override exception macros
2530
#if defined(JSON_THROW_USER)
2531
#undef JSON_THROW
2532
#define JSON_THROW JSON_THROW_USER
2533
#endif
2534
#if defined(JSON_TRY_USER)
2535
#undef JSON_TRY
2536
#define JSON_TRY JSON_TRY_USER
2537
#endif
2538
#if defined(JSON_CATCH_USER)
2539
#undef JSON_CATCH
2540
#define JSON_CATCH JSON_CATCH_USER
2541
#undef JSON_INTERNAL_CATCH
2542
#define JSON_INTERNAL_CATCH JSON_CATCH_USER
2543
#endif
2544
#if defined(JSON_INTERNAL_CATCH_USER)
2545
#undef JSON_INTERNAL_CATCH
2546
#define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2547
#endif
2548
2549
// allow overriding assert
2550
#if !defined(JSON_ASSERT)
2551
#include <cassert> // assert
2552
#define JSON_ASSERT(x) assert(x)
2553
#endif
2554
2555
// allow to access some private functions (needed by the test suite)
2556
#if defined(JSON_TESTS_PRIVATE)
2557
#define JSON_PRIVATE_UNLESS_TESTED public
2558
#else
2559
#define JSON_PRIVATE_UNLESS_TESTED private
2560
#endif
2561
2562
/*!
2563
@brief macro to briefly define a mapping between an enum and JSON
2564
@def NLOHMANN_JSON_SERIALIZE_ENUM
2565
@since version 3.4.0
2566
*/
2567
#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2568
template<typename BasicJsonType> \
2569
inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2570
{ \
2571
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2572
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2573
auto it = std::find_if(std::begin(m), std::end(m), \
2574
[e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2575
{ \
2576
return ej_pair.first == e; \
2577
}); \
2578
j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2579
} \
2580
template<typename BasicJsonType> \
2581
inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2582
{ \
2583
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2584
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2585
auto it = std::find_if(std::begin(m), std::end(m), \
2586
[&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2587
{ \
2588
return ej_pair.second == j; \
2589
}); \
2590
e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2591
}
2592
2593
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2594
// may be removed in the future once the class is split.
2595
2596
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2597
template<template<typename, typename, typename...> class ObjectType, \
2598
template<typename, typename...> class ArrayType, \
2599
class StringType, class BooleanType, class NumberIntegerType, \
2600
class NumberUnsignedType, class NumberFloatType, \
2601
template<typename> class AllocatorType, \
2602
template<typename, typename = void> class JSONSerializer, \
2603
class BinaryType, \
2604
class CustomBaseClass>
2605
2606
#define NLOHMANN_BASIC_JSON_TPL \
2607
basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2608
NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2609
AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2610
2611
// Macros to simplify conversion from/to types
2612
2613
#define NLOHMANN_JSON_EXPAND( x ) x
2614
#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
2615
#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2616
NLOHMANN_JSON_PASTE64, \
2617
NLOHMANN_JSON_PASTE63, \
2618
NLOHMANN_JSON_PASTE62, \
2619
NLOHMANN_JSON_PASTE61, \
2620
NLOHMANN_JSON_PASTE60, \
2621
NLOHMANN_JSON_PASTE59, \
2622
NLOHMANN_JSON_PASTE58, \
2623
NLOHMANN_JSON_PASTE57, \
2624
NLOHMANN_JSON_PASTE56, \
2625
NLOHMANN_JSON_PASTE55, \
2626
NLOHMANN_JSON_PASTE54, \
2627
NLOHMANN_JSON_PASTE53, \
2628
NLOHMANN_JSON_PASTE52, \
2629
NLOHMANN_JSON_PASTE51, \
2630
NLOHMANN_JSON_PASTE50, \
2631
NLOHMANN_JSON_PASTE49, \
2632
NLOHMANN_JSON_PASTE48, \
2633
NLOHMANN_JSON_PASTE47, \
2634
NLOHMANN_JSON_PASTE46, \
2635
NLOHMANN_JSON_PASTE45, \
2636
NLOHMANN_JSON_PASTE44, \
2637
NLOHMANN_JSON_PASTE43, \
2638
NLOHMANN_JSON_PASTE42, \
2639
NLOHMANN_JSON_PASTE41, \
2640
NLOHMANN_JSON_PASTE40, \
2641
NLOHMANN_JSON_PASTE39, \
2642
NLOHMANN_JSON_PASTE38, \
2643
NLOHMANN_JSON_PASTE37, \
2644
NLOHMANN_JSON_PASTE36, \
2645
NLOHMANN_JSON_PASTE35, \
2646
NLOHMANN_JSON_PASTE34, \
2647
NLOHMANN_JSON_PASTE33, \
2648
NLOHMANN_JSON_PASTE32, \
2649
NLOHMANN_JSON_PASTE31, \
2650
NLOHMANN_JSON_PASTE30, \
2651
NLOHMANN_JSON_PASTE29, \
2652
NLOHMANN_JSON_PASTE28, \
2653
NLOHMANN_JSON_PASTE27, \
2654
NLOHMANN_JSON_PASTE26, \
2655
NLOHMANN_JSON_PASTE25, \
2656
NLOHMANN_JSON_PASTE24, \
2657
NLOHMANN_JSON_PASTE23, \
2658
NLOHMANN_JSON_PASTE22, \
2659
NLOHMANN_JSON_PASTE21, \
2660
NLOHMANN_JSON_PASTE20, \
2661
NLOHMANN_JSON_PASTE19, \
2662
NLOHMANN_JSON_PASTE18, \
2663
NLOHMANN_JSON_PASTE17, \
2664
NLOHMANN_JSON_PASTE16, \
2665
NLOHMANN_JSON_PASTE15, \
2666
NLOHMANN_JSON_PASTE14, \
2667
NLOHMANN_JSON_PASTE13, \
2668
NLOHMANN_JSON_PASTE12, \
2669
NLOHMANN_JSON_PASTE11, \
2670
NLOHMANN_JSON_PASTE10, \
2671
NLOHMANN_JSON_PASTE9, \
2672
NLOHMANN_JSON_PASTE8, \
2673
NLOHMANN_JSON_PASTE7, \
2674
NLOHMANN_JSON_PASTE6, \
2675
NLOHMANN_JSON_PASTE5, \
2676
NLOHMANN_JSON_PASTE4, \
2677
NLOHMANN_JSON_PASTE3, \
2678
NLOHMANN_JSON_PASTE2, \
2679
NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2680
#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2681
#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2682
#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2683
#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2684
#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2685
#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)
2686
#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)
2687
#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)
2688
#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)
2689
#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)
2690
#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)
2691
#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)
2692
#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)
2693
#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)
2694
#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)
2695
#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)
2696
#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)
2697
#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)
2698
#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)
2699
#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)
2700
#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)
2701
#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)
2702
#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)
2703
#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)
2704
#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)
2705
#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)
2706
#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)
2707
#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)
2708
#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)
2709
#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)
2710
#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)
2711
#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)
2712
#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)
2713
#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)
2714
#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)
2715
#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)
2716
#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)
2717
#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)
2718
#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)
2719
#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)
2720
#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)
2721
#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)
2722
#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)
2723
#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)
2724
#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)
2725
#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)
2726
#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)
2727
#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)
2728
#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)
2729
#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)
2730
#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)
2731
#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)
2732
#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)
2733
#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)
2734
#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)
2735
#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)
2736
#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)
2737
#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)
2738
#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)
2739
#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)
2740
#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)
2741
#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)
2742
#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)
2743
2744
#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2745
#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2746
#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
2747
2748
/*!
2749
@brief macro
2750
@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
2751
@since version 3.9.0
2752
*/
2753
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2754
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__)) } \
2755
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__)) }
2756
2757
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2758
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__)) } \
2759
friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2760
2761
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2762
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__)) }
2763
2764
/*!
2765
@brief macro
2766
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
2767
@since version 3.9.0
2768
*/
2769
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2770
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__)) } \
2771
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__)) }
2772
2773
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2774
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__)) }
2775
2776
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2777
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__)) } \
2778
inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2779
2780
// inspired from https://stackoverflow.com/a/26745591
2781
// allows to call any std function as if (e.g. with begin):
2782
// using std::begin; begin(x);
2783
//
2784
// it allows using the detected idiom to retrieve the return type
2785
// of such an expression
2786
#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2787
namespace detail { \
2788
using std::std_name; \
2789
\
2790
template<typename... T> \
2791
using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2792
} \
2793
\
2794
namespace detail2 { \
2795
struct std_name##_tag \
2796
{ \
2797
}; \
2798
\
2799
template<typename... T> \
2800
std_name##_tag std_name(T&&...); \
2801
\
2802
template<typename... T> \
2803
using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2804
\
2805
template<typename... T> \
2806
struct would_call_std_##std_name \
2807
{ \
2808
static constexpr auto const value = ::nlohmann::detail:: \
2809
is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2810
}; \
2811
} /* namespace detail2 */ \
2812
\
2813
template<typename... T> \
2814
struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2815
{ \
2816
}
2817
2818
#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2819
#define JSON_USE_IMPLICIT_CONVERSIONS 1
2820
#endif
2821
2822
#if JSON_USE_IMPLICIT_CONVERSIONS
2823
#define JSON_EXPLICIT
2824
#else
2825
#define JSON_EXPLICIT explicit
2826
#endif
2827
2828
#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2829
#define JSON_DISABLE_ENUM_SERIALIZATION 0
2830
#endif
2831
2832
#ifndef JSON_USE_GLOBAL_UDLS
2833
#define JSON_USE_GLOBAL_UDLS 1
2834
#endif
2835
2836
#if JSON_HAS_THREE_WAY_COMPARISON
2837
#include <compare> // partial_ordering
2838
#endif
2839
2840
NLOHMANN_JSON_NAMESPACE_BEGIN
2841
namespace detail
2842
{
2843
2844
///////////////////////////
2845
// JSON type enumeration //
2846
///////////////////////////
2847
2848
/*!
2849
@brief the JSON type enumeration
2850
2851
This enumeration collects the different JSON types. It is internally used to
2852
distinguish the stored values, and the functions @ref basic_json::is_null(),
2853
@ref basic_json::is_object(), @ref basic_json::is_array(),
2854
@ref basic_json::is_string(), @ref basic_json::is_boolean(),
2855
@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
2856
@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
2857
@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
2858
@ref basic_json::is_structured() rely on it.
2859
2860
@note There are three enumeration entries (number_integer, number_unsigned, and
2861
number_float), because the library distinguishes these three types for numbers:
2862
@ref basic_json::number_unsigned_t is used for unsigned integers,
2863
@ref basic_json::number_integer_t is used for signed integers, and
2864
@ref basic_json::number_float_t is used for floating-point numbers or to
2865
approximate integers which do not fit in the limits of their respective type.
2866
2867
@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
2868
value with the default value for a given type
2869
2870
@since version 1.0.0
2871
*/
2872
enum class value_t : std::uint8_t
2873
{
2874
null, ///< null value
2875
object, ///< object (unordered set of name/value pairs)
2876
array, ///< array (ordered collection of values)
2877
string, ///< string value
2878
boolean, ///< boolean value
2879
number_integer, ///< number value (signed integer)
2880
number_unsigned, ///< number value (unsigned integer)
2881
number_float, ///< number value (floating-point)
2882
binary, ///< binary array (ordered collection of bytes)
2883
discarded ///< discarded by the parser callback function
2884
};
2885
2886
/*!
2887
@brief comparison operator for JSON types
2888
2889
Returns an ordering that is similar to Python:
2890
- order: null < boolean < number < object < array < string < binary
2891
- furthermore, each type is not smaller than itself
2892
- discarded values are not comparable
2893
- binary is represented as a b"" string in python and directly comparable to a
2894
string; however, making a binary array directly comparable with a string would
2895
be surprising behavior in a JSON file.
2896
2897
@since version 1.0.0
2898
*/
2899
#if JSON_HAS_THREE_WAY_COMPARISON
2900
inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
2901
#else
2902
inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2903
#endif
2904
{
2905
static constexpr std::array<std::uint8_t, 9> order = {{
2906
0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
2907
1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
2908
6 /* binary */
2909
}
2910
};
2911
2912
const auto l_index = static_cast<std::size_t>(lhs);
2913
const auto r_index = static_cast<std::size_t>(rhs);
2914
#if JSON_HAS_THREE_WAY_COMPARISON
2915
if (l_index < order.size() && r_index < order.size())
2916
{
2917
return order[l_index] <=> order[r_index]; // *NOPAD*
2918
}
2919
return std::partial_ordering::unordered;
2920
#else
2921
return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
2922
#endif
2923
}
2924
2925
// GCC selects the built-in operator< over an operator rewritten from
2926
// a user-defined spaceship operator
2927
// Clang, MSVC, and ICC select the rewritten candidate
2928
// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
2929
#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
2930
inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2931
{
2932
return std::is_lt(lhs <=> rhs); // *NOPAD*
2933
}
2934
#endif
2935
2936
} // namespace detail
2937
NLOHMANN_JSON_NAMESPACE_END
2938
2939
// #include <nlohmann/detail/string_escape.hpp>
2940
// __ _____ _____ _____
2941
// __| | __| | | | JSON for Modern C++
2942
// | | |__ | | | | | | version 3.11.3
2943
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
2944
//
2945
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
2946
// SPDX-License-Identifier: MIT
2947
2948
2949
2950
// #include <nlohmann/detail/abi_macros.hpp>
2951
2952
2953
NLOHMANN_JSON_NAMESPACE_BEGIN
2954
namespace detail
2955
{
2956
2957
/*!
2958
@brief replace all occurrences of a substring by another string
2959
2960
@param[in,out] s the string to manipulate; changed so that all
2961
occurrences of @a f are replaced with @a t
2962
@param[in] f the substring to replace with @a t
2963
@param[in] t the string to replace @a f
2964
2965
@pre The search string @a f must not be empty. **This precondition is
2966
enforced with an assertion.**
2967
2968
@since version 2.0.0
2969
*/
2970
template<typename StringType>
2971
inline void replace_substring(StringType& s, const StringType& f,
2972
const StringType& t)
2973
{
2974
JSON_ASSERT(!f.empty());
2975
for (auto pos = s.find(f); // find first occurrence of f
2976
pos != StringType::npos; // make sure f was found
2977
s.replace(pos, f.size(), t), // replace with t, and
2978
pos = s.find(f, pos + t.size())) // find next occurrence of f
2979
{}
2980
}
2981
2982
/*!
2983
* @brief string escaping as described in RFC 6901 (Sect. 4)
2984
* @param[in] s string to escape
2985
* @return escaped string
2986
*
2987
* Note the order of escaping "~" to "~0" and "/" to "~1" is important.
2988
*/
2989
template<typename StringType>
2990
inline StringType escape(StringType s)
2991
{
2992
replace_substring(s, StringType{"~"}, StringType{"~0"});
2993
replace_substring(s, StringType{"/"}, StringType{"~1"});
2994
return s;
2995
}
2996
2997
/*!
2998
* @brief string unescaping as described in RFC 6901 (Sect. 4)
2999
* @param[in] s string to unescape
3000
* @return unescaped string
3001
*
3002
* Note the order of escaping "~1" to "/" and "~0" to "~" is important.
3003
*/
3004
template<typename StringType>
3005
static void unescape(StringType& s)
3006
{
3007
replace_substring(s, StringType{"~1"}, StringType{"/"});
3008
replace_substring(s, StringType{"~0"}, StringType{"~"});
3009
}
3010
3011
} // namespace detail
3012
NLOHMANN_JSON_NAMESPACE_END
3013
3014
// #include <nlohmann/detail/input/position_t.hpp>
3015
// __ _____ _____ _____
3016
// __| | __| | | | JSON for Modern C++
3017
// | | |__ | | | | | | version 3.11.3
3018
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3019
//
3020
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3021
// SPDX-License-Identifier: MIT
3022
3023
3024
3025
#include <cstddef> // size_t
3026
3027
// #include <nlohmann/detail/abi_macros.hpp>
3028
3029
3030
NLOHMANN_JSON_NAMESPACE_BEGIN
3031
namespace detail
3032
{
3033
3034
/// struct to capture the start position of the current token
3035
struct position_t
3036
{
3037
/// the total number of characters read
3038
std::size_t chars_read_total = 0;
3039
/// the number of characters read in the current line
3040
std::size_t chars_read_current_line = 0;
3041
/// the number of lines read
3042
std::size_t lines_read = 0;
3043
3044
/// conversion to size_t to preserve SAX interface
3045
constexpr operator size_t() const
3046
{
3047
return chars_read_total;
3048
}
3049
};
3050
3051
} // namespace detail
3052
NLOHMANN_JSON_NAMESPACE_END
3053
3054
// #include <nlohmann/detail/macro_scope.hpp>
3055
3056
// #include <nlohmann/detail/meta/cpp_future.hpp>
3057
// __ _____ _____ _____
3058
// __| | __| | | | JSON for Modern C++
3059
// | | |__ | | | | | | version 3.11.3
3060
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3061
//
3062
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3063
// SPDX-FileCopyrightText: 2018 The Abseil Authors
3064
// SPDX-License-Identifier: MIT
3065
3066
3067
3068
#include <array> // array
3069
#include <cstddef> // size_t
3070
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3071
#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3072
3073
// #include <nlohmann/detail/macro_scope.hpp>
3074
3075
3076
NLOHMANN_JSON_NAMESPACE_BEGIN
3077
namespace detail
3078
{
3079
3080
template<typename T>
3081
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3082
3083
#ifdef JSON_HAS_CPP_14
3084
3085
// the following utilities are natively available in C++14
3086
using std::enable_if_t;
3087
using std::index_sequence;
3088
using std::make_index_sequence;
3089
using std::index_sequence_for;
3090
3091
#else
3092
3093
// alias templates to reduce boilerplate
3094
template<bool B, typename T = void>
3095
using enable_if_t = typename std::enable_if<B, T>::type;
3096
3097
// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3098
// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3099
3100
//// START OF CODE FROM GOOGLE ABSEIL
3101
3102
// integer_sequence
3103
//
3104
// Class template representing a compile-time integer sequence. An instantiation
3105
// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3106
// type through its template arguments (which is a common need when
3107
// working with C++11 variadic templates). `absl::integer_sequence` is designed
3108
// to be a drop-in replacement for C++14's `std::integer_sequence`.
3109
//
3110
// Example:
3111
//
3112
// template< class T, T... Ints >
3113
// void user_function(integer_sequence<T, Ints...>);
3114
//
3115
// int main()
3116
// {
3117
// // user_function's `T` will be deduced to `int` and `Ints...`
3118
// // will be deduced to `0, 1, 2, 3, 4`.
3119
// user_function(make_integer_sequence<int, 5>());
3120
// }
3121
template <typename T, T... Ints>
3122
struct integer_sequence
3123
{
3124
using value_type = T;
3125
static constexpr std::size_t size() noexcept
3126
{
3127
return sizeof...(Ints);
3128
}
3129
};
3130
3131
// index_sequence
3132
//
3133
// A helper template for an `integer_sequence` of `size_t`,
3134
// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3135
// `std::index_sequence`.
3136
template <size_t... Ints>
3137
using index_sequence = integer_sequence<size_t, Ints...>;
3138
3139
namespace utility_internal
3140
{
3141
3142
template <typename Seq, size_t SeqSize, size_t Rem>
3143
struct Extend;
3144
3145
// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3146
template <typename T, T... Ints, size_t SeqSize>
3147
struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3148
{
3149
using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3150
};
3151
3152
template <typename T, T... Ints, size_t SeqSize>
3153
struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3154
{
3155
using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3156
};
3157
3158
// Recursion helper for 'make_integer_sequence<T, N>'.
3159
// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3160
template <typename T, size_t N>
3161
struct Gen
3162
{
3163
using type =
3164
typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3165
};
3166
3167
template <typename T>
3168
struct Gen<T, 0>
3169
{
3170
using type = integer_sequence<T>;
3171
};
3172
3173
} // namespace utility_internal
3174
3175
// Compile-time sequences of integers
3176
3177
// make_integer_sequence
3178
//
3179
// This template alias is equivalent to
3180
// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3181
// replacement for C++14's `std::make_integer_sequence`.
3182
template <typename T, T N>
3183
using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
3184
3185
// make_index_sequence
3186
//
3187
// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3188
// and is designed to be a drop-in replacement for C++14's
3189
// `std::make_index_sequence`.
3190
template <size_t N>
3191
using make_index_sequence = make_integer_sequence<size_t, N>;
3192
3193
// index_sequence_for
3194
//
3195
// Converts a typename pack into an index sequence of the same length, and
3196
// is designed to be a drop-in replacement for C++14's
3197
// `std::index_sequence_for()`
3198
template <typename... Ts>
3199
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
3200
3201
//// END OF CODE FROM GOOGLE ABSEIL
3202
3203
#endif
3204
3205
// dispatch utility (taken from ranges-v3)
3206
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3207
template<> struct priority_tag<0> {};
3208
3209
// taken from ranges-v3
3210
template<typename T>
3211
struct static_const
3212
{
3213
static JSON_INLINE_VARIABLE constexpr T value{};
3214
};
3215
3216
#ifndef JSON_HAS_CPP_17
3217
template<typename T>
3218
constexpr T static_const<T>::value;
3219
#endif
3220
3221
template<typename T, typename... Args>
3222
inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3223
{
3224
return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3225
}
3226
3227
} // namespace detail
3228
NLOHMANN_JSON_NAMESPACE_END
3229
3230
// #include <nlohmann/detail/meta/type_traits.hpp>
3231
// __ _____ _____ _____
3232
// __| | __| | | | JSON for Modern C++
3233
// | | |__ | | | | | | version 3.11.3
3234
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3235
//
3236
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3237
// SPDX-License-Identifier: MIT
3238
3239
3240
3241
#include <limits> // numeric_limits
3242
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3243
#include <utility> // declval
3244
#include <tuple> // tuple
3245
#include <string> // char_traits
3246
3247
// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3248
// __ _____ _____ _____
3249
// __| | __| | | | JSON for Modern C++
3250
// | | |__ | | | | | | version 3.11.3
3251
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3252
//
3253
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3254
// SPDX-License-Identifier: MIT
3255
3256
3257
3258
#include <iterator> // random_access_iterator_tag
3259
3260
// #include <nlohmann/detail/abi_macros.hpp>
3261
3262
// #include <nlohmann/detail/meta/void_t.hpp>
3263
3264
// #include <nlohmann/detail/meta/cpp_future.hpp>
3265
3266
3267
NLOHMANN_JSON_NAMESPACE_BEGIN
3268
namespace detail
3269
{
3270
3271
template<typename It, typename = void>
3272
struct iterator_types {};
3273
3274
template<typename It>
3275
struct iterator_types <
3276
It,
3277
void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3278
typename It::reference, typename It::iterator_category >>
3279
{
3280
using difference_type = typename It::difference_type;
3281
using value_type = typename It::value_type;
3282
using pointer = typename It::pointer;
3283
using reference = typename It::reference;
3284
using iterator_category = typename It::iterator_category;
3285
};
3286
3287
// This is required as some compilers implement std::iterator_traits in a way that
3288
// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3289
template<typename T, typename = void>
3290
struct iterator_traits
3291
{
3292
};
3293
3294
template<typename T>
3295
struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3296
: iterator_types<T>
3297
{
3298
};
3299
3300
template<typename T>
3301
struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
3302
{
3303
using iterator_category = std::random_access_iterator_tag;
3304
using value_type = T;
3305
using difference_type = ptrdiff_t;
3306
using pointer = T*;
3307
using reference = T&;
3308
};
3309
3310
} // namespace detail
3311
NLOHMANN_JSON_NAMESPACE_END
3312
3313
// #include <nlohmann/detail/macro_scope.hpp>
3314
3315
// #include <nlohmann/detail/meta/call_std/begin.hpp>
3316
// __ _____ _____ _____
3317
// __| | __| | | | JSON for Modern C++
3318
// | | |__ | | | | | | version 3.11.3
3319
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3320
//
3321
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3322
// SPDX-License-Identifier: MIT
3323
3324
3325
3326
// #include <nlohmann/detail/macro_scope.hpp>
3327
3328
3329
NLOHMANN_JSON_NAMESPACE_BEGIN
3330
3331
NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3332
3333
NLOHMANN_JSON_NAMESPACE_END
3334
3335
// #include <nlohmann/detail/meta/call_std/end.hpp>
3336
// __ _____ _____ _____
3337
// __| | __| | | | JSON for Modern C++
3338
// | | |__ | | | | | | version 3.11.3
3339
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3340
//
3341
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3342
// SPDX-License-Identifier: MIT
3343
3344
3345
3346
// #include <nlohmann/detail/macro_scope.hpp>
3347
3348
3349
NLOHMANN_JSON_NAMESPACE_BEGIN
3350
3351
NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3352
3353
NLOHMANN_JSON_NAMESPACE_END
3354
3355
// #include <nlohmann/detail/meta/cpp_future.hpp>
3356
3357
// #include <nlohmann/detail/meta/detected.hpp>
3358
3359
// #include <nlohmann/json_fwd.hpp>
3360
// __ _____ _____ _____
3361
// __| | __| | | | JSON for Modern C++
3362
// | | |__ | | | | | | version 3.11.3
3363
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3364
//
3365
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3366
// SPDX-License-Identifier: MIT
3367
3368
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3369
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3370
3371
#include <cstdint> // int64_t, uint64_t
3372
#include <map> // map
3373
#include <memory> // allocator
3374
#include <string> // string
3375
#include <vector> // vector
3376
3377
// #include <nlohmann/detail/abi_macros.hpp>
3378
3379
3380
/*!
3381
@brief namespace for Niels Lohmann
3382
@see https://github.com/nlohmann
3383
@since version 1.0.0
3384
*/
3385
NLOHMANN_JSON_NAMESPACE_BEGIN
3386
3387
/*!
3388
@brief default JSONSerializer template argument
3389
3390
This serializer ignores the template arguments and uses ADL
3391
([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
3392
for serialization.
3393
*/
3394
template<typename T = void, typename SFINAE = void>
3395
struct adl_serializer;
3396
3397
/// a class to store JSON values
3398
/// @sa https://json.nlohmann.me/api/basic_json/
3399
template<template<typename U, typename V, typename... Args> class ObjectType =
3400
std::map,
3401
template<typename U, typename... Args> class ArrayType = std::vector,
3402
class StringType = std::string, class BooleanType = bool,
3403
class NumberIntegerType = std::int64_t,
3404
class NumberUnsignedType = std::uint64_t,
3405
class NumberFloatType = double,
3406
template<typename U> class AllocatorType = std::allocator,
3407
template<typename T, typename SFINAE = void> class JSONSerializer =
3408
adl_serializer,
3409
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3410
class CustomBaseClass = void>
3411
class basic_json;
3412
3413
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
3414
/// @sa https://json.nlohmann.me/api/json_pointer/
3415
template<typename RefStringType>
3416
class json_pointer;
3417
3418
/*!
3419
@brief default specialization
3420
@sa https://json.nlohmann.me/api/json/
3421
*/
3422
using json = basic_json<>;
3423
3424
/// @brief a minimal map-like container that preserves insertion order
3425
/// @sa https://json.nlohmann.me/api/ordered_map/
3426
template<class Key, class T, class IgnoredLess, class Allocator>
3427
struct ordered_map;
3428
3429
/// @brief specialization that maintains the insertion order of object keys
3430
/// @sa https://json.nlohmann.me/api/ordered_json/
3431
using ordered_json = basic_json<nlohmann::ordered_map>;
3432
3433
NLOHMANN_JSON_NAMESPACE_END
3434
3435
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3436
3437
3438
NLOHMANN_JSON_NAMESPACE_BEGIN
3439
/*!
3440
@brief detail namespace with internal helper functions
3441
3442
This namespace collects functions that should not be exposed,
3443
implementations of some @ref basic_json methods, and meta-programming helpers.
3444
3445
@since version 2.1.0
3446
*/
3447
namespace detail
3448
{
3449
3450
/////////////
3451
// helpers //
3452
/////////////
3453
3454
// Note to maintainers:
3455
//
3456
// Every trait in this file expects a non CV-qualified type.
3457
// The only exceptions are in the 'aliases for detected' section
3458
// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3459
//
3460
// In this case, T has to be properly CV-qualified to constraint the function arguments
3461
// (e.g. to_json(BasicJsonType&, const T&))
3462
3463
template<typename> struct is_basic_json : std::false_type {};
3464
3465
NLOHMANN_BASIC_JSON_TPL_DECLARATION
3466
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3467
3468
// used by exceptions create() member functions
3469
// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
3470
// false_type otherwise
3471
template<typename BasicJsonContext>
3472
struct is_basic_json_context :
3473
std::integral_constant < bool,
3474
is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3475
|| std::is_same<BasicJsonContext, std::nullptr_t>::value >
3476
{};
3477
3478
//////////////////////
3479
// json_ref helpers //
3480
//////////////////////
3481
3482
template<typename>
3483
class json_ref;
3484
3485
template<typename>
3486
struct is_json_ref : std::false_type {};
3487
3488
template<typename T>
3489
struct is_json_ref<json_ref<T>> : std::true_type {};
3490
3491
//////////////////////////
3492
// aliases for detected //
3493
//////////////////////////
3494
3495
template<typename T>
3496
using mapped_type_t = typename T::mapped_type;
3497
3498
template<typename T>
3499
using key_type_t = typename T::key_type;
3500
3501
template<typename T>
3502
using value_type_t = typename T::value_type;
3503
3504
template<typename T>
3505
using difference_type_t = typename T::difference_type;
3506
3507
template<typename T>
3508
using pointer_t = typename T::pointer;
3509
3510
template<typename T>
3511
using reference_t = typename T::reference;
3512
3513
template<typename T>
3514
using iterator_category_t = typename T::iterator_category;
3515
3516
template<typename T, typename... Args>
3517
using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3518
3519
template<typename T, typename... Args>
3520
using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3521
3522
template<typename T, typename U>
3523
using get_template_function = decltype(std::declval<T>().template get<U>());
3524
3525
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3526
template<typename BasicJsonType, typename T, typename = void>
3527
struct has_from_json : std::false_type {};
3528
3529
// trait checking if j.get<T> is valid
3530
// use this trait instead of std::is_constructible or std::is_convertible,
3531
// both rely on, or make use of implicit conversions, and thus fail when T
3532
// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3533
template <typename BasicJsonType, typename T>
3534
struct is_getable
3535
{
3536
static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3537
};
3538
3539
template<typename BasicJsonType, typename T>
3540
struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3541
{
3542
using serializer = typename BasicJsonType::template json_serializer<T, void>;
3543
3544
static constexpr bool value =
3545
is_detected_exact<void, from_json_function, serializer,
3546
const BasicJsonType&, T&>::value;
3547
};
3548
3549
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3550
// this overload is used for non-default-constructible user-defined-types
3551
template<typename BasicJsonType, typename T, typename = void>
3552
struct has_non_default_from_json : std::false_type {};
3553
3554
template<typename BasicJsonType, typename T>
3555
struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3556
{
3557
using serializer = typename BasicJsonType::template json_serializer<T, void>;
3558
3559
static constexpr bool value =
3560
is_detected_exact<T, from_json_function, serializer,
3561
const BasicJsonType&>::value;
3562
};
3563
3564
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3565
// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3566
template<typename BasicJsonType, typename T, typename = void>
3567
struct has_to_json : std::false_type {};
3568
3569
template<typename BasicJsonType, typename T>
3570
struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3571
{
3572
using serializer = typename BasicJsonType::template json_serializer<T, void>;
3573
3574
static constexpr bool value =
3575
is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3576
T>::value;
3577
};
3578
3579
template<typename T>
3580
using detect_key_compare = typename T::key_compare;
3581
3582
template<typename T>
3583
struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3584
3585
// obtains the actual object key comparator
3586
template<typename BasicJsonType>
3587
struct actual_object_comparator
3588
{
3589
using object_t = typename BasicJsonType::object_t;
3590
using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3591
using type = typename std::conditional < has_key_compare<object_t>::value,
3592
typename object_t::key_compare, object_comparator_t>::type;
3593
};
3594
3595
template<typename BasicJsonType>
3596
using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
3597
3598
/////////////////
3599
// char_traits //
3600
/////////////////
3601
3602
// Primary template of char_traits calls std char_traits
3603
template<typename T>
3604
struct char_traits : std::char_traits<T>
3605
{};
3606
3607
// Explicitly define char traits for unsigned char since it is not standard
3608
template<>
3609
struct char_traits<unsigned char> : std::char_traits<char>
3610
{
3611
using char_type = unsigned char;
3612
using int_type = uint64_t;
3613
3614
// Redefine to_int_type function
3615
static int_type to_int_type(char_type c) noexcept
3616
{
3617
return static_cast<int_type>(c);
3618
}
3619
3620
static char_type to_char_type(int_type i) noexcept
3621
{
3622
return static_cast<char_type>(i);
3623
}
3624
3625
static constexpr int_type eof() noexcept
3626
{
3627
return static_cast<int_type>(EOF);
3628
}
3629
};
3630
3631
// Explicitly define char traits for signed char since it is not standard
3632
template<>
3633
struct char_traits<signed char> : std::char_traits<char>
3634
{
3635
using char_type = signed char;
3636
using int_type = uint64_t;
3637
3638
// Redefine to_int_type function
3639
static int_type to_int_type(char_type c) noexcept
3640
{
3641
return static_cast<int_type>(c);
3642
}
3643
3644
static char_type to_char_type(int_type i) noexcept
3645
{
3646
return static_cast<char_type>(i);
3647
}
3648
3649
static constexpr int_type eof() noexcept
3650
{
3651
return static_cast<int_type>(EOF);
3652
}
3653
};
3654
3655
///////////////////
3656
// is_ functions //
3657
///////////////////
3658
3659
// https://en.cppreference.com/w/cpp/types/conjunction
3660
template<class...> struct conjunction : std::true_type { };
3661
template<class B> struct conjunction<B> : B { };
3662
template<class B, class... Bn>
3663
struct conjunction<B, Bn...>
3664
: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3665
3666
// https://en.cppreference.com/w/cpp/types/negation
3667
template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3668
3669
// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3670
// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3671
// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3672
template <typename T>
3673
struct is_default_constructible : std::is_default_constructible<T> {};
3674
3675
template <typename T1, typename T2>
3676
struct is_default_constructible<std::pair<T1, T2>>
3677
: conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3678
3679
template <typename T1, typename T2>
3680
struct is_default_constructible<const std::pair<T1, T2>>
3681
: conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3682
3683
template <typename... Ts>
3684
struct is_default_constructible<std::tuple<Ts...>>
3685
: conjunction<is_default_constructible<Ts>...> {};
3686
3687
template <typename... Ts>
3688
struct is_default_constructible<const std::tuple<Ts...>>
3689
: conjunction<is_default_constructible<Ts>...> {};
3690
3691
template <typename T, typename... Args>
3692
struct is_constructible : std::is_constructible<T, Args...> {};
3693
3694
template <typename T1, typename T2>
3695
struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3696
3697
template <typename T1, typename T2>
3698
struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3699
3700
template <typename... Ts>
3701
struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3702
3703
template <typename... Ts>
3704
struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3705
3706
template<typename T, typename = void>
3707
struct is_iterator_traits : std::false_type {};
3708
3709
template<typename T>
3710
struct is_iterator_traits<iterator_traits<T>>
3711
{
3712
private:
3713
using traits = iterator_traits<T>;
3714
3715
public:
3716
static constexpr auto value =
3717
is_detected<value_type_t, traits>::value &&
3718
is_detected<difference_type_t, traits>::value &&
3719
is_detected<pointer_t, traits>::value &&
3720
is_detected<iterator_category_t, traits>::value &&
3721
is_detected<reference_t, traits>::value;
3722
};
3723
3724
template<typename T>
3725
struct is_range
3726
{
3727
private:
3728
using t_ref = typename std::add_lvalue_reference<T>::type;
3729
3730
using iterator = detected_t<result_of_begin, t_ref>;
3731
using sentinel = detected_t<result_of_end, t_ref>;
3732
3733
// to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3734
// and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3735
// but reimplementing these would be too much work, as a lot of other concepts are used underneath
3736
static constexpr auto is_iterator_begin =
3737
is_iterator_traits<iterator_traits<iterator>>::value;
3738
3739
public:
3740
static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3741
};
3742
3743
template<typename R>
3744
using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3745
3746
template<typename T>
3747
using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3748
3749
// The following implementation of is_complete_type is taken from
3750
// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3751
// and is written by Xiang Fan who agreed to using it in this library.
3752
3753
template<typename T, typename = void>
3754
struct is_complete_type : std::false_type {};
3755
3756
template<typename T>
3757
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3758
3759
template<typename BasicJsonType, typename CompatibleObjectType,
3760
typename = void>
3761
struct is_compatible_object_type_impl : std::false_type {};
3762
3763
template<typename BasicJsonType, typename CompatibleObjectType>
3764
struct is_compatible_object_type_impl <
3765
BasicJsonType, CompatibleObjectType,
3766
enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3767
is_detected<key_type_t, CompatibleObjectType>::value >>
3768
{
3769
using object_t = typename BasicJsonType::object_t;
3770
3771
// macOS's is_constructible does not play well with nonesuch...
3772
static constexpr bool value =
3773
is_constructible<typename object_t::key_type,
3774
typename CompatibleObjectType::key_type>::value &&
3775
is_constructible<typename object_t::mapped_type,
3776
typename CompatibleObjectType::mapped_type>::value;
3777
};
3778
3779
template<typename BasicJsonType, typename CompatibleObjectType>
3780
struct is_compatible_object_type
3781
: is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3782
3783
template<typename BasicJsonType, typename ConstructibleObjectType,
3784
typename = void>
3785
struct is_constructible_object_type_impl : std::false_type {};
3786
3787
template<typename BasicJsonType, typename ConstructibleObjectType>
3788
struct is_constructible_object_type_impl <
3789
BasicJsonType, ConstructibleObjectType,
3790
enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3791
is_detected<key_type_t, ConstructibleObjectType>::value >>
3792
{
3793
using object_t = typename BasicJsonType::object_t;
3794
3795
static constexpr bool value =
3796
(is_default_constructible<ConstructibleObjectType>::value &&
3797
(std::is_move_assignable<ConstructibleObjectType>::value ||
3798
std::is_copy_assignable<ConstructibleObjectType>::value) &&
3799
(is_constructible<typename ConstructibleObjectType::key_type,
3800
typename object_t::key_type>::value &&
3801
std::is_same <
3802
typename object_t::mapped_type,
3803
typename ConstructibleObjectType::mapped_type >::value)) ||
3804
(has_from_json<BasicJsonType,
3805
typename ConstructibleObjectType::mapped_type>::value ||
3806
has_non_default_from_json <
3807
BasicJsonType,
3808
typename ConstructibleObjectType::mapped_type >::value);
3809
};
3810
3811
template<typename BasicJsonType, typename ConstructibleObjectType>
3812
struct is_constructible_object_type
3813
: is_constructible_object_type_impl<BasicJsonType,
3814
ConstructibleObjectType> {};
3815
3816
template<typename BasicJsonType, typename CompatibleStringType>
3817
struct is_compatible_string_type
3818
{
3819
static constexpr auto value =
3820
is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
3821
};
3822
3823
template<typename BasicJsonType, typename ConstructibleStringType>
3824
struct is_constructible_string_type
3825
{
3826
// launder type through decltype() to fix compilation failure on ICPC
3827
#ifdef __INTEL_COMPILER
3828
using laundered_type = decltype(std::declval<ConstructibleStringType>());
3829
#else
3830
using laundered_type = ConstructibleStringType;
3831
#endif
3832
3833
static constexpr auto value =
3834
conjunction <
3835
is_constructible<laundered_type, typename BasicJsonType::string_t>,
3836
is_detected_exact<typename BasicJsonType::string_t::value_type,
3837
value_type_t, laundered_type >>::value;
3838
};
3839
3840
template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3841
struct is_compatible_array_type_impl : std::false_type {};
3842
3843
template<typename BasicJsonType, typename CompatibleArrayType>
3844
struct is_compatible_array_type_impl <
3845
BasicJsonType, CompatibleArrayType,
3846
enable_if_t <
3847
is_detected<iterator_t, CompatibleArrayType>::value&&
3848
is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3849
// special case for types like std::filesystem::path whose iterator's value_type are themselves
3850
// c.f. https://github.com/nlohmann/json/pull/3073
3851
!std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3852
{
3853
static constexpr bool value =
3854
is_constructible<BasicJsonType,
3855
range_value_t<CompatibleArrayType>>::value;
3856
};
3857
3858
template<typename BasicJsonType, typename CompatibleArrayType>
3859
struct is_compatible_array_type
3860
: is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3861
3862
template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3863
struct is_constructible_array_type_impl : std::false_type {};
3864
3865
template<typename BasicJsonType, typename ConstructibleArrayType>
3866
struct is_constructible_array_type_impl <
3867
BasicJsonType, ConstructibleArrayType,
3868
enable_if_t<std::is_same<ConstructibleArrayType,
3869
typename BasicJsonType::value_type>::value >>
3870
: std::true_type {};
3871
3872
template<typename BasicJsonType, typename ConstructibleArrayType>
3873
struct is_constructible_array_type_impl <
3874
BasicJsonType, ConstructibleArrayType,
3875
enable_if_t < !std::is_same<ConstructibleArrayType,
3876
typename BasicJsonType::value_type>::value&&
3877
!is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3878
is_default_constructible<ConstructibleArrayType>::value&&
3879
(std::is_move_assignable<ConstructibleArrayType>::value ||
3880
std::is_copy_assignable<ConstructibleArrayType>::value)&&
3881
is_detected<iterator_t, ConstructibleArrayType>::value&&
3882
is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3883
is_detected<range_value_t, ConstructibleArrayType>::value&&
3884
// special case for types like std::filesystem::path whose iterator's value_type are themselves
3885
// c.f. https://github.com/nlohmann/json/pull/3073
3886
!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3887
is_complete_type <
3888
detected_t<range_value_t, ConstructibleArrayType >>::value >>
3889
{
3890
using value_type = range_value_t<ConstructibleArrayType>;
3891
3892
static constexpr bool value =
3893
std::is_same<value_type,
3894
typename BasicJsonType::array_t::value_type>::value ||
3895
has_from_json<BasicJsonType,
3896
value_type>::value ||
3897
has_non_default_from_json <
3898
BasicJsonType,
3899
value_type >::value;
3900
};
3901
3902
template<typename BasicJsonType, typename ConstructibleArrayType>
3903
struct is_constructible_array_type
3904
: is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3905
3906
template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3907
typename = void>
3908
struct is_compatible_integer_type_impl : std::false_type {};
3909
3910
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3911
struct is_compatible_integer_type_impl <
3912
RealIntegerType, CompatibleNumberIntegerType,
3913
enable_if_t < std::is_integral<RealIntegerType>::value&&
3914
std::is_integral<CompatibleNumberIntegerType>::value&&
3915
!std::is_same<bool, CompatibleNumberIntegerType>::value >>
3916
{
3917
// is there an assert somewhere on overflows?
3918
using RealLimits = std::numeric_limits<RealIntegerType>;
3919
using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3920
3921
static constexpr auto value =
3922
is_constructible<RealIntegerType,
3923
CompatibleNumberIntegerType>::value &&
3924
CompatibleLimits::is_integer &&
3925
RealLimits::is_signed == CompatibleLimits::is_signed;
3926
};
3927
3928
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3929
struct is_compatible_integer_type
3930
: is_compatible_integer_type_impl<RealIntegerType,
3931
CompatibleNumberIntegerType> {};
3932
3933
template<typename BasicJsonType, typename CompatibleType, typename = void>
3934
struct is_compatible_type_impl: std::false_type {};
3935
3936
template<typename BasicJsonType, typename CompatibleType>
3937
struct is_compatible_type_impl <
3938
BasicJsonType, CompatibleType,
3939
enable_if_t<is_complete_type<CompatibleType>::value >>
3940
{
3941
static constexpr bool value =
3942
has_to_json<BasicJsonType, CompatibleType>::value;
3943
};
3944
3945
template<typename BasicJsonType, typename CompatibleType>
3946
struct is_compatible_type
3947
: is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3948
3949
template<typename T1, typename T2>
3950
struct is_constructible_tuple : std::false_type {};
3951
3952
template<typename T1, typename... Args>
3953
struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3954
3955
template<typename BasicJsonType, typename T>
3956
struct is_json_iterator_of : std::false_type {};
3957
3958
template<typename BasicJsonType>
3959
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
3960
3961
template<typename BasicJsonType>
3962
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
3963
{};
3964
3965
// checks if a given type T is a template specialization of Primary
3966
template<template <typename...> class Primary, typename T>
3967
struct is_specialization_of : std::false_type {};
3968
3969
template<template <typename...> class Primary, typename... Args>
3970
struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
3971
3972
template<typename T>
3973
using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
3974
3975
// checks if A and B are comparable using Compare functor
3976
template<typename Compare, typename A, typename B, typename = void>
3977
struct is_comparable : std::false_type {};
3978
3979
template<typename Compare, typename A, typename B>
3980
struct is_comparable<Compare, A, B, void_t<
3981
decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
3982
decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
3983
>> : std::true_type {};
3984
3985
template<typename T>
3986
using detect_is_transparent = typename T::is_transparent;
3987
3988
// type trait to check if KeyType can be used as object key (without a BasicJsonType)
3989
// see is_usable_as_basic_json_key_type below
3990
template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
3991
bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
3992
using is_usable_as_key_type = typename std::conditional <
3993
is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value
3994
&& !(ExcludeObjectKeyType && std::is_same<KeyType,
3995
ObjectKeyType>::value)
3996
&& (!RequireTransparentComparator
3997
|| is_detected <detect_is_transparent, Comparator>::value)
3998
&& !is_json_pointer<KeyType>::value,
3999
std::true_type,
4000
std::false_type >::type;
4001
4002
// type trait to check if KeyType can be used as object key
4003
// true if:
4004
// - KeyType is comparable with BasicJsonType::object_t::key_type
4005
// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4006
// - the comparator is transparent or RequireTransparentComparator is false
4007
// - KeyType is not a JSON iterator or json_pointer
4008
template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4009
bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4010
using is_usable_as_basic_json_key_type = typename std::conditional <
4011
is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4012
typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4013
RequireTransparentComparator, ExcludeObjectKeyType>::value
4014
&& !is_json_iterator_of<BasicJsonType, KeyType>::value,
4015
std::true_type,
4016
std::false_type >::type;
4017
4018
template<typename ObjectType, typename KeyType>
4019
using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4020
4021
// type trait to check if object_t has an erase() member functions accepting KeyType
4022
template<typename BasicJsonType, typename KeyType>
4023
using has_erase_with_key_type = typename std::conditional <
4024
is_detected <
4025
detect_erase_with_key_type,
4026
typename BasicJsonType::object_t, KeyType >::value,
4027
std::true_type,
4028
std::false_type >::type;
4029
4030
// a naive helper to check if a type is an ordered_map (exploits the fact that
4031
// ordered_map inherits capacity() from std::vector)
4032
template <typename T>
4033
struct is_ordered_map
4034
{
4035
using one = char;
4036
4037
struct two
4038
{
4039
char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4040
};
4041
4042
template <typename C> static one test( decltype(&C::capacity) ) ;
4043
template <typename C> static two test(...);
4044
4045
enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
4046
};
4047
4048
// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4049
template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4050
T conditional_static_cast(U value)
4051
{
4052
return static_cast<T>(value);
4053
}
4054
4055
template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4056
T conditional_static_cast(U value)
4057
{
4058
return value;
4059
}
4060
4061
template<typename... Types>
4062
using all_integral = conjunction<std::is_integral<Types>...>;
4063
4064
template<typename... Types>
4065
using all_signed = conjunction<std::is_signed<Types>...>;
4066
4067
template<typename... Types>
4068
using all_unsigned = conjunction<std::is_unsigned<Types>...>;
4069
4070
// there's a disjunction trait in another PR; replace when merged
4071
template<typename... Types>
4072
using same_sign = std::integral_constant < bool,
4073
all_signed<Types...>::value || all_unsigned<Types...>::value >;
4074
4075
template<typename OfType, typename T>
4076
using never_out_of_range = std::integral_constant < bool,
4077
(std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4078
|| (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4079
4080
template<typename OfType, typename T,
4081
bool OfTypeSigned = std::is_signed<OfType>::value,
4082
bool TSigned = std::is_signed<T>::value>
4083
struct value_in_range_of_impl2;
4084
4085
template<typename OfType, typename T>
4086
struct value_in_range_of_impl2<OfType, T, false, false>
4087
{
4088
static constexpr bool test(T val)
4089
{
4090
using CommonType = typename std::common_type<OfType, T>::type;
4091
return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4092
}
4093
};
4094
4095
template<typename OfType, typename T>
4096
struct value_in_range_of_impl2<OfType, T, true, false>
4097
{
4098
static constexpr bool test(T val)
4099
{
4100
using CommonType = typename std::common_type<OfType, T>::type;
4101
return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4102
}
4103
};
4104
4105
template<typename OfType, typename T>
4106
struct value_in_range_of_impl2<OfType, T, false, true>
4107
{
4108
static constexpr bool test(T val)
4109
{
4110
using CommonType = typename std::common_type<OfType, T>::type;
4111
return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4112
}
4113
};
4114
4115
template<typename OfType, typename T>
4116
struct value_in_range_of_impl2<OfType, T, true, true>
4117
{
4118
static constexpr bool test(T val)
4119
{
4120
using CommonType = typename std::common_type<OfType, T>::type;
4121
return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4122
&& static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4123
}
4124
};
4125
4126
template<typename OfType, typename T,
4127
bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4128
typename = detail::enable_if_t<all_integral<OfType, T>::value>>
4129
struct value_in_range_of_impl1;
4130
4131
template<typename OfType, typename T>
4132
struct value_in_range_of_impl1<OfType, T, false>
4133
{
4134
static constexpr bool test(T val)
4135
{
4136
return value_in_range_of_impl2<OfType, T>::test(val);
4137
}
4138
};
4139
4140
template<typename OfType, typename T>
4141
struct value_in_range_of_impl1<OfType, T, true>
4142
{
4143
static constexpr bool test(T /*val*/)
4144
{
4145
return true;
4146
}
4147
};
4148
4149
template<typename OfType, typename T>
4150
inline constexpr bool value_in_range_of(T val)
4151
{
4152
return value_in_range_of_impl1<OfType, T>::test(val);
4153
}
4154
4155
template<bool Value>
4156
using bool_constant = std::integral_constant<bool, Value>;
4157
4158
///////////////////////////////////////////////////////////////////////////////
4159
// is_c_string
4160
///////////////////////////////////////////////////////////////////////////////
4161
4162
namespace impl
4163
{
4164
4165
template<typename T>
4166
inline constexpr bool is_c_string()
4167
{
4168
using TUnExt = typename std::remove_extent<T>::type;
4169
using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4170
using TUnPtr = typename std::remove_pointer<T>::type;
4171
using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4172
return
4173
(std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4174
|| (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4175
}
4176
4177
} // namespace impl
4178
4179
// checks whether T is a [cv] char */[cv] char[] C string
4180
template<typename T>
4181
struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4182
4183
template<typename T>
4184
using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
4185
4186
///////////////////////////////////////////////////////////////////////////////
4187
// is_transparent
4188
///////////////////////////////////////////////////////////////////////////////
4189
4190
namespace impl
4191
{
4192
4193
template<typename T>
4194
inline constexpr bool is_transparent()
4195
{
4196
return is_detected<detect_is_transparent, T>::value;
4197
}
4198
4199
} // namespace impl
4200
4201
// checks whether T has a member named is_transparent
4202
template<typename T>
4203
struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4204
4205
///////////////////////////////////////////////////////////////////////////////
4206
4207
} // namespace detail
4208
NLOHMANN_JSON_NAMESPACE_END
4209
4210
// #include <nlohmann/detail/string_concat.hpp>
4211
// __ _____ _____ _____
4212
// __| | __| | | | JSON for Modern C++
4213
// | | |__ | | | | | | version 3.11.3
4214
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4215
//
4216
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4217
// SPDX-License-Identifier: MIT
4218
4219
4220
4221
#include <cstring> // strlen
4222
#include <string> // string
4223
#include <utility> // forward
4224
4225
// #include <nlohmann/detail/meta/cpp_future.hpp>
4226
4227
// #include <nlohmann/detail/meta/detected.hpp>
4228
4229
4230
NLOHMANN_JSON_NAMESPACE_BEGIN
4231
namespace detail
4232
{
4233
4234
inline std::size_t concat_length()
4235
{
4236
return 0;
4237
}
4238
4239
template<typename... Args>
4240
inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4241
4242
template<typename StringType, typename... Args>
4243
inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4244
4245
template<typename... Args>
4246
inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4247
{
4248
return 1 + concat_length(rest...);
4249
}
4250
4251
template<typename... Args>
4252
inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4253
{
4254
// cppcheck-suppress ignoredReturnValue
4255
return ::strlen(cstr) + concat_length(rest...);
4256
}
4257
4258
template<typename StringType, typename... Args>
4259
inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4260
{
4261
return str.size() + concat_length(rest...);
4262
}
4263
4264
template<typename OutStringType>
4265
inline void concat_into(OutStringType& /*out*/)
4266
{}
4267
4268
template<typename StringType, typename Arg>
4269
using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4270
4271
template<typename StringType, typename Arg>
4272
using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
4273
4274
template<typename StringType, typename Arg>
4275
using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4276
4277
template<typename StringType, typename Arg>
4278
using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
4279
4280
template<typename StringType, typename Arg>
4281
using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4282
4283
template<typename StringType, typename Arg>
4284
using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
4285
4286
template<typename StringType, typename Arg>
4287
using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4288
4289
template<typename StringType, typename Arg>
4290
using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
4291
4292
template < typename OutStringType, typename Arg, typename... Args,
4293
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4294
&& detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
4295
inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4296
4297
template < typename OutStringType, typename Arg, typename... Args,
4298
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4299
&& !detect_string_can_append_op<OutStringType, Arg>::value
4300
&& detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
4301
inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4302
4303
template < typename OutStringType, typename Arg, typename... Args,
4304
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4305
&& !detect_string_can_append_op<OutStringType, Arg>::value
4306
&& !detect_string_can_append_iter<OutStringType, Arg>::value
4307
&& detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
4308
inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4309
4310
template<typename OutStringType, typename Arg, typename... Args,
4311
enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
4312
inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4313
{
4314
out.append(std::forward<Arg>(arg));
4315
concat_into(out, std::forward<Args>(rest)...);
4316
}
4317
4318
template < typename OutStringType, typename Arg, typename... Args,
4319
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4320
&& detect_string_can_append_op<OutStringType, Arg>::value, int > >
4321
inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4322
{
4323
out += std::forward<Arg>(arg);
4324
concat_into(out, std::forward<Args>(rest)...);
4325
}
4326
4327
template < typename OutStringType, typename Arg, typename... Args,
4328
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4329
&& !detect_string_can_append_op<OutStringType, Arg>::value
4330
&& detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4331
inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4332
{
4333
out.append(arg.begin(), arg.end());
4334
concat_into(out, std::forward<Args>(rest)...);
4335
}
4336
4337
template < typename OutStringType, typename Arg, typename... Args,
4338
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4339
&& !detect_string_can_append_op<OutStringType, Arg>::value
4340
&& !detect_string_can_append_iter<OutStringType, Arg>::value
4341
&& detect_string_can_append_data<OutStringType, Arg>::value, int > >
4342
inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4343
{
4344
out.append(arg.data(), arg.size());
4345
concat_into(out, std::forward<Args>(rest)...);
4346
}
4347
4348
template<typename OutStringType = std::string, typename... Args>
4349
inline OutStringType concat(Args && ... args)
4350
{
4351
OutStringType str;
4352
str.reserve(concat_length(args...));
4353
concat_into(str, std::forward<Args>(args)...);
4354
return str;
4355
}
4356
4357
} // namespace detail
4358
NLOHMANN_JSON_NAMESPACE_END
4359
4360
4361
NLOHMANN_JSON_NAMESPACE_BEGIN
4362
namespace detail
4363
{
4364
4365
////////////////
4366
// exceptions //
4367
////////////////
4368
4369
/// @brief general exception of the @ref basic_json class
4370
/// @sa https://json.nlohmann.me/api/basic_json/exception/
4371
class exception : public std::exception
4372
{
4373
public:
4374
/// returns the explanatory string
4375
const char* what() const noexcept override
4376
{
4377
return m.what();
4378
}
4379
4380
/// the id of the exception
4381
const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4382
4383
protected:
4384
JSON_HEDLEY_NON_NULL(3)
4385
exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4386
4387
static std::string name(const std::string& ename, int id_)
4388
{
4389
return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4390
}
4391
4392
static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4393
{
4394
return "";
4395
}
4396
4397
template<typename BasicJsonType>
4398
static std::string diagnostics(const BasicJsonType* leaf_element)
4399
{
4400
#if JSON_DIAGNOSTICS
4401
std::vector<std::string> tokens;
4402
for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4403
{
4404
switch (current->m_parent->type())
4405
{
4406
case value_t::array:
4407
{
4408
for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4409
{
4410
if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4411
{
4412
tokens.emplace_back(std::to_string(i));
4413
break;
4414
}
4415
}
4416
break;
4417
}
4418
4419
case value_t::object:
4420
{
4421
for (const auto& element : *current->m_parent->m_data.m_value.object)
4422
{
4423
if (&element.second == current)
4424
{
4425
tokens.emplace_back(element.first.c_str());
4426
break;
4427
}
4428
}
4429
break;
4430
}
4431
4432
case value_t::null: // LCOV_EXCL_LINE
4433
case value_t::string: // LCOV_EXCL_LINE
4434
case value_t::boolean: // LCOV_EXCL_LINE
4435
case value_t::number_integer: // LCOV_EXCL_LINE
4436
case value_t::number_unsigned: // LCOV_EXCL_LINE
4437
case value_t::number_float: // LCOV_EXCL_LINE
4438
case value_t::binary: // LCOV_EXCL_LINE
4439
case value_t::discarded: // LCOV_EXCL_LINE
4440
default: // LCOV_EXCL_LINE
4441
break; // LCOV_EXCL_LINE
4442
}
4443
}
4444
4445
if (tokens.empty())
4446
{
4447
return "";
4448
}
4449
4450
auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4451
[](const std::string & a, const std::string & b)
4452
{
4453
return concat(a, '/', detail::escape(b));
4454
});
4455
return concat('(', str, ") ");
4456
#else
4457
static_cast<void>(leaf_element);
4458
return "";
4459
#endif
4460
}
4461
4462
private:
4463
/// an exception object as storage for error messages
4464
std::runtime_error m;
4465
};
4466
4467
/// @brief exception indicating a parse error
4468
/// @sa https://json.nlohmann.me/api/basic_json/parse_error/
4469
class parse_error : public exception
4470
{
4471
public:
4472
/*!
4473
@brief create a parse error exception
4474
@param[in] id_ the id of the exception
4475
@param[in] pos the position where the error occurred (or with
4476
chars_read_total=0 if the position cannot be
4477
determined)
4478
@param[in] what_arg the explanatory string
4479
@return parse_error object
4480
*/
4481
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4482
static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4483
{
4484
const std::string w = concat(exception::name("parse_error", id_), "parse error",
4485
position_string(pos), ": ", exception::diagnostics(context), what_arg);
4486
return {id_, pos.chars_read_total, w.c_str()};
4487
}
4488
4489
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4490
static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4491
{
4492
const std::string w = concat(exception::name("parse_error", id_), "parse error",
4493
(byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4494
": ", exception::diagnostics(context), what_arg);
4495
return {id_, byte_, w.c_str()};
4496
}
4497
4498
/*!
4499
@brief byte index of the parse error
4500
4501
The byte index of the last read character in the input file.
4502
4503
@note For an input with n bytes, 1 is the index of the first character and
4504
n+1 is the index of the terminating null byte or the end of file.
4505
This also holds true when reading a byte vector (CBOR or MessagePack).
4506
*/
4507
const std::size_t byte;
4508
4509
private:
4510
parse_error(int id_, std::size_t byte_, const char* what_arg)
4511
: exception(id_, what_arg), byte(byte_) {}
4512
4513
static std::string position_string(const position_t& pos)
4514
{
4515
return concat(" at line ", std::to_string(pos.lines_read + 1),
4516
", column ", std::to_string(pos.chars_read_current_line));
4517
}
4518
};
4519
4520
/// @brief exception indicating errors with iterators
4521
/// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
4522
class invalid_iterator : public exception
4523
{
4524
public:
4525
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4526
static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4527
{
4528
const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4529
return {id_, w.c_str()};
4530
}
4531
4532
private:
4533
JSON_HEDLEY_NON_NULL(3)
4534
invalid_iterator(int id_, const char* what_arg)
4535
: exception(id_, what_arg) {}
4536
};
4537
4538
/// @brief exception indicating executing a member function with a wrong type
4539
/// @sa https://json.nlohmann.me/api/basic_json/type_error/
4540
class type_error : public exception
4541
{
4542
public:
4543
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4544
static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4545
{
4546
const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4547
return {id_, w.c_str()};
4548
}
4549
4550
private:
4551
JSON_HEDLEY_NON_NULL(3)
4552
type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4553
};
4554
4555
/// @brief exception indicating access out of the defined range
4556
/// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
4557
class out_of_range : public exception
4558
{
4559
public:
4560
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4561
static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4562
{
4563
const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4564
return {id_, w.c_str()};
4565
}
4566
4567
private:
4568
JSON_HEDLEY_NON_NULL(3)
4569
out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4570
};
4571
4572
/// @brief exception indicating other library errors
4573
/// @sa https://json.nlohmann.me/api/basic_json/other_error/
4574
class other_error : public exception
4575
{
4576
public:
4577
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4578
static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4579
{
4580
const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4581
return {id_, w.c_str()};
4582
}
4583
4584
private:
4585
JSON_HEDLEY_NON_NULL(3)
4586
other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4587
};
4588
4589
} // namespace detail
4590
NLOHMANN_JSON_NAMESPACE_END
4591
4592
// #include <nlohmann/detail/macro_scope.hpp>
4593
4594
// #include <nlohmann/detail/meta/cpp_future.hpp>
4595
4596
// #include <nlohmann/detail/meta/identity_tag.hpp>
4597
// __ _____ _____ _____
4598
// __| | __| | | | JSON for Modern C++
4599
// | | |__ | | | | | | version 3.11.3
4600
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4601
//
4602
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4603
// SPDX-License-Identifier: MIT
4604
4605
4606
4607
// #include <nlohmann/detail/abi_macros.hpp>
4608
4609
4610
NLOHMANN_JSON_NAMESPACE_BEGIN
4611
namespace detail
4612
{
4613
4614
// dispatching helper struct
4615
template <class T> struct identity_tag {};
4616
4617
} // namespace detail
4618
NLOHMANN_JSON_NAMESPACE_END
4619
4620
// #include <nlohmann/detail/meta/std_fs.hpp>
4621
// __ _____ _____ _____
4622
// __| | __| | | | JSON for Modern C++
4623
// | | |__ | | | | | | version 3.11.3
4624
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4625
//
4626
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4627
// SPDX-License-Identifier: MIT
4628
4629
4630
4631
// #include <nlohmann/detail/macro_scope.hpp>
4632
4633
4634
#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4635
#include <experimental/filesystem>
4636
NLOHMANN_JSON_NAMESPACE_BEGIN
4637
namespace detail
4638
{
4639
namespace std_fs = std::experimental::filesystem;
4640
} // namespace detail
4641
NLOHMANN_JSON_NAMESPACE_END
4642
#elif JSON_HAS_FILESYSTEM
4643
#include <filesystem>
4644
NLOHMANN_JSON_NAMESPACE_BEGIN
4645
namespace detail
4646
{
4647
namespace std_fs = std::filesystem;
4648
} // namespace detail
4649
NLOHMANN_JSON_NAMESPACE_END
4650
#endif
4651
4652
// #include <nlohmann/detail/meta/type_traits.hpp>
4653
4654
// #include <nlohmann/detail/string_concat.hpp>
4655
4656
// #include <nlohmann/detail/value_t.hpp>
4657
4658
4659
NLOHMANN_JSON_NAMESPACE_BEGIN
4660
namespace detail
4661
{
4662
4663
template<typename BasicJsonType>
4664
inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4665
{
4666
if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4667
{
4668
JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4669
}
4670
n = nullptr;
4671
}
4672
4673
// overloads for basic_json template parameters
4674
template < typename BasicJsonType, typename ArithmeticType,
4675
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4676
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4677
int > = 0 >
4678
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4679
{
4680
switch (static_cast<value_t>(j))
4681
{
4682
case value_t::number_unsigned:
4683
{
4684
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4685
break;
4686
}
4687
case value_t::number_integer:
4688
{
4689
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4690
break;
4691
}
4692
case value_t::number_float:
4693
{
4694
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4695
break;
4696
}
4697
4698
case value_t::null:
4699
case value_t::object:
4700
case value_t::array:
4701
case value_t::string:
4702
case value_t::boolean:
4703
case value_t::binary:
4704
case value_t::discarded:
4705
default:
4706
JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4707
}
4708
}
4709
4710
template<typename BasicJsonType>
4711
inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4712
{
4713
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4714
{
4715
JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4716
}
4717
b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4718
}
4719
4720
template<typename BasicJsonType>
4721
inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4722
{
4723
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4724
{
4725
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4726
}
4727
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4728
}
4729
4730
template <
4731
typename BasicJsonType, typename StringType,
4732
enable_if_t <
4733
std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4734
&& is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4735
&& !std::is_same<typename BasicJsonType::string_t, StringType>::value
4736
&& !is_json_ref<StringType>::value, int > = 0 >
4737
inline void from_json(const BasicJsonType& j, StringType& s)
4738
{
4739
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4740
{
4741
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4742
}
4743
4744
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4745
}
4746
4747
template<typename BasicJsonType>
4748
inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4749
{
4750
get_arithmetic_value(j, val);
4751
}
4752
4753
template<typename BasicJsonType>
4754
inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4755
{
4756
get_arithmetic_value(j, val);
4757
}
4758
4759
template<typename BasicJsonType>
4760
inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4761
{
4762
get_arithmetic_value(j, val);
4763
}
4764
4765
#if !JSON_DISABLE_ENUM_SERIALIZATION
4766
template<typename BasicJsonType, typename EnumType,
4767
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4768
inline void from_json(const BasicJsonType& j, EnumType& e)
4769
{
4770
typename std::underlying_type<EnumType>::type val;
4771
get_arithmetic_value(j, val);
4772
e = static_cast<EnumType>(val);
4773
}
4774
#endif // JSON_DISABLE_ENUM_SERIALIZATION
4775
4776
// forward_list doesn't have an insert method
4777
template<typename BasicJsonType, typename T, typename Allocator,
4778
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4779
inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4780
{
4781
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4782
{
4783
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4784
}
4785
l.clear();
4786
std::transform(j.rbegin(), j.rend(),
4787
std::front_inserter(l), [](const BasicJsonType & i)
4788
{
4789
return i.template get<T>();
4790
});
4791
}
4792
4793
// valarray doesn't have an insert method
4794
template<typename BasicJsonType, typename T,
4795
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4796
inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
4797
{
4798
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4799
{
4800
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4801
}
4802
l.resize(j.size());
4803
std::transform(j.begin(), j.end(), std::begin(l),
4804
[](const BasicJsonType & elem)
4805
{
4806
return elem.template get<T>();
4807
});
4808
}
4809
4810
template<typename BasicJsonType, typename T, std::size_t N>
4811
auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4812
-> decltype(j.template get<T>(), void())
4813
{
4814
for (std::size_t i = 0; i < N; ++i)
4815
{
4816
arr[i] = j.at(i).template get<T>();
4817
}
4818
}
4819
4820
template<typename BasicJsonType>
4821
inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
4822
{
4823
arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
4824
}
4825
4826
template<typename BasicJsonType, typename T, std::size_t N>
4827
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
4828
priority_tag<2> /*unused*/)
4829
-> decltype(j.template get<T>(), void())
4830
{
4831
for (std::size_t i = 0; i < N; ++i)
4832
{
4833
arr[i] = j.at(i).template get<T>();
4834
}
4835
}
4836
4837
template<typename BasicJsonType, typename ConstructibleArrayType,
4838
enable_if_t<
4839
std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4840
int> = 0>
4841
auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4842
-> decltype(
4843
arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4844
j.template get<typename ConstructibleArrayType::value_type>(),
4845
void())
4846
{
4847
using std::end;
4848
4849
ConstructibleArrayType ret;
4850
ret.reserve(j.size());
4851
std::transform(j.begin(), j.end(),
4852
std::inserter(ret, end(ret)), [](const BasicJsonType & i)
4853
{
4854
// get<BasicJsonType>() returns *this, this won't call a from_json
4855
// method when value_type is BasicJsonType
4856
return i.template get<typename ConstructibleArrayType::value_type>();
4857
});
4858
arr = std::move(ret);
4859
}
4860
4861
template<typename BasicJsonType, typename ConstructibleArrayType,
4862
enable_if_t<
4863
std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4864
int> = 0>
4865
inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4866
priority_tag<0> /*unused*/)
4867
{
4868
using std::end;
4869
4870
ConstructibleArrayType ret;
4871
std::transform(
4872
j.begin(), j.end(), std::inserter(ret, end(ret)),
4873
[](const BasicJsonType & i)
4874
{
4875
// get<BasicJsonType>() returns *this, this won't call a from_json
4876
// method when value_type is BasicJsonType
4877
return i.template get<typename ConstructibleArrayType::value_type>();
4878
});
4879
arr = std::move(ret);
4880
}
4881
4882
template < typename BasicJsonType, typename ConstructibleArrayType,
4883
enable_if_t <
4884
is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4885
!is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4886
!is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4887
!std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4888
!is_basic_json<ConstructibleArrayType>::value,
4889
int > = 0 >
4890
auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4891
-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4892
j.template get<typename ConstructibleArrayType::value_type>(),
4893
void())
4894
{
4895
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4896
{
4897
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4898
}
4899
4900
from_json_array_impl(j, arr, priority_tag<3> {});
4901
}
4902
4903
template < typename BasicJsonType, typename T, std::size_t... Idx >
4904
std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4905
identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4906
{
4907
return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4908
}
4909
4910
template < typename BasicJsonType, typename T, std::size_t N >
4911
auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4912
-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4913
{
4914
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4915
{
4916
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4917
}
4918
4919
return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4920
}
4921
4922
template<typename BasicJsonType>
4923
inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4924
{
4925
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4926
{
4927
JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
4928
}
4929
4930
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4931
}
4932
4933
template<typename BasicJsonType, typename ConstructibleObjectType,
4934
enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
4935
inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
4936
{
4937
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
4938
{
4939
JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
4940
}
4941
4942
ConstructibleObjectType ret;
4943
const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4944
using value_type = typename ConstructibleObjectType::value_type;
4945
std::transform(
4946
inner_object->begin(), inner_object->end(),
4947
std::inserter(ret, ret.begin()),
4948
[](typename BasicJsonType::object_t::value_type const & p)
4949
{
4950
return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
4951
});
4952
obj = std::move(ret);
4953
}
4954
4955
// overload for arithmetic types, not chosen for basic_json template arguments
4956
// (BooleanType, etc..); note: Is it really necessary to provide explicit
4957
// overloads for boolean_t etc. in case of a custom BooleanType which is not
4958
// an arithmetic type?
4959
template < typename BasicJsonType, typename ArithmeticType,
4960
enable_if_t <
4961
std::is_arithmetic<ArithmeticType>::value&&
4962
!std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
4963
!std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
4964
!std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
4965
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4966
int > = 0 >
4967
inline void from_json(const BasicJsonType& j, ArithmeticType& val)
4968
{
4969
switch (static_cast<value_t>(j))
4970
{
4971
case value_t::number_unsigned:
4972
{
4973
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4974
break;
4975
}
4976
case value_t::number_integer:
4977
{
4978
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4979
break;
4980
}
4981
case value_t::number_float:
4982
{
4983
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4984
break;
4985
}
4986
case value_t::boolean:
4987
{
4988
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
4989
break;
4990
}
4991
4992
case value_t::null:
4993
case value_t::object:
4994
case value_t::array:
4995
case value_t::string:
4996
case value_t::binary:
4997
case value_t::discarded:
4998
default:
4999
JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5000
}
5001
}
5002
5003
template<typename BasicJsonType, typename... Args, std::size_t... Idx>
5004
std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5005
{
5006
return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
5007
}
5008
5009
template < typename BasicJsonType, class A1, class A2 >
5010
std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5011
{
5012
return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5013
std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5014
}
5015
5016
template<typename BasicJsonType, typename A1, typename A2>
5017
inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5018
{
5019
p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5020
}
5021
5022
template<typename BasicJsonType, typename... Args>
5023
std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5024
{
5025
return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5026
}
5027
5028
template<typename BasicJsonType, typename... Args>
5029
inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5030
{
5031
t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5032
}
5033
5034
template<typename BasicJsonType, typename TupleRelated>
5035
auto from_json(BasicJsonType&& j, TupleRelated&& t)
5036
-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5037
{
5038
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5039
{
5040
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5041
}
5042
5043
return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5044
}
5045
5046
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5047
typename = enable_if_t < !std::is_constructible <
5048
typename BasicJsonType::string_t, Key >::value >>
5049
inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5050
{
5051
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5052
{
5053
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5054
}
5055
m.clear();
5056
for (const auto& p : j)
5057
{
5058
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5059
{
5060
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5061
}
5062
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5063
}
5064
}
5065
5066
template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5067
typename = enable_if_t < !std::is_constructible <
5068
typename BasicJsonType::string_t, Key >::value >>
5069
inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5070
{
5071
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5072
{
5073
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5074
}
5075
m.clear();
5076
for (const auto& p : j)
5077
{
5078
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5079
{
5080
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5081
}
5082
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5083
}
5084
}
5085
5086
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5087
template<typename BasicJsonType>
5088
inline void from_json(const BasicJsonType& j, std_fs::path& p)
5089
{
5090
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5091
{
5092
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5093
}
5094
p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5095
}
5096
#endif
5097
5098
struct from_json_fn
5099
{
5100
template<typename BasicJsonType, typename T>
5101
auto operator()(const BasicJsonType& j, T&& val) const
5102
noexcept(noexcept(from_json(j, std::forward<T>(val))))
5103
-> decltype(from_json(j, std::forward<T>(val)))
5104
{
5105
return from_json(j, std::forward<T>(val));
5106
}
5107
};
5108
5109
} // namespace detail
5110
5111
#ifndef JSON_HAS_CPP_17
5112
/// namespace to hold default `from_json` function
5113
/// to see why this is required:
5114
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
5115
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5116
{
5117
#endif
5118
JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5119
detail::static_const<detail::from_json_fn>::value;
5120
#ifndef JSON_HAS_CPP_17
5121
} // namespace
5122
#endif
5123
5124
NLOHMANN_JSON_NAMESPACE_END
5125
5126
// #include <nlohmann/detail/conversions/to_json.hpp>
5127
// __ _____ _____ _____
5128
// __| | __| | | | JSON for Modern C++
5129
// | | |__ | | | | | | version 3.11.3
5130
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5131
//
5132
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5133
// SPDX-License-Identifier: MIT
5134
5135
5136
5137
#include <algorithm> // copy
5138
#include <iterator> // begin, end
5139
#include <string> // string
5140
#include <tuple> // tuple, get
5141
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5142
#include <utility> // move, forward, declval, pair
5143
#include <valarray> // valarray
5144
#include <vector> // vector
5145
5146
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5147
// __ _____ _____ _____
5148
// __| | __| | | | JSON for Modern C++
5149
// | | |__ | | | | | | version 3.11.3
5150
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5151
//
5152
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5153
// SPDX-License-Identifier: MIT
5154
5155
5156
5157
#include <cstddef> // size_t
5158
#include <iterator> // input_iterator_tag
5159
#include <string> // string, to_string
5160
#include <tuple> // tuple_size, get, tuple_element
5161
#include <utility> // move
5162
5163
#if JSON_HAS_RANGES
5164
#include <ranges> // enable_borrowed_range
5165
#endif
5166
5167
// #include <nlohmann/detail/abi_macros.hpp>
5168
5169
// #include <nlohmann/detail/meta/type_traits.hpp>
5170
5171
// #include <nlohmann/detail/value_t.hpp>
5172
5173
5174
NLOHMANN_JSON_NAMESPACE_BEGIN
5175
namespace detail
5176
{
5177
5178
template<typename string_type>
5179
void int_to_string( string_type& target, std::size_t value )
5180
{
5181
// For ADL
5182
using std::to_string;
5183
target = to_string(value);
5184
}
5185
template<typename IteratorType> class iteration_proxy_value
5186
{
5187
public:
5188
using difference_type = std::ptrdiff_t;
5189
using value_type = iteration_proxy_value;
5190
using pointer = value_type *;
5191
using reference = value_type &;
5192
using iterator_category = std::input_iterator_tag;
5193
using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5194
5195
private:
5196
/// the iterator
5197
IteratorType anchor{};
5198
/// an index for arrays (used to create key names)
5199
std::size_t array_index = 0;
5200
/// last stringified array index
5201
mutable std::size_t array_index_last = 0;
5202
/// a string representation of the array index
5203
mutable string_type array_index_str = "0";
5204
/// an empty string (to return a reference for primitive values)
5205
string_type empty_str{};
5206
5207
public:
5208
explicit iteration_proxy_value() = default;
5209
explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5210
noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5211
&& std::is_nothrow_default_constructible<string_type>::value)
5212
: anchor(std::move(it))
5213
, array_index(array_index_)
5214
{}
5215
5216
iteration_proxy_value(iteration_proxy_value const&) = default;
5217
iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
5218
// older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5219
iteration_proxy_value(iteration_proxy_value&&)
5220
noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5221
&& std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5222
iteration_proxy_value& operator=(iteration_proxy_value&&)
5223
noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5224
&& std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5225
~iteration_proxy_value() = default;
5226
5227
/// dereference operator (needed for range-based for)
5228
const iteration_proxy_value& operator*() const
5229
{
5230
return *this;
5231
}
5232
5233
/// increment operator (needed for range-based for)
5234
iteration_proxy_value& operator++()
5235
{
5236
++anchor;
5237
++array_index;
5238
5239
return *this;
5240
}
5241
5242
iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5243
{
5244
auto tmp = iteration_proxy_value(anchor, array_index);
5245
++anchor;
5246
++array_index;
5247
return tmp;
5248
}
5249
5250
/// equality operator (needed for InputIterator)
5251
bool operator==(const iteration_proxy_value& o) const
5252
{
5253
return anchor == o.anchor;
5254
}
5255
5256
/// inequality operator (needed for range-based for)
5257
bool operator!=(const iteration_proxy_value& o) const
5258
{
5259
return anchor != o.anchor;
5260
}
5261
5262
/// return key of the iterator
5263
const string_type& key() const
5264
{
5265
JSON_ASSERT(anchor.m_object != nullptr);
5266
5267
switch (anchor.m_object->type())
5268
{
5269
// use integer array index as key
5270
case value_t::array:
5271
{
5272
if (array_index != array_index_last)
5273
{
5274
int_to_string( array_index_str, array_index );
5275
array_index_last = array_index;
5276
}
5277
return array_index_str;
5278
}
5279
5280
// use key from the object
5281
case value_t::object:
5282
return anchor.key();
5283
5284
// use an empty key for all primitive types
5285
case value_t::null:
5286
case value_t::string:
5287
case value_t::boolean:
5288
case value_t::number_integer:
5289
case value_t::number_unsigned:
5290
case value_t::number_float:
5291
case value_t::binary:
5292
case value_t::discarded:
5293
default:
5294
return empty_str;
5295
}
5296
}
5297
5298
/// return value of the iterator
5299
typename IteratorType::reference value() const
5300
{
5301
return anchor.value();
5302
}
5303
};
5304
5305
/// proxy class for the items() function
5306
template<typename IteratorType> class iteration_proxy
5307
{
5308
private:
5309
/// the container to iterate
5310
typename IteratorType::pointer container = nullptr;
5311
5312
public:
5313
explicit iteration_proxy() = default;
5314
5315
/// construct iteration proxy from a container
5316
explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5317
: container(&cont) {}
5318
5319
iteration_proxy(iteration_proxy const&) = default;
5320
iteration_proxy& operator=(iteration_proxy const&) = default;
5321
iteration_proxy(iteration_proxy&&) noexcept = default;
5322
iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5323
~iteration_proxy() = default;
5324
5325
/// return iterator begin (needed for range-based for)
5326
iteration_proxy_value<IteratorType> begin() const noexcept
5327
{
5328
return iteration_proxy_value<IteratorType>(container->begin());
5329
}
5330
5331
/// return iterator end (needed for range-based for)
5332
iteration_proxy_value<IteratorType> end() const noexcept
5333
{
5334
return iteration_proxy_value<IteratorType>(container->end());
5335
}
5336
};
5337
5338
// Structured Bindings Support
5339
// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5340
// And see https://github.com/nlohmann/json/pull/1391
5341
template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5342
auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5343
{
5344
return i.key();
5345
}
5346
// Structured Bindings Support
5347
// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5348
// And see https://github.com/nlohmann/json/pull/1391
5349
template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5350
auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5351
{
5352
return i.value();
5353
}
5354
5355
} // namespace detail
5356
NLOHMANN_JSON_NAMESPACE_END
5357
5358
// The Addition to the STD Namespace is required to add
5359
// Structured Bindings Support to the iteration_proxy_value class
5360
// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5361
// And see https://github.com/nlohmann/json/pull/1391
5362
namespace std
5363
{
5364
5365
#if defined(__clang__)
5366
// Fix: https://github.com/nlohmann/json/issues/1401
5367
#pragma clang diagnostic push
5368
#pragma clang diagnostic ignored "-Wmismatched-tags"
5369
#endif
5370
template<typename IteratorType>
5371
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5372
: public std::integral_constant<std::size_t, 2> {};
5373
5374
template<std::size_t N, typename IteratorType>
5375
class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5376
{
5377
public:
5378
using type = decltype(
5379
get<N>(std::declval <
5380
::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5381
};
5382
#if defined(__clang__)
5383
#pragma clang diagnostic pop
5384
#endif
5385
5386
} // namespace std
5387
5388
#if JSON_HAS_RANGES
5389
template <typename IteratorType>
5390
inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5391
#endif
5392
5393
// #include <nlohmann/detail/macro_scope.hpp>
5394
5395
// #include <nlohmann/detail/meta/cpp_future.hpp>
5396
5397
// #include <nlohmann/detail/meta/std_fs.hpp>
5398
5399
// #include <nlohmann/detail/meta/type_traits.hpp>
5400
5401
// #include <nlohmann/detail/value_t.hpp>
5402
5403
5404
NLOHMANN_JSON_NAMESPACE_BEGIN
5405
namespace detail
5406
{
5407
5408
//////////////////
5409
// constructors //
5410
//////////////////
5411
5412
/*
5413
* Note all external_constructor<>::construct functions need to call
5414
* j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5415
* allocated value (e.g., a string). See bug issue
5416
* https://github.com/nlohmann/json/issues/2865 for more information.
5417
*/
5418
5419
template<value_t> struct external_constructor;
5420
5421
template<>
5422
struct external_constructor<value_t::boolean>
5423
{
5424
template<typename BasicJsonType>
5425
static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5426
{
5427
j.m_data.m_value.destroy(j.m_data.m_type);
5428
j.m_data.m_type = value_t::boolean;
5429
j.m_data.m_value = b;
5430
j.assert_invariant();
5431
}
5432
};
5433
5434
template<>
5435
struct external_constructor<value_t::string>
5436
{
5437
template<typename BasicJsonType>
5438
static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5439
{
5440
j.m_data.m_value.destroy(j.m_data.m_type);
5441
j.m_data.m_type = value_t::string;
5442
j.m_data.m_value = s;
5443
j.assert_invariant();
5444
}
5445
5446
template<typename BasicJsonType>
5447
static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5448
{
5449
j.m_data.m_value.destroy(j.m_data.m_type);
5450
j.m_data.m_type = value_t::string;
5451
j.m_data.m_value = std::move(s);
5452
j.assert_invariant();
5453
}
5454
5455
template < typename BasicJsonType, typename CompatibleStringType,
5456
enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5457
int > = 0 >
5458
static void construct(BasicJsonType& j, const CompatibleStringType& str)
5459
{
5460
j.m_data.m_value.destroy(j.m_data.m_type);
5461
j.m_data.m_type = value_t::string;
5462
j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5463
j.assert_invariant();
5464
}
5465
};
5466
5467
template<>
5468
struct external_constructor<value_t::binary>
5469
{
5470
template<typename BasicJsonType>
5471
static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5472
{
5473
j.m_data.m_value.destroy(j.m_data.m_type);
5474
j.m_data.m_type = value_t::binary;
5475
j.m_data.m_value = typename BasicJsonType::binary_t(b);
5476
j.assert_invariant();
5477
}
5478
5479
template<typename BasicJsonType>
5480
static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5481
{
5482
j.m_data.m_value.destroy(j.m_data.m_type);
5483
j.m_data.m_type = value_t::binary;
5484
j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5485
j.assert_invariant();
5486
}
5487
};
5488
5489
template<>
5490
struct external_constructor<value_t::number_float>
5491
{
5492
template<typename BasicJsonType>
5493
static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5494
{
5495
j.m_data.m_value.destroy(j.m_data.m_type);
5496
j.m_data.m_type = value_t::number_float;
5497
j.m_data.m_value = val;
5498
j.assert_invariant();
5499
}
5500
};
5501
5502
template<>
5503
struct external_constructor<value_t::number_unsigned>
5504
{
5505
template<typename BasicJsonType>
5506
static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5507
{
5508
j.m_data.m_value.destroy(j.m_data.m_type);
5509
j.m_data.m_type = value_t::number_unsigned;
5510
j.m_data.m_value = val;
5511
j.assert_invariant();
5512
}
5513
};
5514
5515
template<>
5516
struct external_constructor<value_t::number_integer>
5517
{
5518
template<typename BasicJsonType>
5519
static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5520
{
5521
j.m_data.m_value.destroy(j.m_data.m_type);
5522
j.m_data.m_type = value_t::number_integer;
5523
j.m_data.m_value = val;
5524
j.assert_invariant();
5525
}
5526
};
5527
5528
template<>
5529
struct external_constructor<value_t::array>
5530
{
5531
template<typename BasicJsonType>
5532
static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5533
{
5534
j.m_data.m_value.destroy(j.m_data.m_type);
5535
j.m_data.m_type = value_t::array;
5536
j.m_data.m_value = arr;
5537
j.set_parents();
5538
j.assert_invariant();
5539
}
5540
5541
template<typename BasicJsonType>
5542
static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5543
{
5544
j.m_data.m_value.destroy(j.m_data.m_type);
5545
j.m_data.m_type = value_t::array;
5546
j.m_data.m_value = std::move(arr);
5547
j.set_parents();
5548
j.assert_invariant();
5549
}
5550
5551
template < typename BasicJsonType, typename CompatibleArrayType,
5552
enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5553
int > = 0 >
5554
static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5555
{
5556
using std::begin;
5557
using std::end;
5558
5559
j.m_data.m_value.destroy(j.m_data.m_type);
5560
j.m_data.m_type = value_t::array;
5561
j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5562
j.set_parents();
5563
j.assert_invariant();
5564
}
5565
5566
template<typename BasicJsonType>
5567
static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5568
{
5569
j.m_data.m_value.destroy(j.m_data.m_type);
5570
j.m_data.m_type = value_t::array;
5571
j.m_data.m_value = value_t::array;
5572
j.m_data.m_value.array->reserve(arr.size());
5573
for (const bool x : arr)
5574
{
5575
j.m_data.m_value.array->push_back(x);
5576
j.set_parent(j.m_data.m_value.array->back());
5577
}
5578
j.assert_invariant();
5579
}
5580
5581
template<typename BasicJsonType, typename T,
5582
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5583
static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5584
{
5585
j.m_data.m_value.destroy(j.m_data.m_type);
5586
j.m_data.m_type = value_t::array;
5587
j.m_data.m_value = value_t::array;
5588
j.m_data.m_value.array->resize(arr.size());
5589
if (arr.size() > 0)
5590
{
5591
std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5592
}
5593
j.set_parents();
5594
j.assert_invariant();
5595
}
5596
};
5597
5598
template<>
5599
struct external_constructor<value_t::object>
5600
{
5601
template<typename BasicJsonType>
5602
static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5603
{
5604
j.m_data.m_value.destroy(j.m_data.m_type);
5605
j.m_data.m_type = value_t::object;
5606
j.m_data.m_value = obj;
5607
j.set_parents();
5608
j.assert_invariant();
5609
}
5610
5611
template<typename BasicJsonType>
5612
static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5613
{
5614
j.m_data.m_value.destroy(j.m_data.m_type);
5615
j.m_data.m_type = value_t::object;
5616
j.m_data.m_value = std::move(obj);
5617
j.set_parents();
5618
j.assert_invariant();
5619
}
5620
5621
template < typename BasicJsonType, typename CompatibleObjectType,
5622
enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5623
static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5624
{
5625
using std::begin;
5626
using std::end;
5627
5628
j.m_data.m_value.destroy(j.m_data.m_type);
5629
j.m_data.m_type = value_t::object;
5630
j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5631
j.set_parents();
5632
j.assert_invariant();
5633
}
5634
};
5635
5636
/////////////
5637
// to_json //
5638
/////////////
5639
5640
template<typename BasicJsonType, typename T,
5641
enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5642
inline void to_json(BasicJsonType& j, T b) noexcept
5643
{
5644
external_constructor<value_t::boolean>::construct(j, b);
5645
}
5646
5647
template < typename BasicJsonType, typename BoolRef,
5648
enable_if_t <
5649
((std::is_same<std::vector<bool>::reference, BoolRef>::value
5650
&& !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5651
|| (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5652
&& !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5653
typename BasicJsonType::boolean_t >::value))
5654
&& std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5655
inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5656
{
5657
external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5658
}
5659
5660
template<typename BasicJsonType, typename CompatibleString,
5661
enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5662
inline void to_json(BasicJsonType& j, const CompatibleString& s)
5663
{
5664
external_constructor<value_t::string>::construct(j, s);
5665
}
5666
5667
template<typename BasicJsonType>
5668
inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5669
{
5670
external_constructor<value_t::string>::construct(j, std::move(s));
5671
}
5672
5673
template<typename BasicJsonType, typename FloatType,
5674
enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5675
inline void to_json(BasicJsonType& j, FloatType val) noexcept
5676
{
5677
external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
5678
}
5679
5680
template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
5681
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
5682
inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
5683
{
5684
external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5685
}
5686
5687
template<typename BasicJsonType, typename CompatibleNumberIntegerType,
5688
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
5689
inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
5690
{
5691
external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
5692
}
5693
5694
#if !JSON_DISABLE_ENUM_SERIALIZATION
5695
template<typename BasicJsonType, typename EnumType,
5696
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5697
inline void to_json(BasicJsonType& j, EnumType e) noexcept
5698
{
5699
using underlying_type = typename std::underlying_type<EnumType>::type;
5700
static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
5701
external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
5702
}
5703
#endif // JSON_DISABLE_ENUM_SERIALIZATION
5704
5705
template<typename BasicJsonType>
5706
inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
5707
{
5708
external_constructor<value_t::array>::construct(j, e);
5709
}
5710
5711
template < typename BasicJsonType, typename CompatibleArrayType,
5712
enable_if_t < is_compatible_array_type<BasicJsonType,
5713
CompatibleArrayType>::value&&
5714
!is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
5715
!is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
5716
!std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
5717
!is_basic_json<CompatibleArrayType>::value,
5718
int > = 0 >
5719
inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
5720
{
5721
external_constructor<value_t::array>::construct(j, arr);
5722
}
5723
5724
template<typename BasicJsonType>
5725
inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
5726
{
5727
external_constructor<value_t::binary>::construct(j, bin);
5728
}
5729
5730
template<typename BasicJsonType, typename T,
5731
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5732
inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
5733
{
5734
external_constructor<value_t::array>::construct(j, std::move(arr));
5735
}
5736
5737
template<typename BasicJsonType>
5738
inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5739
{
5740
external_constructor<value_t::array>::construct(j, std::move(arr));
5741
}
5742
5743
template < typename BasicJsonType, typename CompatibleObjectType,
5744
enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
5745
inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
5746
{
5747
external_constructor<value_t::object>::construct(j, obj);
5748
}
5749
5750
template<typename BasicJsonType>
5751
inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5752
{
5753
external_constructor<value_t::object>::construct(j, std::move(obj));
5754
}
5755
5756
template <
5757
typename BasicJsonType, typename T, std::size_t N,
5758
enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
5759
const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5760
int > = 0 >
5761
inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5762
{
5763
external_constructor<value_t::array>::construct(j, arr);
5764
}
5765
5766
template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
5767
inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
5768
{
5769
j = { p.first, p.second };
5770
}
5771
5772
// for https://github.com/nlohmann/json/pull/1134
5773
template<typename BasicJsonType, typename T,
5774
enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
5775
inline void to_json(BasicJsonType& j, const T& b)
5776
{
5777
j = { {b.key(), b.value()} };
5778
}
5779
5780
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
5781
inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
5782
{
5783
j = { std::get<Idx>(t)... };
5784
}
5785
5786
template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
5787
inline void to_json(BasicJsonType& j, const T& t)
5788
{
5789
to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
5790
}
5791
5792
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5793
template<typename BasicJsonType>
5794
inline void to_json(BasicJsonType& j, const std_fs::path& p)
5795
{
5796
j = p.string();
5797
}
5798
#endif
5799
5800
struct to_json_fn
5801
{
5802
template<typename BasicJsonType, typename T>
5803
auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
5804
-> decltype(to_json(j, std::forward<T>(val)), void())
5805
{
5806
return to_json(j, std::forward<T>(val));
5807
}
5808
};
5809
} // namespace detail
5810
5811
#ifndef JSON_HAS_CPP_17
5812
/// namespace to hold default `to_json` function
5813
/// to see why this is required:
5814
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
5815
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5816
{
5817
#endif
5818
JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
5819
detail::static_const<detail::to_json_fn>::value;
5820
#ifndef JSON_HAS_CPP_17
5821
} // namespace
5822
#endif
5823
5824
NLOHMANN_JSON_NAMESPACE_END
5825
5826
// #include <nlohmann/detail/meta/identity_tag.hpp>
5827
5828
5829
NLOHMANN_JSON_NAMESPACE_BEGIN
5830
5831
/// @sa https://json.nlohmann.me/api/adl_serializer/
5832
template<typename ValueType, typename>
5833
struct adl_serializer
5834
{
5835
/// @brief convert a JSON value to any value type
5836
/// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
5837
template<typename BasicJsonType, typename TargetType = ValueType>
5838
static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
5839
noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
5840
-> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
5841
{
5842
::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
5843
}
5844
5845
/// @brief convert a JSON value to any value type
5846
/// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
5847
template<typename BasicJsonType, typename TargetType = ValueType>
5848
static auto from_json(BasicJsonType && j) noexcept(
5849
noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
5850
-> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
5851
{
5852
return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
5853
}
5854
5855
/// @brief convert any value type to a JSON value
5856
/// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
5857
template<typename BasicJsonType, typename TargetType = ValueType>
5858
static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
5859
noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
5860
-> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
5861
{
5862
::nlohmann::to_json(j, std::forward<TargetType>(val));
5863
}
5864
};
5865
5866
NLOHMANN_JSON_NAMESPACE_END
5867
5868
// #include <nlohmann/byte_container_with_subtype.hpp>
5869
// __ _____ _____ _____
5870
// __| | __| | | | JSON for Modern C++
5871
// | | |__ | | | | | | version 3.11.3
5872
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5873
//
5874
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5875
// SPDX-License-Identifier: MIT
5876
5877
5878
5879
#include <cstdint> // uint8_t, uint64_t
5880
#include <tuple> // tie
5881
#include <utility> // move
5882
5883
// #include <nlohmann/detail/abi_macros.hpp>
5884
5885
5886
NLOHMANN_JSON_NAMESPACE_BEGIN
5887
5888
/// @brief an internal type for a backed binary type
5889
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
5890
template<typename BinaryType>
5891
class byte_container_with_subtype : public BinaryType
5892
{
5893
public:
5894
using container_type = BinaryType;
5895
using subtype_type = std::uint64_t;
5896
5897
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5898
byte_container_with_subtype() noexcept(noexcept(container_type()))
5899
: container_type()
5900
{}
5901
5902
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5903
byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
5904
: container_type(b)
5905
{}
5906
5907
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5908
byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
5909
: container_type(std::move(b))
5910
{}
5911
5912
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5913
byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
5914
: container_type(b)
5915
, m_subtype(subtype_)
5916
, m_has_subtype(true)
5917
{}
5918
5919
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5920
byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
5921
: container_type(std::move(b))
5922
, m_subtype(subtype_)
5923
, m_has_subtype(true)
5924
{}
5925
5926
bool operator==(const byte_container_with_subtype& rhs) const
5927
{
5928
return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
5929
std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5930
}
5931
5932
bool operator!=(const byte_container_with_subtype& rhs) const
5933
{
5934
return !(rhs == *this);
5935
}
5936
5937
/// @brief sets the binary subtype
5938
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/
5939
void set_subtype(subtype_type subtype_) noexcept
5940
{
5941
m_subtype = subtype_;
5942
m_has_subtype = true;
5943
}
5944
5945
/// @brief return the binary subtype
5946
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/
5947
constexpr subtype_type subtype() const noexcept
5948
{
5949
return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
5950
}
5951
5952
/// @brief return whether the value has a subtype
5953
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/
5954
constexpr bool has_subtype() const noexcept
5955
{
5956
return m_has_subtype;
5957
}
5958
5959
/// @brief clears the binary subtype
5960
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/
5961
void clear_subtype() noexcept
5962
{
5963
m_subtype = 0;
5964
m_has_subtype = false;
5965
}
5966
5967
private:
5968
subtype_type m_subtype = 0;
5969
bool m_has_subtype = false;
5970
};
5971
5972
NLOHMANN_JSON_NAMESPACE_END
5973
5974
// #include <nlohmann/detail/conversions/from_json.hpp>
5975
5976
// #include <nlohmann/detail/conversions/to_json.hpp>
5977
5978
// #include <nlohmann/detail/exceptions.hpp>
5979
5980
// #include <nlohmann/detail/hash.hpp>
5981
// __ _____ _____ _____
5982
// __| | __| | | | JSON for Modern C++
5983
// | | |__ | | | | | | version 3.11.3
5984
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5985
//
5986
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5987
// SPDX-License-Identifier: MIT
5988
5989
5990
5991
#include <cstdint> // uint8_t
5992
#include <cstddef> // size_t
5993
#include <functional> // hash
5994
5995
// #include <nlohmann/detail/abi_macros.hpp>
5996
5997
// #include <nlohmann/detail/value_t.hpp>
5998
5999
6000
NLOHMANN_JSON_NAMESPACE_BEGIN
6001
namespace detail
6002
{
6003
6004
// boost::hash_combine
6005
inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6006
{
6007
seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6008
return seed;
6009
}
6010
6011
/*!
6012
@brief hash a JSON value
6013
6014
The hash function tries to rely on std::hash where possible. Furthermore, the
6015
type of the JSON value is taken into account to have different hash values for
6016
null, 0, 0U, and false, etc.
6017
6018
@tparam BasicJsonType basic_json specialization
6019
@param j JSON value to hash
6020
@return hash value of j
6021
*/
6022
template<typename BasicJsonType>
6023
std::size_t hash(const BasicJsonType& j)
6024
{
6025
using string_t = typename BasicJsonType::string_t;
6026
using number_integer_t = typename BasicJsonType::number_integer_t;
6027
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6028
using number_float_t = typename BasicJsonType::number_float_t;
6029
6030
const auto type = static_cast<std::size_t>(j.type());
6031
switch (j.type())
6032
{
6033
case BasicJsonType::value_t::null:
6034
case BasicJsonType::value_t::discarded:
6035
{
6036
return combine(type, 0);
6037
}
6038
6039
case BasicJsonType::value_t::object:
6040
{
6041
auto seed = combine(type, j.size());
6042
for (const auto& element : j.items())
6043
{
6044
const auto h = std::hash<string_t> {}(element.key());
6045
seed = combine(seed, h);
6046
seed = combine(seed, hash(element.value()));
6047
}
6048
return seed;
6049
}
6050
6051
case BasicJsonType::value_t::array:
6052
{
6053
auto seed = combine(type, j.size());
6054
for (const auto& element : j)
6055
{
6056
seed = combine(seed, hash(element));
6057
}
6058
return seed;
6059
}
6060
6061
case BasicJsonType::value_t::string:
6062
{
6063
const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6064
return combine(type, h);
6065
}
6066
6067
case BasicJsonType::value_t::boolean:
6068
{
6069
const auto h = std::hash<bool> {}(j.template get<bool>());
6070
return combine(type, h);
6071
}
6072
6073
case BasicJsonType::value_t::number_integer:
6074
{
6075
const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6076
return combine(type, h);
6077
}
6078
6079
case BasicJsonType::value_t::number_unsigned:
6080
{
6081
const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6082
return combine(type, h);
6083
}
6084
6085
case BasicJsonType::value_t::number_float:
6086
{
6087
const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6088
return combine(type, h);
6089
}
6090
6091
case BasicJsonType::value_t::binary:
6092
{
6093
auto seed = combine(type, j.get_binary().size());
6094
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6095
seed = combine(seed, h);
6096
seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6097
for (const auto byte : j.get_binary())
6098
{
6099
seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6100
}
6101
return seed;
6102
}
6103
6104
default: // LCOV_EXCL_LINE
6105
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6106
return 0; // LCOV_EXCL_LINE
6107
}
6108
}
6109
6110
} // namespace detail
6111
NLOHMANN_JSON_NAMESPACE_END
6112
6113
// #include <nlohmann/detail/input/binary_reader.hpp>
6114
// __ _____ _____ _____
6115
// __| | __| | | | JSON for Modern C++
6116
// | | |__ | | | | | | version 3.11.3
6117
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6118
//
6119
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6120
// SPDX-License-Identifier: MIT
6121
6122
6123
6124
#include <algorithm> // generate_n
6125
#include <array> // array
6126
#include <cmath> // ldexp
6127
#include <cstddef> // size_t
6128
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6129
#include <cstdio> // snprintf
6130
#include <cstring> // memcpy
6131
#include <iterator> // back_inserter
6132
#include <limits> // numeric_limits
6133
#include <string> // char_traits, string
6134
#include <utility> // make_pair, move
6135
#include <vector> // vector
6136
6137
// #include <nlohmann/detail/exceptions.hpp>
6138
6139
// #include <nlohmann/detail/input/input_adapters.hpp>
6140
// __ _____ _____ _____
6141
// __| | __| | | | JSON for Modern C++
6142
// | | |__ | | | | | | version 3.11.3
6143
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6144
//
6145
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6146
// SPDX-License-Identifier: MIT
6147
6148
6149
6150
#include <array> // array
6151
#include <cstddef> // size_t
6152
#include <cstring> // strlen
6153
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6154
#include <memory> // shared_ptr, make_shared, addressof
6155
#include <numeric> // accumulate
6156
#include <string> // string, char_traits
6157
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6158
#include <utility> // pair, declval
6159
6160
#ifndef JSON_NO_IO
6161
#include <cstdio> // FILE *
6162
#include <istream> // istream
6163
#endif // JSON_NO_IO
6164
6165
// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6166
6167
// #include <nlohmann/detail/macro_scope.hpp>
6168
6169
// #include <nlohmann/detail/meta/type_traits.hpp>
6170
6171
6172
NLOHMANN_JSON_NAMESPACE_BEGIN
6173
namespace detail
6174
{
6175
6176
/// the supported input formats
6177
enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
6178
6179
////////////////////
6180
// input adapters //
6181
////////////////////
6182
6183
#ifndef JSON_NO_IO
6184
/*!
6185
Input adapter for stdio file access. This adapter read only 1 byte and do not use any
6186
buffer. This adapter is a very low level adapter.
6187
*/
6188
class file_input_adapter
6189
{
6190
public:
6191
using char_type = char;
6192
6193
JSON_HEDLEY_NON_NULL(2)
6194
explicit file_input_adapter(std::FILE* f) noexcept
6195
: m_file(f)
6196
{
6197
JSON_ASSERT(m_file != nullptr);
6198
}
6199
6200
// make class move-only
6201
file_input_adapter(const file_input_adapter&) = delete;
6202
file_input_adapter(file_input_adapter&&) noexcept = default;
6203
file_input_adapter& operator=(const file_input_adapter&) = delete;
6204
file_input_adapter& operator=(file_input_adapter&&) = delete;
6205
~file_input_adapter() = default;
6206
6207
std::char_traits<char>::int_type get_character() noexcept
6208
{
6209
return std::fgetc(m_file);
6210
}
6211
6212
private:
6213
/// the file pointer to read from
6214
std::FILE* m_file;
6215
};
6216
6217
/*!
6218
Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
6219
beginning of input. Does not support changing the underlying std::streambuf
6220
in mid-input. Maintains underlying std::istream and std::streambuf to support
6221
subsequent use of standard std::istream operations to process any input
6222
characters following those used in parsing the JSON input. Clears the
6223
std::istream flags; any input errors (e.g., EOF) will be detected by the first
6224
subsequent call for input from the std::istream.
6225
*/
6226
class input_stream_adapter
6227
{
6228
public:
6229
using char_type = char;
6230
6231
~input_stream_adapter()
6232
{
6233
// clear stream flags; we use underlying streambuf I/O, do not
6234
// maintain ifstream flags, except eof
6235
if (is != nullptr)
6236
{
6237
is->clear(is->rdstate() & std::ios::eofbit);
6238
}
6239
}
6240
6241
explicit input_stream_adapter(std::istream& i)
6242
: is(&i), sb(i.rdbuf())
6243
{}
6244
6245
// delete because of pointer members
6246
input_stream_adapter(const input_stream_adapter&) = delete;
6247
input_stream_adapter& operator=(input_stream_adapter&) = delete;
6248
input_stream_adapter& operator=(input_stream_adapter&&) = delete;
6249
6250
input_stream_adapter(input_stream_adapter&& rhs) noexcept
6251
: is(rhs.is), sb(rhs.sb)
6252
{
6253
rhs.is = nullptr;
6254
rhs.sb = nullptr;
6255
}
6256
6257
// std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6258
// ensure that std::char_traits<char>::eof() and the character 0xFF do not
6259
// end up as the same value, e.g. 0xFFFFFFFF.
6260
std::char_traits<char>::int_type get_character()
6261
{
6262
auto res = sb->sbumpc();
6263
// set eof manually, as we don't use the istream interface.
6264
if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6265
{
6266
is->clear(is->rdstate() | std::ios::eofbit);
6267
}
6268
return res;
6269
}
6270
6271
private:
6272
/// the associated input stream
6273
std::istream* is = nullptr;
6274
std::streambuf* sb = nullptr;
6275
};
6276
#endif // JSON_NO_IO
6277
6278
// General-purpose iterator-based adapter. It might not be as fast as
6279
// theoretically possible for some containers, but it is extremely versatile.
6280
template<typename IteratorType>
6281
class iterator_input_adapter
6282
{
6283
public:
6284
using char_type = typename std::iterator_traits<IteratorType>::value_type;
6285
6286
iterator_input_adapter(IteratorType first, IteratorType last)
6287
: current(std::move(first)), end(std::move(last))
6288
{}
6289
6290
typename char_traits<char_type>::int_type get_character()
6291
{
6292
if (JSON_HEDLEY_LIKELY(current != end))
6293
{
6294
auto result = char_traits<char_type>::to_int_type(*current);
6295
std::advance(current, 1);
6296
return result;
6297
}
6298
6299
return char_traits<char_type>::eof();
6300
}
6301
6302
private:
6303
IteratorType current;
6304
IteratorType end;
6305
6306
template<typename BaseInputAdapter, size_t T>
6307
friend struct wide_string_input_helper;
6308
6309
bool empty() const
6310
{
6311
return current == end;
6312
}
6313
};
6314
6315
template<typename BaseInputAdapter, size_t T>
6316
struct wide_string_input_helper;
6317
6318
template<typename BaseInputAdapter>
6319
struct wide_string_input_helper<BaseInputAdapter, 4>
6320
{
6321
// UTF-32
6322
static void fill_buffer(BaseInputAdapter& input,
6323
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6324
size_t& utf8_bytes_index,
6325
size_t& utf8_bytes_filled)
6326
{
6327
utf8_bytes_index = 0;
6328
6329
if (JSON_HEDLEY_UNLIKELY(input.empty()))
6330
{
6331
utf8_bytes[0] = std::char_traits<char>::eof();
6332
utf8_bytes_filled = 1;
6333
}
6334
else
6335
{
6336
// get the current character
6337
const auto wc = input.get_character();
6338
6339
// UTF-32 to UTF-8 encoding
6340
if (wc < 0x80)
6341
{
6342
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6343
utf8_bytes_filled = 1;
6344
}
6345
else if (wc <= 0x7FF)
6346
{
6347
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6348
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6349
utf8_bytes_filled = 2;
6350
}
6351
else if (wc <= 0xFFFF)
6352
{
6353
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6354
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6355
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6356
utf8_bytes_filled = 3;
6357
}
6358
else if (wc <= 0x10FFFF)
6359
{
6360
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6361
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6362
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6363
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6364
utf8_bytes_filled = 4;
6365
}
6366
else
6367
{
6368
// unknown character
6369
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6370
utf8_bytes_filled = 1;
6371
}
6372
}
6373
}
6374
};
6375
6376
template<typename BaseInputAdapter>
6377
struct wide_string_input_helper<BaseInputAdapter, 2>
6378
{
6379
// UTF-16
6380
static void fill_buffer(BaseInputAdapter& input,
6381
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6382
size_t& utf8_bytes_index,
6383
size_t& utf8_bytes_filled)
6384
{
6385
utf8_bytes_index = 0;
6386
6387
if (JSON_HEDLEY_UNLIKELY(input.empty()))
6388
{
6389
utf8_bytes[0] = std::char_traits<char>::eof();
6390
utf8_bytes_filled = 1;
6391
}
6392
else
6393
{
6394
// get the current character
6395
const auto wc = input.get_character();
6396
6397
// UTF-16 to UTF-8 encoding
6398
if (wc < 0x80)
6399
{
6400
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6401
utf8_bytes_filled = 1;
6402
}
6403
else if (wc <= 0x7FF)
6404
{
6405
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6406
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6407
utf8_bytes_filled = 2;
6408
}
6409
else if (0xD800 > wc || wc >= 0xE000)
6410
{
6411
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6412
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6413
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6414
utf8_bytes_filled = 3;
6415
}
6416
else
6417
{
6418
if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6419
{
6420
const auto wc2 = static_cast<unsigned int>(input.get_character());
6421
const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6422
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6423
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6424
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6425
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6426
utf8_bytes_filled = 4;
6427
}
6428
else
6429
{
6430
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6431
utf8_bytes_filled = 1;
6432
}
6433
}
6434
}
6435
}
6436
};
6437
6438
// Wraps another input adapter to convert wide character types into individual bytes.
6439
template<typename BaseInputAdapter, typename WideCharType>
6440
class wide_string_input_adapter
6441
{
6442
public:
6443
using char_type = char;
6444
6445
wide_string_input_adapter(BaseInputAdapter base)
6446
: base_adapter(base) {}
6447
6448
typename std::char_traits<char>::int_type get_character() noexcept
6449
{
6450
// check if buffer needs to be filled
6451
if (utf8_bytes_index == utf8_bytes_filled)
6452
{
6453
fill_buffer<sizeof(WideCharType)>();
6454
6455
JSON_ASSERT(utf8_bytes_filled > 0);
6456
JSON_ASSERT(utf8_bytes_index == 0);
6457
}
6458
6459
// use buffer
6460
JSON_ASSERT(utf8_bytes_filled > 0);
6461
JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6462
return utf8_bytes[utf8_bytes_index++];
6463
}
6464
6465
private:
6466
BaseInputAdapter base_adapter;
6467
6468
template<size_t T>
6469
void fill_buffer()
6470
{
6471
wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6472
}
6473
6474
/// a buffer for UTF-8 bytes
6475
std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6476
6477
/// index to the utf8_codes array for the next valid byte
6478
std::size_t utf8_bytes_index = 0;
6479
/// number of valid bytes in the utf8_codes array
6480
std::size_t utf8_bytes_filled = 0;
6481
};
6482
6483
template<typename IteratorType, typename Enable = void>
6484
struct iterator_input_adapter_factory
6485
{
6486
using iterator_type = IteratorType;
6487
using char_type = typename std::iterator_traits<iterator_type>::value_type;
6488
using adapter_type = iterator_input_adapter<iterator_type>;
6489
6490
static adapter_type create(IteratorType first, IteratorType last)
6491
{
6492
return adapter_type(std::move(first), std::move(last));
6493
}
6494
};
6495
6496
template<typename T>
6497
struct is_iterator_of_multibyte
6498
{
6499
using value_type = typename std::iterator_traits<T>::value_type;
6500
enum
6501
{
6502
value = sizeof(value_type) > 1
6503
};
6504
};
6505
6506
template<typename IteratorType>
6507
struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
6508
{
6509
using iterator_type = IteratorType;
6510
using char_type = typename std::iterator_traits<iterator_type>::value_type;
6511
using base_adapter_type = iterator_input_adapter<iterator_type>;
6512
using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
6513
6514
static adapter_type create(IteratorType first, IteratorType last)
6515
{
6516
return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6517
}
6518
};
6519
6520
// General purpose iterator-based input
6521
template<typename IteratorType>
6522
typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
6523
{
6524
using factory_type = iterator_input_adapter_factory<IteratorType>;
6525
return factory_type::create(first, last);
6526
}
6527
6528
// Convenience shorthand from container to iterator
6529
// Enables ADL on begin(container) and end(container)
6530
// Encloses the using declarations in namespace for not to leak them to outside scope
6531
6532
namespace container_input_adapter_factory_impl
6533
{
6534
6535
using std::begin;
6536
using std::end;
6537
6538
template<typename ContainerType, typename Enable = void>
6539
struct container_input_adapter_factory {};
6540
6541
template<typename ContainerType>
6542
struct container_input_adapter_factory< ContainerType,
6543
void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6544
{
6545
using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6546
6547
static adapter_type create(const ContainerType& container)
6548
{
6549
return input_adapter(begin(container), end(container));
6550
}
6551
};
6552
6553
} // namespace container_input_adapter_factory_impl
6554
6555
template<typename ContainerType>
6556
typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
6557
{
6558
return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
6559
}
6560
6561
#ifndef JSON_NO_IO
6562
// Special cases with fast paths
6563
inline file_input_adapter input_adapter(std::FILE* file)
6564
{
6565
return file_input_adapter(file);
6566
}
6567
6568
inline input_stream_adapter input_adapter(std::istream& stream)
6569
{
6570
return input_stream_adapter(stream);
6571
}
6572
6573
inline input_stream_adapter input_adapter(std::istream&& stream)
6574
{
6575
return input_stream_adapter(stream);
6576
}
6577
#endif // JSON_NO_IO
6578
6579
using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6580
6581
// Null-delimited strings, and the like.
6582
template < typename CharT,
6583
typename std::enable_if <
6584
std::is_pointer<CharT>::value&&
6585
!std::is_array<CharT>::value&&
6586
std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6587
sizeof(typename std::remove_pointer<CharT>::type) == 1,
6588
int >::type = 0 >
6589
contiguous_bytes_input_adapter input_adapter(CharT b)
6590
{
6591
auto length = std::strlen(reinterpret_cast<const char*>(b));
6592
const auto* ptr = reinterpret_cast<const char*>(b);
6593
return input_adapter(ptr, ptr + length);
6594
}
6595
6596
template<typename T, std::size_t N>
6597
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)
6598
{
6599
return input_adapter(array, array + N);
6600
}
6601
6602
// This class only handles inputs of input_buffer_adapter type.
6603
// It's required so that expressions like {ptr, len} can be implicitly cast
6604
// to the correct adapter.
6605
class span_input_adapter
6606
{
6607
public:
6608
template < typename CharT,
6609
typename std::enable_if <
6610
std::is_pointer<CharT>::value&&
6611
std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6612
sizeof(typename std::remove_pointer<CharT>::type) == 1,
6613
int >::type = 0 >
6614
span_input_adapter(CharT b, std::size_t l)
6615
: ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6616
6617
template<class IteratorType,
6618
typename std::enable_if<
6619
std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
6620
int>::type = 0>
6621
span_input_adapter(IteratorType first, IteratorType last)
6622
: ia(input_adapter(first, last)) {}
6623
6624
contiguous_bytes_input_adapter&& get()
6625
{
6626
return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6627
}
6628
6629
private:
6630
contiguous_bytes_input_adapter ia;
6631
};
6632
6633
} // namespace detail
6634
NLOHMANN_JSON_NAMESPACE_END
6635
6636
// #include <nlohmann/detail/input/json_sax.hpp>
6637
// __ _____ _____ _____
6638
// __| | __| | | | JSON for Modern C++
6639
// | | |__ | | | | | | version 3.11.3
6640
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6641
//
6642
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6643
// SPDX-License-Identifier: MIT
6644
6645
6646
6647
#include <cstddef>
6648
#include <string> // string
6649
#include <utility> // move
6650
#include <vector> // vector
6651
6652
// #include <nlohmann/detail/exceptions.hpp>
6653
6654
// #include <nlohmann/detail/macro_scope.hpp>
6655
6656
// #include <nlohmann/detail/string_concat.hpp>
6657
6658
6659
NLOHMANN_JSON_NAMESPACE_BEGIN
6660
6661
/*!
6662
@brief SAX interface
6663
6664
This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
6665
Each function is called in different situations while the input is parsed. The
6666
boolean return value informs the parser whether to continue processing the
6667
input.
6668
*/
6669
template<typename BasicJsonType>
6670
struct json_sax
6671
{
6672
using number_integer_t = typename BasicJsonType::number_integer_t;
6673
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6674
using number_float_t = typename BasicJsonType::number_float_t;
6675
using string_t = typename BasicJsonType::string_t;
6676
using binary_t = typename BasicJsonType::binary_t;
6677
6678
/*!
6679
@brief a null value was read
6680
@return whether parsing should proceed
6681
*/
6682
virtual bool null() = 0;
6683
6684
/*!
6685
@brief a boolean value was read
6686
@param[in] val boolean value
6687
@return whether parsing should proceed
6688
*/
6689
virtual bool boolean(bool val) = 0;
6690
6691
/*!
6692
@brief an integer number was read
6693
@param[in] val integer value
6694
@return whether parsing should proceed
6695
*/
6696
virtual bool number_integer(number_integer_t val) = 0;
6697
6698
/*!
6699
@brief an unsigned integer number was read
6700
@param[in] val unsigned integer value
6701
@return whether parsing should proceed
6702
*/
6703
virtual bool number_unsigned(number_unsigned_t val) = 0;
6704
6705
/*!
6706
@brief a floating-point number was read
6707
@param[in] val floating-point value
6708
@param[in] s raw token value
6709
@return whether parsing should proceed
6710
*/
6711
virtual bool number_float(number_float_t val, const string_t& s) = 0;
6712
6713
/*!
6714
@brief a string value was read
6715
@param[in] val string value
6716
@return whether parsing should proceed
6717
@note It is safe to move the passed string value.
6718
*/
6719
virtual bool string(string_t& val) = 0;
6720
6721
/*!
6722
@brief a binary value was read
6723
@param[in] val binary value
6724
@return whether parsing should proceed
6725
@note It is safe to move the passed binary value.
6726
*/
6727
virtual bool binary(binary_t& val) = 0;
6728
6729
/*!
6730
@brief the beginning of an object was read
6731
@param[in] elements number of object elements or -1 if unknown
6732
@return whether parsing should proceed
6733
@note binary formats may report the number of elements
6734
*/
6735
virtual bool start_object(std::size_t elements) = 0;
6736
6737
/*!
6738
@brief an object key was read
6739
@param[in] val object key
6740
@return whether parsing should proceed
6741
@note It is safe to move the passed string.
6742
*/
6743
virtual bool key(string_t& val) = 0;
6744
6745
/*!
6746
@brief the end of an object was read
6747
@return whether parsing should proceed
6748
*/
6749
virtual bool end_object() = 0;
6750
6751
/*!
6752
@brief the beginning of an array was read
6753
@param[in] elements number of array elements or -1 if unknown
6754
@return whether parsing should proceed
6755
@note binary formats may report the number of elements
6756
*/
6757
virtual bool start_array(std::size_t elements) = 0;
6758
6759
/*!
6760
@brief the end of an array was read
6761
@return whether parsing should proceed
6762
*/
6763
virtual bool end_array() = 0;
6764
6765
/*!
6766
@brief a parse error occurred
6767
@param[in] position the position in the input where the error occurs
6768
@param[in] last_token the last read token
6769
@param[in] ex an exception object describing the error
6770
@return whether parsing should proceed (must return false)
6771
*/
6772
virtual bool parse_error(std::size_t position,
6773
const std::string& last_token,
6774
const detail::exception& ex) = 0;
6775
6776
json_sax() = default;
6777
json_sax(const json_sax&) = default;
6778
json_sax(json_sax&&) noexcept = default;
6779
json_sax& operator=(const json_sax&) = default;
6780
json_sax& operator=(json_sax&&) noexcept = default;
6781
virtual ~json_sax() = default;
6782
};
6783
6784
namespace detail
6785
{
6786
/*!
6787
@brief SAX implementation to create a JSON value from SAX events
6788
6789
This class implements the @ref json_sax interface and processes the SAX events
6790
to create a JSON value which makes it basically a DOM parser. The structure or
6791
hierarchy of the JSON value is managed by the stack `ref_stack` which contains
6792
a pointer to the respective array or object for each recursion depth.
6793
6794
After successful parsing, the value that is passed by reference to the
6795
constructor contains the parsed value.
6796
6797
@tparam BasicJsonType the JSON type
6798
*/
6799
template<typename BasicJsonType>
6800
class json_sax_dom_parser
6801
{
6802
public:
6803
using number_integer_t = typename BasicJsonType::number_integer_t;
6804
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6805
using number_float_t = typename BasicJsonType::number_float_t;
6806
using string_t = typename BasicJsonType::string_t;
6807
using binary_t = typename BasicJsonType::binary_t;
6808
6809
/*!
6810
@param[in,out] r reference to a JSON value that is manipulated while
6811
parsing
6812
@param[in] allow_exceptions_ whether parse errors yield exceptions
6813
*/
6814
explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
6815
: root(r), allow_exceptions(allow_exceptions_)
6816
{}
6817
6818
// make class move-only
6819
json_sax_dom_parser(const json_sax_dom_parser&) = delete;
6820
json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6821
json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
6822
json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6823
~json_sax_dom_parser() = default;
6824
6825
bool null()
6826
{
6827
handle_value(nullptr);
6828
return true;
6829
}
6830
6831
bool boolean(bool val)
6832
{
6833
handle_value(val);
6834
return true;
6835
}
6836
6837
bool number_integer(number_integer_t val)
6838
{
6839
handle_value(val);
6840
return true;
6841
}
6842
6843
bool number_unsigned(number_unsigned_t val)
6844
{
6845
handle_value(val);
6846
return true;
6847
}
6848
6849
bool number_float(number_float_t val, const string_t& /*unused*/)
6850
{
6851
handle_value(val);
6852
return true;
6853
}
6854
6855
bool string(string_t& val)
6856
{
6857
handle_value(val);
6858
return true;
6859
}
6860
6861
bool binary(binary_t& val)
6862
{
6863
handle_value(std::move(val));
6864
return true;
6865
}
6866
6867
bool start_object(std::size_t len)
6868
{
6869
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
6870
6871
if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6872
{
6873
JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6874
}
6875
6876
return true;
6877
}
6878
6879
bool key(string_t& val)
6880
{
6881
JSON_ASSERT(!ref_stack.empty());
6882
JSON_ASSERT(ref_stack.back()->is_object());
6883
6884
// add null at given key and store the reference for later
6885
object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
6886
return true;
6887
}
6888
6889
bool end_object()
6890
{
6891
JSON_ASSERT(!ref_stack.empty());
6892
JSON_ASSERT(ref_stack.back()->is_object());
6893
6894
ref_stack.back()->set_parents();
6895
ref_stack.pop_back();
6896
return true;
6897
}
6898
6899
bool start_array(std::size_t len)
6900
{
6901
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
6902
6903
if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6904
{
6905
JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
6906
}
6907
6908
return true;
6909
}
6910
6911
bool end_array()
6912
{
6913
JSON_ASSERT(!ref_stack.empty());
6914
JSON_ASSERT(ref_stack.back()->is_array());
6915
6916
ref_stack.back()->set_parents();
6917
ref_stack.pop_back();
6918
return true;
6919
}
6920
6921
template<class Exception>
6922
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
6923
const Exception& ex)
6924
{
6925
errored = true;
6926
static_cast<void>(ex);
6927
if (allow_exceptions)
6928
{
6929
JSON_THROW(ex);
6930
}
6931
return false;
6932
}
6933
6934
constexpr bool is_errored() const
6935
{
6936
return errored;
6937
}
6938
6939
private:
6940
/*!
6941
@invariant If the ref stack is empty, then the passed value will be the new
6942
root.
6943
@invariant If the ref stack contains a value, then it is an array or an
6944
object to which we can add elements
6945
*/
6946
template<typename Value>
6947
JSON_HEDLEY_RETURNS_NON_NULL
6948
BasicJsonType* handle_value(Value&& v)
6949
{
6950
if (ref_stack.empty())
6951
{
6952
root = BasicJsonType(std::forward<Value>(v));
6953
return &root;
6954
}
6955
6956
JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6957
6958
if (ref_stack.back()->is_array())
6959
{
6960
ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
6961
return &(ref_stack.back()->m_data.m_value.array->back());
6962
}
6963
6964
JSON_ASSERT(ref_stack.back()->is_object());
6965
JSON_ASSERT(object_element);
6966
*object_element = BasicJsonType(std::forward<Value>(v));
6967
return object_element;
6968
}
6969
6970
/// the parsed JSON value
6971
BasicJsonType& root;
6972
/// stack to model hierarchy of values
6973
std::vector<BasicJsonType*> ref_stack {};
6974
/// helper to hold the reference for the next object element
6975
BasicJsonType* object_element = nullptr;
6976
/// whether a syntax error occurred
6977
bool errored = false;
6978
/// whether to throw exceptions in case of errors
6979
const bool allow_exceptions = true;
6980
};
6981
6982
template<typename BasicJsonType>
6983
class json_sax_dom_callback_parser
6984
{
6985
public:
6986
using number_integer_t = typename BasicJsonType::number_integer_t;
6987
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6988
using number_float_t = typename BasicJsonType::number_float_t;
6989
using string_t = typename BasicJsonType::string_t;
6990
using binary_t = typename BasicJsonType::binary_t;
6991
using parser_callback_t = typename BasicJsonType::parser_callback_t;
6992
using parse_event_t = typename BasicJsonType::parse_event_t;
6993
6994
json_sax_dom_callback_parser(BasicJsonType& r,
6995
const parser_callback_t cb,
6996
const bool allow_exceptions_ = true)
6997
: root(r), callback(cb), allow_exceptions(allow_exceptions_)
6998
{
6999
keep_stack.push_back(true);
7000
}
7001
7002
// make class move-only
7003
json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
7004
json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7005
json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
7006
json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7007
~json_sax_dom_callback_parser() = default;
7008
7009
bool null()
7010
{
7011
handle_value(nullptr);
7012
return true;
7013
}
7014
7015
bool boolean(bool val)
7016
{
7017
handle_value(val);
7018
return true;
7019
}
7020
7021
bool number_integer(number_integer_t val)
7022
{
7023
handle_value(val);
7024
return true;
7025
}
7026
7027
bool number_unsigned(number_unsigned_t val)
7028
{
7029
handle_value(val);
7030
return true;
7031
}
7032
7033
bool number_float(number_float_t val, const string_t& /*unused*/)
7034
{
7035
handle_value(val);
7036
return true;
7037
}
7038
7039
bool string(string_t& val)
7040
{
7041
handle_value(val);
7042
return true;
7043
}
7044
7045
bool binary(binary_t& val)
7046
{
7047
handle_value(std::move(val));
7048
return true;
7049
}
7050
7051
bool start_object(std::size_t len)
7052
{
7053
// check callback for object start
7054
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
7055
keep_stack.push_back(keep);
7056
7057
auto val = handle_value(BasicJsonType::value_t::object, true);
7058
ref_stack.push_back(val.second);
7059
7060
// check object limit
7061
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7062
{
7063
JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
7064
}
7065
7066
return true;
7067
}
7068
7069
bool key(string_t& val)
7070
{
7071
BasicJsonType k = BasicJsonType(val);
7072
7073
// check callback for key
7074
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
7075
key_keep_stack.push_back(keep);
7076
7077
// add discarded value at given key and store the reference for later
7078
if (keep && ref_stack.back())
7079
{
7080
object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
7081
}
7082
7083
return true;
7084
}
7085
7086
bool end_object()
7087
{
7088
if (ref_stack.back())
7089
{
7090
if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
7091
{
7092
// discard object
7093
*ref_stack.back() = discarded;
7094
}
7095
else
7096
{
7097
ref_stack.back()->set_parents();
7098
}
7099
}
7100
7101
JSON_ASSERT(!ref_stack.empty());
7102
JSON_ASSERT(!keep_stack.empty());
7103
ref_stack.pop_back();
7104
keep_stack.pop_back();
7105
7106
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
7107
{
7108
// remove discarded value
7109
for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
7110
{
7111
if (it->is_discarded())
7112
{
7113
ref_stack.back()->erase(it);
7114
break;
7115
}
7116
}
7117
}
7118
7119
return true;
7120
}
7121
7122
bool start_array(std::size_t len)
7123
{
7124
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
7125
keep_stack.push_back(keep);
7126
7127
auto val = handle_value(BasicJsonType::value_t::array, true);
7128
ref_stack.push_back(val.second);
7129
7130
// check array limit
7131
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7132
{
7133
JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
7134
}
7135
7136
return true;
7137
}
7138
7139
bool end_array()
7140
{
7141
bool keep = true;
7142
7143
if (ref_stack.back())
7144
{
7145
keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
7146
if (keep)
7147
{
7148
ref_stack.back()->set_parents();
7149
}
7150
else
7151
{
7152
// discard array
7153
*ref_stack.back() = discarded;
7154
}
7155
}
7156
7157
JSON_ASSERT(!ref_stack.empty());
7158
JSON_ASSERT(!keep_stack.empty());
7159
ref_stack.pop_back();
7160
keep_stack.pop_back();
7161
7162
// remove discarded value
7163
if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
7164
{
7165
ref_stack.back()->m_data.m_value.array->pop_back();
7166
}
7167
7168
return true;
7169
}
7170
7171
template<class Exception>
7172
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
7173
const Exception& ex)
7174
{
7175
errored = true;
7176
static_cast<void>(ex);
7177
if (allow_exceptions)
7178
{
7179
JSON_THROW(ex);
7180
}
7181
return false;
7182
}
7183
7184
constexpr bool is_errored() const
7185
{
7186
return errored;
7187
}
7188
7189
private:
7190
/*!
7191
@param[in] v value to add to the JSON value we build during parsing
7192
@param[in] skip_callback whether we should skip calling the callback
7193
function; this is required after start_array() and
7194
start_object() SAX events, because otherwise we would call the
7195
callback function with an empty array or object, respectively.
7196
7197
@invariant If the ref stack is empty, then the passed value will be the new
7198
root.
7199
@invariant If the ref stack contains a value, then it is an array or an
7200
object to which we can add elements
7201
7202
@return pair of boolean (whether value should be kept) and pointer (to the
7203
passed value in the ref_stack hierarchy; nullptr if not kept)
7204
*/
7205
template<typename Value>
7206
std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
7207
{
7208
JSON_ASSERT(!keep_stack.empty());
7209
7210
// do not handle this value if we know it would be added to a discarded
7211
// container
7212
if (!keep_stack.back())
7213
{
7214
return {false, nullptr};
7215
}
7216
7217
// create value
7218
auto value = BasicJsonType(std::forward<Value>(v));
7219
7220
// check callback
7221
const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
7222
7223
// do not handle this value if we just learnt it shall be discarded
7224
if (!keep)
7225
{
7226
return {false, nullptr};
7227
}
7228
7229
if (ref_stack.empty())
7230
{
7231
root = std::move(value);
7232
return {true, & root};
7233
}
7234
7235
// skip this value if we already decided to skip the parent
7236
// (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
7237
if (!ref_stack.back())
7238
{
7239
return {false, nullptr};
7240
}
7241
7242
// we now only expect arrays and objects
7243
JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
7244
7245
// array
7246
if (ref_stack.back()->is_array())
7247
{
7248
ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
7249
return {true, & (ref_stack.back()->m_data.m_value.array->back())};
7250
}
7251
7252
// object
7253
JSON_ASSERT(ref_stack.back()->is_object());
7254
// check if we should store an element for the current key
7255
JSON_ASSERT(!key_keep_stack.empty());
7256
const bool store_element = key_keep_stack.back();
7257
key_keep_stack.pop_back();
7258
7259
if (!store_element)
7260
{
7261
return {false, nullptr};
7262
}
7263
7264
JSON_ASSERT(object_element);
7265
*object_element = std::move(value);
7266
return {true, object_element};
7267
}
7268
7269
/// the parsed JSON value
7270
BasicJsonType& root;
7271
/// stack to model hierarchy of values
7272
std::vector<BasicJsonType*> ref_stack {};
7273
/// stack to manage which values to keep
7274
std::vector<bool> keep_stack {};
7275
/// stack to manage which object keys to keep
7276
std::vector<bool> key_keep_stack {};
7277
/// helper to hold the reference for the next object element
7278
BasicJsonType* object_element = nullptr;
7279
/// whether a syntax error occurred
7280
bool errored = false;
7281
/// callback function
7282
const parser_callback_t callback = nullptr;
7283
/// whether to throw exceptions in case of errors
7284
const bool allow_exceptions = true;
7285
/// a discarded value for the callback
7286
BasicJsonType discarded = BasicJsonType::value_t::discarded;
7287
};
7288
7289
template<typename BasicJsonType>
7290
class json_sax_acceptor
7291
{
7292
public:
7293
using number_integer_t = typename BasicJsonType::number_integer_t;
7294
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7295
using number_float_t = typename BasicJsonType::number_float_t;
7296
using string_t = typename BasicJsonType::string_t;
7297
using binary_t = typename BasicJsonType::binary_t;
7298
7299
bool null()
7300
{
7301
return true;
7302
}
7303
7304
bool boolean(bool /*unused*/)
7305
{
7306
return true;
7307
}
7308
7309
bool number_integer(number_integer_t /*unused*/)
7310
{
7311
return true;
7312
}
7313
7314
bool number_unsigned(number_unsigned_t /*unused*/)
7315
{
7316
return true;
7317
}
7318
7319
bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
7320
{
7321
return true;
7322
}
7323
7324
bool string(string_t& /*unused*/)
7325
{
7326
return true;
7327
}
7328
7329
bool binary(binary_t& /*unused*/)
7330
{
7331
return true;
7332
}
7333
7334
bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7335
{
7336
return true;
7337
}
7338
7339
bool key(string_t& /*unused*/)
7340
{
7341
return true;
7342
}
7343
7344
bool end_object()
7345
{
7346
return true;
7347
}
7348
7349
bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7350
{
7351
return true;
7352
}
7353
7354
bool end_array()
7355
{
7356
return true;
7357
}
7358
7359
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
7360
{
7361
return false;
7362
}
7363
};
7364
7365
} // namespace detail
7366
NLOHMANN_JSON_NAMESPACE_END
7367
7368
// #include <nlohmann/detail/input/lexer.hpp>
7369
// __ _____ _____ _____
7370
// __| | __| | | | JSON for Modern C++
7371
// | | |__ | | | | | | version 3.11.3
7372
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7373
//
7374
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
7375
// SPDX-License-Identifier: MIT
7376
7377
7378
7379
#include <array> // array
7380
#include <clocale> // localeconv
7381
#include <cstddef> // size_t
7382
#include <cstdio> // snprintf
7383
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7384
#include <initializer_list> // initializer_list
7385
#include <string> // char_traits, string
7386
#include <utility> // move
7387
#include <vector> // vector
7388
7389
// #include <nlohmann/detail/input/input_adapters.hpp>
7390
7391
// #include <nlohmann/detail/input/position_t.hpp>
7392
7393
// #include <nlohmann/detail/macro_scope.hpp>
7394
7395
// #include <nlohmann/detail/meta/type_traits.hpp>
7396
7397
7398
NLOHMANN_JSON_NAMESPACE_BEGIN
7399
namespace detail
7400
{
7401
7402
///////////
7403
// lexer //
7404
///////////
7405
7406
template<typename BasicJsonType>
7407
class lexer_base
7408
{
7409
public:
7410
/// token types for the parser
7411
enum class token_type
7412
{
7413
uninitialized, ///< indicating the scanner is uninitialized
7414
literal_true, ///< the `true` literal
7415
literal_false, ///< the `false` literal
7416
literal_null, ///< the `null` literal
7417
value_string, ///< a string -- use get_string() for actual value
7418
value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
7419
value_integer, ///< a signed integer -- use get_number_integer() for actual value
7420
value_float, ///< an floating point number -- use get_number_float() for actual value
7421
begin_array, ///< the character for array begin `[`
7422
begin_object, ///< the character for object begin `{`
7423
end_array, ///< the character for array end `]`
7424
end_object, ///< the character for object end `}`
7425
name_separator, ///< the name separator `:`
7426
value_separator, ///< the value separator `,`
7427
parse_error, ///< indicating a parse error
7428
end_of_input, ///< indicating the end of the input buffer
7429
literal_or_value ///< a literal or the begin of a value (only for diagnostics)
7430
};
7431
7432
/// return name of values of type token_type (only used for errors)
7433
JSON_HEDLEY_RETURNS_NON_NULL
7434
JSON_HEDLEY_CONST
7435
static const char* token_type_name(const token_type t) noexcept
7436
{
7437
switch (t)
7438
{
7439
case token_type::uninitialized:
7440
return "<uninitialized>";
7441
case token_type::literal_true:
7442
return "true literal";
7443
case token_type::literal_false:
7444
return "false literal";
7445
case token_type::literal_null:
7446
return "null literal";
7447
case token_type::value_string:
7448
return "string literal";
7449
case token_type::value_unsigned:
7450
case token_type::value_integer:
7451
case token_type::value_float:
7452
return "number literal";
7453
case token_type::begin_array:
7454
return "'['";
7455
case token_type::begin_object:
7456
return "'{'";
7457
case token_type::end_array:
7458
return "']'";
7459
case token_type::end_object:
7460
return "'}'";
7461
case token_type::name_separator:
7462
return "':'";
7463
case token_type::value_separator:
7464
return "','";
7465
case token_type::parse_error:
7466
return "<parse error>";
7467
case token_type::end_of_input:
7468
return "end of input";
7469
case token_type::literal_or_value:
7470
return "'[', '{', or a literal";
7471
// LCOV_EXCL_START
7472
default: // catch non-enum values
7473
return "unknown token";
7474
// LCOV_EXCL_STOP
7475
}
7476
}
7477
};
7478
/*!
7479
@brief lexical analysis
7480
7481
This class organizes the lexical analysis during JSON deserialization.
7482
*/
7483
template<typename BasicJsonType, typename InputAdapterType>
7484
class lexer : public lexer_base<BasicJsonType>
7485
{
7486
using number_integer_t = typename BasicJsonType::number_integer_t;
7487
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7488
using number_float_t = typename BasicJsonType::number_float_t;
7489
using string_t = typename BasicJsonType::string_t;
7490
using char_type = typename InputAdapterType::char_type;
7491
using char_int_type = typename char_traits<char_type>::int_type;
7492
7493
public:
7494
using token_type = typename lexer_base<BasicJsonType>::token_type;
7495
7496
explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7497
: ia(std::move(adapter))
7498
, ignore_comments(ignore_comments_)
7499
, decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7500
{}
7501
7502
// delete because of pointer members
7503
lexer(const lexer&) = delete;
7504
lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7505
lexer& operator=(lexer&) = delete;
7506
lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7507
~lexer() = default;
7508
7509
private:
7510
/////////////////////
7511
// locales
7512
/////////////////////
7513
7514
/// return the locale-dependent decimal point
7515
JSON_HEDLEY_PURE
7516
static char get_decimal_point() noexcept
7517
{
7518
const auto* loc = localeconv();
7519
JSON_ASSERT(loc != nullptr);
7520
return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7521
}
7522
7523
/////////////////////
7524
// scan functions
7525
/////////////////////
7526
7527
/*!
7528
@brief get codepoint from 4 hex characters following `\u`
7529
7530
For input "\u c1 c2 c3 c4" the codepoint is:
7531
(c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
7532
= (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
7533
7534
Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
7535
must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
7536
conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
7537
between the ASCII value of the character and the desired integer value.
7538
7539
@return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
7540
non-hex character)
7541
*/
7542
int get_codepoint()
7543
{
7544
// this function only makes sense after reading `\u`
7545
JSON_ASSERT(current == 'u');
7546
int codepoint = 0;
7547
7548
const auto factors = { 12u, 8u, 4u, 0u };
7549
for (const auto factor : factors)
7550
{
7551
get();
7552
7553
if (current >= '0' && current <= '9')
7554
{
7555
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7556
}
7557
else if (current >= 'A' && current <= 'F')
7558
{
7559
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7560
}
7561
else if (current >= 'a' && current <= 'f')
7562
{
7563
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7564
}
7565
else
7566
{
7567
return -1;
7568
}
7569
}
7570
7571
JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7572
return codepoint;
7573
}
7574
7575
/*!
7576
@brief check if the next byte(s) are inside a given range
7577
7578
Adds the current byte and, for each passed range, reads a new byte and
7579
checks if it is inside the range. If a violation was detected, set up an
7580
error message and return false. Otherwise, return true.
7581
7582
@param[in] ranges list of integers; interpreted as list of pairs of
7583
inclusive lower and upper bound, respectively
7584
7585
@pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
7586
1, 2, or 3 pairs. This precondition is enforced by an assertion.
7587
7588
@return true if and only if no range violation was detected
7589
*/
7590
bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7591
{
7592
JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7593
add(current);
7594
7595
for (auto range = ranges.begin(); range != ranges.end(); ++range)
7596
{
7597
get();
7598
if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7599
{
7600
add(current);
7601
}
7602
else
7603
{
7604
error_message = "invalid string: ill-formed UTF-8 byte";
7605
return false;
7606
}
7607
}
7608
7609
return true;
7610
}
7611
7612
/*!
7613
@brief scan a string literal
7614
7615
This function scans a string according to Sect. 7 of RFC 8259. While
7616
scanning, bytes are escaped and copied into buffer token_buffer. Then the
7617
function returns successfully, token_buffer is *not* null-terminated (as it
7618
may contain \0 bytes), and token_buffer.size() is the number of bytes in the
7619
string.
7620
7621
@return token_type::value_string if string could be successfully scanned,
7622
token_type::parse_error otherwise
7623
7624
@note In case of errors, variable error_message contains a textual
7625
description.
7626
*/
7627
token_type scan_string()
7628
{
7629
// reset token_buffer (ignore opening quote)
7630
reset();
7631
7632
// we entered the function by reading an open quote
7633
JSON_ASSERT(current == '\"');
7634
7635
while (true)
7636
{
7637
// get next character
7638
switch (get())
7639
{
7640
// end of file while parsing string
7641
case char_traits<char_type>::eof():
7642
{
7643
error_message = "invalid string: missing closing quote";
7644
return token_type::parse_error;
7645
}
7646
7647
// closing quote
7648
case '\"':
7649
{
7650
return token_type::value_string;
7651
}
7652
7653
// escapes
7654
case '\\':
7655
{
7656
switch (get())
7657
{
7658
// quotation mark
7659
case '\"':
7660
add('\"');
7661
break;
7662
// reverse solidus
7663
case '\\':
7664
add('\\');
7665
break;
7666
// solidus
7667
case '/':
7668
add('/');
7669
break;
7670
// backspace
7671
case 'b':
7672
add('\b');
7673
break;
7674
// form feed
7675
case 'f':
7676
add('\f');
7677
break;
7678
// line feed
7679
case 'n':
7680
add('\n');
7681
break;
7682
// carriage return
7683
case 'r':
7684
add('\r');
7685
break;
7686
// tab
7687
case 't':
7688
add('\t');
7689
break;
7690
7691
// unicode escapes
7692
case 'u':
7693
{
7694
const int codepoint1 = get_codepoint();
7695
int codepoint = codepoint1; // start with codepoint1
7696
7697
if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7698
{
7699
error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7700
return token_type::parse_error;
7701
}
7702
7703
// check if code point is a high surrogate
7704
if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7705
{
7706
// expect next \uxxxx entry
7707
if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7708
{
7709
const int codepoint2 = get_codepoint();
7710
7711
if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7712
{
7713
error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7714
return token_type::parse_error;
7715
}
7716
7717
// check if codepoint2 is a low surrogate
7718
if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7719
{
7720
// overwrite codepoint
7721
codepoint = static_cast<int>(
7722
// high surrogate occupies the most significant 22 bits
7723
(static_cast<unsigned int>(codepoint1) << 10u)
7724
// low surrogate occupies the least significant 15 bits
7725
+ static_cast<unsigned int>(codepoint2)
7726
// there is still the 0xD800, 0xDC00 and 0x10000 noise
7727
// in the result, so we have to subtract with:
7728
// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7729
- 0x35FDC00u);
7730
}
7731
else
7732
{
7733
error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7734
return token_type::parse_error;
7735
}
7736
}
7737
else
7738
{
7739
error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7740
return token_type::parse_error;
7741
}
7742
}
7743
else
7744
{
7745
if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7746
{
7747
error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7748
return token_type::parse_error;
7749
}
7750
}
7751
7752
// result of the above calculation yields a proper codepoint
7753
JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7754
7755
// translate codepoint into bytes
7756
if (codepoint < 0x80)
7757
{
7758
// 1-byte characters: 0xxxxxxx (ASCII)
7759
add(static_cast<char_int_type>(codepoint));
7760
}
7761
else if (codepoint <= 0x7FF)
7762
{
7763
// 2-byte characters: 110xxxxx 10xxxxxx
7764
add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7765
add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7766
}
7767
else if (codepoint <= 0xFFFF)
7768
{
7769
// 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7770
add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7771
add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7772
add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7773
}
7774
else
7775
{
7776
// 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7777
add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7778
add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7779
add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7780
add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7781
}
7782
7783
break;
7784
}
7785
7786
// other characters after escape
7787
default:
7788
error_message = "invalid string: forbidden character after backslash";
7789
return token_type::parse_error;
7790
}
7791
7792
break;
7793
}
7794
7795
// invalid control characters
7796
case 0x00:
7797
{
7798
error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7799
return token_type::parse_error;
7800
}
7801
7802
case 0x01:
7803
{
7804
error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7805
return token_type::parse_error;
7806
}
7807
7808
case 0x02:
7809
{
7810
error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7811
return token_type::parse_error;
7812
}
7813
7814
case 0x03:
7815
{
7816
error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7817
return token_type::parse_error;
7818
}
7819
7820
case 0x04:
7821
{
7822
error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7823
return token_type::parse_error;
7824
}
7825
7826
case 0x05:
7827
{
7828
error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7829
return token_type::parse_error;
7830
}
7831
7832
case 0x06:
7833
{
7834
error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7835
return token_type::parse_error;
7836
}
7837
7838
case 0x07:
7839
{
7840
error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7841
return token_type::parse_error;
7842
}
7843
7844
case 0x08:
7845
{
7846
error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7847
return token_type::parse_error;
7848
}
7849
7850
case 0x09:
7851
{
7852
error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7853
return token_type::parse_error;
7854
}
7855
7856
case 0x0A:
7857
{
7858
error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7859
return token_type::parse_error;
7860
}
7861
7862
case 0x0B:
7863
{
7864
error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7865
return token_type::parse_error;
7866
}
7867
7868
case 0x0C:
7869
{
7870
error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7871
return token_type::parse_error;
7872
}
7873
7874
case 0x0D:
7875
{
7876
error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7877
return token_type::parse_error;
7878
}
7879
7880
case 0x0E:
7881
{
7882
error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7883
return token_type::parse_error;
7884
}
7885
7886
case 0x0F:
7887
{
7888
error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7889
return token_type::parse_error;
7890
}
7891
7892
case 0x10:
7893
{
7894
error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7895
return token_type::parse_error;
7896
}
7897
7898
case 0x11:
7899
{
7900
error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7901
return token_type::parse_error;
7902
}
7903
7904
case 0x12:
7905
{
7906
error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7907
return token_type::parse_error;
7908
}
7909
7910
case 0x13:
7911
{
7912
error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7913
return token_type::parse_error;
7914
}
7915
7916
case 0x14:
7917
{
7918
error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7919
return token_type::parse_error;
7920
}
7921
7922
case 0x15:
7923
{
7924
error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7925
return token_type::parse_error;
7926
}
7927
7928
case 0x16:
7929
{
7930
error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7931
return token_type::parse_error;
7932
}
7933
7934
case 0x17:
7935
{
7936
error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7937
return token_type::parse_error;
7938
}
7939
7940
case 0x18:
7941
{
7942
error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7943
return token_type::parse_error;
7944
}
7945
7946
case 0x19:
7947
{
7948
error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7949
return token_type::parse_error;
7950
}
7951
7952
case 0x1A:
7953
{
7954
error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7955
return token_type::parse_error;
7956
}
7957
7958
case 0x1B:
7959
{
7960
error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7961
return token_type::parse_error;
7962
}
7963
7964
case 0x1C:
7965
{
7966
error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7967
return token_type::parse_error;
7968
}
7969
7970
case 0x1D:
7971
{
7972
error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7973
return token_type::parse_error;
7974
}
7975
7976
case 0x1E:
7977
{
7978
error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7979
return token_type::parse_error;
7980
}
7981
7982
case 0x1F:
7983
{
7984
error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7985
return token_type::parse_error;
7986
}
7987
7988
// U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7989
case 0x20:
7990
case 0x21:
7991
case 0x23:
7992
case 0x24:
7993
case 0x25:
7994
case 0x26:
7995
case 0x27:
7996
case 0x28:
7997
case 0x29:
7998
case 0x2A:
7999
case 0x2B:
8000
case 0x2C:
8001
case 0x2D:
8002
case 0x2E:
8003
case 0x2F:
8004
case 0x30:
8005
case 0x31:
8006
case 0x32:
8007
case 0x33:
8008
case 0x34:
8009
case 0x35:
8010
case 0x36:
8011
case 0x37:
8012
case 0x38:
8013
case 0x39:
8014
case 0x3A:
8015
case 0x3B:
8016
case 0x3C:
8017
case 0x3D:
8018
case 0x3E:
8019
case 0x3F:
8020
case 0x40:
8021
case 0x41:
8022
case 0x42:
8023
case 0x43:
8024
case 0x44:
8025
case 0x45:
8026
case 0x46:
8027
case 0x47:
8028
case 0x48:
8029
case 0x49:
8030
case 0x4A:
8031
case 0x4B:
8032
case 0x4C:
8033
case 0x4D:
8034
case 0x4E:
8035
case 0x4F:
8036
case 0x50:
8037
case 0x51:
8038
case 0x52:
8039
case 0x53:
8040
case 0x54:
8041
case 0x55:
8042
case 0x56:
8043
case 0x57:
8044
case 0x58:
8045
case 0x59:
8046
case 0x5A:
8047
case 0x5B:
8048
case 0x5D:
8049
case 0x5E:
8050
case 0x5F:
8051
case 0x60:
8052
case 0x61:
8053
case 0x62:
8054
case 0x63:
8055
case 0x64:
8056
case 0x65:
8057
case 0x66:
8058
case 0x67:
8059
case 0x68:
8060
case 0x69:
8061
case 0x6A:
8062
case 0x6B:
8063
case 0x6C:
8064
case 0x6D:
8065
case 0x6E:
8066
case 0x6F:
8067
case 0x70:
8068
case 0x71:
8069
case 0x72:
8070
case 0x73:
8071
case 0x74:
8072
case 0x75:
8073
case 0x76:
8074
case 0x77:
8075
case 0x78:
8076
case 0x79:
8077
case 0x7A:
8078
case 0x7B:
8079
case 0x7C:
8080
case 0x7D:
8081
case 0x7E:
8082
case 0x7F:
8083
{
8084
add(current);
8085
break;
8086
}
8087
8088
// U+0080..U+07FF: bytes C2..DF 80..BF
8089
case 0xC2:
8090
case 0xC3:
8091
case 0xC4:
8092
case 0xC5:
8093
case 0xC6:
8094
case 0xC7:
8095
case 0xC8:
8096
case 0xC9:
8097
case 0xCA:
8098
case 0xCB:
8099
case 0xCC:
8100
case 0xCD:
8101
case 0xCE:
8102
case 0xCF:
8103
case 0xD0:
8104
case 0xD1:
8105
case 0xD2:
8106
case 0xD3:
8107
case 0xD4:
8108
case 0xD5:
8109
case 0xD6:
8110
case 0xD7:
8111
case 0xD8:
8112
case 0xD9:
8113
case 0xDA:
8114
case 0xDB:
8115
case 0xDC:
8116
case 0xDD:
8117
case 0xDE:
8118
case 0xDF:
8119
{
8120
if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
8121
{
8122
return token_type::parse_error;
8123
}
8124
break;
8125
}
8126
8127
// U+0800..U+0FFF: bytes E0 A0..BF 80..BF
8128
case 0xE0:
8129
{
8130
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
8131
{
8132
return token_type::parse_error;
8133
}
8134
break;
8135
}
8136
8137
// U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
8138
// U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
8139
case 0xE1:
8140
case 0xE2:
8141
case 0xE3:
8142
case 0xE4:
8143
case 0xE5:
8144
case 0xE6:
8145
case 0xE7:
8146
case 0xE8:
8147
case 0xE9:
8148
case 0xEA:
8149
case 0xEB:
8150
case 0xEC:
8151
case 0xEE:
8152
case 0xEF:
8153
{
8154
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
8155
{
8156
return token_type::parse_error;
8157
}
8158
break;
8159
}
8160
8161
// U+D000..U+D7FF: bytes ED 80..9F 80..BF
8162
case 0xED:
8163
{
8164
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
8165
{
8166
return token_type::parse_error;
8167
}
8168
break;
8169
}
8170
8171
// U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
8172
case 0xF0:
8173
{
8174
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8175
{
8176
return token_type::parse_error;
8177
}
8178
break;
8179
}
8180
8181
// U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
8182
case 0xF1:
8183
case 0xF2:
8184
case 0xF3:
8185
{
8186
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8187
{
8188
return token_type::parse_error;
8189
}
8190
break;
8191
}
8192
8193
// U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
8194
case 0xF4:
8195
{
8196
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
8197
{
8198
return token_type::parse_error;
8199
}
8200
break;
8201
}
8202
8203
// remaining bytes (80..C1 and F5..FF) are ill-formed
8204
default:
8205
{
8206
error_message = "invalid string: ill-formed UTF-8 byte";
8207
return token_type::parse_error;
8208
}
8209
}
8210
}
8211
}
8212
8213
/*!
8214
* @brief scan a comment
8215
* @return whether comment could be scanned successfully
8216
*/
8217
bool scan_comment()
8218
{
8219
switch (get())
8220
{
8221
// single-line comments skip input until a newline or EOF is read
8222
case '/':
8223
{
8224
while (true)
8225
{
8226
switch (get())
8227
{
8228
case '\n':
8229
case '\r':
8230
case char_traits<char_type>::eof():
8231
case '\0':
8232
return true;
8233
8234
default:
8235
break;
8236
}
8237
}
8238
}
8239
8240
// multi-line comments skip input until */ is read
8241
case '*':
8242
{
8243
while (true)
8244
{
8245
switch (get())
8246
{
8247
case char_traits<char_type>::eof():
8248
case '\0':
8249
{
8250
error_message = "invalid comment; missing closing '*/'";
8251
return false;
8252
}
8253
8254
case '*':
8255
{
8256
switch (get())
8257
{
8258
case '/':
8259
return true;
8260
8261
default:
8262
{
8263
unget();
8264
continue;
8265
}
8266
}
8267
}
8268
8269
default:
8270
continue;
8271
}
8272
}
8273
}
8274
8275
// unexpected character after reading '/'
8276
default:
8277
{
8278
error_message = "invalid comment; expecting '/' or '*' after '/'";
8279
return false;
8280
}
8281
}
8282
}
8283
8284
JSON_HEDLEY_NON_NULL(2)
8285
static void strtof(float& f, const char* str, char** endptr) noexcept
8286
{
8287
f = std::strtof(str, endptr);
8288
}
8289
8290
JSON_HEDLEY_NON_NULL(2)
8291
static void strtof(double& f, const char* str, char** endptr) noexcept
8292
{
8293
f = std::strtod(str, endptr);
8294
}
8295
8296
JSON_HEDLEY_NON_NULL(2)
8297
static void strtof(long double& f, const char* str, char** endptr) noexcept
8298
{
8299
f = std::strtold(str, endptr);
8300
}
8301
8302
/*!
8303
@brief scan a number literal
8304
8305
This function scans a string according to Sect. 6 of RFC 8259.
8306
8307
The function is realized with a deterministic finite state machine derived
8308
from the grammar described in RFC 8259. Starting in state "init", the
8309
input is read and used to determined the next state. Only state "done"
8310
accepts the number. State "error" is a trap state to model errors. In the
8311
table below, "anything" means any character but the ones listed before.
8312
8313
state | 0 | 1-9 | e E | + | - | . | anything
8314
---------|----------|----------|----------|---------|---------|----------|-----------
8315
init | zero | any1 | [error] | [error] | minus | [error] | [error]
8316
minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
8317
zero | done | done | exponent | done | done | decimal1 | done
8318
any1 | any1 | any1 | exponent | done | done | decimal1 | done
8319
decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error]
8320
decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
8321
exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
8322
sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
8323
any2 | any2 | any2 | done | done | done | done | done
8324
8325
The state machine is realized with one label per state (prefixed with
8326
"scan_number_") and `goto` statements between them. The state machine
8327
contains cycles, but any cycle can be left when EOF is read. Therefore,
8328
the function is guaranteed to terminate.
8329
8330
During scanning, the read bytes are stored in token_buffer. This string is
8331
then converted to a signed integer, an unsigned integer, or a
8332
floating-point number.
8333
8334
@return token_type::value_unsigned, token_type::value_integer, or
8335
token_type::value_float if number could be successfully scanned,
8336
token_type::parse_error otherwise
8337
8338
@note The scanner is independent of the current locale. Internally, the
8339
locale's decimal point is used instead of `.` to work with the
8340
locale-dependent converters.
8341
*/
8342
token_type scan_number() // lgtm [cpp/use-of-goto]
8343
{
8344
// reset token_buffer to store the number's bytes
8345
reset();
8346
8347
// the type of the parsed number; initially set to unsigned; will be
8348
// changed if minus sign, decimal point or exponent is read
8349
token_type number_type = token_type::value_unsigned;
8350
8351
// state (init): we just found out we need to scan a number
8352
switch (current)
8353
{
8354
case '-':
8355
{
8356
add(current);
8357
goto scan_number_minus;
8358
}
8359
8360
case '0':
8361
{
8362
add(current);
8363
goto scan_number_zero;
8364
}
8365
8366
case '1':
8367
case '2':
8368
case '3':
8369
case '4':
8370
case '5':
8371
case '6':
8372
case '7':
8373
case '8':
8374
case '9':
8375
{
8376
add(current);
8377
goto scan_number_any1;
8378
}
8379
8380
// all other characters are rejected outside scan_number()
8381
default: // LCOV_EXCL_LINE
8382
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8383
}
8384
8385
scan_number_minus:
8386
// state: we just parsed a leading minus sign
8387
number_type = token_type::value_integer;
8388
switch (get())
8389
{
8390
case '0':
8391
{
8392
add(current);
8393
goto scan_number_zero;
8394
}
8395
8396
case '1':
8397
case '2':
8398
case '3':
8399
case '4':
8400
case '5':
8401
case '6':
8402
case '7':
8403
case '8':
8404
case '9':
8405
{
8406
add(current);
8407
goto scan_number_any1;
8408
}
8409
8410
default:
8411
{
8412
error_message = "invalid number; expected digit after '-'";
8413
return token_type::parse_error;
8414
}
8415
}
8416
8417
scan_number_zero:
8418
// state: we just parse a zero (maybe with a leading minus sign)
8419
switch (get())
8420
{
8421
case '.':
8422
{
8423
add(decimal_point_char);
8424
goto scan_number_decimal1;
8425
}
8426
8427
case 'e':
8428
case 'E':
8429
{
8430
add(current);
8431
goto scan_number_exponent;
8432
}
8433
8434
default:
8435
goto scan_number_done;
8436
}
8437
8438
scan_number_any1:
8439
// state: we just parsed a number 0-9 (maybe with a leading minus sign)
8440
switch (get())
8441
{
8442
case '0':
8443
case '1':
8444
case '2':
8445
case '3':
8446
case '4':
8447
case '5':
8448
case '6':
8449
case '7':
8450
case '8':
8451
case '9':
8452
{
8453
add(current);
8454
goto scan_number_any1;
8455
}
8456
8457
case '.':
8458
{
8459
add(decimal_point_char);
8460
goto scan_number_decimal1;
8461
}
8462
8463
case 'e':
8464
case 'E':
8465
{
8466
add(current);
8467
goto scan_number_exponent;
8468
}
8469
8470
default:
8471
goto scan_number_done;
8472
}
8473
8474
scan_number_decimal1:
8475
// state: we just parsed a decimal point
8476
number_type = token_type::value_float;
8477
switch (get())
8478
{
8479
case '0':
8480
case '1':
8481
case '2':
8482
case '3':
8483
case '4':
8484
case '5':
8485
case '6':
8486
case '7':
8487
case '8':
8488
case '9':
8489
{
8490
add(current);
8491
goto scan_number_decimal2;
8492
}
8493
8494
default:
8495
{
8496
error_message = "invalid number; expected digit after '.'";
8497
return token_type::parse_error;
8498
}
8499
}
8500
8501
scan_number_decimal2:
8502
// we just parsed at least one number after a decimal point
8503
switch (get())
8504
{
8505
case '0':
8506
case '1':
8507
case '2':
8508
case '3':
8509
case '4':
8510
case '5':
8511
case '6':
8512
case '7':
8513
case '8':
8514
case '9':
8515
{
8516
add(current);
8517
goto scan_number_decimal2;
8518
}
8519
8520
case 'e':
8521
case 'E':
8522
{
8523
add(current);
8524
goto scan_number_exponent;
8525
}
8526
8527
default:
8528
goto scan_number_done;
8529
}
8530
8531
scan_number_exponent:
8532
// we just parsed an exponent
8533
number_type = token_type::value_float;
8534
switch (get())
8535
{
8536
case '+':
8537
case '-':
8538
{
8539
add(current);
8540
goto scan_number_sign;
8541
}
8542
8543
case '0':
8544
case '1':
8545
case '2':
8546
case '3':
8547
case '4':
8548
case '5':
8549
case '6':
8550
case '7':
8551
case '8':
8552
case '9':
8553
{
8554
add(current);
8555
goto scan_number_any2;
8556
}
8557
8558
default:
8559
{
8560
error_message =
8561
"invalid number; expected '+', '-', or digit after exponent";
8562
return token_type::parse_error;
8563
}
8564
}
8565
8566
scan_number_sign:
8567
// we just parsed an exponent sign
8568
switch (get())
8569
{
8570
case '0':
8571
case '1':
8572
case '2':
8573
case '3':
8574
case '4':
8575
case '5':
8576
case '6':
8577
case '7':
8578
case '8':
8579
case '9':
8580
{
8581
add(current);
8582
goto scan_number_any2;
8583
}
8584
8585
default:
8586
{
8587
error_message = "invalid number; expected digit after exponent sign";
8588
return token_type::parse_error;
8589
}
8590
}
8591
8592
scan_number_any2:
8593
// we just parsed a number after the exponent or exponent sign
8594
switch (get())
8595
{
8596
case '0':
8597
case '1':
8598
case '2':
8599
case '3':
8600
case '4':
8601
case '5':
8602
case '6':
8603
case '7':
8604
case '8':
8605
case '9':
8606
{
8607
add(current);
8608
goto scan_number_any2;
8609
}
8610
8611
default:
8612
goto scan_number_done;
8613
}
8614
8615
scan_number_done:
8616
// unget the character after the number (we only read it to know that
8617
// we are done scanning a number)
8618
unget();
8619
8620
char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8621
errno = 0;
8622
8623
// try to parse integers first and fall back to floats
8624
if (number_type == token_type::value_unsigned)
8625
{
8626
const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8627
8628
// we checked the number format before
8629
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8630
8631
if (errno == 0)
8632
{
8633
value_unsigned = static_cast<number_unsigned_t>(x);
8634
if (value_unsigned == x)
8635
{
8636
return token_type::value_unsigned;
8637
}
8638
}
8639
}
8640
else if (number_type == token_type::value_integer)
8641
{
8642
const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8643
8644
// we checked the number format before
8645
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8646
8647
if (errno == 0)
8648
{
8649
value_integer = static_cast<number_integer_t>(x);
8650
if (value_integer == x)
8651
{
8652
return token_type::value_integer;
8653
}
8654
}
8655
}
8656
8657
// this code is reached if we parse a floating-point number or if an
8658
// integer conversion above failed
8659
strtof(value_float, token_buffer.data(), &endptr);
8660
8661
// we checked the number format before
8662
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8663
8664
return token_type::value_float;
8665
}
8666
8667
/*!
8668
@param[in] literal_text the literal text to expect
8669
@param[in] length the length of the passed literal text
8670
@param[in] return_type the token type to return on success
8671
*/
8672
JSON_HEDLEY_NON_NULL(2)
8673
token_type scan_literal(const char_type* literal_text, const std::size_t length,
8674
token_type return_type)
8675
{
8676
JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
8677
for (std::size_t i = 1; i < length; ++i)
8678
{
8679
if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8680
{
8681
error_message = "invalid literal";
8682
return token_type::parse_error;
8683
}
8684
}
8685
return return_type;
8686
}
8687
8688
/////////////////////
8689
// input management
8690
/////////////////////
8691
8692
/// reset token_buffer; current character is beginning of token
8693
void reset() noexcept
8694
{
8695
token_buffer.clear();
8696
token_string.clear();
8697
token_string.push_back(char_traits<char_type>::to_char_type(current));
8698
}
8699
8700
/*
8701
@brief get next character from the input
8702
8703
This function provides the interface to the used input adapter. It does
8704
not throw in case the input reached EOF, but returns a
8705
`char_traits<char>::eof()` in that case. Stores the scanned characters
8706
for use in error messages.
8707
8708
@return character read from the input
8709
*/
8710
char_int_type get()
8711
{
8712
++position.chars_read_total;
8713
++position.chars_read_current_line;
8714
8715
if (next_unget)
8716
{
8717
// just reset the next_unget variable and work with current
8718
next_unget = false;
8719
}
8720
else
8721
{
8722
current = ia.get_character();
8723
}
8724
8725
if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8726
{
8727
token_string.push_back(char_traits<char_type>::to_char_type(current));
8728
}
8729
8730
if (current == '\n')
8731
{
8732
++position.lines_read;
8733
position.chars_read_current_line = 0;
8734
}
8735
8736
return current;
8737
}
8738
8739
/*!
8740
@brief unget current character (read it again on next get)
8741
8742
We implement unget by setting variable next_unget to true. The input is not
8743
changed - we just simulate ungetting by modifying chars_read_total,
8744
chars_read_current_line, and token_string. The next call to get() will
8745
behave as if the unget character is read again.
8746
*/
8747
void unget()
8748
{
8749
next_unget = true;
8750
8751
--position.chars_read_total;
8752
8753
// in case we "unget" a newline, we have to also decrement the lines_read
8754
if (position.chars_read_current_line == 0)
8755
{
8756
if (position.lines_read > 0)
8757
{
8758
--position.lines_read;
8759
}
8760
}
8761
else
8762
{
8763
--position.chars_read_current_line;
8764
}
8765
8766
if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8767
{
8768
JSON_ASSERT(!token_string.empty());
8769
token_string.pop_back();
8770
}
8771
}
8772
8773
/// add a character to token_buffer
8774
void add(char_int_type c)
8775
{
8776
token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8777
}
8778
8779
public:
8780
/////////////////////
8781
// value getters
8782
/////////////////////
8783
8784
/// return integer value
8785
constexpr number_integer_t get_number_integer() const noexcept
8786
{
8787
return value_integer;
8788
}
8789
8790
/// return unsigned integer value
8791
constexpr number_unsigned_t get_number_unsigned() const noexcept
8792
{
8793
return value_unsigned;
8794
}
8795
8796
/// return floating-point value
8797
constexpr number_float_t get_number_float() const noexcept
8798
{
8799
return value_float;
8800
}
8801
8802
/// return current string value (implicitly resets the token; useful only once)
8803
string_t& get_string()
8804
{
8805
return token_buffer;
8806
}
8807
8808
/////////////////////
8809
// diagnostics
8810
/////////////////////
8811
8812
/// return position of last read token
8813
constexpr position_t get_position() const noexcept
8814
{
8815
return position;
8816
}
8817
8818
/// return the last read token (for errors only). Will never contain EOF
8819
/// (an arbitrary value that is not a valid char value, often -1), because
8820
/// 255 may legitimately occur. May contain NUL, which should be escaped.
8821
std::string get_token_string() const
8822
{
8823
// escape control characters
8824
std::string result;
8825
for (const auto c : token_string)
8826
{
8827
if (static_cast<unsigned char>(c) <= '\x1F')
8828
{
8829
// escape control characters
8830
std::array<char, 9> cs{{}};
8831
static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8832
result += cs.data();
8833
}
8834
else
8835
{
8836
// add character as is
8837
result.push_back(static_cast<std::string::value_type>(c));
8838
}
8839
}
8840
8841
return result;
8842
}
8843
8844
/// return syntax error message
8845
JSON_HEDLEY_RETURNS_NON_NULL
8846
constexpr const char* get_error_message() const noexcept
8847
{
8848
return error_message;
8849
}
8850
8851
/////////////////////
8852
// actual scanner
8853
/////////////////////
8854
8855
/*!
8856
@brief skip the UTF-8 byte order mark
8857
@return true iff there is no BOM or the correct BOM has been skipped
8858
*/
8859
bool skip_bom()
8860
{
8861
if (get() == 0xEF)
8862
{
8863
// check if we completely parse the BOM
8864
return get() == 0xBB && get() == 0xBF;
8865
}
8866
8867
// the first character is not the beginning of the BOM; unget it to
8868
// process is later
8869
unget();
8870
return true;
8871
}
8872
8873
void skip_whitespace()
8874
{
8875
do
8876
{
8877
get();
8878
}
8879
while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8880
}
8881
8882
token_type scan()
8883
{
8884
// initially, skip the BOM
8885
if (position.chars_read_total == 0 && !skip_bom())
8886
{
8887
error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8888
return token_type::parse_error;
8889
}
8890
8891
// read next character and ignore whitespace
8892
skip_whitespace();
8893
8894
// ignore comments
8895
while (ignore_comments && current == '/')
8896
{
8897
if (!scan_comment())
8898
{
8899
return token_type::parse_error;
8900
}
8901
8902
// skip following whitespace
8903
skip_whitespace();
8904
}
8905
8906
switch (current)
8907
{
8908
// structural characters
8909
case '[':
8910
return token_type::begin_array;
8911
case ']':
8912
return token_type::end_array;
8913
case '{':
8914
return token_type::begin_object;
8915
case '}':
8916
return token_type::end_object;
8917
case ':':
8918
return token_type::name_separator;
8919
case ',':
8920
return token_type::value_separator;
8921
8922
// literals
8923
case 't':
8924
{
8925
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')}};
8926
return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8927
}
8928
case 'f':
8929
{
8930
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')}};
8931
return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8932
}
8933
case 'n':
8934
{
8935
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')}};
8936
return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8937
}
8938
8939
// string
8940
case '\"':
8941
return scan_string();
8942
8943
// number
8944
case '-':
8945
case '0':
8946
case '1':
8947
case '2':
8948
case '3':
8949
case '4':
8950
case '5':
8951
case '6':
8952
case '7':
8953
case '8':
8954
case '9':
8955
return scan_number();
8956
8957
// end of input (the null byte is needed when parsing from
8958
// string literals)
8959
case '\0':
8960
case char_traits<char_type>::eof():
8961
return token_type::end_of_input;
8962
8963
// error
8964
default:
8965
error_message = "invalid literal";
8966
return token_type::parse_error;
8967
}
8968
}
8969
8970
private:
8971
/// input adapter
8972
InputAdapterType ia;
8973
8974
/// whether comments should be ignored (true) or signaled as errors (false)
8975
const bool ignore_comments = false;
8976
8977
/// the current character
8978
char_int_type current = char_traits<char_type>::eof();
8979
8980
/// whether the next get() call should just return current
8981
bool next_unget = false;
8982
8983
/// the start position of the current token
8984
position_t position {};
8985
8986
/// raw input token string (for error messages)
8987
std::vector<char_type> token_string {};
8988
8989
/// buffer for variable-length tokens (numbers, strings)
8990
string_t token_buffer {};
8991
8992
/// a description of occurred lexer errors
8993
const char* error_message = "";
8994
8995
// number values
8996
number_integer_t value_integer = 0;
8997
number_unsigned_t value_unsigned = 0;
8998
number_float_t value_float = 0;
8999
9000
/// the decimal point
9001
const char_int_type decimal_point_char = '.';
9002
};
9003
9004
} // namespace detail
9005
NLOHMANN_JSON_NAMESPACE_END
9006
9007
// #include <nlohmann/detail/macro_scope.hpp>
9008
9009
// #include <nlohmann/detail/meta/is_sax.hpp>
9010
// __ _____ _____ _____
9011
// __| | __| | | | JSON for Modern C++
9012
// | | |__ | | | | | | version 3.11.3
9013
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9014
//
9015
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
9016
// SPDX-License-Identifier: MIT
9017
9018
9019
9020
#include <cstdint> // size_t
9021
#include <utility> // declval
9022
#include <string> // string
9023
9024
// #include <nlohmann/detail/abi_macros.hpp>
9025
9026
// #include <nlohmann/detail/meta/detected.hpp>
9027
9028
// #include <nlohmann/detail/meta/type_traits.hpp>
9029
9030
9031
NLOHMANN_JSON_NAMESPACE_BEGIN
9032
namespace detail
9033
{
9034
9035
template<typename T>
9036
using null_function_t = decltype(std::declval<T&>().null());
9037
9038
template<typename T>
9039
using boolean_function_t =
9040
decltype(std::declval<T&>().boolean(std::declval<bool>()));
9041
9042
template<typename T, typename Integer>
9043
using number_integer_function_t =
9044
decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9045
9046
template<typename T, typename Unsigned>
9047
using number_unsigned_function_t =
9048
decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9049
9050
template<typename T, typename Float, typename String>
9051
using number_float_function_t = decltype(std::declval<T&>().number_float(
9052
std::declval<Float>(), std::declval<const String&>()));
9053
9054
template<typename T, typename String>
9055
using string_function_t =
9056
decltype(std::declval<T&>().string(std::declval<String&>()));
9057
9058
template<typename T, typename Binary>
9059
using binary_function_t =
9060
decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9061
9062
template<typename T>
9063
using start_object_function_t =
9064
decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9065
9066
template<typename T, typename String>
9067
using key_function_t =
9068
decltype(std::declval<T&>().key(std::declval<String&>()));
9069
9070
template<typename T>
9071
using end_object_function_t = decltype(std::declval<T&>().end_object());
9072
9073
template<typename T>
9074
using start_array_function_t =
9075
decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9076
9077
template<typename T>
9078
using end_array_function_t = decltype(std::declval<T&>().end_array());
9079
9080
template<typename T, typename Exception>
9081
using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9082
std::declval<std::size_t>(), std::declval<const std::string&>(),
9083
std::declval<const Exception&>()));
9084
9085
template<typename SAX, typename BasicJsonType>
9086
struct is_sax
9087
{
9088
private:
9089
static_assert(is_basic_json<BasicJsonType>::value,
9090
"BasicJsonType must be of type basic_json<...>");
9091
9092
using number_integer_t = typename BasicJsonType::number_integer_t;
9093
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9094
using number_float_t = typename BasicJsonType::number_float_t;
9095
using string_t = typename BasicJsonType::string_t;
9096
using binary_t = typename BasicJsonType::binary_t;
9097
using exception_t = typename BasicJsonType::exception;
9098
9099
public:
9100
static constexpr bool value =
9101
is_detected_exact<bool, null_function_t, SAX>::value &&
9102
is_detected_exact<bool, boolean_function_t, SAX>::value &&
9103
is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
9104
is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
9105
is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
9106
is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
9107
is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
9108
is_detected_exact<bool, start_object_function_t, SAX>::value &&
9109
is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
9110
is_detected_exact<bool, end_object_function_t, SAX>::value &&
9111
is_detected_exact<bool, start_array_function_t, SAX>::value &&
9112
is_detected_exact<bool, end_array_function_t, SAX>::value &&
9113
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
9114
};
9115
9116
template<typename SAX, typename BasicJsonType>
9117
struct is_sax_static_asserts
9118
{
9119
private:
9120
static_assert(is_basic_json<BasicJsonType>::value,
9121
"BasicJsonType must be of type basic_json<...>");
9122
9123
using number_integer_t = typename BasicJsonType::number_integer_t;
9124
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9125
using number_float_t = typename BasicJsonType::number_float_t;
9126
using string_t = typename BasicJsonType::string_t;
9127
using binary_t = typename BasicJsonType::binary_t;
9128
using exception_t = typename BasicJsonType::exception;
9129
9130
public:
9131
static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
9132
"Missing/invalid function: bool null()");
9133
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9134
"Missing/invalid function: bool boolean(bool)");
9135
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9136
"Missing/invalid function: bool boolean(bool)");
9137
static_assert(
9138
is_detected_exact<bool, number_integer_function_t, SAX,
9139
number_integer_t>::value,
9140
"Missing/invalid function: bool number_integer(number_integer_t)");
9141
static_assert(
9142
is_detected_exact<bool, number_unsigned_function_t, SAX,
9143
number_unsigned_t>::value,
9144
"Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9145
static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9146
number_float_t, string_t>::value,
9147
"Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9148
static_assert(
9149
is_detected_exact<bool, string_function_t, SAX, string_t>::value,
9150
"Missing/invalid function: bool string(string_t&)");
9151
static_assert(
9152
is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
9153
"Missing/invalid function: bool binary(binary_t&)");
9154
static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
9155
"Missing/invalid function: bool start_object(std::size_t)");
9156
static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
9157
"Missing/invalid function: bool key(string_t&)");
9158
static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
9159
"Missing/invalid function: bool end_object()");
9160
static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
9161
"Missing/invalid function: bool start_array(std::size_t)");
9162
static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
9163
"Missing/invalid function: bool end_array()");
9164
static_assert(
9165
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
9166
"Missing/invalid function: bool parse_error(std::size_t, const "
9167
"std::string&, const exception&)");
9168
};
9169
9170
} // namespace detail
9171
NLOHMANN_JSON_NAMESPACE_END
9172
9173
// #include <nlohmann/detail/meta/type_traits.hpp>
9174
9175
// #include <nlohmann/detail/string_concat.hpp>
9176
9177
// #include <nlohmann/detail/value_t.hpp>
9178
9179
9180
NLOHMANN_JSON_NAMESPACE_BEGIN
9181
namespace detail
9182
{
9183
9184
/// how to treat CBOR tags
9185
enum class cbor_tag_handler_t
9186
{
9187
error, ///< throw a parse_error exception in case of a tag
9188
ignore, ///< ignore tags
9189
store ///< store tags as binary type
9190
};
9191
9192
/*!
9193
@brief determine system byte order
9194
9195
@return true if and only if system's byte order is little endian
9196
9197
@note from https://stackoverflow.com/a/1001328/266378
9198
*/
9199
static inline bool little_endianness(int num = 1) noexcept
9200
{
9201
return *reinterpret_cast<char*>(&num) == 1;
9202
}
9203
9204
///////////////////
9205
// binary reader //
9206
///////////////////
9207
9208
/*!
9209
@brief deserialization of CBOR, MessagePack, and UBJSON values
9210
*/
9211
template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
9212
class binary_reader
9213
{
9214
using number_integer_t = typename BasicJsonType::number_integer_t;
9215
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9216
using number_float_t = typename BasicJsonType::number_float_t;
9217
using string_t = typename BasicJsonType::string_t;
9218
using binary_t = typename BasicJsonType::binary_t;
9219
using json_sax_t = SAX;
9220
using char_type = typename InputAdapterType::char_type;
9221
using char_int_type = typename char_traits<char_type>::int_type;
9222
9223
public:
9224
/*!
9225
@brief create a binary reader
9226
9227
@param[in] adapter input adapter to read from
9228
*/
9229
explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9230
{
9231
(void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
9232
}
9233
9234
// make class move-only
9235
binary_reader(const binary_reader&) = delete;
9236
binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9237
binary_reader& operator=(const binary_reader&) = delete;
9238
binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9239
~binary_reader() = default;
9240
9241
/*!
9242
@param[in] format the binary format to parse
9243
@param[in] sax_ a SAX event processor
9244
@param[in] strict whether to expect the input to be consumed completed
9245
@param[in] tag_handler how to treat CBOR tags
9246
9247
@return whether parsing was successful
9248
*/
9249
JSON_HEDLEY_NON_NULL(3)
9250
bool sax_parse(const input_format_t format,
9251
json_sax_t* sax_,
9252
const bool strict = true,
9253
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9254
{
9255
sax = sax_;
9256
bool result = false;
9257
9258
switch (format)
9259
{
9260
case input_format_t::bson:
9261
result = parse_bson_internal();
9262
break;
9263
9264
case input_format_t::cbor:
9265
result = parse_cbor_internal(true, tag_handler);
9266
break;
9267
9268
case input_format_t::msgpack:
9269
result = parse_msgpack_internal();
9270
break;
9271
9272
case input_format_t::ubjson:
9273
case input_format_t::bjdata:
9274
result = parse_ubjson_internal();
9275
break;
9276
9277
case input_format_t::json: // LCOV_EXCL_LINE
9278
default: // LCOV_EXCL_LINE
9279
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9280
}
9281
9282
// strict mode: next byte must be EOF
9283
if (result && strict)
9284
{
9285
if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9286
{
9287
get_ignore_noop();
9288
}
9289
else
9290
{
9291
get();
9292
}
9293
9294
if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
9295
{
9296
return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9297
exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9298
}
9299
}
9300
9301
return result;
9302
}
9303
9304
private:
9305
//////////
9306
// BSON //
9307
//////////
9308
9309
/*!
9310
@brief Reads in a BSON-object and passes it to the SAX-parser.
9311
@return whether a valid BSON-value was passed to the SAX parser
9312
*/
9313
bool parse_bson_internal()
9314
{
9315
std::int32_t document_size{};
9316
get_number<std::int32_t, true>(input_format_t::bson, document_size);
9317
9318
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
9319
{
9320
return false;
9321
}
9322
9323
if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
9324
{
9325
return false;
9326
}
9327
9328
return sax->end_object();
9329
}
9330
9331
/*!
9332
@brief Parses a C-style string from the BSON input.
9333
@param[in,out] result A reference to the string variable where the read
9334
string is to be stored.
9335
@return `true` if the \x00-byte indicating the end of the string was
9336
encountered before the EOF; false` indicates an unexpected EOF.
9337
*/
9338
bool get_bson_cstr(string_t& result)
9339
{
9340
auto out = std::back_inserter(result);
9341
while (true)
9342
{
9343
get();
9344
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
9345
{
9346
return false;
9347
}
9348
if (current == 0x00)
9349
{
9350
return true;
9351
}
9352
*out++ = static_cast<typename string_t::value_type>(current);
9353
}
9354
}
9355
9356
/*!
9357
@brief Parses a zero-terminated string of length @a len from the BSON
9358
input.
9359
@param[in] len The length (including the zero-byte at the end) of the
9360
string to be read.
9361
@param[in,out] result A reference to the string variable where the read
9362
string is to be stored.
9363
@tparam NumberType The type of the length @a len
9364
@pre len >= 1
9365
@return `true` if the string was successfully parsed
9366
*/
9367
template<typename NumberType>
9368
bool get_bson_string(const NumberType len, string_t& result)
9369
{
9370
if (JSON_HEDLEY_UNLIKELY(len < 1))
9371
{
9372
auto last_token = get_token_string();
9373
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9374
exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
9375
}
9376
9377
return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
9378
}
9379
9380
/*!
9381
@brief Parses a byte array input of length @a len from the BSON input.
9382
@param[in] len The length of the byte array to be read.
9383
@param[in,out] result A reference to the binary variable where the read
9384
array is to be stored.
9385
@tparam NumberType The type of the length @a len
9386
@pre len >= 0
9387
@return `true` if the byte array was successfully parsed
9388
*/
9389
template<typename NumberType>
9390
bool get_bson_binary(const NumberType len, binary_t& result)
9391
{
9392
if (JSON_HEDLEY_UNLIKELY(len < 0))
9393
{
9394
auto last_token = get_token_string();
9395
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9396
exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
9397
}
9398
9399
// All BSON binary values have a subtype
9400
std::uint8_t subtype{};
9401
get_number<std::uint8_t>(input_format_t::bson, subtype);
9402
result.set_subtype(subtype);
9403
9404
return get_binary(input_format_t::bson, len, result);
9405
}
9406
9407
/*!
9408
@brief Read a BSON document element of the given @a element_type.
9409
@param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
9410
@param[in] element_type_parse_position The position in the input stream,
9411
where the `element_type` was read.
9412
@warning Not all BSON element types are supported yet. An unsupported
9413
@a element_type will give rise to a parse_error.114:
9414
Unsupported BSON record type 0x...
9415
@return whether a valid BSON-object/array was passed to the SAX parser
9416
*/
9417
bool parse_bson_element_internal(const char_int_type element_type,
9418
const std::size_t element_type_parse_position)
9419
{
9420
switch (element_type)
9421
{
9422
case 0x01: // double
9423
{
9424
double number{};
9425
return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9426
}
9427
9428
case 0x02: // string
9429
{
9430
std::int32_t len{};
9431
string_t value;
9432
return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
9433
}
9434
9435
case 0x03: // object
9436
{
9437
return parse_bson_internal();
9438
}
9439
9440
case 0x04: // array
9441
{
9442
return parse_bson_array();
9443
}
9444
9445
case 0x05: // binary
9446
{
9447
std::int32_t len{};
9448
binary_t value;
9449
return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
9450
}
9451
9452
case 0x08: // boolean
9453
{
9454
return sax->boolean(get() != 0);
9455
}
9456
9457
case 0x0A: // null
9458
{
9459
return sax->null();
9460
}
9461
9462
case 0x10: // int32
9463
{
9464
std::int32_t value{};
9465
return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9466
}
9467
9468
case 0x12: // int64
9469
{
9470
std::int64_t value{};
9471
return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9472
}
9473
9474
default: // anything else not supported (yet)
9475
{
9476
std::array<char, 3> cr{{}};
9477
static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
9478
const std::string cr_str{cr.data()};
9479
return sax->parse_error(element_type_parse_position, cr_str,
9480
parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
9481
}
9482
}
9483
}
9484
9485
/*!
9486
@brief Read a BSON element list (as specified in the BSON-spec)
9487
9488
The same binary layout is used for objects and arrays, hence it must be
9489
indicated with the argument @a is_array which one is expected
9490
(true --> array, false --> object).
9491
9492
@param[in] is_array Determines if the element list being read is to be
9493
treated as an object (@a is_array == false), or as an
9494
array (@a is_array == true).
9495
@return whether a valid BSON-object/array was passed to the SAX parser
9496
*/
9497
bool parse_bson_element_list(const bool is_array)
9498
{
9499
string_t key;
9500
9501
while (auto element_type = get())
9502
{
9503
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
9504
{
9505
return false;
9506
}
9507
9508
const std::size_t element_type_parse_position = chars_read;
9509
if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
9510
{
9511
return false;
9512
}
9513
9514
if (!is_array && !sax->key(key))
9515
{
9516
return false;
9517
}
9518
9519
if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
9520
{
9521
return false;
9522
}
9523
9524
// get_bson_cstr only appends
9525
key.clear();
9526
}
9527
9528
return true;
9529
}
9530
9531
/*!
9532
@brief Reads an array from the BSON input and passes it to the SAX-parser.
9533
@return whether a valid BSON-array was passed to the SAX parser
9534
*/
9535
bool parse_bson_array()
9536
{
9537
std::int32_t document_size{};
9538
get_number<std::int32_t, true>(input_format_t::bson, document_size);
9539
9540
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
9541
{
9542
return false;
9543
}
9544
9545
if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
9546
{
9547
return false;
9548
}
9549
9550
return sax->end_array();
9551
}
9552
9553
//////////
9554
// CBOR //
9555
//////////
9556
9557
/*!
9558
@param[in] get_char whether a new character should be retrieved from the
9559
input (true) or whether the last read character should
9560
be considered instead (false)
9561
@param[in] tag_handler how CBOR tags should be treated
9562
9563
@return whether a valid CBOR value was passed to the SAX parser
9564
*/
9565
bool parse_cbor_internal(const bool get_char,
9566
const cbor_tag_handler_t tag_handler)
9567
{
9568
switch (get_char ? get() : current)
9569
{
9570
// EOF
9571
case char_traits<char_type>::eof():
9572
return unexpect_eof(input_format_t::cbor, "value");
9573
9574
// Integer 0x00..0x17 (0..23)
9575
case 0x00:
9576
case 0x01:
9577
case 0x02:
9578
case 0x03:
9579
case 0x04:
9580
case 0x05:
9581
case 0x06:
9582
case 0x07:
9583
case 0x08:
9584
case 0x09:
9585
case 0x0A:
9586
case 0x0B:
9587
case 0x0C:
9588
case 0x0D:
9589
case 0x0E:
9590
case 0x0F:
9591
case 0x10:
9592
case 0x11:
9593
case 0x12:
9594
case 0x13:
9595
case 0x14:
9596
case 0x15:
9597
case 0x16:
9598
case 0x17:
9599
return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9600
9601
case 0x18: // Unsigned integer (one-byte uint8_t follows)
9602
{
9603
std::uint8_t number{};
9604
return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9605
}
9606
9607
case 0x19: // Unsigned integer (two-byte uint16_t follows)
9608
{
9609
std::uint16_t number{};
9610
return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9611
}
9612
9613
case 0x1A: // Unsigned integer (four-byte uint32_t follows)
9614
{
9615
std::uint32_t number{};
9616
return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9617
}
9618
9619
case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
9620
{
9621
std::uint64_t number{};
9622
return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9623
}
9624
9625
// Negative integer -1-0x00..-1-0x17 (-1..-24)
9626
case 0x20:
9627
case 0x21:
9628
case 0x22:
9629
case 0x23:
9630
case 0x24:
9631
case 0x25:
9632
case 0x26:
9633
case 0x27:
9634
case 0x28:
9635
case 0x29:
9636
case 0x2A:
9637
case 0x2B:
9638
case 0x2C:
9639
case 0x2D:
9640
case 0x2E:
9641
case 0x2F:
9642
case 0x30:
9643
case 0x31:
9644
case 0x32:
9645
case 0x33:
9646
case 0x34:
9647
case 0x35:
9648
case 0x36:
9649
case 0x37:
9650
return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
9651
9652
case 0x38: // Negative integer (one-byte uint8_t follows)
9653
{
9654
std::uint8_t number{};
9655
return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9656
}
9657
9658
case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
9659
{
9660
std::uint16_t number{};
9661
return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9662
}
9663
9664
case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
9665
{
9666
std::uint32_t number{};
9667
return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9668
}
9669
9670
case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
9671
{
9672
std::uint64_t number{};
9673
return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
9674
- static_cast<number_integer_t>(number));
9675
}
9676
9677
// Binary data (0x00..0x17 bytes follow)
9678
case 0x40:
9679
case 0x41:
9680
case 0x42:
9681
case 0x43:
9682
case 0x44:
9683
case 0x45:
9684
case 0x46:
9685
case 0x47:
9686
case 0x48:
9687
case 0x49:
9688
case 0x4A:
9689
case 0x4B:
9690
case 0x4C:
9691
case 0x4D:
9692
case 0x4E:
9693
case 0x4F:
9694
case 0x50:
9695
case 0x51:
9696
case 0x52:
9697
case 0x53:
9698
case 0x54:
9699
case 0x55:
9700
case 0x56:
9701
case 0x57:
9702
case 0x58: // Binary data (one-byte uint8_t for n follows)
9703
case 0x59: // Binary data (two-byte uint16_t for n follow)
9704
case 0x5A: // Binary data (four-byte uint32_t for n follow)
9705
case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9706
case 0x5F: // Binary data (indefinite length)
9707
{
9708
binary_t b;
9709
return get_cbor_binary(b) && sax->binary(b);
9710
}
9711
9712
// UTF-8 string (0x00..0x17 bytes follow)
9713
case 0x60:
9714
case 0x61:
9715
case 0x62:
9716
case 0x63:
9717
case 0x64:
9718
case 0x65:
9719
case 0x66:
9720
case 0x67:
9721
case 0x68:
9722
case 0x69:
9723
case 0x6A:
9724
case 0x6B:
9725
case 0x6C:
9726
case 0x6D:
9727
case 0x6E:
9728
case 0x6F:
9729
case 0x70:
9730
case 0x71:
9731
case 0x72:
9732
case 0x73:
9733
case 0x74:
9734
case 0x75:
9735
case 0x76:
9736
case 0x77:
9737
case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9738
case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9739
case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9740
case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9741
case 0x7F: // UTF-8 string (indefinite length)
9742
{
9743
string_t s;
9744
return get_cbor_string(s) && sax->string(s);
9745
}
9746
9747
// array (0x00..0x17 data items follow)
9748
case 0x80:
9749
case 0x81:
9750
case 0x82:
9751
case 0x83:
9752
case 0x84:
9753
case 0x85:
9754
case 0x86:
9755
case 0x87:
9756
case 0x88:
9757
case 0x89:
9758
case 0x8A:
9759
case 0x8B:
9760
case 0x8C:
9761
case 0x8D:
9762
case 0x8E:
9763
case 0x8F:
9764
case 0x90:
9765
case 0x91:
9766
case 0x92:
9767
case 0x93:
9768
case 0x94:
9769
case 0x95:
9770
case 0x96:
9771
case 0x97:
9772
return get_cbor_array(
9773
conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9774
9775
case 0x98: // array (one-byte uint8_t for n follows)
9776
{
9777
std::uint8_t len{};
9778
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9779
}
9780
9781
case 0x99: // array (two-byte uint16_t for n follow)
9782
{
9783
std::uint16_t len{};
9784
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9785
}
9786
9787
case 0x9A: // array (four-byte uint32_t for n follow)
9788
{
9789
std::uint32_t len{};
9790
return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9791
}
9792
9793
case 0x9B: // array (eight-byte uint64_t for n follow)
9794
{
9795
std::uint64_t len{};
9796
return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9797
}
9798
9799
case 0x9F: // array (indefinite length)
9800
return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
9801
9802
// map (0x00..0x17 pairs of data items follow)
9803
case 0xA0:
9804
case 0xA1:
9805
case 0xA2:
9806
case 0xA3:
9807
case 0xA4:
9808
case 0xA5:
9809
case 0xA6:
9810
case 0xA7:
9811
case 0xA8:
9812
case 0xA9:
9813
case 0xAA:
9814
case 0xAB:
9815
case 0xAC:
9816
case 0xAD:
9817
case 0xAE:
9818
case 0xAF:
9819
case 0xB0:
9820
case 0xB1:
9821
case 0xB2:
9822
case 0xB3:
9823
case 0xB4:
9824
case 0xB5:
9825
case 0xB6:
9826
case 0xB7:
9827
return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9828
9829
case 0xB8: // map (one-byte uint8_t for n follows)
9830
{
9831
std::uint8_t len{};
9832
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9833
}
9834
9835
case 0xB9: // map (two-byte uint16_t for n follow)
9836
{
9837
std::uint16_t len{};
9838
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9839
}
9840
9841
case 0xBA: // map (four-byte uint32_t for n follow)
9842
{
9843
std::uint32_t len{};
9844
return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9845
}
9846
9847
case 0xBB: // map (eight-byte uint64_t for n follow)
9848
{
9849
std::uint64_t len{};
9850
return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9851
}
9852
9853
case 0xBF: // map (indefinite length)
9854
return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
9855
9856
case 0xC6: // tagged item
9857
case 0xC7:
9858
case 0xC8:
9859
case 0xC9:
9860
case 0xCA:
9861
case 0xCB:
9862
case 0xCC:
9863
case 0xCD:
9864
case 0xCE:
9865
case 0xCF:
9866
case 0xD0:
9867
case 0xD1:
9868
case 0xD2:
9869
case 0xD3:
9870
case 0xD4:
9871
case 0xD8: // tagged item (1 bytes follow)
9872
case 0xD9: // tagged item (2 bytes follow)
9873
case 0xDA: // tagged item (4 bytes follow)
9874
case 0xDB: // tagged item (8 bytes follow)
9875
{
9876
switch (tag_handler)
9877
{
9878
case cbor_tag_handler_t::error:
9879
{
9880
auto last_token = get_token_string();
9881
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9882
exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
9883
}
9884
9885
case cbor_tag_handler_t::ignore:
9886
{
9887
// ignore binary subtype
9888
switch (current)
9889
{
9890
case 0xD8:
9891
{
9892
std::uint8_t subtype_to_ignore{};
9893
get_number(input_format_t::cbor, subtype_to_ignore);
9894
break;
9895
}
9896
case 0xD9:
9897
{
9898
std::uint16_t subtype_to_ignore{};
9899
get_number(input_format_t::cbor, subtype_to_ignore);
9900
break;
9901
}
9902
case 0xDA:
9903
{
9904
std::uint32_t subtype_to_ignore{};
9905
get_number(input_format_t::cbor, subtype_to_ignore);
9906
break;
9907
}
9908
case 0xDB:
9909
{
9910
std::uint64_t subtype_to_ignore{};
9911
get_number(input_format_t::cbor, subtype_to_ignore);
9912
break;
9913
}
9914
default:
9915
break;
9916
}
9917
return parse_cbor_internal(true, tag_handler);
9918
}
9919
9920
case cbor_tag_handler_t::store:
9921
{
9922
binary_t b;
9923
// use binary subtype and store in binary container
9924
switch (current)
9925
{
9926
case 0xD8:
9927
{
9928
std::uint8_t subtype{};
9929
get_number(input_format_t::cbor, subtype);
9930
b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9931
break;
9932
}
9933
case 0xD9:
9934
{
9935
std::uint16_t subtype{};
9936
get_number(input_format_t::cbor, subtype);
9937
b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9938
break;
9939
}
9940
case 0xDA:
9941
{
9942
std::uint32_t subtype{};
9943
get_number(input_format_t::cbor, subtype);
9944
b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9945
break;
9946
}
9947
case 0xDB:
9948
{
9949
std::uint64_t subtype{};
9950
get_number(input_format_t::cbor, subtype);
9951
b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9952
break;
9953
}
9954
default:
9955
return parse_cbor_internal(true, tag_handler);
9956
}
9957
get();
9958
return get_cbor_binary(b) && sax->binary(b);
9959
}
9960
9961
default: // LCOV_EXCL_LINE
9962
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9963
return false; // LCOV_EXCL_LINE
9964
}
9965
}
9966
9967
case 0xF4: // false
9968
return sax->boolean(false);
9969
9970
case 0xF5: // true
9971
return sax->boolean(true);
9972
9973
case 0xF6: // null
9974
return sax->null();
9975
9976
case 0xF9: // Half-Precision Float (two-byte IEEE 754)
9977
{
9978
const auto byte1_raw = get();
9979
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9980
{
9981
return false;
9982
}
9983
const auto byte2_raw = get();
9984
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9985
{
9986
return false;
9987
}
9988
9989
const auto byte1 = static_cast<unsigned char>(byte1_raw);
9990
const auto byte2 = static_cast<unsigned char>(byte2_raw);
9991
9992
// code from RFC 7049, Appendix D, Figure 3:
9993
// As half-precision floating-point numbers were only added
9994
// to IEEE 754 in 2008, today's programming platforms often
9995
// still only have limited support for them. It is very
9996
// easy to include at least decoding support for them even
9997
// without such support. An example of a small decoder for
9998
// half-precision floating-point numbers in the C language
9999
// is shown in Fig. 3.
10000
const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10001
const double val = [&half]
10002
{
10003
const int exp = (half >> 10u) & 0x1Fu;
10004
const unsigned int mant = half & 0x3FFu;
10005
JSON_ASSERT(0 <= exp&& exp <= 32);
10006
JSON_ASSERT(mant <= 1024);
10007
switch (exp)
10008
{
10009
case 0:
10010
return std::ldexp(mant, -24);
10011
case 31:
10012
return (mant == 0)
10013
? std::numeric_limits<double>::infinity()
10014
: std::numeric_limits<double>::quiet_NaN();
10015
default:
10016
return std::ldexp(mant + 1024, exp - 25);
10017
}
10018
}();
10019
return sax->number_float((half & 0x8000u) != 0
10020
? static_cast<number_float_t>(-val)
10021
: static_cast<number_float_t>(val), "");
10022
}
10023
10024
case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10025
{
10026
float number{};
10027
return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10028
}
10029
10030
case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10031
{
10032
double number{};
10033
return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10034
}
10035
10036
default: // anything else (0xFF is handled inside the other types)
10037
{
10038
auto last_token = get_token_string();
10039
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10040
exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10041
}
10042
}
10043
}
10044
10045
/*!
10046
@brief reads a CBOR string
10047
10048
This function first reads starting bytes to determine the expected
10049
string length and then copies this number of bytes into a string.
10050
Additionally, CBOR's strings with indefinite lengths are supported.
10051
10052
@param[out] result created string
10053
10054
@return whether string creation completed
10055
*/
10056
bool get_cbor_string(string_t& result)
10057
{
10058
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10059
{
10060
return false;
10061
}
10062
10063
switch (current)
10064
{
10065
// UTF-8 string (0x00..0x17 bytes follow)
10066
case 0x60:
10067
case 0x61:
10068
case 0x62:
10069
case 0x63:
10070
case 0x64:
10071
case 0x65:
10072
case 0x66:
10073
case 0x67:
10074
case 0x68:
10075
case 0x69:
10076
case 0x6A:
10077
case 0x6B:
10078
case 0x6C:
10079
case 0x6D:
10080
case 0x6E:
10081
case 0x6F:
10082
case 0x70:
10083
case 0x71:
10084
case 0x72:
10085
case 0x73:
10086
case 0x74:
10087
case 0x75:
10088
case 0x76:
10089
case 0x77:
10090
{
10091
return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10092
}
10093
10094
case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10095
{
10096
std::uint8_t len{};
10097
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10098
}
10099
10100
case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10101
{
10102
std::uint16_t len{};
10103
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10104
}
10105
10106
case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10107
{
10108
std::uint32_t len{};
10109
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10110
}
10111
10112
case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10113
{
10114
std::uint64_t len{};
10115
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10116
}
10117
10118
case 0x7F: // UTF-8 string (indefinite length)
10119
{
10120
while (get() != 0xFF)
10121
{
10122
string_t chunk;
10123
if (!get_cbor_string(chunk))
10124
{
10125
return false;
10126
}
10127
result.append(chunk);
10128
}
10129
return true;
10130
}
10131
10132
default:
10133
{
10134
auto last_token = get_token_string();
10135
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10136
exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10137
}
10138
}
10139
}
10140
10141
/*!
10142
@brief reads a CBOR byte array
10143
10144
This function first reads starting bytes to determine the expected
10145
byte array length and then copies this number of bytes into the byte array.
10146
Additionally, CBOR's byte arrays with indefinite lengths are supported.
10147
10148
@param[out] result created byte array
10149
10150
@return whether byte array creation completed
10151
*/
10152
bool get_cbor_binary(binary_t& result)
10153
{
10154
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10155
{
10156
return false;
10157
}
10158
10159
switch (current)
10160
{
10161
// Binary data (0x00..0x17 bytes follow)
10162
case 0x40:
10163
case 0x41:
10164
case 0x42:
10165
case 0x43:
10166
case 0x44:
10167
case 0x45:
10168
case 0x46:
10169
case 0x47:
10170
case 0x48:
10171
case 0x49:
10172
case 0x4A:
10173
case 0x4B:
10174
case 0x4C:
10175
case 0x4D:
10176
case 0x4E:
10177
case 0x4F:
10178
case 0x50:
10179
case 0x51:
10180
case 0x52:
10181
case 0x53:
10182
case 0x54:
10183
case 0x55:
10184
case 0x56:
10185
case 0x57:
10186
{
10187
return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10188
}
10189
10190
case 0x58: // Binary data (one-byte uint8_t for n follows)
10191
{
10192
std::uint8_t len{};
10193
return get_number(input_format_t::cbor, len) &&
10194
get_binary(input_format_t::cbor, len, result);
10195
}
10196
10197
case 0x59: // Binary data (two-byte uint16_t for n follow)
10198
{
10199
std::uint16_t len{};
10200
return get_number(input_format_t::cbor, len) &&
10201
get_binary(input_format_t::cbor, len, result);
10202
}
10203
10204
case 0x5A: // Binary data (four-byte uint32_t for n follow)
10205
{
10206
std::uint32_t len{};
10207
return get_number(input_format_t::cbor, len) &&
10208
get_binary(input_format_t::cbor, len, result);
10209
}
10210
10211
case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10212
{
10213
std::uint64_t len{};
10214
return get_number(input_format_t::cbor, len) &&
10215
get_binary(input_format_t::cbor, len, result);
10216
}
10217
10218
case 0x5F: // Binary data (indefinite length)
10219
{
10220
while (get() != 0xFF)
10221
{
10222
binary_t chunk;
10223
if (!get_cbor_binary(chunk))
10224
{
10225
return false;
10226
}
10227
result.insert(result.end(), chunk.begin(), chunk.end());
10228
}
10229
return true;
10230
}
10231
10232
default:
10233
{
10234
auto last_token = get_token_string();
10235
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10236
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));
10237
}
10238
}
10239
}
10240
10241
/*!
10242
@param[in] len the length of the array or static_cast<std::size_t>(-1) for an
10243
array of indefinite size
10244
@param[in] tag_handler how CBOR tags should be treated
10245
@return whether array creation completed
10246
*/
10247
bool get_cbor_array(const std::size_t len,
10248
const cbor_tag_handler_t tag_handler)
10249
{
10250
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10251
{
10252
return false;
10253
}
10254
10255
if (len != static_cast<std::size_t>(-1))
10256
{
10257
for (std::size_t i = 0; i < len; ++i)
10258
{
10259
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10260
{
10261
return false;
10262
}
10263
}
10264
}
10265
else
10266
{
10267
while (get() != 0xFF)
10268
{
10269
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10270
{
10271
return false;
10272
}
10273
}
10274
}
10275
10276
return sax->end_array();
10277
}
10278
10279
/*!
10280
@param[in] len the length of the object or static_cast<std::size_t>(-1) for an
10281
object of indefinite size
10282
@param[in] tag_handler how CBOR tags should be treated
10283
@return whether object creation completed
10284
*/
10285
bool get_cbor_object(const std::size_t len,
10286
const cbor_tag_handler_t tag_handler)
10287
{
10288
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10289
{
10290
return false;
10291
}
10292
10293
if (len != 0)
10294
{
10295
string_t key;
10296
if (len != static_cast<std::size_t>(-1))
10297
{
10298
for (std::size_t i = 0; i < len; ++i)
10299
{
10300
get();
10301
if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10302
{
10303
return false;
10304
}
10305
10306
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10307
{
10308
return false;
10309
}
10310
key.clear();
10311
}
10312
}
10313
else
10314
{
10315
while (get() != 0xFF)
10316
{
10317
if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10318
{
10319
return false;
10320
}
10321
10322
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10323
{
10324
return false;
10325
}
10326
key.clear();
10327
}
10328
}
10329
}
10330
10331
return sax->end_object();
10332
}
10333
10334
/////////////
10335
// MsgPack //
10336
/////////////
10337
10338
/*!
10339
@return whether a valid MessagePack value was passed to the SAX parser
10340
*/
10341
bool parse_msgpack_internal()
10342
{
10343
switch (get())
10344
{
10345
// EOF
10346
case char_traits<char_type>::eof():
10347
return unexpect_eof(input_format_t::msgpack, "value");
10348
10349
// positive fixint
10350
case 0x00:
10351
case 0x01:
10352
case 0x02:
10353
case 0x03:
10354
case 0x04:
10355
case 0x05:
10356
case 0x06:
10357
case 0x07:
10358
case 0x08:
10359
case 0x09:
10360
case 0x0A:
10361
case 0x0B:
10362
case 0x0C:
10363
case 0x0D:
10364
case 0x0E:
10365
case 0x0F:
10366
case 0x10:
10367
case 0x11:
10368
case 0x12:
10369
case 0x13:
10370
case 0x14:
10371
case 0x15:
10372
case 0x16:
10373
case 0x17:
10374
case 0x18:
10375
case 0x19:
10376
case 0x1A:
10377
case 0x1B:
10378
case 0x1C:
10379
case 0x1D:
10380
case 0x1E:
10381
case 0x1F:
10382
case 0x20:
10383
case 0x21:
10384
case 0x22:
10385
case 0x23:
10386
case 0x24:
10387
case 0x25:
10388
case 0x26:
10389
case 0x27:
10390
case 0x28:
10391
case 0x29:
10392
case 0x2A:
10393
case 0x2B:
10394
case 0x2C:
10395
case 0x2D:
10396
case 0x2E:
10397
case 0x2F:
10398
case 0x30:
10399
case 0x31:
10400
case 0x32:
10401
case 0x33:
10402
case 0x34:
10403
case 0x35:
10404
case 0x36:
10405
case 0x37:
10406
case 0x38:
10407
case 0x39:
10408
case 0x3A:
10409
case 0x3B:
10410
case 0x3C:
10411
case 0x3D:
10412
case 0x3E:
10413
case 0x3F:
10414
case 0x40:
10415
case 0x41:
10416
case 0x42:
10417
case 0x43:
10418
case 0x44:
10419
case 0x45:
10420
case 0x46:
10421
case 0x47:
10422
case 0x48:
10423
case 0x49:
10424
case 0x4A:
10425
case 0x4B:
10426
case 0x4C:
10427
case 0x4D:
10428
case 0x4E:
10429
case 0x4F:
10430
case 0x50:
10431
case 0x51:
10432
case 0x52:
10433
case 0x53:
10434
case 0x54:
10435
case 0x55:
10436
case 0x56:
10437
case 0x57:
10438
case 0x58:
10439
case 0x59:
10440
case 0x5A:
10441
case 0x5B:
10442
case 0x5C:
10443
case 0x5D:
10444
case 0x5E:
10445
case 0x5F:
10446
case 0x60:
10447
case 0x61:
10448
case 0x62:
10449
case 0x63:
10450
case 0x64:
10451
case 0x65:
10452
case 0x66:
10453
case 0x67:
10454
case 0x68:
10455
case 0x69:
10456
case 0x6A:
10457
case 0x6B:
10458
case 0x6C:
10459
case 0x6D:
10460
case 0x6E:
10461
case 0x6F:
10462
case 0x70:
10463
case 0x71:
10464
case 0x72:
10465
case 0x73:
10466
case 0x74:
10467
case 0x75:
10468
case 0x76:
10469
case 0x77:
10470
case 0x78:
10471
case 0x79:
10472
case 0x7A:
10473
case 0x7B:
10474
case 0x7C:
10475
case 0x7D:
10476
case 0x7E:
10477
case 0x7F:
10478
return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10479
10480
// fixmap
10481
case 0x80:
10482
case 0x81:
10483
case 0x82:
10484
case 0x83:
10485
case 0x84:
10486
case 0x85:
10487
case 0x86:
10488
case 0x87:
10489
case 0x88:
10490
case 0x89:
10491
case 0x8A:
10492
case 0x8B:
10493
case 0x8C:
10494
case 0x8D:
10495
case 0x8E:
10496
case 0x8F:
10497
return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10498
10499
// fixarray
10500
case 0x90:
10501
case 0x91:
10502
case 0x92:
10503
case 0x93:
10504
case 0x94:
10505
case 0x95:
10506
case 0x96:
10507
case 0x97:
10508
case 0x98:
10509
case 0x99:
10510
case 0x9A:
10511
case 0x9B:
10512
case 0x9C:
10513
case 0x9D:
10514
case 0x9E:
10515
case 0x9F:
10516
return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10517
10518
// fixstr
10519
case 0xA0:
10520
case 0xA1:
10521
case 0xA2:
10522
case 0xA3:
10523
case 0xA4:
10524
case 0xA5:
10525
case 0xA6:
10526
case 0xA7:
10527
case 0xA8:
10528
case 0xA9:
10529
case 0xAA:
10530
case 0xAB:
10531
case 0xAC:
10532
case 0xAD:
10533
case 0xAE:
10534
case 0xAF:
10535
case 0xB0:
10536
case 0xB1:
10537
case 0xB2:
10538
case 0xB3:
10539
case 0xB4:
10540
case 0xB5:
10541
case 0xB6:
10542
case 0xB7:
10543
case 0xB8:
10544
case 0xB9:
10545
case 0xBA:
10546
case 0xBB:
10547
case 0xBC:
10548
case 0xBD:
10549
case 0xBE:
10550
case 0xBF:
10551
case 0xD9: // str 8
10552
case 0xDA: // str 16
10553
case 0xDB: // str 32
10554
{
10555
string_t s;
10556
return get_msgpack_string(s) && sax->string(s);
10557
}
10558
10559
case 0xC0: // nil
10560
return sax->null();
10561
10562
case 0xC2: // false
10563
return sax->boolean(false);
10564
10565
case 0xC3: // true
10566
return sax->boolean(true);
10567
10568
case 0xC4: // bin 8
10569
case 0xC5: // bin 16
10570
case 0xC6: // bin 32
10571
case 0xC7: // ext 8
10572
case 0xC8: // ext 16
10573
case 0xC9: // ext 32
10574
case 0xD4: // fixext 1
10575
case 0xD5: // fixext 2
10576
case 0xD6: // fixext 4
10577
case 0xD7: // fixext 8
10578
case 0xD8: // fixext 16
10579
{
10580
binary_t b;
10581
return get_msgpack_binary(b) && sax->binary(b);
10582
}
10583
10584
case 0xCA: // float 32
10585
{
10586
float number{};
10587
return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10588
}
10589
10590
case 0xCB: // float 64
10591
{
10592
double number{};
10593
return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10594
}
10595
10596
case 0xCC: // uint 8
10597
{
10598
std::uint8_t number{};
10599
return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10600
}
10601
10602
case 0xCD: // uint 16
10603
{
10604
std::uint16_t number{};
10605
return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10606
}
10607
10608
case 0xCE: // uint 32
10609
{
10610
std::uint32_t number{};
10611
return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10612
}
10613
10614
case 0xCF: // uint 64
10615
{
10616
std::uint64_t number{};
10617
return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10618
}
10619
10620
case 0xD0: // int 8
10621
{
10622
std::int8_t number{};
10623
return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10624
}
10625
10626
case 0xD1: // int 16
10627
{
10628
std::int16_t number{};
10629
return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10630
}
10631
10632
case 0xD2: // int 32
10633
{
10634
std::int32_t number{};
10635
return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10636
}
10637
10638
case 0xD3: // int 64
10639
{
10640
std::int64_t number{};
10641
return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10642
}
10643
10644
case 0xDC: // array 16
10645
{
10646
std::uint16_t len{};
10647
return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
10648
}
10649
10650
case 0xDD: // array 32
10651
{
10652
std::uint32_t len{};
10653
return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
10654
}
10655
10656
case 0xDE: // map 16
10657
{
10658
std::uint16_t len{};
10659
return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
10660
}
10661
10662
case 0xDF: // map 32
10663
{
10664
std::uint32_t len{};
10665
return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
10666
}
10667
10668
// negative fixint
10669
case 0xE0:
10670
case 0xE1:
10671
case 0xE2:
10672
case 0xE3:
10673
case 0xE4:
10674
case 0xE5:
10675
case 0xE6:
10676
case 0xE7:
10677
case 0xE8:
10678
case 0xE9:
10679
case 0xEA:
10680
case 0xEB:
10681
case 0xEC:
10682
case 0xED:
10683
case 0xEE:
10684
case 0xEF:
10685
case 0xF0:
10686
case 0xF1:
10687
case 0xF2:
10688
case 0xF3:
10689
case 0xF4:
10690
case 0xF5:
10691
case 0xF6:
10692
case 0xF7:
10693
case 0xF8:
10694
case 0xF9:
10695
case 0xFA:
10696
case 0xFB:
10697
case 0xFC:
10698
case 0xFD:
10699
case 0xFE:
10700
case 0xFF:
10701
return sax->number_integer(static_cast<std::int8_t>(current));
10702
10703
default: // anything else
10704
{
10705
auto last_token = get_token_string();
10706
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10707
exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
10708
}
10709
}
10710
}
10711
10712
/*!
10713
@brief reads a MessagePack string
10714
10715
This function first reads starting bytes to determine the expected
10716
string length and then copies this number of bytes into a string.
10717
10718
@param[out] result created string
10719
10720
@return whether string creation completed
10721
*/
10722
bool get_msgpack_string(string_t& result)
10723
{
10724
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
10725
{
10726
return false;
10727
}
10728
10729
switch (current)
10730
{
10731
// fixstr
10732
case 0xA0:
10733
case 0xA1:
10734
case 0xA2:
10735
case 0xA3:
10736
case 0xA4:
10737
case 0xA5:
10738
case 0xA6:
10739
case 0xA7:
10740
case 0xA8:
10741
case 0xA9:
10742
case 0xAA:
10743
case 0xAB:
10744
case 0xAC:
10745
case 0xAD:
10746
case 0xAE:
10747
case 0xAF:
10748
case 0xB0:
10749
case 0xB1:
10750
case 0xB2:
10751
case 0xB3:
10752
case 0xB4:
10753
case 0xB5:
10754
case 0xB6:
10755
case 0xB7:
10756
case 0xB8:
10757
case 0xB9:
10758
case 0xBA:
10759
case 0xBB:
10760
case 0xBC:
10761
case 0xBD:
10762
case 0xBE:
10763
case 0xBF:
10764
{
10765
return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
10766
}
10767
10768
case 0xD9: // str 8
10769
{
10770
std::uint8_t len{};
10771
return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10772
}
10773
10774
case 0xDA: // str 16
10775
{
10776
std::uint16_t len{};
10777
return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10778
}
10779
10780
case 0xDB: // str 32
10781
{
10782
std::uint32_t len{};
10783
return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10784
}
10785
10786
default:
10787
{
10788
auto last_token = get_token_string();
10789
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10790
exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
10791
}
10792
}
10793
}
10794
10795
/*!
10796
@brief reads a MessagePack byte array
10797
10798
This function first reads starting bytes to determine the expected
10799
byte array length and then copies this number of bytes into a byte array.
10800
10801
@param[out] result created byte array
10802
10803
@return whether byte array creation completed
10804
*/
10805
bool get_msgpack_binary(binary_t& result)
10806
{
10807
// helper function to set the subtype
10808
auto assign_and_return_true = [&result](std::int8_t subtype)
10809
{
10810
result.set_subtype(static_cast<std::uint8_t>(subtype));
10811
return true;
10812
};
10813
10814
switch (current)
10815
{
10816
case 0xC4: // bin 8
10817
{
10818
std::uint8_t len{};
10819
return get_number(input_format_t::msgpack, len) &&
10820
get_binary(input_format_t::msgpack, len, result);
10821
}
10822
10823
case 0xC5: // bin 16
10824
{
10825
std::uint16_t len{};
10826
return get_number(input_format_t::msgpack, len) &&
10827
get_binary(input_format_t::msgpack, len, result);
10828
}
10829
10830
case 0xC6: // bin 32
10831
{
10832
std::uint32_t len{};
10833
return get_number(input_format_t::msgpack, len) &&
10834
get_binary(input_format_t::msgpack, len, result);
10835
}
10836
10837
case 0xC7: // ext 8
10838
{
10839
std::uint8_t len{};
10840
std::int8_t subtype{};
10841
return get_number(input_format_t::msgpack, len) &&
10842
get_number(input_format_t::msgpack, subtype) &&
10843
get_binary(input_format_t::msgpack, len, result) &&
10844
assign_and_return_true(subtype);
10845
}
10846
10847
case 0xC8: // ext 16
10848
{
10849
std::uint16_t len{};
10850
std::int8_t subtype{};
10851
return get_number(input_format_t::msgpack, len) &&
10852
get_number(input_format_t::msgpack, subtype) &&
10853
get_binary(input_format_t::msgpack, len, result) &&
10854
assign_and_return_true(subtype);
10855
}
10856
10857
case 0xC9: // ext 32
10858
{
10859
std::uint32_t len{};
10860
std::int8_t subtype{};
10861
return get_number(input_format_t::msgpack, len) &&
10862
get_number(input_format_t::msgpack, subtype) &&
10863
get_binary(input_format_t::msgpack, len, result) &&
10864
assign_and_return_true(subtype);
10865
}
10866
10867
case 0xD4: // fixext 1
10868
{
10869
std::int8_t subtype{};
10870
return get_number(input_format_t::msgpack, subtype) &&
10871
get_binary(input_format_t::msgpack, 1, result) &&
10872
assign_and_return_true(subtype);
10873
}
10874
10875
case 0xD5: // fixext 2
10876
{
10877
std::int8_t subtype{};
10878
return get_number(input_format_t::msgpack, subtype) &&
10879
get_binary(input_format_t::msgpack, 2, result) &&
10880
assign_and_return_true(subtype);
10881
}
10882
10883
case 0xD6: // fixext 4
10884
{
10885
std::int8_t subtype{};
10886
return get_number(input_format_t::msgpack, subtype) &&
10887
get_binary(input_format_t::msgpack, 4, result) &&
10888
assign_and_return_true(subtype);
10889
}
10890
10891
case 0xD7: // fixext 8
10892
{
10893
std::int8_t subtype{};
10894
return get_number(input_format_t::msgpack, subtype) &&
10895
get_binary(input_format_t::msgpack, 8, result) &&
10896
assign_and_return_true(subtype);
10897
}
10898
10899
case 0xD8: // fixext 16
10900
{
10901
std::int8_t subtype{};
10902
return get_number(input_format_t::msgpack, subtype) &&
10903
get_binary(input_format_t::msgpack, 16, result) &&
10904
assign_and_return_true(subtype);
10905
}
10906
10907
default: // LCOV_EXCL_LINE
10908
return false; // LCOV_EXCL_LINE
10909
}
10910
}
10911
10912
/*!
10913
@param[in] len the length of the array
10914
@return whether array creation completed
10915
*/
10916
bool get_msgpack_array(const std::size_t len)
10917
{
10918
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10919
{
10920
return false;
10921
}
10922
10923
for (std::size_t i = 0; i < len; ++i)
10924
{
10925
if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10926
{
10927
return false;
10928
}
10929
}
10930
10931
return sax->end_array();
10932
}
10933
10934
/*!
10935
@param[in] len the length of the object
10936
@return whether object creation completed
10937
*/
10938
bool get_msgpack_object(const std::size_t len)
10939
{
10940
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10941
{
10942
return false;
10943
}
10944
10945
string_t key;
10946
for (std::size_t i = 0; i < len; ++i)
10947
{
10948
get();
10949
if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
10950
{
10951
return false;
10952
}
10953
10954
if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10955
{
10956
return false;
10957
}
10958
key.clear();
10959
}
10960
10961
return sax->end_object();
10962
}
10963
10964
////////////
10965
// UBJSON //
10966
////////////
10967
10968
/*!
10969
@param[in] get_char whether a new character should be retrieved from the
10970
input (true, default) or whether the last read
10971
character should be considered instead
10972
10973
@return whether a valid UBJSON value was passed to the SAX parser
10974
*/
10975
bool parse_ubjson_internal(const bool get_char = true)
10976
{
10977
return get_ubjson_value(get_char ? get_ignore_noop() : current);
10978
}
10979
10980
/*!
10981
@brief reads a UBJSON string
10982
10983
This function is either called after reading the 'S' byte explicitly
10984
indicating a string, or in case of an object key where the 'S' byte can be
10985
left out.
10986
10987
@param[out] result created string
10988
@param[in] get_char whether a new character should be retrieved from the
10989
input (true, default) or whether the last read
10990
character should be considered instead
10991
10992
@return whether string creation completed
10993
*/
10994
bool get_ubjson_string(string_t& result, const bool get_char = true)
10995
{
10996
if (get_char)
10997
{
10998
get(); // TODO(niels): may we ignore N here?
10999
}
11000
11001
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11002
{
11003
return false;
11004
}
11005
11006
switch (current)
11007
{
11008
case 'U':
11009
{
11010
std::uint8_t len{};
11011
return get_number(input_format, len) && get_string(input_format, len, result);
11012
}
11013
11014
case 'i':
11015
{
11016
std::int8_t len{};
11017
return get_number(input_format, len) && get_string(input_format, len, result);
11018
}
11019
11020
case 'I':
11021
{
11022
std::int16_t len{};
11023
return get_number(input_format, len) && get_string(input_format, len, result);
11024
}
11025
11026
case 'l':
11027
{
11028
std::int32_t len{};
11029
return get_number(input_format, len) && get_string(input_format, len, result);
11030
}
11031
11032
case 'L':
11033
{
11034
std::int64_t len{};
11035
return get_number(input_format, len) && get_string(input_format, len, result);
11036
}
11037
11038
case 'u':
11039
{
11040
if (input_format != input_format_t::bjdata)
11041
{
11042
break;
11043
}
11044
std::uint16_t len{};
11045
return get_number(input_format, len) && get_string(input_format, len, result);
11046
}
11047
11048
case 'm':
11049
{
11050
if (input_format != input_format_t::bjdata)
11051
{
11052
break;
11053
}
11054
std::uint32_t len{};
11055
return get_number(input_format, len) && get_string(input_format, len, result);
11056
}
11057
11058
case 'M':
11059
{
11060
if (input_format != input_format_t::bjdata)
11061
{
11062
break;
11063
}
11064
std::uint64_t len{};
11065
return get_number(input_format, len) && get_string(input_format, len, result);
11066
}
11067
11068
default:
11069
break;
11070
}
11071
auto last_token = get_token_string();
11072
std::string message;
11073
11074
if (input_format != input_format_t::bjdata)
11075
{
11076
message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11077
}
11078
else
11079
{
11080
message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11081
}
11082
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11083
}
11084
11085
/*!
11086
@param[out] dim an integer vector storing the ND array dimensions
11087
@return whether reading ND array size vector is successful
11088
*/
11089
bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11090
{
11091
std::pair<std::size_t, char_int_type> size_and_type;
11092
size_t dimlen = 0;
11093
bool no_ndarray = true;
11094
11095
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11096
{
11097
return false;
11098
}
11099
11100
if (size_and_type.first != npos)
11101
{
11102
if (size_and_type.second != 0)
11103
{
11104
if (size_and_type.second != 'N')
11105
{
11106
for (std::size_t i = 0; i < size_and_type.first; ++i)
11107
{
11108
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11109
{
11110
return false;
11111
}
11112
dim.push_back(dimlen);
11113
}
11114
}
11115
}
11116
else
11117
{
11118
for (std::size_t i = 0; i < size_and_type.first; ++i)
11119
{
11120
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11121
{
11122
return false;
11123
}
11124
dim.push_back(dimlen);
11125
}
11126
}
11127
}
11128
else
11129
{
11130
while (current != ']')
11131
{
11132
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11133
{
11134
return false;
11135
}
11136
dim.push_back(dimlen);
11137
get_ignore_noop();
11138
}
11139
}
11140
return true;
11141
}
11142
11143
/*!
11144
@param[out] result determined size
11145
@param[in,out] is_ndarray for input, `true` means already inside an ndarray vector
11146
or ndarray dimension is not allowed; `false` means ndarray
11147
is allowed; for output, `true` means an ndarray is found;
11148
is_ndarray can only return `true` when its initial value
11149
is `false`
11150
@param[in] prefix type marker if already read, otherwise set to 0
11151
11152
@return whether size determination completed
11153
*/
11154
bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11155
{
11156
if (prefix == 0)
11157
{
11158
prefix = get_ignore_noop();
11159
}
11160
11161
switch (prefix)
11162
{
11163
case 'U':
11164
{
11165
std::uint8_t number{};
11166
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11167
{
11168
return false;
11169
}
11170
result = static_cast<std::size_t>(number);
11171
return true;
11172
}
11173
11174
case 'i':
11175
{
11176
std::int8_t number{};
11177
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11178
{
11179
return false;
11180
}
11181
if (number < 0)
11182
{
11183
return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11184
exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11185
}
11186
result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11187
return true;
11188
}
11189
11190
case 'I':
11191
{
11192
std::int16_t number{};
11193
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11194
{
11195
return false;
11196
}
11197
if (number < 0)
11198
{
11199
return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11200
exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11201
}
11202
result = static_cast<std::size_t>(number);
11203
return true;
11204
}
11205
11206
case 'l':
11207
{
11208
std::int32_t number{};
11209
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11210
{
11211
return false;
11212
}
11213
if (number < 0)
11214
{
11215
return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11216
exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11217
}
11218
result = static_cast<std::size_t>(number);
11219
return true;
11220
}
11221
11222
case 'L':
11223
{
11224
std::int64_t number{};
11225
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11226
{
11227
return false;
11228
}
11229
if (number < 0)
11230
{
11231
return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11232
exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11233
}
11234
if (!value_in_range_of<std::size_t>(number))
11235
{
11236
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11237
exception_message(input_format, "integer value overflow", "size"), nullptr));
11238
}
11239
result = static_cast<std::size_t>(number);
11240
return true;
11241
}
11242
11243
case 'u':
11244
{
11245
if (input_format != input_format_t::bjdata)
11246
{
11247
break;
11248
}
11249
std::uint16_t number{};
11250
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11251
{
11252
return false;
11253
}
11254
result = static_cast<std::size_t>(number);
11255
return true;
11256
}
11257
11258
case 'm':
11259
{
11260
if (input_format != input_format_t::bjdata)
11261
{
11262
break;
11263
}
11264
std::uint32_t number{};
11265
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11266
{
11267
return false;
11268
}
11269
result = conditional_static_cast<std::size_t>(number);
11270
return true;
11271
}
11272
11273
case 'M':
11274
{
11275
if (input_format != input_format_t::bjdata)
11276
{
11277
break;
11278
}
11279
std::uint64_t number{};
11280
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11281
{
11282
return false;
11283
}
11284
if (!value_in_range_of<std::size_t>(number))
11285
{
11286
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11287
exception_message(input_format, "integer value overflow", "size"), nullptr));
11288
}
11289
result = detail::conditional_static_cast<std::size_t>(number);
11290
return true;
11291
}
11292
11293
case '[':
11294
{
11295
if (input_format != input_format_t::bjdata)
11296
{
11297
break;
11298
}
11299
if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
11300
{
11301
return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr));
11302
}
11303
std::vector<size_t> dim;
11304
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11305
{
11306
return false;
11307
}
11308
if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11309
{
11310
result = dim.at(dim.size() - 1);
11311
return true;
11312
}
11313
if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
11314
{
11315
for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11316
{
11317
if ( i == 0 )
11318
{
11319
result = 0;
11320
return true;
11321
}
11322
}
11323
11324
string_t key = "_ArraySize_";
11325
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
11326
{
11327
return false;
11328
}
11329
result = 1;
11330
for (auto i : dim)
11331
{
11332
result *= i;
11333
if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type()
11334
{
11335
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));
11336
}
11337
if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
11338
{
11339
return false;
11340
}
11341
}
11342
is_ndarray = true;
11343
return sax->end_array();
11344
}
11345
result = 0;
11346
return true;
11347
}
11348
11349
default:
11350
break;
11351
}
11352
auto last_token = get_token_string();
11353
std::string message;
11354
11355
if (input_format != input_format_t::bjdata)
11356
{
11357
message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11358
}
11359
else
11360
{
11361
message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
11362
}
11363
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
11364
}
11365
11366
/*!
11367
@brief determine the type and size for a container
11368
11369
In the optimized UBJSON format, a type and a size can be provided to allow
11370
for a more compact representation.
11371
11372
@param[out] result pair of the size and the type
11373
@param[in] inside_ndarray whether the parser is parsing an ND array dimensional vector
11374
11375
@return whether pair creation completed
11376
*/
11377
bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
11378
{
11379
result.first = npos; // size
11380
result.second = 0; // type
11381
bool is_ndarray = false;
11382
11383
get_ignore_noop();
11384
11385
if (current == '$')
11386
{
11387
result.second = get(); // must not ignore 'N', because 'N' maybe the type
11388
if (input_format == input_format_t::bjdata
11389
&& JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
11390
{
11391
auto last_token = get_token_string();
11392
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11393
exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
11394
}
11395
11396
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
11397
{
11398
return false;
11399
}
11400
11401
get_ignore_noop();
11402
if (JSON_HEDLEY_UNLIKELY(current != '#'))
11403
{
11404
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11405
{
11406
return false;
11407
}
11408
auto last_token = get_token_string();
11409
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11410
exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
11411
}
11412
11413
const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11414
if (input_format == input_format_t::bjdata && is_ndarray)
11415
{
11416
if (inside_ndarray)
11417
{
11418
return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11419
exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
11420
}
11421
result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
11422
}
11423
return is_error;
11424
}
11425
11426
if (current == '#')
11427
{
11428
const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11429
if (input_format == input_format_t::bjdata && is_ndarray)
11430
{
11431
return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11432
exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
11433
}
11434
return is_error;
11435
}
11436
11437
return true;
11438
}
11439
11440
/*!
11441
@param prefix the previously read or set type prefix
11442
@return whether value creation completed
11443
*/
11444
bool get_ubjson_value(const char_int_type prefix)
11445
{
11446
switch (prefix)
11447
{
11448
case char_traits<char_type>::eof(): // EOF
11449
return unexpect_eof(input_format, "value");
11450
11451
case 'T': // true
11452
return sax->boolean(true);
11453
case 'F': // false
11454
return sax->boolean(false);
11455
11456
case 'Z': // null
11457
return sax->null();
11458
11459
case 'U':
11460
{
11461
std::uint8_t number{};
11462
return get_number(input_format, number) && sax->number_unsigned(number);
11463
}
11464
11465
case 'i':
11466
{
11467
std::int8_t number{};
11468
return get_number(input_format, number) && sax->number_integer(number);
11469
}
11470
11471
case 'I':
11472
{
11473
std::int16_t number{};
11474
return get_number(input_format, number) && sax->number_integer(number);
11475
}
11476
11477
case 'l':
11478
{
11479
std::int32_t number{};
11480
return get_number(input_format, number) && sax->number_integer(number);
11481
}
11482
11483
case 'L':
11484
{
11485
std::int64_t number{};
11486
return get_number(input_format, number) && sax->number_integer(number);
11487
}
11488
11489
case 'u':
11490
{
11491
if (input_format != input_format_t::bjdata)
11492
{
11493
break;
11494
}
11495
std::uint16_t number{};
11496
return get_number(input_format, number) && sax->number_unsigned(number);
11497
}
11498
11499
case 'm':
11500
{
11501
if (input_format != input_format_t::bjdata)
11502
{
11503
break;
11504
}
11505
std::uint32_t number{};
11506
return get_number(input_format, number) && sax->number_unsigned(number);
11507
}
11508
11509
case 'M':
11510
{
11511
if (input_format != input_format_t::bjdata)
11512
{
11513
break;
11514
}
11515
std::uint64_t number{};
11516
return get_number(input_format, number) && sax->number_unsigned(number);
11517
}
11518
11519
case 'h':
11520
{
11521
if (input_format != input_format_t::bjdata)
11522
{
11523
break;
11524
}
11525
const auto byte1_raw = get();
11526
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11527
{
11528
return false;
11529
}
11530
const auto byte2_raw = get();
11531
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11532
{
11533
return false;
11534
}
11535
11536
const auto byte1 = static_cast<unsigned char>(byte1_raw);
11537
const auto byte2 = static_cast<unsigned char>(byte2_raw);
11538
11539
// code from RFC 7049, Appendix D, Figure 3:
11540
// As half-precision floating-point numbers were only added
11541
// to IEEE 754 in 2008, today's programming platforms often
11542
// still only have limited support for them. It is very
11543
// easy to include at least decoding support for them even
11544
// without such support. An example of a small decoder for
11545
// half-precision floating-point numbers in the C language
11546
// is shown in Fig. 3.
11547
const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
11548
const double val = [&half]
11549
{
11550
const int exp = (half >> 10u) & 0x1Fu;
11551
const unsigned int mant = half & 0x3FFu;
11552
JSON_ASSERT(0 <= exp&& exp <= 32);
11553
JSON_ASSERT(mant <= 1024);
11554
switch (exp)
11555
{
11556
case 0:
11557
return std::ldexp(mant, -24);
11558
case 31:
11559
return (mant == 0)
11560
? std::numeric_limits<double>::infinity()
11561
: std::numeric_limits<double>::quiet_NaN();
11562
default:
11563
return std::ldexp(mant + 1024, exp - 25);
11564
}
11565
}();
11566
return sax->number_float((half & 0x8000u) != 0
11567
? static_cast<number_float_t>(-val)
11568
: static_cast<number_float_t>(val), "");
11569
}
11570
11571
case 'd':
11572
{
11573
float number{};
11574
return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11575
}
11576
11577
case 'D':
11578
{
11579
double number{};
11580
return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11581
}
11582
11583
case 'H':
11584
{
11585
return get_ubjson_high_precision_number();
11586
}
11587
11588
case 'C': // char
11589
{
11590
get();
11591
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
11592
{
11593
return false;
11594
}
11595
if (JSON_HEDLEY_UNLIKELY(current > 127))
11596
{
11597
auto last_token = get_token_string();
11598
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11599
exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
11600
}
11601
string_t s(1, static_cast<typename string_t::value_type>(current));
11602
return sax->string(s);
11603
}
11604
11605
case 'S': // string
11606
{
11607
string_t s;
11608
return get_ubjson_string(s) && sax->string(s);
11609
}
11610
11611
case '[': // array
11612
return get_ubjson_array();
11613
11614
case '{': // object
11615
return get_ubjson_object();
11616
11617
default: // anything else
11618
break;
11619
}
11620
auto last_token = get_token_string();
11621
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));
11622
}
11623
11624
/*!
11625
@return whether array creation completed
11626
*/
11627
bool get_ubjson_array()
11628
{
11629
std::pair<std::size_t, char_int_type> size_and_type;
11630
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11631
{
11632
return false;
11633
}
11634
11635
// 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):
11636
// {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
11637
11638
if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11639
{
11640
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
11641
auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t)
11642
{
11643
return p.first < t;
11644
});
11645
string_t key = "_ArrayType_";
11646
if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
11647
{
11648
auto last_token = get_token_string();
11649
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11650
exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
11651
}
11652
11653
string_t type = it->second; // sax->string() takes a reference
11654
if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
11655
{
11656
return false;
11657
}
11658
11659
if (size_and_type.second == 'C')
11660
{
11661
size_and_type.second = 'U';
11662
}
11663
11664
key = "_ArrayData_";
11665
if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
11666
{
11667
return false;
11668
}
11669
11670
for (std::size_t i = 0; i < size_and_type.first; ++i)
11671
{
11672
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11673
{
11674
return false;
11675
}
11676
}
11677
11678
return (sax->end_array() && sax->end_object());
11679
}
11680
11681
if (size_and_type.first != npos)
11682
{
11683
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
11684
{
11685
return false;
11686
}
11687
11688
if (size_and_type.second != 0)
11689
{
11690
if (size_and_type.second != 'N')
11691
{
11692
for (std::size_t i = 0; i < size_and_type.first; ++i)
11693
{
11694
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11695
{
11696
return false;
11697
}
11698
}
11699
}
11700
}
11701
else
11702
{
11703
for (std::size_t i = 0; i < size_and_type.first; ++i)
11704
{
11705
if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11706
{
11707
return false;
11708
}
11709
}
11710
}
11711
}
11712
else
11713
{
11714
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
11715
{
11716
return false;
11717
}
11718
11719
while (current != ']')
11720
{
11721
if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
11722
{
11723
return false;
11724
}
11725
get_ignore_noop();
11726
}
11727
}
11728
11729
return sax->end_array();
11730
}
11731
11732
/*!
11733
@return whether object creation completed
11734
*/
11735
bool get_ubjson_object()
11736
{
11737
std::pair<std::size_t, char_int_type> size_and_type;
11738
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11739
{
11740
return false;
11741
}
11742
11743
// do not accept ND-array size in objects in BJData
11744
if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11745
{
11746
auto last_token = get_token_string();
11747
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11748
exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
11749
}
11750
11751
string_t key;
11752
if (size_and_type.first != npos)
11753
{
11754
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
11755
{
11756
return false;
11757
}
11758
11759
if (size_and_type.second != 0)
11760
{
11761
for (std::size_t i = 0; i < size_and_type.first; ++i)
11762
{
11763
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11764
{
11765
return false;
11766
}
11767
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11768
{
11769
return false;
11770
}
11771
key.clear();
11772
}
11773
}
11774
else
11775
{
11776
for (std::size_t i = 0; i < size_and_type.first; ++i)
11777
{
11778
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11779
{
11780
return false;
11781
}
11782
if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11783
{
11784
return false;
11785
}
11786
key.clear();
11787
}
11788
}
11789
}
11790
else
11791
{
11792
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
11793
{
11794
return false;
11795
}
11796
11797
while (current != '}')
11798
{
11799
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
11800
{
11801
return false;
11802
}
11803
if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11804
{
11805
return false;
11806
}
11807
get_ignore_noop();
11808
key.clear();
11809
}
11810
}
11811
11812
return sax->end_object();
11813
}
11814
11815
// Note, no reader for UBJSON binary types is implemented because they do
11816
// not exist
11817
11818
bool get_ubjson_high_precision_number()
11819
{
11820
// get size of following number string
11821
std::size_t size{};
11822
bool no_ndarray = true;
11823
auto res = get_ubjson_size_value(size, no_ndarray);
11824
if (JSON_HEDLEY_UNLIKELY(!res))
11825
{
11826
return res;
11827
}
11828
11829
// get number string
11830
std::vector<char> number_vector;
11831
for (std::size_t i = 0; i < size; ++i)
11832
{
11833
get();
11834
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11835
{
11836
return false;
11837
}
11838
number_vector.push_back(static_cast<char>(current));
11839
}
11840
11841
// parse number string
11842
using ia_type = decltype(detail::input_adapter(number_vector));
11843
auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
11844
const auto result_number = number_lexer.scan();
11845
const auto number_string = number_lexer.get_token_string();
11846
const auto result_remainder = number_lexer.scan();
11847
11848
using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
11849
11850
if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
11851
{
11852
return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11853
exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11854
}
11855
11856
switch (result_number)
11857
{
11858
case token_type::value_integer:
11859
return sax->number_integer(number_lexer.get_number_integer());
11860
case token_type::value_unsigned:
11861
return sax->number_unsigned(number_lexer.get_number_unsigned());
11862
case token_type::value_float:
11863
return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
11864
case token_type::uninitialized:
11865
case token_type::literal_true:
11866
case token_type::literal_false:
11867
case token_type::literal_null:
11868
case token_type::value_string:
11869
case token_type::begin_array:
11870
case token_type::begin_object:
11871
case token_type::end_array:
11872
case token_type::end_object:
11873
case token_type::name_separator:
11874
case token_type::value_separator:
11875
case token_type::parse_error:
11876
case token_type::end_of_input:
11877
case token_type::literal_or_value:
11878
default:
11879
return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11880
exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11881
}
11882
}
11883
11884
///////////////////////
11885
// Utility functions //
11886
///////////////////////
11887
11888
/*!
11889
@brief get next character from the input
11890
11891
This function provides the interface to the used input adapter. It does
11892
not throw in case the input reached EOF, but returns a -'ve valued
11893
`char_traits<char_type>::eof()` in that case.
11894
11895
@return character read from the input
11896
*/
11897
char_int_type get()
11898
{
11899
++chars_read;
11900
return current = ia.get_character();
11901
}
11902
11903
/*!
11904
@return character read from the input after ignoring all 'N' entries
11905
*/
11906
char_int_type get_ignore_noop()
11907
{
11908
do
11909
{
11910
get();
11911
}
11912
while (current == 'N');
11913
11914
return current;
11915
}
11916
11917
/*
11918
@brief read a number from the input
11919
11920
@tparam NumberType the type of the number
11921
@param[in] format the current format (for diagnostics)
11922
@param[out] result number of type @a NumberType
11923
11924
@return whether conversion completed
11925
11926
@note This function needs to respect the system's endianness, because
11927
bytes in CBOR, MessagePack, and UBJSON are stored in network order
11928
(big endian) and therefore need reordering on little endian systems.
11929
On the other hand, BSON and BJData use little endian and should reorder
11930
on big endian systems.
11931
*/
11932
template<typename NumberType, bool InputIsLittleEndian = false>
11933
bool get_number(const input_format_t format, NumberType& result)
11934
{
11935
// step 1: read input into array with system's byte order
11936
std::array<std::uint8_t, sizeof(NumberType)> vec{};
11937
for (std::size_t i = 0; i < sizeof(NumberType); ++i)
11938
{
11939
get();
11940
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
11941
{
11942
return false;
11943
}
11944
11945
// reverse byte order prior to conversion if necessary
11946
if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
11947
{
11948
vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
11949
}
11950
else
11951
{
11952
vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
11953
}
11954
}
11955
11956
// step 2: convert array into number of type T and return
11957
std::memcpy(&result, vec.data(), sizeof(NumberType));
11958
return true;
11959
}
11960
11961
/*!
11962
@brief create a string by reading characters from the input
11963
11964
@tparam NumberType the type of the number
11965
@param[in] format the current format (for diagnostics)
11966
@param[in] len number of characters to read
11967
@param[out] result string created by reading @a len bytes
11968
11969
@return whether string creation completed
11970
11971
@note We can not reserve @a len bytes for the result, because @a len
11972
may be too large. Usually, @ref unexpect_eof() detects the end of
11973
the input before we run out of string memory.
11974
*/
11975
template<typename NumberType>
11976
bool get_string(const input_format_t format,
11977
const NumberType len,
11978
string_t& result)
11979
{
11980
bool success = true;
11981
for (NumberType i = 0; i < len; i++)
11982
{
11983
get();
11984
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
11985
{
11986
success = false;
11987
break;
11988
}
11989
result.push_back(static_cast<typename string_t::value_type>(current));
11990
}
11991
return success;
11992
}
11993
11994
/*!
11995
@brief create a byte array by reading bytes from the input
11996
11997
@tparam NumberType the type of the number
11998
@param[in] format the current format (for diagnostics)
11999
@param[in] len number of bytes to read
12000
@param[out] result byte array created by reading @a len bytes
12001
12002
@return whether byte array creation completed
12003
12004
@note We can not reserve @a len bytes for the result, because @a len
12005
may be too large. Usually, @ref unexpect_eof() detects the end of
12006
the input before we run out of memory.
12007
*/
12008
template<typename NumberType>
12009
bool get_binary(const input_format_t format,
12010
const NumberType len,
12011
binary_t& result)
12012
{
12013
bool success = true;
12014
for (NumberType i = 0; i < len; i++)
12015
{
12016
get();
12017
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12018
{
12019
success = false;
12020
break;
12021
}
12022
result.push_back(static_cast<std::uint8_t>(current));
12023
}
12024
return success;
12025
}
12026
12027
/*!
12028
@param[in] format the current format (for diagnostics)
12029
@param[in] context further context information (for diagnostics)
12030
@return whether the last read character is not EOF
12031
*/
12032
JSON_HEDLEY_NON_NULL(3)
12033
bool unexpect_eof(const input_format_t format, const char* context) const
12034
{
12035
if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
12036
{
12037
return sax->parse_error(chars_read, "<end of file>",
12038
parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12039
}
12040
return true;
12041
}
12042
12043
/*!
12044
@return a string representation of the last read byte
12045
*/
12046
std::string get_token_string() const
12047
{
12048
std::array<char, 3> cr{{}};
12049
static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12050
return std::string{cr.data()};
12051
}
12052
12053
/*!
12054
@param[in] format the current format
12055
@param[in] detail a detailed error message
12056
@param[in] context further context information
12057
@return a message string to use in the parse_error exceptions
12058
*/
12059
std::string exception_message(const input_format_t format,
12060
const std::string& detail,
12061
const std::string& context) const
12062
{
12063
std::string error_msg = "syntax error while parsing ";
12064
12065
switch (format)
12066
{
12067
case input_format_t::cbor:
12068
error_msg += "CBOR";
12069
break;
12070
12071
case input_format_t::msgpack:
12072
error_msg += "MessagePack";
12073
break;
12074
12075
case input_format_t::ubjson:
12076
error_msg += "UBJSON";
12077
break;
12078
12079
case input_format_t::bson:
12080
error_msg += "BSON";
12081
break;
12082
12083
case input_format_t::bjdata:
12084
error_msg += "BJData";
12085
break;
12086
12087
case input_format_t::json: // LCOV_EXCL_LINE
12088
default: // LCOV_EXCL_LINE
12089
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12090
}
12091
12092
return concat(error_msg, ' ', context, ": ", detail);
12093
}
12094
12095
private:
12096
static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1);
12097
12098
/// input adapter
12099
InputAdapterType ia;
12100
12101
/// the current character
12102
char_int_type current = char_traits<char_type>::eof();
12103
12104
/// the number of characters read
12105
std::size_t chars_read = 0;
12106
12107
/// whether we can assume little endianness
12108
const bool is_little_endian = little_endianness();
12109
12110
/// input format
12111
const input_format_t input_format = input_format_t::json;
12112
12113
/// the SAX parser
12114
json_sax_t* sax = nullptr;
12115
12116
// excluded markers in bjdata optimized type
12117
#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12118
make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12119
12120
#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12121
make_array<bjd_type>( \
12122
bjd_type{'C', "char"}, \
12123
bjd_type{'D', "double"}, \
12124
bjd_type{'I', "int16"}, \
12125
bjd_type{'L', "int64"}, \
12126
bjd_type{'M', "uint64"}, \
12127
bjd_type{'U', "uint8"}, \
12128
bjd_type{'d', "single"}, \
12129
bjd_type{'i', "int8"}, \
12130
bjd_type{'l', "int32"}, \
12131
bjd_type{'m', "uint32"}, \
12132
bjd_type{'u', "uint16"})
12133
12134
JSON_PRIVATE_UNLESS_TESTED:
12135
// lookup tables
12136
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12137
const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12138
JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
12139
12140
using bjd_type = std::pair<char_int_type, string_t>;
12141
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12142
const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12143
JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
12144
12145
#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12146
#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12147
};
12148
12149
#ifndef JSON_HAS_CPP_17
12150
template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12151
constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12152
#endif
12153
12154
} // namespace detail
12155
NLOHMANN_JSON_NAMESPACE_END
12156
12157
// #include <nlohmann/detail/input/input_adapters.hpp>
12158
12159
// #include <nlohmann/detail/input/lexer.hpp>
12160
12161
// #include <nlohmann/detail/input/parser.hpp>
12162
// __ _____ _____ _____
12163
// __| | __| | | | JSON for Modern C++
12164
// | | |__ | | | | | | version 3.11.3
12165
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12166
//
12167
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12168
// SPDX-License-Identifier: MIT
12169
12170
12171
12172
#include <cmath> // isfinite
12173
#include <cstdint> // uint8_t
12174
#include <functional> // function
12175
#include <string> // string
12176
#include <utility> // move
12177
#include <vector> // vector
12178
12179
// #include <nlohmann/detail/exceptions.hpp>
12180
12181
// #include <nlohmann/detail/input/input_adapters.hpp>
12182
12183
// #include <nlohmann/detail/input/json_sax.hpp>
12184
12185
// #include <nlohmann/detail/input/lexer.hpp>
12186
12187
// #include <nlohmann/detail/macro_scope.hpp>
12188
12189
// #include <nlohmann/detail/meta/is_sax.hpp>
12190
12191
// #include <nlohmann/detail/string_concat.hpp>
12192
12193
// #include <nlohmann/detail/value_t.hpp>
12194
12195
12196
NLOHMANN_JSON_NAMESPACE_BEGIN
12197
namespace detail
12198
{
12199
////////////
12200
// parser //
12201
////////////
12202
12203
enum class parse_event_t : std::uint8_t
12204
{
12205
/// the parser read `{` and started to process a JSON object
12206
object_start,
12207
/// the parser read `}` and finished processing a JSON object
12208
object_end,
12209
/// the parser read `[` and started to process a JSON array
12210
array_start,
12211
/// the parser read `]` and finished processing a JSON array
12212
array_end,
12213
/// the parser read a key of a value in an object
12214
key,
12215
/// the parser finished reading a JSON value
12216
value
12217
};
12218
12219
template<typename BasicJsonType>
12220
using parser_callback_t =
12221
std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12222
12223
/*!
12224
@brief syntax analysis
12225
12226
This class implements a recursive descent parser.
12227
*/
12228
template<typename BasicJsonType, typename InputAdapterType>
12229
class parser
12230
{
12231
using number_integer_t = typename BasicJsonType::number_integer_t;
12232
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12233
using number_float_t = typename BasicJsonType::number_float_t;
12234
using string_t = typename BasicJsonType::string_t;
12235
using lexer_t = lexer<BasicJsonType, InputAdapterType>;
12236
using token_type = typename lexer_t::token_type;
12237
12238
public:
12239
/// a parser reading from an input adapter
12240
explicit parser(InputAdapterType&& adapter,
12241
const parser_callback_t<BasicJsonType> cb = nullptr,
12242
const bool allow_exceptions_ = true,
12243
const bool skip_comments = false)
12244
: callback(cb)
12245
, m_lexer(std::move(adapter), skip_comments)
12246
, allow_exceptions(allow_exceptions_)
12247
{
12248
// read first token
12249
get_token();
12250
}
12251
12252
/*!
12253
@brief public parser interface
12254
12255
@param[in] strict whether to expect the last token to be EOF
12256
@param[in,out] result parsed JSON value
12257
12258
@throw parse_error.101 in case of an unexpected token
12259
@throw parse_error.102 if to_unicode fails or surrogate error
12260
@throw parse_error.103 if to_unicode fails
12261
*/
12262
void parse(const bool strict, BasicJsonType& result)
12263
{
12264
if (callback)
12265
{
12266
json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
12267
sax_parse_internal(&sdp);
12268
12269
// in strict mode, input must be completely read
12270
if (strict && (get_token() != token_type::end_of_input))
12271
{
12272
sdp.parse_error(m_lexer.get_position(),
12273
m_lexer.get_token_string(),
12274
parse_error::create(101, m_lexer.get_position(),
12275
exception_message(token_type::end_of_input, "value"), nullptr));
12276
}
12277
12278
// in case of an error, return discarded value
12279
if (sdp.is_errored())
12280
{
12281
result = value_t::discarded;
12282
return;
12283
}
12284
12285
// set top-level value to null if it was discarded by the callback
12286
// function
12287
if (result.is_discarded())
12288
{
12289
result = nullptr;
12290
}
12291
}
12292
else
12293
{
12294
json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
12295
sax_parse_internal(&sdp);
12296
12297
// in strict mode, input must be completely read
12298
if (strict && (get_token() != token_type::end_of_input))
12299
{
12300
sdp.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::end_of_input, "value"), nullptr));
12303
}
12304
12305
// in case of an error, return discarded value
12306
if (sdp.is_errored())
12307
{
12308
result = value_t::discarded;
12309
return;
12310
}
12311
}
12312
12313
result.assert_invariant();
12314
}
12315
12316
/*!
12317
@brief public accept interface
12318
12319
@param[in] strict whether to expect the last token to be EOF
12320
@return whether the input is a proper JSON text
12321
*/
12322
bool accept(const bool strict = true)
12323
{
12324
json_sax_acceptor<BasicJsonType> sax_acceptor;
12325
return sax_parse(&sax_acceptor, strict);
12326
}
12327
12328
template<typename SAX>
12329
JSON_HEDLEY_NON_NULL(2)
12330
bool sax_parse(SAX* sax, const bool strict = true)
12331
{
12332
(void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
12333
const bool result = sax_parse_internal(sax);
12334
12335
// strict mode: next byte must be EOF
12336
if (result && strict && (get_token() != token_type::end_of_input))
12337
{
12338
return sax->parse_error(m_lexer.get_position(),
12339
m_lexer.get_token_string(),
12340
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12341
}
12342
12343
return result;
12344
}
12345
12346
private:
12347
template<typename SAX>
12348
JSON_HEDLEY_NON_NULL(2)
12349
bool sax_parse_internal(SAX* sax)
12350
{
12351
// stack to remember the hierarchy of structured values we are parsing
12352
// true = array; false = object
12353
std::vector<bool> states;
12354
// value to avoid a goto (see comment where set to true)
12355
bool skip_to_state_evaluation = false;
12356
12357
while (true)
12358
{
12359
if (!skip_to_state_evaluation)
12360
{
12361
// invariant: get_token() was called before each iteration
12362
switch (last_token)
12363
{
12364
case token_type::begin_object:
12365
{
12366
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
12367
{
12368
return false;
12369
}
12370
12371
// closing } -> we are done
12372
if (get_token() == token_type::end_object)
12373
{
12374
if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12375
{
12376
return false;
12377
}
12378
break;
12379
}
12380
12381
// parse key
12382
if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
12383
{
12384
return sax->parse_error(m_lexer.get_position(),
12385
m_lexer.get_token_string(),
12386
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12387
}
12388
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12389
{
12390
return false;
12391
}
12392
12393
// parse separator (:)
12394
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12395
{
12396
return sax->parse_error(m_lexer.get_position(),
12397
m_lexer.get_token_string(),
12398
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12399
}
12400
12401
// remember we are now inside an object
12402
states.push_back(false);
12403
12404
// parse values
12405
get_token();
12406
continue;
12407
}
12408
12409
case token_type::begin_array:
12410
{
12411
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
12412
{
12413
return false;
12414
}
12415
12416
// closing ] -> we are done
12417
if (get_token() == token_type::end_array)
12418
{
12419
if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12420
{
12421
return false;
12422
}
12423
break;
12424
}
12425
12426
// remember we are now inside an array
12427
states.push_back(true);
12428
12429
// parse values (no need to call get_token)
12430
continue;
12431
}
12432
12433
case token_type::value_float:
12434
{
12435
const auto res = m_lexer.get_number_float();
12436
12437
if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
12438
{
12439
return sax->parse_error(m_lexer.get_position(),
12440
m_lexer.get_token_string(),
12441
out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
12442
}
12443
12444
if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
12445
{
12446
return false;
12447
}
12448
12449
break;
12450
}
12451
12452
case token_type::literal_false:
12453
{
12454
if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
12455
{
12456
return false;
12457
}
12458
break;
12459
}
12460
12461
case token_type::literal_null:
12462
{
12463
if (JSON_HEDLEY_UNLIKELY(!sax->null()))
12464
{
12465
return false;
12466
}
12467
break;
12468
}
12469
12470
case token_type::literal_true:
12471
{
12472
if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
12473
{
12474
return false;
12475
}
12476
break;
12477
}
12478
12479
case token_type::value_integer:
12480
{
12481
if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
12482
{
12483
return false;
12484
}
12485
break;
12486
}
12487
12488
case token_type::value_string:
12489
{
12490
if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
12491
{
12492
return false;
12493
}
12494
break;
12495
}
12496
12497
case token_type::value_unsigned:
12498
{
12499
if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
12500
{
12501
return false;
12502
}
12503
break;
12504
}
12505
12506
case token_type::parse_error:
12507
{
12508
// using "uninitialized" to avoid "expected" message
12509
return sax->parse_error(m_lexer.get_position(),
12510
m_lexer.get_token_string(),
12511
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
12512
}
12513
case token_type::end_of_input:
12514
{
12515
if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
12516
{
12517
return sax->parse_error(m_lexer.get_position(),
12518
m_lexer.get_token_string(),
12519
parse_error::create(101, m_lexer.get_position(),
12520
"attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
12521
}
12522
12523
return sax->parse_error(m_lexer.get_position(),
12524
m_lexer.get_token_string(),
12525
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12526
}
12527
case token_type::uninitialized:
12528
case token_type::end_array:
12529
case token_type::end_object:
12530
case token_type::name_separator:
12531
case token_type::value_separator:
12532
case token_type::literal_or_value:
12533
default: // the last token was unexpected
12534
{
12535
return sax->parse_error(m_lexer.get_position(),
12536
m_lexer.get_token_string(),
12537
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12538
}
12539
}
12540
}
12541
else
12542
{
12543
skip_to_state_evaluation = false;
12544
}
12545
12546
// we reached this line after we successfully parsed a value
12547
if (states.empty())
12548
{
12549
// empty stack: we reached the end of the hierarchy: done
12550
return true;
12551
}
12552
12553
if (states.back()) // array
12554
{
12555
// comma -> next value
12556
if (get_token() == token_type::value_separator)
12557
{
12558
// parse a new value
12559
get_token();
12560
continue;
12561
}
12562
12563
// closing ]
12564
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
12565
{
12566
if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12567
{
12568
return false;
12569
}
12570
12571
// We are done with this array. Before we can parse a
12572
// new value, we need to evaluate the new state first.
12573
// By setting skip_to_state_evaluation to false, we
12574
// are effectively jumping to the beginning of this if.
12575
JSON_ASSERT(!states.empty());
12576
states.pop_back();
12577
skip_to_state_evaluation = true;
12578
continue;
12579
}
12580
12581
return sax->parse_error(m_lexer.get_position(),
12582
m_lexer.get_token_string(),
12583
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
12584
}
12585
12586
// states.back() is false -> object
12587
12588
// comma -> next value
12589
if (get_token() == token_type::value_separator)
12590
{
12591
// parse key
12592
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
12593
{
12594
return sax->parse_error(m_lexer.get_position(),
12595
m_lexer.get_token_string(),
12596
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12597
}
12598
12599
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12600
{
12601
return false;
12602
}
12603
12604
// parse separator (:)
12605
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12606
{
12607
return sax->parse_error(m_lexer.get_position(),
12608
m_lexer.get_token_string(),
12609
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12610
}
12611
12612
// parse values
12613
get_token();
12614
continue;
12615
}
12616
12617
// closing }
12618
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
12619
{
12620
if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12621
{
12622
return false;
12623
}
12624
12625
// We are done with this object. Before we can parse a
12626
// new value, we need to evaluate the new state first.
12627
// By setting skip_to_state_evaluation to false, we
12628
// are effectively jumping to the beginning of this if.
12629
JSON_ASSERT(!states.empty());
12630
states.pop_back();
12631
skip_to_state_evaluation = true;
12632
continue;
12633
}
12634
12635
return sax->parse_error(m_lexer.get_position(),
12636
m_lexer.get_token_string(),
12637
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
12638
}
12639
}
12640
12641
/// get next token from lexer
12642
token_type get_token()
12643
{
12644
return last_token = m_lexer.scan();
12645
}
12646
12647
std::string exception_message(const token_type expected, const std::string& context)
12648
{
12649
std::string error_msg = "syntax error ";
12650
12651
if (!context.empty())
12652
{
12653
error_msg += concat("while parsing ", context, ' ');
12654
}
12655
12656
error_msg += "- ";
12657
12658
if (last_token == token_type::parse_error)
12659
{
12660
error_msg += concat(m_lexer.get_error_message(), "; last read: '",
12661
m_lexer.get_token_string(), '\'');
12662
}
12663
else
12664
{
12665
error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
12666
}
12667
12668
if (expected != token_type::uninitialized)
12669
{
12670
error_msg += concat("; expected ", lexer_t::token_type_name(expected));
12671
}
12672
12673
return error_msg;
12674
}
12675
12676
private:
12677
/// callback function
12678
const parser_callback_t<BasicJsonType> callback = nullptr;
12679
/// the type of the last read token
12680
token_type last_token = token_type::uninitialized;
12681
/// the lexer
12682
lexer_t m_lexer;
12683
/// whether to throw exceptions in case of errors
12684
const bool allow_exceptions = true;
12685
};
12686
12687
} // namespace detail
12688
NLOHMANN_JSON_NAMESPACE_END
12689
12690
// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12691
// __ _____ _____ _____
12692
// __| | __| | | | JSON for Modern C++
12693
// | | |__ | | | | | | version 3.11.3
12694
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12695
//
12696
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12697
// SPDX-License-Identifier: MIT
12698
12699
12700
12701
// #include <nlohmann/detail/abi_macros.hpp>
12702
12703
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12704
// __ _____ _____ _____
12705
// __| | __| | | | JSON for Modern C++
12706
// | | |__ | | | | | | version 3.11.3
12707
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12708
//
12709
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12710
// SPDX-License-Identifier: MIT
12711
12712
12713
12714
#include <cstddef> // ptrdiff_t
12715
#include <limits> // numeric_limits
12716
12717
// #include <nlohmann/detail/macro_scope.hpp>
12718
12719
12720
NLOHMANN_JSON_NAMESPACE_BEGIN
12721
namespace detail
12722
{
12723
12724
/*
12725
@brief an iterator for primitive JSON types
12726
12727
This class models an iterator for primitive JSON types (boolean, number,
12728
string). It's only purpose is to allow the iterator/const_iterator classes
12729
to "iterate" over primitive values. Internally, the iterator is modeled by
12730
a `difference_type` variable. Value begin_value (`0`) models the begin,
12731
end_value (`1`) models past the end.
12732
*/
12733
class primitive_iterator_t
12734
{
12735
private:
12736
using difference_type = std::ptrdiff_t;
12737
static constexpr difference_type begin_value = 0;
12738
static constexpr difference_type end_value = begin_value + 1;
12739
12740
JSON_PRIVATE_UNLESS_TESTED:
12741
/// iterator as signed integer type
12742
difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
12743
12744
public:
12745
constexpr difference_type get_value() const noexcept
12746
{
12747
return m_it;
12748
}
12749
12750
/// set iterator to a defined beginning
12751
void set_begin() noexcept
12752
{
12753
m_it = begin_value;
12754
}
12755
12756
/// set iterator to a defined past the end
12757
void set_end() noexcept
12758
{
12759
m_it = end_value;
12760
}
12761
12762
/// return whether the iterator can be dereferenced
12763
constexpr bool is_begin() const noexcept
12764
{
12765
return m_it == begin_value;
12766
}
12767
12768
/// return whether the iterator is at end
12769
constexpr bool is_end() const noexcept
12770
{
12771
return m_it == end_value;
12772
}
12773
12774
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12775
{
12776
return lhs.m_it == rhs.m_it;
12777
}
12778
12779
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12780
{
12781
return lhs.m_it < rhs.m_it;
12782
}
12783
12784
primitive_iterator_t operator+(difference_type n) noexcept
12785
{
12786
auto result = *this;
12787
result += n;
12788
return result;
12789
}
12790
12791
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12792
{
12793
return lhs.m_it - rhs.m_it;
12794
}
12795
12796
primitive_iterator_t& operator++() noexcept
12797
{
12798
++m_it;
12799
return *this;
12800
}
12801
12802
primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
12803
{
12804
auto result = *this;
12805
++m_it;
12806
return result;
12807
}
12808
12809
primitive_iterator_t& operator--() noexcept
12810
{
12811
--m_it;
12812
return *this;
12813
}
12814
12815
primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
12816
{
12817
auto result = *this;
12818
--m_it;
12819
return result;
12820
}
12821
12822
primitive_iterator_t& operator+=(difference_type n) noexcept
12823
{
12824
m_it += n;
12825
return *this;
12826
}
12827
12828
primitive_iterator_t& operator-=(difference_type n) noexcept
12829
{
12830
m_it -= n;
12831
return *this;
12832
}
12833
};
12834
12835
} // namespace detail
12836
NLOHMANN_JSON_NAMESPACE_END
12837
12838
12839
NLOHMANN_JSON_NAMESPACE_BEGIN
12840
namespace detail
12841
{
12842
12843
/*!
12844
@brief an iterator value
12845
12846
@note This structure could easily be a union, but MSVC currently does not allow
12847
unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
12848
*/
12849
template<typename BasicJsonType> struct internal_iterator
12850
{
12851
/// iterator for JSON objects
12852
typename BasicJsonType::object_t::iterator object_iterator {};
12853
/// iterator for JSON arrays
12854
typename BasicJsonType::array_t::iterator array_iterator {};
12855
/// generic iterator for all other types
12856
primitive_iterator_t primitive_iterator {};
12857
};
12858
12859
} // namespace detail
12860
NLOHMANN_JSON_NAMESPACE_END
12861
12862
// #include <nlohmann/detail/iterators/iter_impl.hpp>
12863
// __ _____ _____ _____
12864
// __| | __| | | | JSON for Modern C++
12865
// | | |__ | | | | | | version 3.11.3
12866
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12867
//
12868
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12869
// SPDX-License-Identifier: MIT
12870
12871
12872
12873
#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
12874
#include <type_traits> // conditional, is_const, remove_const
12875
12876
// #include <nlohmann/detail/exceptions.hpp>
12877
12878
// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12879
12880
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12881
12882
// #include <nlohmann/detail/macro_scope.hpp>
12883
12884
// #include <nlohmann/detail/meta/cpp_future.hpp>
12885
12886
// #include <nlohmann/detail/meta/type_traits.hpp>
12887
12888
// #include <nlohmann/detail/value_t.hpp>
12889
12890
12891
NLOHMANN_JSON_NAMESPACE_BEGIN
12892
namespace detail
12893
{
12894
12895
// forward declare, to be able to friend it later on
12896
template<typename IteratorType> class iteration_proxy;
12897
template<typename IteratorType> class iteration_proxy_value;
12898
12899
/*!
12900
@brief a template for a bidirectional iterator for the @ref basic_json class
12901
This class implements a both iterators (iterator and const_iterator) for the
12902
@ref basic_json class.
12903
@note An iterator is called *initialized* when a pointer to a JSON value has
12904
been set (e.g., by a constructor or a copy assignment). If the iterator is
12905
default-constructed, it is *uninitialized* and most methods are undefined.
12906
**The library uses assertions to detect calls on uninitialized iterators.**
12907
@requirement The class satisfies the following concept requirements:
12908
-
12909
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
12910
The iterator that can be moved can be moved in both directions (i.e.
12911
incremented and decremented).
12912
@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
12913
iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
12914
*/
12915
template<typename BasicJsonType>
12916
class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
12917
{
12918
/// the iterator with BasicJsonType of different const-ness
12919
using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
12920
/// allow basic_json to access private members
12921
friend other_iter_impl;
12922
friend BasicJsonType;
12923
friend iteration_proxy<iter_impl>;
12924
friend iteration_proxy_value<iter_impl>;
12925
12926
using object_t = typename BasicJsonType::object_t;
12927
using array_t = typename BasicJsonType::array_t;
12928
// make sure BasicJsonType is basic_json or const basic_json
12929
static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
12930
"iter_impl only accepts (const) basic_json");
12931
// superficial check for the LegacyBidirectionalIterator named requirement
12932
static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
12933
&& std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
12934
"basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
12935
12936
public:
12937
/// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
12938
/// The C++ Standard has never required user-defined iterators to derive from std::iterator.
12939
/// A user-defined iterator should provide publicly accessible typedefs named
12940
/// iterator_category, value_type, difference_type, pointer, and reference.
12941
/// Note that value_type is required to be non-const, even for constant iterators.
12942
using iterator_category = std::bidirectional_iterator_tag;
12943
12944
/// the type of the values when the iterator is dereferenced
12945
using value_type = typename BasicJsonType::value_type;
12946
/// a type to represent differences between iterators
12947
using difference_type = typename BasicJsonType::difference_type;
12948
/// defines a pointer to the type iterated over (value_type)
12949
using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
12950
typename BasicJsonType::const_pointer,
12951
typename BasicJsonType::pointer>::type;
12952
/// defines a reference to the type iterated over (value_type)
12953
using reference =
12954
typename std::conditional<std::is_const<BasicJsonType>::value,
12955
typename BasicJsonType::const_reference,
12956
typename BasicJsonType::reference>::type;
12957
12958
iter_impl() = default;
12959
~iter_impl() = default;
12960
iter_impl(iter_impl&&) noexcept = default;
12961
iter_impl& operator=(iter_impl&&) noexcept = default;
12962
12963
/*!
12964
@brief constructor for a given JSON instance
12965
@param[in] object pointer to a JSON object for this iterator
12966
@pre object != nullptr
12967
@post The iterator is initialized; i.e. `m_object != nullptr`.
12968
*/
12969
explicit iter_impl(pointer object) noexcept : m_object(object)
12970
{
12971
JSON_ASSERT(m_object != nullptr);
12972
12973
switch (m_object->m_data.m_type)
12974
{
12975
case value_t::object:
12976
{
12977
m_it.object_iterator = typename object_t::iterator();
12978
break;
12979
}
12980
12981
case value_t::array:
12982
{
12983
m_it.array_iterator = typename array_t::iterator();
12984
break;
12985
}
12986
12987
case value_t::null:
12988
case value_t::string:
12989
case value_t::boolean:
12990
case value_t::number_integer:
12991
case value_t::number_unsigned:
12992
case value_t::number_float:
12993
case value_t::binary:
12994
case value_t::discarded:
12995
default:
12996
{
12997
m_it.primitive_iterator = primitive_iterator_t();
12998
break;
12999
}
13000
}
13001
}
13002
13003
/*!
13004
@note The conventional copy constructor and copy assignment are implicitly
13005
defined. Combined with the following converting constructor and
13006
assignment, they support: (1) copy from iterator to iterator, (2)
13007
copy from const iterator to const iterator, and (3) conversion from
13008
iterator to const iterator. However conversion from const iterator
13009
to iterator is not defined.
13010
*/
13011
13012
/*!
13013
@brief const copy constructor
13014
@param[in] other const iterator to copy from
13015
@note This copy constructor had to be defined explicitly to circumvent a bug
13016
occurring on msvc v19.0 compiler (VS 2015) debug build. For more
13017
information refer to: https://github.com/nlohmann/json/issues/1608
13018
*/
13019
iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
13020
: m_object(other.m_object), m_it(other.m_it)
13021
{}
13022
13023
/*!
13024
@brief converting assignment
13025
@param[in] other const iterator to copy from
13026
@return const/non-const iterator
13027
@note It is not checked whether @a other is initialized.
13028
*/
13029
iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
13030
{
13031
if (&other != this)
13032
{
13033
m_object = other.m_object;
13034
m_it = other.m_it;
13035
}
13036
return *this;
13037
}
13038
13039
/*!
13040
@brief converting constructor
13041
@param[in] other non-const iterator to copy from
13042
@note It is not checked whether @a other is initialized.
13043
*/
13044
iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13045
: m_object(other.m_object), m_it(other.m_it)
13046
{}
13047
13048
/*!
13049
@brief converting assignment
13050
@param[in] other non-const iterator to copy from
13051
@return const/non-const iterator
13052
@note It is not checked whether @a other is initialized.
13053
*/
13054
iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13055
{
13056
m_object = other.m_object;
13057
m_it = other.m_it;
13058
return *this;
13059
}
13060
13061
JSON_PRIVATE_UNLESS_TESTED:
13062
/*!
13063
@brief set the iterator to the first value
13064
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13065
*/
13066
void set_begin() noexcept
13067
{
13068
JSON_ASSERT(m_object != nullptr);
13069
13070
switch (m_object->m_data.m_type)
13071
{
13072
case value_t::object:
13073
{
13074
m_it.object_iterator = m_object->m_data.m_value.object->begin();
13075
break;
13076
}
13077
13078
case value_t::array:
13079
{
13080
m_it.array_iterator = m_object->m_data.m_value.array->begin();
13081
break;
13082
}
13083
13084
case value_t::null:
13085
{
13086
// set to end so begin()==end() is true: null is empty
13087
m_it.primitive_iterator.set_end();
13088
break;
13089
}
13090
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
{
13100
m_it.primitive_iterator.set_begin();
13101
break;
13102
}
13103
}
13104
}
13105
13106
/*!
13107
@brief set the iterator past the last value
13108
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13109
*/
13110
void set_end() noexcept
13111
{
13112
JSON_ASSERT(m_object != nullptr);
13113
13114
switch (m_object->m_data.m_type)
13115
{
13116
case value_t::object:
13117
{
13118
m_it.object_iterator = m_object->m_data.m_value.object->end();
13119
break;
13120
}
13121
13122
case value_t::array:
13123
{
13124
m_it.array_iterator = m_object->m_data.m_value.array->end();
13125
break;
13126
}
13127
13128
case value_t::null:
13129
case value_t::string:
13130
case value_t::boolean:
13131
case value_t::number_integer:
13132
case value_t::number_unsigned:
13133
case value_t::number_float:
13134
case value_t::binary:
13135
case value_t::discarded:
13136
default:
13137
{
13138
m_it.primitive_iterator.set_end();
13139
break;
13140
}
13141
}
13142
}
13143
13144
public:
13145
/*!
13146
@brief return a reference to the value pointed to by the iterator
13147
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13148
*/
13149
reference operator*() const
13150
{
13151
JSON_ASSERT(m_object != nullptr);
13152
13153
switch (m_object->m_data.m_type)
13154
{
13155
case value_t::object:
13156
{
13157
JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13158
return m_it.object_iterator->second;
13159
}
13160
13161
case value_t::array:
13162
{
13163
JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13164
return *m_it.array_iterator;
13165
}
13166
13167
case value_t::null:
13168
JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13169
13170
case value_t::string:
13171
case value_t::boolean:
13172
case value_t::number_integer:
13173
case value_t::number_unsigned:
13174
case value_t::number_float:
13175
case value_t::binary:
13176
case value_t::discarded:
13177
default:
13178
{
13179
if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13180
{
13181
return *m_object;
13182
}
13183
13184
JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13185
}
13186
}
13187
}
13188
13189
/*!
13190
@brief dereference the iterator
13191
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13192
*/
13193
pointer operator->() const
13194
{
13195
JSON_ASSERT(m_object != nullptr);
13196
13197
switch (m_object->m_data.m_type)
13198
{
13199
case value_t::object:
13200
{
13201
JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13202
return &(m_it.object_iterator->second);
13203
}
13204
13205
case value_t::array:
13206
{
13207
JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13208
return &*m_it.array_iterator;
13209
}
13210
13211
case value_t::null:
13212
case value_t::string:
13213
case value_t::boolean:
13214
case value_t::number_integer:
13215
case value_t::number_unsigned:
13216
case value_t::number_float:
13217
case value_t::binary:
13218
case value_t::discarded:
13219
default:
13220
{
13221
if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13222
{
13223
return m_object;
13224
}
13225
13226
JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13227
}
13228
}
13229
}
13230
13231
/*!
13232
@brief post-increment (it++)
13233
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13234
*/
13235
iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
13236
{
13237
auto result = *this;
13238
++(*this);
13239
return result;
13240
}
13241
13242
/*!
13243
@brief pre-increment (++it)
13244
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13245
*/
13246
iter_impl& operator++()
13247
{
13248
JSON_ASSERT(m_object != nullptr);
13249
13250
switch (m_object->m_data.m_type)
13251
{
13252
case value_t::object:
13253
{
13254
std::advance(m_it.object_iterator, 1);
13255
break;
13256
}
13257
13258
case value_t::array:
13259
{
13260
std::advance(m_it.array_iterator, 1);
13261
break;
13262
}
13263
13264
case value_t::null:
13265
case value_t::string:
13266
case value_t::boolean:
13267
case value_t::number_integer:
13268
case value_t::number_unsigned:
13269
case value_t::number_float:
13270
case value_t::binary:
13271
case value_t::discarded:
13272
default:
13273
{
13274
++m_it.primitive_iterator;
13275
break;
13276
}
13277
}
13278
13279
return *this;
13280
}
13281
13282
/*!
13283
@brief post-decrement (it--)
13284
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13285
*/
13286
iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
13287
{
13288
auto result = *this;
13289
--(*this);
13290
return result;
13291
}
13292
13293
/*!
13294
@brief pre-decrement (--it)
13295
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13296
*/
13297
iter_impl& operator--()
13298
{
13299
JSON_ASSERT(m_object != nullptr);
13300
13301
switch (m_object->m_data.m_type)
13302
{
13303
case value_t::object:
13304
{
13305
std::advance(m_it.object_iterator, -1);
13306
break;
13307
}
13308
13309
case value_t::array:
13310
{
13311
std::advance(m_it.array_iterator, -1);
13312
break;
13313
}
13314
13315
case value_t::null:
13316
case value_t::string:
13317
case value_t::boolean:
13318
case value_t::number_integer:
13319
case value_t::number_unsigned:
13320
case value_t::number_float:
13321
case value_t::binary:
13322
case value_t::discarded:
13323
default:
13324
{
13325
--m_it.primitive_iterator;
13326
break;
13327
}
13328
}
13329
13330
return *this;
13331
}
13332
13333
/*!
13334
@brief comparison: equal
13335
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13336
*/
13337
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 >
13338
bool operator==(const IterImpl& other) const
13339
{
13340
// if objects are not the same, the comparison is undefined
13341
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13342
{
13343
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13344
}
13345
13346
JSON_ASSERT(m_object != nullptr);
13347
13348
switch (m_object->m_data.m_type)
13349
{
13350
case value_t::object:
13351
return (m_it.object_iterator == other.m_it.object_iterator);
13352
13353
case value_t::array:
13354
return (m_it.array_iterator == other.m_it.array_iterator);
13355
13356
case value_t::null:
13357
case value_t::string:
13358
case value_t::boolean:
13359
case value_t::number_integer:
13360
case value_t::number_unsigned:
13361
case value_t::number_float:
13362
case value_t::binary:
13363
case value_t::discarded:
13364
default:
13365
return (m_it.primitive_iterator == other.m_it.primitive_iterator);
13366
}
13367
}
13368
13369
/*!
13370
@brief comparison: not equal
13371
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13372
*/
13373
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 >
13374
bool operator!=(const IterImpl& other) const
13375
{
13376
return !operator==(other);
13377
}
13378
13379
/*!
13380
@brief comparison: smaller
13381
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13382
*/
13383
bool operator<(const iter_impl& other) const
13384
{
13385
// if objects are not the same, the comparison is undefined
13386
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13387
{
13388
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13389
}
13390
13391
JSON_ASSERT(m_object != nullptr);
13392
13393
switch (m_object->m_data.m_type)
13394
{
13395
case value_t::object:
13396
JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
13397
13398
case value_t::array:
13399
return (m_it.array_iterator < other.m_it.array_iterator);
13400
13401
case value_t::null:
13402
case value_t::string:
13403
case value_t::boolean:
13404
case value_t::number_integer:
13405
case value_t::number_unsigned:
13406
case value_t::number_float:
13407
case value_t::binary:
13408
case value_t::discarded:
13409
default:
13410
return (m_it.primitive_iterator < other.m_it.primitive_iterator);
13411
}
13412
}
13413
13414
/*!
13415
@brief comparison: less than or equal
13416
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13417
*/
13418
bool operator<=(const iter_impl& other) const
13419
{
13420
return !other.operator < (*this);
13421
}
13422
13423
/*!
13424
@brief comparison: greater than
13425
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13426
*/
13427
bool operator>(const iter_impl& other) const
13428
{
13429
return !operator<=(other);
13430
}
13431
13432
/*!
13433
@brief comparison: greater than or equal
13434
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13435
*/
13436
bool operator>=(const iter_impl& other) const
13437
{
13438
return !operator<(other);
13439
}
13440
13441
/*!
13442
@brief add to iterator
13443
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13444
*/
13445
iter_impl& operator+=(difference_type i)
13446
{
13447
JSON_ASSERT(m_object != nullptr);
13448
13449
switch (m_object->m_data.m_type)
13450
{
13451
case value_t::object:
13452
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13453
13454
case value_t::array:
13455
{
13456
std::advance(m_it.array_iterator, i);
13457
break;
13458
}
13459
13460
case value_t::null:
13461
case value_t::string:
13462
case value_t::boolean:
13463
case value_t::number_integer:
13464
case value_t::number_unsigned:
13465
case value_t::number_float:
13466
case value_t::binary:
13467
case value_t::discarded:
13468
default:
13469
{
13470
m_it.primitive_iterator += i;
13471
break;
13472
}
13473
}
13474
13475
return *this;
13476
}
13477
13478
/*!
13479
@brief subtract from iterator
13480
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13481
*/
13482
iter_impl& operator-=(difference_type i)
13483
{
13484
return operator+=(-i);
13485
}
13486
13487
/*!
13488
@brief add to iterator
13489
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13490
*/
13491
iter_impl operator+(difference_type i) const
13492
{
13493
auto result = *this;
13494
result += i;
13495
return result;
13496
}
13497
13498
/*!
13499
@brief addition of distance and iterator
13500
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13501
*/
13502
friend iter_impl operator+(difference_type i, const iter_impl& it)
13503
{
13504
auto result = it;
13505
result += i;
13506
return result;
13507
}
13508
13509
/*!
13510
@brief subtract from iterator
13511
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13512
*/
13513
iter_impl operator-(difference_type i) const
13514
{
13515
auto result = *this;
13516
result -= i;
13517
return result;
13518
}
13519
13520
/*!
13521
@brief return difference
13522
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13523
*/
13524
difference_type operator-(const iter_impl& other) const
13525
{
13526
JSON_ASSERT(m_object != nullptr);
13527
13528
switch (m_object->m_data.m_type)
13529
{
13530
case value_t::object:
13531
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13532
13533
case value_t::array:
13534
return m_it.array_iterator - other.m_it.array_iterator;
13535
13536
case value_t::null:
13537
case value_t::string:
13538
case value_t::boolean:
13539
case value_t::number_integer:
13540
case value_t::number_unsigned:
13541
case value_t::number_float:
13542
case value_t::binary:
13543
case value_t::discarded:
13544
default:
13545
return m_it.primitive_iterator - other.m_it.primitive_iterator;
13546
}
13547
}
13548
13549
/*!
13550
@brief access to successor
13551
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13552
*/
13553
reference operator[](difference_type n) const
13554
{
13555
JSON_ASSERT(m_object != nullptr);
13556
13557
switch (m_object->m_data.m_type)
13558
{
13559
case value_t::object:
13560
JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
13561
13562
case value_t::array:
13563
return *std::next(m_it.array_iterator, n);
13564
13565
case value_t::null:
13566
JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13567
13568
case value_t::string:
13569
case value_t::boolean:
13570
case value_t::number_integer:
13571
case value_t::number_unsigned:
13572
case value_t::number_float:
13573
case value_t::binary:
13574
case value_t::discarded:
13575
default:
13576
{
13577
if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
13578
{
13579
return *m_object;
13580
}
13581
13582
JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13583
}
13584
}
13585
}
13586
13587
/*!
13588
@brief return the key of an object iterator
13589
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13590
*/
13591
const typename object_t::key_type& key() const
13592
{
13593
JSON_ASSERT(m_object != nullptr);
13594
13595
if (JSON_HEDLEY_LIKELY(m_object->is_object()))
13596
{
13597
return m_it.object_iterator->first;
13598
}
13599
13600
JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
13601
}
13602
13603
/*!
13604
@brief return the value of an iterator
13605
@pre The iterator is initialized; i.e. `m_object != nullptr`.
13606
*/
13607
reference value() const
13608
{
13609
return operator*();
13610
}
13611
13612
JSON_PRIVATE_UNLESS_TESTED:
13613
/// associated JSON instance
13614
pointer m_object = nullptr;
13615
/// the actual iterator of the associated instance
13616
internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
13617
};
13618
13619
} // namespace detail
13620
NLOHMANN_JSON_NAMESPACE_END
13621
13622
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
13623
13624
// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
13625
// __ _____ _____ _____
13626
// __| | __| | | | JSON for Modern C++
13627
// | | |__ | | | | | | version 3.11.3
13628
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13629
//
13630
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13631
// SPDX-License-Identifier: MIT
13632
13633
13634
13635
#include <cstddef> // ptrdiff_t
13636
#include <iterator> // reverse_iterator
13637
#include <utility> // declval
13638
13639
// #include <nlohmann/detail/abi_macros.hpp>
13640
13641
13642
NLOHMANN_JSON_NAMESPACE_BEGIN
13643
namespace detail
13644
{
13645
13646
//////////////////////
13647
// reverse_iterator //
13648
//////////////////////
13649
13650
/*!
13651
@brief a template for a reverse iterator class
13652
13653
@tparam Base the base iterator type to reverse. Valid types are @ref
13654
iterator (to create @ref reverse_iterator) and @ref const_iterator (to
13655
create @ref const_reverse_iterator).
13656
13657
@requirement The class satisfies the following concept requirements:
13658
-
13659
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
13660
The iterator that can be moved can be moved in both directions (i.e.
13661
incremented and decremented).
13662
- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
13663
It is possible to write to the pointed-to element (only if @a Base is
13664
@ref iterator).
13665
13666
@since version 1.0.0
13667
*/
13668
template<typename Base>
13669
class json_reverse_iterator : public std::reverse_iterator<Base>
13670
{
13671
public:
13672
using difference_type = std::ptrdiff_t;
13673
/// shortcut to the reverse iterator adapter
13674
using base_iterator = std::reverse_iterator<Base>;
13675
/// the reference type for the pointed-to element
13676
using reference = typename Base::reference;
13677
13678
/// create reverse iterator from iterator
13679
explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
13680
: base_iterator(it) {}
13681
13682
/// create reverse iterator from base class
13683
explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
13684
13685
/// post-increment (it++)
13686
json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
13687
{
13688
return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
13689
}
13690
13691
/// pre-increment (++it)
13692
json_reverse_iterator& operator++()
13693
{
13694
return static_cast<json_reverse_iterator&>(base_iterator::operator++());
13695
}
13696
13697
/// post-decrement (it--)
13698
json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
13699
{
13700
return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
13701
}
13702
13703
/// pre-decrement (--it)
13704
json_reverse_iterator& operator--()
13705
{
13706
return static_cast<json_reverse_iterator&>(base_iterator::operator--());
13707
}
13708
13709
/// add to iterator
13710
json_reverse_iterator& operator+=(difference_type i)
13711
{
13712
return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
13713
}
13714
13715
/// add to iterator
13716
json_reverse_iterator operator+(difference_type i) const
13717
{
13718
return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
13719
}
13720
13721
/// subtract from iterator
13722
json_reverse_iterator operator-(difference_type i) const
13723
{
13724
return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
13725
}
13726
13727
/// return difference
13728
difference_type operator-(const json_reverse_iterator& other) const
13729
{
13730
return base_iterator(*this) - base_iterator(other);
13731
}
13732
13733
/// access to successor
13734
reference operator[](difference_type n) const
13735
{
13736
return *(this->operator+(n));
13737
}
13738
13739
/// return the key of an object iterator
13740
auto key() const -> decltype(std::declval<Base>().key())
13741
{
13742
auto it = --this->base();
13743
return it.key();
13744
}
13745
13746
/// return the value of an iterator
13747
reference value() const
13748
{
13749
auto it = --this->base();
13750
return it.operator * ();
13751
}
13752
};
13753
13754
} // namespace detail
13755
NLOHMANN_JSON_NAMESPACE_END
13756
13757
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13758
13759
// #include <nlohmann/detail/json_custom_base_class.hpp>
13760
// __ _____ _____ _____
13761
// __| | __| | | | JSON for Modern C++
13762
// | | |__ | | | | | | version 3.11.3
13763
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13764
//
13765
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13766
// SPDX-License-Identifier: MIT
13767
13768
13769
13770
#include <type_traits> // conditional, is_same
13771
13772
// #include <nlohmann/detail/abi_macros.hpp>
13773
13774
13775
NLOHMANN_JSON_NAMESPACE_BEGIN
13776
namespace detail
13777
{
13778
13779
/*!
13780
@brief Default base class of the @ref basic_json class.
13781
13782
So that the correct implementations of the copy / move ctors / assign operators
13783
of @ref basic_json do not require complex case distinctions
13784
(no base class / custom base class used as customization point),
13785
@ref basic_json always has a base class.
13786
By default, this class is used because it is empty and thus has no effect
13787
on the behavior of @ref basic_json.
13788
*/
13789
struct json_default_base {};
13790
13791
template<class T>
13792
using json_base_class = typename std::conditional <
13793
std::is_same<T, void>::value,
13794
json_default_base,
13795
T
13796
>::type;
13797
13798
} // namespace detail
13799
NLOHMANN_JSON_NAMESPACE_END
13800
13801
// #include <nlohmann/detail/json_pointer.hpp>
13802
// __ _____ _____ _____
13803
// __| | __| | | | JSON for Modern C++
13804
// | | |__ | | | | | | version 3.11.3
13805
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13806
//
13807
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13808
// SPDX-License-Identifier: MIT
13809
13810
13811
13812
#include <algorithm> // all_of
13813
#include <cctype> // isdigit
13814
#include <cerrno> // errno, ERANGE
13815
#include <cstdlib> // strtoull
13816
#ifndef JSON_NO_IO
13817
#include <iosfwd> // ostream
13818
#endif // JSON_NO_IO
13819
#include <limits> // max
13820
#include <numeric> // accumulate
13821
#include <string> // string
13822
#include <utility> // move
13823
#include <vector> // vector
13824
13825
// #include <nlohmann/detail/exceptions.hpp>
13826
13827
// #include <nlohmann/detail/macro_scope.hpp>
13828
13829
// #include <nlohmann/detail/string_concat.hpp>
13830
13831
// #include <nlohmann/detail/string_escape.hpp>
13832
13833
// #include <nlohmann/detail/value_t.hpp>
13834
13835
13836
NLOHMANN_JSON_NAMESPACE_BEGIN
13837
13838
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
13839
/// @sa https://json.nlohmann.me/api/json_pointer/
13840
template<typename RefStringType>
13841
class json_pointer
13842
{
13843
// allow basic_json to access private members
13844
NLOHMANN_BASIC_JSON_TPL_DECLARATION
13845
friend class basic_json;
13846
13847
template<typename>
13848
friend class json_pointer;
13849
13850
template<typename T>
13851
struct string_t_helper
13852
{
13853
using type = T;
13854
};
13855
13856
NLOHMANN_BASIC_JSON_TPL_DECLARATION
13857
struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
13858
{
13859
using type = StringType;
13860
};
13861
13862
public:
13863
// for backwards compatibility accept BasicJsonType
13864
using string_t = typename string_t_helper<RefStringType>::type;
13865
13866
/// @brief create JSON pointer
13867
/// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
13868
explicit json_pointer(const string_t& s = "")
13869
: reference_tokens(split(s))
13870
{}
13871
13872
/// @brief return a string representation of the JSON pointer
13873
/// @sa https://json.nlohmann.me/api/json_pointer/to_string/
13874
string_t to_string() const
13875
{
13876
return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
13877
string_t{},
13878
[](const string_t& a, const string_t& b)
13879
{
13880
return detail::concat(a, '/', detail::escape(b));
13881
});
13882
}
13883
13884
/// @brief return a string representation of the JSON pointer
13885
/// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
13886
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
13887
operator string_t() const
13888
{
13889
return to_string();
13890
}
13891
13892
#ifndef JSON_NO_IO
13893
/// @brief write string representation of the JSON pointer to stream
13894
/// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
13895
friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
13896
{
13897
o << ptr.to_string();
13898
return o;
13899
}
13900
#endif
13901
13902
/// @brief append another JSON pointer at the end of this JSON pointer
13903
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
13904
json_pointer& operator/=(const json_pointer& ptr)
13905
{
13906
reference_tokens.insert(reference_tokens.end(),
13907
ptr.reference_tokens.begin(),
13908
ptr.reference_tokens.end());
13909
return *this;
13910
}
13911
13912
/// @brief append an unescaped reference token at the end of this JSON pointer
13913
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
13914
json_pointer& operator/=(string_t token)
13915
{
13916
push_back(std::move(token));
13917
return *this;
13918
}
13919
13920
/// @brief append an array index at the end of this JSON pointer
13921
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
13922
json_pointer& operator/=(std::size_t array_idx)
13923
{
13924
return *this /= std::to_string(array_idx);
13925
}
13926
13927
/// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
13928
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
13929
friend json_pointer operator/(const json_pointer& lhs,
13930
const json_pointer& rhs)
13931
{
13932
return json_pointer(lhs) /= rhs;
13933
}
13934
13935
/// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
13936
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
13937
friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
13938
{
13939
return json_pointer(lhs) /= std::move(token);
13940
}
13941
13942
/// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
13943
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
13944
friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
13945
{
13946
return json_pointer(lhs) /= array_idx;
13947
}
13948
13949
/// @brief returns the parent of this JSON pointer
13950
/// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
13951
json_pointer parent_pointer() const
13952
{
13953
if (empty())
13954
{
13955
return *this;
13956
}
13957
13958
json_pointer res = *this;
13959
res.pop_back();
13960
return res;
13961
}
13962
13963
/// @brief remove last reference token
13964
/// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
13965
void pop_back()
13966
{
13967
if (JSON_HEDLEY_UNLIKELY(empty()))
13968
{
13969
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13970
}
13971
13972
reference_tokens.pop_back();
13973
}
13974
13975
/// @brief return last reference token
13976
/// @sa https://json.nlohmann.me/api/json_pointer/back/
13977
const string_t& back() const
13978
{
13979
if (JSON_HEDLEY_UNLIKELY(empty()))
13980
{
13981
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13982
}
13983
13984
return reference_tokens.back();
13985
}
13986
13987
/// @brief append an unescaped token at the end of the reference pointer
13988
/// @sa https://json.nlohmann.me/api/json_pointer/push_back/
13989
void push_back(const string_t& token)
13990
{
13991
reference_tokens.push_back(token);
13992
}
13993
13994
/// @brief append an unescaped token at the end of the reference pointer
13995
/// @sa https://json.nlohmann.me/api/json_pointer/push_back/
13996
void push_back(string_t&& token)
13997
{
13998
reference_tokens.push_back(std::move(token));
13999
}
14000
14001
/// @brief return whether pointer points to the root document
14002
/// @sa https://json.nlohmann.me/api/json_pointer/empty/
14003
bool empty() const noexcept
14004
{
14005
return reference_tokens.empty();
14006
}
14007
14008
private:
14009
/*!
14010
@param[in] s reference token to be converted into an array index
14011
14012
@return integer representation of @a s
14013
14014
@throw parse_error.106 if an array index begins with '0'
14015
@throw parse_error.109 if an array index begins not with a digit
14016
@throw out_of_range.404 if string @a s could not be converted to an integer
14017
@throw out_of_range.410 if an array index exceeds size_type
14018
*/
14019
template<typename BasicJsonType>
14020
static typename BasicJsonType::size_type array_index(const string_t& s)
14021
{
14022
using size_type = typename BasicJsonType::size_type;
14023
14024
// error condition (cf. RFC 6901, Sect. 4)
14025
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14026
{
14027
JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14028
}
14029
14030
// error condition (cf. RFC 6901, Sect. 4)
14031
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14032
{
14033
JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14034
}
14035
14036
const char* p = s.c_str();
14037
char* p_end = nullptr;
14038
errno = 0; // strtoull doesn't reset errno
14039
const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14040
if (p == p_end // invalid input or empty string
14041
|| errno == ERANGE // out of range
14042
|| JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14043
{
14044
JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14045
}
14046
14047
// only triggered on special platforms (like 32bit), see also
14048
// https://github.com/nlohmann/json/pull/2203
14049
if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
14050
{
14051
JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14052
}
14053
14054
return static_cast<size_type>(res);
14055
}
14056
14057
JSON_PRIVATE_UNLESS_TESTED:
14058
json_pointer top() const
14059
{
14060
if (JSON_HEDLEY_UNLIKELY(empty()))
14061
{
14062
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14063
}
14064
14065
json_pointer result = *this;
14066
result.reference_tokens = {reference_tokens[0]};
14067
return result;
14068
}
14069
14070
private:
14071
/*!
14072
@brief create and return a reference to the pointed to value
14073
14074
@complexity Linear in the number of reference tokens.
14075
14076
@throw parse_error.109 if array index is not a number
14077
@throw type_error.313 if value cannot be unflattened
14078
*/
14079
template<typename BasicJsonType>
14080
BasicJsonType& get_and_create(BasicJsonType& j) const
14081
{
14082
auto* result = &j;
14083
14084
// in case no reference tokens exist, return a reference to the JSON value
14085
// j which will be overwritten by a primitive value
14086
for (const auto& reference_token : reference_tokens)
14087
{
14088
switch (result->type())
14089
{
14090
case detail::value_t::null:
14091
{
14092
if (reference_token == "0")
14093
{
14094
// start a new array if reference token is 0
14095
result = &result->operator[](0);
14096
}
14097
else
14098
{
14099
// start a new object otherwise
14100
result = &result->operator[](reference_token);
14101
}
14102
break;
14103
}
14104
14105
case detail::value_t::object:
14106
{
14107
// create an entry in the object
14108
result = &result->operator[](reference_token);
14109
break;
14110
}
14111
14112
case detail::value_t::array:
14113
{
14114
// create an entry in the array
14115
result = &result->operator[](array_index<BasicJsonType>(reference_token));
14116
break;
14117
}
14118
14119
/*
14120
The following code is only reached if there exists a reference
14121
token _and_ the current value is primitive. In this case, we have
14122
an error situation, because primitive values may only occur as
14123
single value; that is, with an empty list of reference tokens.
14124
*/
14125
case detail::value_t::string:
14126
case detail::value_t::boolean:
14127
case detail::value_t::number_integer:
14128
case detail::value_t::number_unsigned:
14129
case detail::value_t::number_float:
14130
case detail::value_t::binary:
14131
case detail::value_t::discarded:
14132
default:
14133
JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14134
}
14135
}
14136
14137
return *result;
14138
}
14139
14140
/*!
14141
@brief return a reference to the pointed to value
14142
14143
@note This version does not throw if a value is not present, but tries to
14144
create nested values instead. For instance, calling this function
14145
with pointer `"/this/that"` on a null value is equivalent to calling
14146
`operator[]("this").operator[]("that")` on that value, effectively
14147
changing the null value to an object.
14148
14149
@param[in] ptr a JSON value
14150
14151
@return reference to the JSON value pointed to by the JSON pointer
14152
14153
@complexity Linear in the length of the JSON pointer.
14154
14155
@throw parse_error.106 if an array index begins with '0'
14156
@throw parse_error.109 if an array index was not a number
14157
@throw out_of_range.404 if the JSON pointer can not be resolved
14158
*/
14159
template<typename BasicJsonType>
14160
BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14161
{
14162
for (const auto& reference_token : reference_tokens)
14163
{
14164
// convert null values to arrays or objects before continuing
14165
if (ptr->is_null())
14166
{
14167
// check if reference token is a number
14168
const bool nums =
14169
std::all_of(reference_token.begin(), reference_token.end(),
14170
[](const unsigned char x)
14171
{
14172
return std::isdigit(x);
14173
});
14174
14175
// change value to array for numbers or "-" or to object otherwise
14176
*ptr = (nums || reference_token == "-")
14177
? detail::value_t::array
14178
: detail::value_t::object;
14179
}
14180
14181
switch (ptr->type())
14182
{
14183
case detail::value_t::object:
14184
{
14185
// use unchecked object access
14186
ptr = &ptr->operator[](reference_token);
14187
break;
14188
}
14189
14190
case detail::value_t::array:
14191
{
14192
if (reference_token == "-")
14193
{
14194
// explicitly treat "-" as index beyond the end
14195
ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14196
}
14197
else
14198
{
14199
// convert array index to number; unchecked access
14200
ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14201
}
14202
break;
14203
}
14204
14205
case detail::value_t::null:
14206
case detail::value_t::string:
14207
case detail::value_t::boolean:
14208
case detail::value_t::number_integer:
14209
case detail::value_t::number_unsigned:
14210
case detail::value_t::number_float:
14211
case detail::value_t::binary:
14212
case detail::value_t::discarded:
14213
default:
14214
JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14215
}
14216
}
14217
14218
return *ptr;
14219
}
14220
14221
/*!
14222
@throw parse_error.106 if an array index begins with '0'
14223
@throw parse_error.109 if an array index was not a number
14224
@throw out_of_range.402 if the array index '-' is used
14225
@throw out_of_range.404 if the JSON pointer can not be resolved
14226
*/
14227
template<typename BasicJsonType>
14228
BasicJsonType& get_checked(BasicJsonType* ptr) const
14229
{
14230
for (const auto& reference_token : reference_tokens)
14231
{
14232
switch (ptr->type())
14233
{
14234
case detail::value_t::object:
14235
{
14236
// note: at performs range check
14237
ptr = &ptr->at(reference_token);
14238
break;
14239
}
14240
14241
case detail::value_t::array:
14242
{
14243
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14244
{
14245
// "-" always fails the range check
14246
JSON_THROW(detail::out_of_range::create(402, detail::concat(
14247
"array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14248
") is out of range"), ptr));
14249
}
14250
14251
// note: at performs range check
14252
ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14253
break;
14254
}
14255
14256
case detail::value_t::null:
14257
case detail::value_t::string:
14258
case detail::value_t::boolean:
14259
case detail::value_t::number_integer:
14260
case detail::value_t::number_unsigned:
14261
case detail::value_t::number_float:
14262
case detail::value_t::binary:
14263
case detail::value_t::discarded:
14264
default:
14265
JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14266
}
14267
}
14268
14269
return *ptr;
14270
}
14271
14272
/*!
14273
@brief return a const reference to the pointed to value
14274
14275
@param[in] ptr a JSON value
14276
14277
@return const reference to the JSON value pointed to by the JSON
14278
pointer
14279
14280
@throw parse_error.106 if an array index begins with '0'
14281
@throw parse_error.109 if an array index was not a number
14282
@throw out_of_range.402 if the array index '-' is used
14283
@throw out_of_range.404 if the JSON pointer can not be resolved
14284
*/
14285
template<typename BasicJsonType>
14286
const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
14287
{
14288
for (const auto& reference_token : reference_tokens)
14289
{
14290
switch (ptr->type())
14291
{
14292
case detail::value_t::object:
14293
{
14294
// use unchecked object access
14295
ptr = &ptr->operator[](reference_token);
14296
break;
14297
}
14298
14299
case detail::value_t::array:
14300
{
14301
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14302
{
14303
// "-" cannot be used for const access
14304
JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr));
14305
}
14306
14307
// use unchecked array access
14308
ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14309
break;
14310
}
14311
14312
case detail::value_t::null:
14313
case detail::value_t::string:
14314
case detail::value_t::boolean:
14315
case detail::value_t::number_integer:
14316
case detail::value_t::number_unsigned:
14317
case detail::value_t::number_float:
14318
case detail::value_t::binary:
14319
case detail::value_t::discarded:
14320
default:
14321
JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14322
}
14323
}
14324
14325
return *ptr;
14326
}
14327
14328
/*!
14329
@throw parse_error.106 if an array index begins with '0'
14330
@throw parse_error.109 if an array index was not a number
14331
@throw out_of_range.402 if the array index '-' is used
14332
@throw out_of_range.404 if the JSON pointer can not be resolved
14333
*/
14334
template<typename BasicJsonType>
14335
const BasicJsonType& get_checked(const BasicJsonType* ptr) const
14336
{
14337
for (const auto& reference_token : reference_tokens)
14338
{
14339
switch (ptr->type())
14340
{
14341
case detail::value_t::object:
14342
{
14343
// note: at performs range check
14344
ptr = &ptr->at(reference_token);
14345
break;
14346
}
14347
14348
case detail::value_t::array:
14349
{
14350
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14351
{
14352
// "-" always fails the range check
14353
JSON_THROW(detail::out_of_range::create(402, detail::concat(
14354
"array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14355
") is out of range"), ptr));
14356
}
14357
14358
// note: at performs range check
14359
ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14360
break;
14361
}
14362
14363
case detail::value_t::null:
14364
case detail::value_t::string:
14365
case detail::value_t::boolean:
14366
case detail::value_t::number_integer:
14367
case detail::value_t::number_unsigned:
14368
case detail::value_t::number_float:
14369
case detail::value_t::binary:
14370
case detail::value_t::discarded:
14371
default:
14372
JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14373
}
14374
}
14375
14376
return *ptr;
14377
}
14378
14379
/*!
14380
@throw parse_error.106 if an array index begins with '0'
14381
@throw parse_error.109 if an array index was not a number
14382
*/
14383
template<typename BasicJsonType>
14384
bool contains(const BasicJsonType* ptr) const
14385
{
14386
for (const auto& reference_token : reference_tokens)
14387
{
14388
switch (ptr->type())
14389
{
14390
case detail::value_t::object:
14391
{
14392
if (!ptr->contains(reference_token))
14393
{
14394
// we did not find the key in the object
14395
return false;
14396
}
14397
14398
ptr = &ptr->operator[](reference_token);
14399
break;
14400
}
14401
14402
case detail::value_t::array:
14403
{
14404
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14405
{
14406
// "-" always fails the range check
14407
return false;
14408
}
14409
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
14410
{
14411
// invalid char
14412
return false;
14413
}
14414
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
14415
{
14416
if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
14417
{
14418
// first char should be between '1' and '9'
14419
return false;
14420
}
14421
for (std::size_t i = 1; i < reference_token.size(); i++)
14422
{
14423
if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
14424
{
14425
// other char should be between '0' and '9'
14426
return false;
14427
}
14428
}
14429
}
14430
14431
const auto idx = array_index<BasicJsonType>(reference_token);
14432
if (idx >= ptr->size())
14433
{
14434
// index out of range
14435
return false;
14436
}
14437
14438
ptr = &ptr->operator[](idx);
14439
break;
14440
}
14441
14442
case detail::value_t::null:
14443
case detail::value_t::string:
14444
case detail::value_t::boolean:
14445
case detail::value_t::number_integer:
14446
case detail::value_t::number_unsigned:
14447
case detail::value_t::number_float:
14448
case detail::value_t::binary:
14449
case detail::value_t::discarded:
14450
default:
14451
{
14452
// we do not expect primitive values if there is still a
14453
// reference token to process
14454
return false;
14455
}
14456
}
14457
}
14458
14459
// no reference token left means we found a primitive value
14460
return true;
14461
}
14462
14463
/*!
14464
@brief split the string input to reference tokens
14465
14466
@note This function is only called by the json_pointer constructor.
14467
All exceptions below are documented there.
14468
14469
@throw parse_error.107 if the pointer is not empty or begins with '/'
14470
@throw parse_error.108 if character '~' is not followed by '0' or '1'
14471
*/
14472
static std::vector<string_t> split(const string_t& reference_string)
14473
{
14474
std::vector<string_t> result;
14475
14476
// special case: empty reference string -> no reference tokens
14477
if (reference_string.empty())
14478
{
14479
return result;
14480
}
14481
14482
// check if nonempty reference string begins with slash
14483
if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
14484
{
14485
JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
14486
}
14487
14488
// extract the reference tokens:
14489
// - slash: position of the last read slash (or end of string)
14490
// - start: position after the previous slash
14491
for (
14492
// search for the first slash after the first character
14493
std::size_t slash = reference_string.find_first_of('/', 1),
14494
// set the beginning of the first reference token
14495
start = 1;
14496
// we can stop if start == 0 (if slash == string_t::npos)
14497
start != 0;
14498
// set the beginning of the next reference token
14499
// (will eventually be 0 if slash == string_t::npos)
14500
start = (slash == string_t::npos) ? 0 : slash + 1,
14501
// find next slash
14502
slash = reference_string.find_first_of('/', start))
14503
{
14504
// use the text between the beginning of the reference token
14505
// (start) and the last slash (slash).
14506
auto reference_token = reference_string.substr(start, slash - start);
14507
14508
// check reference tokens are properly escaped
14509
for (std::size_t pos = reference_token.find_first_of('~');
14510
pos != string_t::npos;
14511
pos = reference_token.find_first_of('~', pos + 1))
14512
{
14513
JSON_ASSERT(reference_token[pos] == '~');
14514
14515
// ~ must be followed by 0 or 1
14516
if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
14517
(reference_token[pos + 1] != '0' &&
14518
reference_token[pos + 1] != '1')))
14519
{
14520
JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
14521
}
14522
}
14523
14524
// finally, store the reference token
14525
detail::unescape(reference_token);
14526
result.push_back(reference_token);
14527
}
14528
14529
return result;
14530
}
14531
14532
private:
14533
/*!
14534
@param[in] reference_string the reference string to the current value
14535
@param[in] value the value to consider
14536
@param[in,out] result the result object to insert values to
14537
14538
@note Empty objects or arrays are flattened to `null`.
14539
*/
14540
template<typename BasicJsonType>
14541
static void flatten(const string_t& reference_string,
14542
const BasicJsonType& value,
14543
BasicJsonType& result)
14544
{
14545
switch (value.type())
14546
{
14547
case detail::value_t::array:
14548
{
14549
if (value.m_data.m_value.array->empty())
14550
{
14551
// flatten empty array as null
14552
result[reference_string] = nullptr;
14553
}
14554
else
14555
{
14556
// iterate array and use index as reference string
14557
for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
14558
{
14559
flatten(detail::concat(reference_string, '/', std::to_string(i)),
14560
value.m_data.m_value.array->operator[](i), result);
14561
}
14562
}
14563
break;
14564
}
14565
14566
case detail::value_t::object:
14567
{
14568
if (value.m_data.m_value.object->empty())
14569
{
14570
// flatten empty object as null
14571
result[reference_string] = nullptr;
14572
}
14573
else
14574
{
14575
// iterate object and use keys as reference string
14576
for (const auto& element : *value.m_data.m_value.object)
14577
{
14578
flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
14579
}
14580
}
14581
break;
14582
}
14583
14584
case detail::value_t::null:
14585
case detail::value_t::string:
14586
case detail::value_t::boolean:
14587
case detail::value_t::number_integer:
14588
case detail::value_t::number_unsigned:
14589
case detail::value_t::number_float:
14590
case detail::value_t::binary:
14591
case detail::value_t::discarded:
14592
default:
14593
{
14594
// add primitive value with its reference string
14595
result[reference_string] = value;
14596
break;
14597
}
14598
}
14599
}
14600
14601
/*!
14602
@param[in] value flattened JSON
14603
14604
@return unflattened JSON
14605
14606
@throw parse_error.109 if array index is not a number
14607
@throw type_error.314 if value is not an object
14608
@throw type_error.315 if object values are not primitive
14609
@throw type_error.313 if value cannot be unflattened
14610
*/
14611
template<typename BasicJsonType>
14612
static BasicJsonType
14613
unflatten(const BasicJsonType& value)
14614
{
14615
if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
14616
{
14617
JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
14618
}
14619
14620
BasicJsonType result;
14621
14622
// iterate the JSON object values
14623
for (const auto& element : *value.m_data.m_value.object)
14624
{
14625
if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
14626
{
14627
JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
14628
}
14629
14630
// assign value to reference pointed to by JSON pointer; Note that if
14631
// the JSON pointer is "" (i.e., points to the whole value), function
14632
// get_and_create returns a reference to result itself. An assignment
14633
// will then create a primitive value.
14634
json_pointer(element.first).get_and_create(result) = element.second;
14635
}
14636
14637
return result;
14638
}
14639
14640
// can't use conversion operator because of ambiguity
14641
json_pointer<string_t> convert() const&
14642
{
14643
json_pointer<string_t> result;
14644
result.reference_tokens = reference_tokens;
14645
return result;
14646
}
14647
14648
json_pointer<string_t> convert()&&
14649
{
14650
json_pointer<string_t> result;
14651
result.reference_tokens = std::move(reference_tokens);
14652
return result;
14653
}
14654
14655
public:
14656
#if JSON_HAS_THREE_WAY_COMPARISON
14657
/// @brief compares two JSON pointers for equality
14658
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14659
template<typename RefStringTypeRhs>
14660
bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
14661
{
14662
return reference_tokens == rhs.reference_tokens;
14663
}
14664
14665
/// @brief compares JSON pointer and string for equality
14666
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14667
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
14668
bool operator==(const string_t& rhs) const
14669
{
14670
return *this == json_pointer(rhs);
14671
}
14672
14673
/// @brief 3-way compares two JSON pointers
14674
template<typename RefStringTypeRhs>
14675
std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
14676
{
14677
return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
14678
}
14679
#else
14680
/// @brief compares two JSON pointers for equality
14681
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14682
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14683
// NOLINTNEXTLINE(readability-redundant-declaration)
14684
friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14685
const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14686
14687
/// @brief compares JSON pointer and string for equality
14688
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14689
template<typename RefStringTypeLhs, typename StringType>
14690
// NOLINTNEXTLINE(readability-redundant-declaration)
14691
friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14692
const StringType& rhs);
14693
14694
/// @brief compares string and JSON pointer for equality
14695
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14696
template<typename RefStringTypeRhs, typename StringType>
14697
// NOLINTNEXTLINE(readability-redundant-declaration)
14698
friend bool operator==(const StringType& lhs,
14699
const json_pointer<RefStringTypeRhs>& rhs);
14700
14701
/// @brief compares two JSON pointers for inequality
14702
/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
14703
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14704
// NOLINTNEXTLINE(readability-redundant-declaration)
14705
friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14706
const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14707
14708
/// @brief compares JSON pointer and string for inequality
14709
/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
14710
template<typename RefStringTypeLhs, typename StringType>
14711
// NOLINTNEXTLINE(readability-redundant-declaration)
14712
friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14713
const StringType& rhs);
14714
14715
/// @brief compares string and JSON pointer for inequality
14716
/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
14717
template<typename RefStringTypeRhs, typename StringType>
14718
// NOLINTNEXTLINE(readability-redundant-declaration)
14719
friend bool operator!=(const StringType& lhs,
14720
const json_pointer<RefStringTypeRhs>& rhs);
14721
14722
/// @brief compares two JSON pointer for less-than
14723
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14724
// NOLINTNEXTLINE(readability-redundant-declaration)
14725
friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14726
const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14727
#endif
14728
14729
private:
14730
/// the reference tokens
14731
std::vector<string_t> reference_tokens;
14732
};
14733
14734
#if !JSON_HAS_THREE_WAY_COMPARISON
14735
// functions cannot be defined inside class due to ODR violations
14736
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14737
inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14738
const json_pointer<RefStringTypeRhs>& rhs) noexcept
14739
{
14740
return lhs.reference_tokens == rhs.reference_tokens;
14741
}
14742
14743
template<typename RefStringTypeLhs,
14744
typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14745
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
14746
inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14747
const StringType& rhs)
14748
{
14749
return lhs == json_pointer<RefStringTypeLhs>(rhs);
14750
}
14751
14752
template<typename RefStringTypeRhs,
14753
typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14754
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
14755
inline bool operator==(const StringType& lhs,
14756
const json_pointer<RefStringTypeRhs>& rhs)
14757
{
14758
return json_pointer<RefStringTypeRhs>(lhs) == rhs;
14759
}
14760
14761
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14762
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14763
const json_pointer<RefStringTypeRhs>& rhs) noexcept
14764
{
14765
return !(lhs == rhs);
14766
}
14767
14768
template<typename RefStringTypeLhs,
14769
typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14770
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
14771
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14772
const StringType& rhs)
14773
{
14774
return !(lhs == rhs);
14775
}
14776
14777
template<typename RefStringTypeRhs,
14778
typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14779
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
14780
inline bool operator!=(const StringType& lhs,
14781
const json_pointer<RefStringTypeRhs>& rhs)
14782
{
14783
return !(lhs == rhs);
14784
}
14785
14786
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14787
inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14788
const json_pointer<RefStringTypeRhs>& rhs) noexcept
14789
{
14790
return lhs.reference_tokens < rhs.reference_tokens;
14791
}
14792
#endif
14793
14794
NLOHMANN_JSON_NAMESPACE_END
14795
14796
// #include <nlohmann/detail/json_ref.hpp>
14797
// __ _____ _____ _____
14798
// __| | __| | | | JSON for Modern C++
14799
// | | |__ | | | | | | version 3.11.3
14800
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14801
//
14802
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14803
// SPDX-License-Identifier: MIT
14804
14805
14806
14807
#include <initializer_list>
14808
#include <utility>
14809
14810
// #include <nlohmann/detail/abi_macros.hpp>
14811
14812
// #include <nlohmann/detail/meta/type_traits.hpp>
14813
14814
14815
NLOHMANN_JSON_NAMESPACE_BEGIN
14816
namespace detail
14817
{
14818
14819
template<typename BasicJsonType>
14820
class json_ref
14821
{
14822
public:
14823
using value_type = BasicJsonType;
14824
14825
json_ref(value_type&& value)
14826
: owned_value(std::move(value))
14827
{}
14828
14829
json_ref(const value_type& value)
14830
: value_ref(&value)
14831
{}
14832
14833
json_ref(std::initializer_list<json_ref> init)
14834
: owned_value(init)
14835
{}
14836
14837
template <
14838
class... Args,
14839
enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
14840
json_ref(Args && ... args)
14841
: owned_value(std::forward<Args>(args)...)
14842
{}
14843
14844
// class should be movable only
14845
json_ref(json_ref&&) noexcept = default;
14846
json_ref(const json_ref&) = delete;
14847
json_ref& operator=(const json_ref&) = delete;
14848
json_ref& operator=(json_ref&&) = delete;
14849
~json_ref() = default;
14850
14851
value_type moved_or_copied() const
14852
{
14853
if (value_ref == nullptr)
14854
{
14855
return std::move(owned_value);
14856
}
14857
return *value_ref;
14858
}
14859
14860
value_type const& operator*() const
14861
{
14862
return value_ref ? *value_ref : owned_value;
14863
}
14864
14865
value_type const* operator->() const
14866
{
14867
return &** this;
14868
}
14869
14870
private:
14871
mutable value_type owned_value = nullptr;
14872
value_type const* value_ref = nullptr;
14873
};
14874
14875
} // namespace detail
14876
NLOHMANN_JSON_NAMESPACE_END
14877
14878
// #include <nlohmann/detail/macro_scope.hpp>
14879
14880
// #include <nlohmann/detail/string_concat.hpp>
14881
14882
// #include <nlohmann/detail/string_escape.hpp>
14883
14884
// #include <nlohmann/detail/meta/cpp_future.hpp>
14885
14886
// #include <nlohmann/detail/meta/type_traits.hpp>
14887
14888
// #include <nlohmann/detail/output/binary_writer.hpp>
14889
// __ _____ _____ _____
14890
// __| | __| | | | JSON for Modern C++
14891
// | | |__ | | | | | | version 3.11.3
14892
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14893
//
14894
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14895
// SPDX-License-Identifier: MIT
14896
14897
14898
14899
#include <algorithm> // reverse
14900
#include <array> // array
14901
#include <map> // map
14902
#include <cmath> // isnan, isinf
14903
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
14904
#include <cstring> // memcpy
14905
#include <limits> // numeric_limits
14906
#include <string> // string
14907
#include <utility> // move
14908
#include <vector> // vector
14909
14910
// #include <nlohmann/detail/input/binary_reader.hpp>
14911
14912
// #include <nlohmann/detail/macro_scope.hpp>
14913
14914
// #include <nlohmann/detail/output/output_adapters.hpp>
14915
// __ _____ _____ _____
14916
// __| | __| | | | JSON for Modern C++
14917
// | | |__ | | | | | | version 3.11.3
14918
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14919
//
14920
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14921
// SPDX-License-Identifier: MIT
14922
14923
14924
14925
#include <algorithm> // copy
14926
#include <cstddef> // size_t
14927
#include <iterator> // back_inserter
14928
#include <memory> // shared_ptr, make_shared
14929
#include <string> // basic_string
14930
#include <vector> // vector
14931
14932
#ifndef JSON_NO_IO
14933
#include <ios> // streamsize
14934
#include <ostream> // basic_ostream
14935
#endif // JSON_NO_IO
14936
14937
// #include <nlohmann/detail/macro_scope.hpp>
14938
14939
14940
NLOHMANN_JSON_NAMESPACE_BEGIN
14941
namespace detail
14942
{
14943
14944
/// abstract output adapter interface
14945
template<typename CharType> struct output_adapter_protocol
14946
{
14947
virtual void write_character(CharType c) = 0;
14948
virtual void write_characters(const CharType* s, std::size_t length) = 0;
14949
virtual ~output_adapter_protocol() = default;
14950
14951
output_adapter_protocol() = default;
14952
output_adapter_protocol(const output_adapter_protocol&) = default;
14953
output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
14954
output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
14955
output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
14956
};
14957
14958
/// a type to simplify interfaces
14959
template<typename CharType>
14960
using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
14961
14962
/// output adapter for byte vectors
14963
template<typename CharType, typename AllocatorType = std::allocator<CharType>>
14964
class output_vector_adapter : public output_adapter_protocol<CharType>
14965
{
14966
public:
14967
explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
14968
: v(vec)
14969
{}
14970
14971
void write_character(CharType c) override
14972
{
14973
v.push_back(c);
14974
}
14975
14976
JSON_HEDLEY_NON_NULL(2)
14977
void write_characters(const CharType* s, std::size_t length) override
14978
{
14979
v.insert(v.end(), s, s + length);
14980
}
14981
14982
private:
14983
std::vector<CharType, AllocatorType>& v;
14984
};
14985
14986
#ifndef JSON_NO_IO
14987
/// output adapter for output streams
14988
template<typename CharType>
14989
class output_stream_adapter : public output_adapter_protocol<CharType>
14990
{
14991
public:
14992
explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
14993
: stream(s)
14994
{}
14995
14996
void write_character(CharType c) override
14997
{
14998
stream.put(c);
14999
}
15000
15001
JSON_HEDLEY_NON_NULL(2)
15002
void write_characters(const CharType* s, std::size_t length) override
15003
{
15004
stream.write(s, static_cast<std::streamsize>(length));
15005
}
15006
15007
private:
15008
std::basic_ostream<CharType>& stream;
15009
};
15010
#endif // JSON_NO_IO
15011
15012
/// output adapter for basic_string
15013
template<typename CharType, typename StringType = std::basic_string<CharType>>
15014
class output_string_adapter : public output_adapter_protocol<CharType>
15015
{
15016
public:
15017
explicit output_string_adapter(StringType& s) noexcept
15018
: str(s)
15019
{}
15020
15021
void write_character(CharType c) override
15022
{
15023
str.push_back(c);
15024
}
15025
15026
JSON_HEDLEY_NON_NULL(2)
15027
void write_characters(const CharType* s, std::size_t length) override
15028
{
15029
str.append(s, length);
15030
}
15031
15032
private:
15033
StringType& str;
15034
};
15035
15036
template<typename CharType, typename StringType = std::basic_string<CharType>>
15037
class output_adapter
15038
{
15039
public:
15040
template<typename AllocatorType = std::allocator<CharType>>
15041
output_adapter(std::vector<CharType, AllocatorType>& vec)
15042
: oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15043
15044
#ifndef JSON_NO_IO
15045
output_adapter(std::basic_ostream<CharType>& s)
15046
: oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15047
#endif // JSON_NO_IO
15048
15049
output_adapter(StringType& s)
15050
: oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15051
15052
operator output_adapter_t<CharType>()
15053
{
15054
return oa;
15055
}
15056
15057
private:
15058
output_adapter_t<CharType> oa = nullptr;
15059
};
15060
15061
} // namespace detail
15062
NLOHMANN_JSON_NAMESPACE_END
15063
15064
// #include <nlohmann/detail/string_concat.hpp>
15065
15066
15067
NLOHMANN_JSON_NAMESPACE_BEGIN
15068
namespace detail
15069
{
15070
15071
///////////////////
15072
// binary writer //
15073
///////////////////
15074
15075
/*!
15076
@brief serialization to CBOR and MessagePack values
15077
*/
15078
template<typename BasicJsonType, typename CharType>
15079
class binary_writer
15080
{
15081
using string_t = typename BasicJsonType::string_t;
15082
using binary_t = typename BasicJsonType::binary_t;
15083
using number_float_t = typename BasicJsonType::number_float_t;
15084
15085
public:
15086
/*!
15087
@brief create a binary writer
15088
15089
@param[in] adapter output adapter to write to
15090
*/
15091
explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15092
{
15093
JSON_ASSERT(oa);
15094
}
15095
15096
/*!
15097
@param[in] j JSON value to serialize
15098
@pre j.type() == value_t::object
15099
*/
15100
void write_bson(const BasicJsonType& j)
15101
{
15102
switch (j.type())
15103
{
15104
case value_t::object:
15105
{
15106
write_bson_object(*j.m_data.m_value.object);
15107
break;
15108
}
15109
15110
case value_t::null:
15111
case value_t::array:
15112
case value_t::string:
15113
case value_t::boolean:
15114
case value_t::number_integer:
15115
case value_t::number_unsigned:
15116
case value_t::number_float:
15117
case value_t::binary:
15118
case value_t::discarded:
15119
default:
15120
{
15121
JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15122
}
15123
}
15124
}
15125
15126
/*!
15127
@param[in] j JSON value to serialize
15128
*/
15129
void write_cbor(const BasicJsonType& j)
15130
{
15131
switch (j.type())
15132
{
15133
case value_t::null:
15134
{
15135
oa->write_character(to_char_type(0xF6));
15136
break;
15137
}
15138
15139
case value_t::boolean:
15140
{
15141
oa->write_character(j.m_data.m_value.boolean
15142
? to_char_type(0xF5)
15143
: to_char_type(0xF4));
15144
break;
15145
}
15146
15147
case value_t::number_integer:
15148
{
15149
if (j.m_data.m_value.number_integer >= 0)
15150
{
15151
// CBOR does not differentiate between positive signed
15152
// integers and unsigned integers. Therefore, we used the
15153
// code from the value_t::number_unsigned case here.
15154
if (j.m_data.m_value.number_integer <= 0x17)
15155
{
15156
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15157
}
15158
else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15159
{
15160
oa->write_character(to_char_type(0x18));
15161
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15162
}
15163
else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15164
{
15165
oa->write_character(to_char_type(0x19));
15166
write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15167
}
15168
else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15169
{
15170
oa->write_character(to_char_type(0x1A));
15171
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15172
}
15173
else
15174
{
15175
oa->write_character(to_char_type(0x1B));
15176
write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15177
}
15178
}
15179
else
15180
{
15181
// The conversions below encode the sign in the first
15182
// byte, and the value is converted to a positive number.
15183
const auto positive_number = -1 - j.m_data.m_value.number_integer;
15184
if (j.m_data.m_value.number_integer >= -24)
15185
{
15186
write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15187
}
15188
else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15189
{
15190
oa->write_character(to_char_type(0x38));
15191
write_number(static_cast<std::uint8_t>(positive_number));
15192
}
15193
else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15194
{
15195
oa->write_character(to_char_type(0x39));
15196
write_number(static_cast<std::uint16_t>(positive_number));
15197
}
15198
else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15199
{
15200
oa->write_character(to_char_type(0x3A));
15201
write_number(static_cast<std::uint32_t>(positive_number));
15202
}
15203
else
15204
{
15205
oa->write_character(to_char_type(0x3B));
15206
write_number(static_cast<std::uint64_t>(positive_number));
15207
}
15208
}
15209
break;
15210
}
15211
15212
case value_t::number_unsigned:
15213
{
15214
if (j.m_data.m_value.number_unsigned <= 0x17)
15215
{
15216
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15217
}
15218
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15219
{
15220
oa->write_character(to_char_type(0x18));
15221
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15222
}
15223
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15224
{
15225
oa->write_character(to_char_type(0x19));
15226
write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
15227
}
15228
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15229
{
15230
oa->write_character(to_char_type(0x1A));
15231
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
15232
}
15233
else
15234
{
15235
oa->write_character(to_char_type(0x1B));
15236
write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
15237
}
15238
break;
15239
}
15240
15241
case value_t::number_float:
15242
{
15243
if (std::isnan(j.m_data.m_value.number_float))
15244
{
15245
// NaN is 0xf97e00 in CBOR
15246
oa->write_character(to_char_type(0xF9));
15247
oa->write_character(to_char_type(0x7E));
15248
oa->write_character(to_char_type(0x00));
15249
}
15250
else if (std::isinf(j.m_data.m_value.number_float))
15251
{
15252
// Infinity is 0xf97c00, -Infinity is 0xf9fc00
15253
oa->write_character(to_char_type(0xf9));
15254
oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
15255
oa->write_character(to_char_type(0x00));
15256
}
15257
else
15258
{
15259
write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
15260
}
15261
break;
15262
}
15263
15264
case value_t::string:
15265
{
15266
// step 1: write control byte and the string length
15267
const auto N = j.m_data.m_value.string->size();
15268
if (N <= 0x17)
15269
{
15270
write_number(static_cast<std::uint8_t>(0x60 + N));
15271
}
15272
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15273
{
15274
oa->write_character(to_char_type(0x78));
15275
write_number(static_cast<std::uint8_t>(N));
15276
}
15277
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15278
{
15279
oa->write_character(to_char_type(0x79));
15280
write_number(static_cast<std::uint16_t>(N));
15281
}
15282
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15283
{
15284
oa->write_character(to_char_type(0x7A));
15285
write_number(static_cast<std::uint32_t>(N));
15286
}
15287
// LCOV_EXCL_START
15288
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15289
{
15290
oa->write_character(to_char_type(0x7B));
15291
write_number(static_cast<std::uint64_t>(N));
15292
}
15293
// LCOV_EXCL_STOP
15294
15295
// step 2: write the string
15296
oa->write_characters(
15297
reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15298
j.m_data.m_value.string->size());
15299
break;
15300
}
15301
15302
case value_t::array:
15303
{
15304
// step 1: write control byte and the array size
15305
const auto N = j.m_data.m_value.array->size();
15306
if (N <= 0x17)
15307
{
15308
write_number(static_cast<std::uint8_t>(0x80 + N));
15309
}
15310
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15311
{
15312
oa->write_character(to_char_type(0x98));
15313
write_number(static_cast<std::uint8_t>(N));
15314
}
15315
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15316
{
15317
oa->write_character(to_char_type(0x99));
15318
write_number(static_cast<std::uint16_t>(N));
15319
}
15320
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15321
{
15322
oa->write_character(to_char_type(0x9A));
15323
write_number(static_cast<std::uint32_t>(N));
15324
}
15325
// LCOV_EXCL_START
15326
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15327
{
15328
oa->write_character(to_char_type(0x9B));
15329
write_number(static_cast<std::uint64_t>(N));
15330
}
15331
// LCOV_EXCL_STOP
15332
15333
// step 2: write each element
15334
for (const auto& el : *j.m_data.m_value.array)
15335
{
15336
write_cbor(el);
15337
}
15338
break;
15339
}
15340
15341
case value_t::binary:
15342
{
15343
if (j.m_data.m_value.binary->has_subtype())
15344
{
15345
if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
15346
{
15347
write_number(static_cast<std::uint8_t>(0xd8));
15348
write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
15349
}
15350
else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
15351
{
15352
write_number(static_cast<std::uint8_t>(0xd9));
15353
write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
15354
}
15355
else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
15356
{
15357
write_number(static_cast<std::uint8_t>(0xda));
15358
write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
15359
}
15360
else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
15361
{
15362
write_number(static_cast<std::uint8_t>(0xdb));
15363
write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
15364
}
15365
}
15366
15367
// step 1: write control byte and the binary array size
15368
const auto N = j.m_data.m_value.binary->size();
15369
if (N <= 0x17)
15370
{
15371
write_number(static_cast<std::uint8_t>(0x40 + N));
15372
}
15373
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15374
{
15375
oa->write_character(to_char_type(0x58));
15376
write_number(static_cast<std::uint8_t>(N));
15377
}
15378
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15379
{
15380
oa->write_character(to_char_type(0x59));
15381
write_number(static_cast<std::uint16_t>(N));
15382
}
15383
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15384
{
15385
oa->write_character(to_char_type(0x5A));
15386
write_number(static_cast<std::uint32_t>(N));
15387
}
15388
// LCOV_EXCL_START
15389
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15390
{
15391
oa->write_character(to_char_type(0x5B));
15392
write_number(static_cast<std::uint64_t>(N));
15393
}
15394
// LCOV_EXCL_STOP
15395
15396
// step 2: write each element
15397
oa->write_characters(
15398
reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15399
N);
15400
15401
break;
15402
}
15403
15404
case value_t::object:
15405
{
15406
// step 1: write control byte and the object size
15407
const auto N = j.m_data.m_value.object->size();
15408
if (N <= 0x17)
15409
{
15410
write_number(static_cast<std::uint8_t>(0xA0 + N));
15411
}
15412
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15413
{
15414
oa->write_character(to_char_type(0xB8));
15415
write_number(static_cast<std::uint8_t>(N));
15416
}
15417
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15418
{
15419
oa->write_character(to_char_type(0xB9));
15420
write_number(static_cast<std::uint16_t>(N));
15421
}
15422
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15423
{
15424
oa->write_character(to_char_type(0xBA));
15425
write_number(static_cast<std::uint32_t>(N));
15426
}
15427
// LCOV_EXCL_START
15428
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15429
{
15430
oa->write_character(to_char_type(0xBB));
15431
write_number(static_cast<std::uint64_t>(N));
15432
}
15433
// LCOV_EXCL_STOP
15434
15435
// step 2: write each element
15436
for (const auto& el : *j.m_data.m_value.object)
15437
{
15438
write_cbor(el.first);
15439
write_cbor(el.second);
15440
}
15441
break;
15442
}
15443
15444
case value_t::discarded:
15445
default:
15446
break;
15447
}
15448
}
15449
15450
/*!
15451
@param[in] j JSON value to serialize
15452
*/
15453
void write_msgpack(const BasicJsonType& j)
15454
{
15455
switch (j.type())
15456
{
15457
case value_t::null: // nil
15458
{
15459
oa->write_character(to_char_type(0xC0));
15460
break;
15461
}
15462
15463
case value_t::boolean: // true and false
15464
{
15465
oa->write_character(j.m_data.m_value.boolean
15466
? to_char_type(0xC3)
15467
: to_char_type(0xC2));
15468
break;
15469
}
15470
15471
case value_t::number_integer:
15472
{
15473
if (j.m_data.m_value.number_integer >= 0)
15474
{
15475
// MessagePack does not differentiate between positive
15476
// signed integers and unsigned integers. Therefore, we used
15477
// the code from the value_t::number_unsigned case here.
15478
if (j.m_data.m_value.number_unsigned < 128)
15479
{
15480
// positive fixnum
15481
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15482
}
15483
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15484
{
15485
// uint 8
15486
oa->write_character(to_char_type(0xCC));
15487
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15488
}
15489
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15490
{
15491
// uint 16
15492
oa->write_character(to_char_type(0xCD));
15493
write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15494
}
15495
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15496
{
15497
// uint 32
15498
oa->write_character(to_char_type(0xCE));
15499
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15500
}
15501
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15502
{
15503
// uint 64
15504
oa->write_character(to_char_type(0xCF));
15505
write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15506
}
15507
}
15508
else
15509
{
15510
if (j.m_data.m_value.number_integer >= -32)
15511
{
15512
// negative fixnum
15513
write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15514
}
15515
else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
15516
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
15517
{
15518
// int 8
15519
oa->write_character(to_char_type(0xD0));
15520
write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15521
}
15522
else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
15523
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
15524
{
15525
// int 16
15526
oa->write_character(to_char_type(0xD1));
15527
write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
15528
}
15529
else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
15530
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
15531
{
15532
// int 32
15533
oa->write_character(to_char_type(0xD2));
15534
write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
15535
}
15536
else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
15537
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
15538
{
15539
// int 64
15540
oa->write_character(to_char_type(0xD3));
15541
write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
15542
}
15543
}
15544
break;
15545
}
15546
15547
case value_t::number_unsigned:
15548
{
15549
if (j.m_data.m_value.number_unsigned < 128)
15550
{
15551
// positive fixnum
15552
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15553
}
15554
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15555
{
15556
// uint 8
15557
oa->write_character(to_char_type(0xCC));
15558
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15559
}
15560
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15561
{
15562
// uint 16
15563
oa->write_character(to_char_type(0xCD));
15564
write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15565
}
15566
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15567
{
15568
// uint 32
15569
oa->write_character(to_char_type(0xCE));
15570
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15571
}
15572
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15573
{
15574
// uint 64
15575
oa->write_character(to_char_type(0xCF));
15576
write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15577
}
15578
break;
15579
}
15580
15581
case value_t::number_float:
15582
{
15583
write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
15584
break;
15585
}
15586
15587
case value_t::string:
15588
{
15589
// step 1: write control byte and the string length
15590
const auto N = j.m_data.m_value.string->size();
15591
if (N <= 31)
15592
{
15593
// fixstr
15594
write_number(static_cast<std::uint8_t>(0xA0 | N));
15595
}
15596
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15597
{
15598
// str 8
15599
oa->write_character(to_char_type(0xD9));
15600
write_number(static_cast<std::uint8_t>(N));
15601
}
15602
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15603
{
15604
// str 16
15605
oa->write_character(to_char_type(0xDA));
15606
write_number(static_cast<std::uint16_t>(N));
15607
}
15608
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15609
{
15610
// str 32
15611
oa->write_character(to_char_type(0xDB));
15612
write_number(static_cast<std::uint32_t>(N));
15613
}
15614
15615
// step 2: write the string
15616
oa->write_characters(
15617
reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15618
j.m_data.m_value.string->size());
15619
break;
15620
}
15621
15622
case value_t::array:
15623
{
15624
// step 1: write control byte and the array size
15625
const auto N = j.m_data.m_value.array->size();
15626
if (N <= 15)
15627
{
15628
// fixarray
15629
write_number(static_cast<std::uint8_t>(0x90 | N));
15630
}
15631
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15632
{
15633
// array 16
15634
oa->write_character(to_char_type(0xDC));
15635
write_number(static_cast<std::uint16_t>(N));
15636
}
15637
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15638
{
15639
// array 32
15640
oa->write_character(to_char_type(0xDD));
15641
write_number(static_cast<std::uint32_t>(N));
15642
}
15643
15644
// step 2: write each element
15645
for (const auto& el : *j.m_data.m_value.array)
15646
{
15647
write_msgpack(el);
15648
}
15649
break;
15650
}
15651
15652
case value_t::binary:
15653
{
15654
// step 0: determine if the binary type has a set subtype to
15655
// determine whether or not to use the ext or fixext types
15656
const bool use_ext = j.m_data.m_value.binary->has_subtype();
15657
15658
// step 1: write control byte and the byte string length
15659
const auto N = j.m_data.m_value.binary->size();
15660
if (N <= (std::numeric_limits<std::uint8_t>::max)())
15661
{
15662
std::uint8_t output_type{};
15663
bool fixed = true;
15664
if (use_ext)
15665
{
15666
switch (N)
15667
{
15668
case 1:
15669
output_type = 0xD4; // fixext 1
15670
break;
15671
case 2:
15672
output_type = 0xD5; // fixext 2
15673
break;
15674
case 4:
15675
output_type = 0xD6; // fixext 4
15676
break;
15677
case 8:
15678
output_type = 0xD7; // fixext 8
15679
break;
15680
case 16:
15681
output_type = 0xD8; // fixext 16
15682
break;
15683
default:
15684
output_type = 0xC7; // ext 8
15685
fixed = false;
15686
break;
15687
}
15688
15689
}
15690
else
15691
{
15692
output_type = 0xC4; // bin 8
15693
fixed = false;
15694
}
15695
15696
oa->write_character(to_char_type(output_type));
15697
if (!fixed)
15698
{
15699
write_number(static_cast<std::uint8_t>(N));
15700
}
15701
}
15702
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15703
{
15704
const std::uint8_t output_type = use_ext
15705
? 0xC8 // ext 16
15706
: 0xC5; // bin 16
15707
15708
oa->write_character(to_char_type(output_type));
15709
write_number(static_cast<std::uint16_t>(N));
15710
}
15711
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15712
{
15713
const std::uint8_t output_type = use_ext
15714
? 0xC9 // ext 32
15715
: 0xC6; // bin 32
15716
15717
oa->write_character(to_char_type(output_type));
15718
write_number(static_cast<std::uint32_t>(N));
15719
}
15720
15721
// step 1.5: if this is an ext type, write the subtype
15722
if (use_ext)
15723
{
15724
write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
15725
}
15726
15727
// step 2: write the byte string
15728
oa->write_characters(
15729
reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15730
N);
15731
15732
break;
15733
}
15734
15735
case value_t::object:
15736
{
15737
// step 1: write control byte and the object size
15738
const auto N = j.m_data.m_value.object->size();
15739
if (N <= 15)
15740
{
15741
// fixmap
15742
write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
15743
}
15744
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15745
{
15746
// map 16
15747
oa->write_character(to_char_type(0xDE));
15748
write_number(static_cast<std::uint16_t>(N));
15749
}
15750
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15751
{
15752
// map 32
15753
oa->write_character(to_char_type(0xDF));
15754
write_number(static_cast<std::uint32_t>(N));
15755
}
15756
15757
// step 2: write each element
15758
for (const auto& el : *j.m_data.m_value.object)
15759
{
15760
write_msgpack(el.first);
15761
write_msgpack(el.second);
15762
}
15763
break;
15764
}
15765
15766
case value_t::discarded:
15767
default:
15768
break;
15769
}
15770
}
15771
15772
/*!
15773
@param[in] j JSON value to serialize
15774
@param[in] use_count whether to use '#' prefixes (optimized format)
15775
@param[in] use_type whether to use '$' prefixes (optimized format)
15776
@param[in] add_prefix whether prefixes need to be used for this value
15777
@param[in] use_bjdata whether write in BJData format, default is false
15778
*/
15779
void write_ubjson(const BasicJsonType& j, const bool use_count,
15780
const bool use_type, const bool add_prefix = true,
15781
const bool use_bjdata = false)
15782
{
15783
switch (j.type())
15784
{
15785
case value_t::null:
15786
{
15787
if (add_prefix)
15788
{
15789
oa->write_character(to_char_type('Z'));
15790
}
15791
break;
15792
}
15793
15794
case value_t::boolean:
15795
{
15796
if (add_prefix)
15797
{
15798
oa->write_character(j.m_data.m_value.boolean
15799
? to_char_type('T')
15800
: to_char_type('F'));
15801
}
15802
break;
15803
}
15804
15805
case value_t::number_integer:
15806
{
15807
write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
15808
break;
15809
}
15810
15811
case value_t::number_unsigned:
15812
{
15813
write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
15814
break;
15815
}
15816
15817
case value_t::number_float:
15818
{
15819
write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
15820
break;
15821
}
15822
15823
case value_t::string:
15824
{
15825
if (add_prefix)
15826
{
15827
oa->write_character(to_char_type('S'));
15828
}
15829
write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
15830
oa->write_characters(
15831
reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15832
j.m_data.m_value.string->size());
15833
break;
15834
}
15835
15836
case value_t::array:
15837
{
15838
if (add_prefix)
15839
{
15840
oa->write_character(to_char_type('['));
15841
}
15842
15843
bool prefix_required = true;
15844
if (use_type && !j.m_data.m_value.array->empty())
15845
{
15846
JSON_ASSERT(use_count);
15847
const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15848
const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
15849
[this, first_prefix, use_bjdata](const BasicJsonType & v)
15850
{
15851
return ubjson_prefix(v, use_bjdata) == first_prefix;
15852
});
15853
15854
std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15855
15856
if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15857
{
15858
prefix_required = false;
15859
oa->write_character(to_char_type('$'));
15860
oa->write_character(first_prefix);
15861
}
15862
}
15863
15864
if (use_count)
15865
{
15866
oa->write_character(to_char_type('#'));
15867
write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
15868
}
15869
15870
for (const auto& el : *j.m_data.m_value.array)
15871
{
15872
write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
15873
}
15874
15875
if (!use_count)
15876
{
15877
oa->write_character(to_char_type(']'));
15878
}
15879
15880
break;
15881
}
15882
15883
case value_t::binary:
15884
{
15885
if (add_prefix)
15886
{
15887
oa->write_character(to_char_type('['));
15888
}
15889
15890
if (use_type && !j.m_data.m_value.binary->empty())
15891
{
15892
JSON_ASSERT(use_count);
15893
oa->write_character(to_char_type('$'));
15894
oa->write_character('U');
15895
}
15896
15897
if (use_count)
15898
{
15899
oa->write_character(to_char_type('#'));
15900
write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
15901
}
15902
15903
if (use_type)
15904
{
15905
oa->write_characters(
15906
reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15907
j.m_data.m_value.binary->size());
15908
}
15909
else
15910
{
15911
for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
15912
{
15913
oa->write_character(to_char_type('U'));
15914
oa->write_character(j.m_data.m_value.binary->data()[i]);
15915
}
15916
}
15917
15918
if (!use_count)
15919
{
15920
oa->write_character(to_char_type(']'));
15921
}
15922
15923
break;
15924
}
15925
15926
case value_t::object:
15927
{
15928
if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end())
15929
{
15930
if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
15931
{
15932
break;
15933
}
15934
}
15935
15936
if (add_prefix)
15937
{
15938
oa->write_character(to_char_type('{'));
15939
}
15940
15941
bool prefix_required = true;
15942
if (use_type && !j.m_data.m_value.object->empty())
15943
{
15944
JSON_ASSERT(use_count);
15945
const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15946
const bool same_prefix = std::all_of(j.begin(), j.end(),
15947
[this, first_prefix, use_bjdata](const BasicJsonType & v)
15948
{
15949
return ubjson_prefix(v, use_bjdata) == first_prefix;
15950
});
15951
15952
std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15953
15954
if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15955
{
15956
prefix_required = false;
15957
oa->write_character(to_char_type('$'));
15958
oa->write_character(first_prefix);
15959
}
15960
}
15961
15962
if (use_count)
15963
{
15964
oa->write_character(to_char_type('#'));
15965
write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
15966
}
15967
15968
for (const auto& el : *j.m_data.m_value.object)
15969
{
15970
write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
15971
oa->write_characters(
15972
reinterpret_cast<const CharType*>(el.first.c_str()),
15973
el.first.size());
15974
write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
15975
}
15976
15977
if (!use_count)
15978
{
15979
oa->write_character(to_char_type('}'));
15980
}
15981
15982
break;
15983
}
15984
15985
case value_t::discarded:
15986
default:
15987
break;
15988
}
15989
}
15990
15991
private:
15992
//////////
15993
// BSON //
15994
//////////
15995
15996
/*!
15997
@return The size of a BSON document entry header, including the id marker
15998
and the entry name size (and its null-terminator).
15999
*/
16000
static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16001
{
16002
const auto it = name.find(static_cast<typename string_t::value_type>(0));
16003
if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16004
{
16005
JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16006
static_cast<void>(j);
16007
}
16008
16009
return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16010
}
16011
16012
/*!
16013
@brief Writes the given @a element_type and @a name to the output adapter
16014
*/
16015
void write_bson_entry_header(const string_t& name,
16016
const std::uint8_t element_type)
16017
{
16018
oa->write_character(to_char_type(element_type)); // boolean
16019
oa->write_characters(
16020
reinterpret_cast<const CharType*>(name.c_str()),
16021
name.size() + 1u);
16022
}
16023
16024
/*!
16025
@brief Writes a BSON element with key @a name and boolean value @a value
16026
*/
16027
void write_bson_boolean(const string_t& name,
16028
const bool value)
16029
{
16030
write_bson_entry_header(name, 0x08);
16031
oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16032
}
16033
16034
/*!
16035
@brief Writes a BSON element with key @a name and double value @a value
16036
*/
16037
void write_bson_double(const string_t& name,
16038
const double value)
16039
{
16040
write_bson_entry_header(name, 0x01);
16041
write_number<double>(value, true);
16042
}
16043
16044
/*!
16045
@return The size of the BSON-encoded string in @a value
16046
*/
16047
static std::size_t calc_bson_string_size(const string_t& value)
16048
{
16049
return sizeof(std::int32_t) + value.size() + 1ul;
16050
}
16051
16052
/*!
16053
@brief Writes a BSON element with key @a name and string value @a value
16054
*/
16055
void write_bson_string(const string_t& name,
16056
const string_t& value)
16057
{
16058
write_bson_entry_header(name, 0x02);
16059
16060
write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16061
oa->write_characters(
16062
reinterpret_cast<const CharType*>(value.c_str()),
16063
value.size() + 1);
16064
}
16065
16066
/*!
16067
@brief Writes a BSON element with key @a name and null value
16068
*/
16069
void write_bson_null(const string_t& name)
16070
{
16071
write_bson_entry_header(name, 0x0A);
16072
}
16073
16074
/*!
16075
@return The size of the BSON-encoded integer @a value
16076
*/
16077
static std::size_t calc_bson_integer_size(const std::int64_t value)
16078
{
16079
return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16080
? sizeof(std::int32_t)
16081
: sizeof(std::int64_t);
16082
}
16083
16084
/*!
16085
@brief Writes a BSON element with key @a name and integer @a value
16086
*/
16087
void write_bson_integer(const string_t& name,
16088
const std::int64_t value)
16089
{
16090
if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16091
{
16092
write_bson_entry_header(name, 0x10); // int32
16093
write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16094
}
16095
else
16096
{
16097
write_bson_entry_header(name, 0x12); // int64
16098
write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16099
}
16100
}
16101
16102
/*!
16103
@return The size of the BSON-encoded unsigned integer in @a j
16104
*/
16105
static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16106
{
16107
return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16108
? sizeof(std::int32_t)
16109
: sizeof(std::int64_t);
16110
}
16111
16112
/*!
16113
@brief Writes a BSON element with key @a name and unsigned @a value
16114
*/
16115
void write_bson_unsigned(const string_t& name,
16116
const BasicJsonType& j)
16117
{
16118
if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16119
{
16120
write_bson_entry_header(name, 0x10 /* int32 */);
16121
write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16122
}
16123
else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16124
{
16125
write_bson_entry_header(name, 0x12 /* int64 */);
16126
write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16127
}
16128
else
16129
{
16130
JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
16131
}
16132
}
16133
16134
/*!
16135
@brief Writes a BSON element with key @a name and object @a value
16136
*/
16137
void write_bson_object_entry(const string_t& name,
16138
const typename BasicJsonType::object_t& value)
16139
{
16140
write_bson_entry_header(name, 0x03); // object
16141
write_bson_object(value);
16142
}
16143
16144
/*!
16145
@return The size of the BSON-encoded array @a value
16146
*/
16147
static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16148
{
16149
std::size_t array_index = 0ul;
16150
16151
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)
16152
{
16153
return result + calc_bson_element_size(std::to_string(array_index++), el);
16154
});
16155
16156
return sizeof(std::int32_t) + embedded_document_size + 1ul;
16157
}
16158
16159
/*!
16160
@return The size of the BSON-encoded binary array @a value
16161
*/
16162
static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16163
{
16164
return sizeof(std::int32_t) + value.size() + 1ul;
16165
}
16166
16167
/*!
16168
@brief Writes a BSON element with key @a name and array @a value
16169
*/
16170
void write_bson_array(const string_t& name,
16171
const typename BasicJsonType::array_t& value)
16172
{
16173
write_bson_entry_header(name, 0x04); // array
16174
write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16175
16176
std::size_t array_index = 0ul;
16177
16178
for (const auto& el : value)
16179
{
16180
write_bson_element(std::to_string(array_index++), el);
16181
}
16182
16183
oa->write_character(to_char_type(0x00));
16184
}
16185
16186
/*!
16187
@brief Writes a BSON element with key @a name and binary value @a value
16188
*/
16189
void write_bson_binary(const string_t& name,
16190
const binary_t& value)
16191
{
16192
write_bson_entry_header(name, 0x05);
16193
16194
write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16195
write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16196
16197
oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16198
}
16199
16200
/*!
16201
@brief Calculates the size necessary to serialize the JSON value @a j with its @a name
16202
@return The calculated size for the BSON document entry for @a j with the given @a name.
16203
*/
16204
static std::size_t calc_bson_element_size(const string_t& name,
16205
const BasicJsonType& j)
16206
{
16207
const auto header_size = calc_bson_entry_header_size(name, j);
16208
switch (j.type())
16209
{
16210
case value_t::object:
16211
return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16212
16213
case value_t::array:
16214
return header_size + calc_bson_array_size(*j.m_data.m_value.array);
16215
16216
case value_t::binary:
16217
return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
16218
16219
case value_t::boolean:
16220
return header_size + 1ul;
16221
16222
case value_t::number_float:
16223
return header_size + 8ul;
16224
16225
case value_t::number_integer:
16226
return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
16227
16228
case value_t::number_unsigned:
16229
return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
16230
16231
case value_t::string:
16232
return header_size + calc_bson_string_size(*j.m_data.m_value.string);
16233
16234
case value_t::null:
16235
return header_size + 0ul;
16236
16237
// LCOV_EXCL_START
16238
case value_t::discarded:
16239
default:
16240
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16241
return 0ul;
16242
// LCOV_EXCL_STOP
16243
}
16244
}
16245
16246
/*!
16247
@brief Serializes the JSON value @a j to BSON and associates it with the
16248
key @a name.
16249
@param name The name to associate with the JSON entity @a j within the
16250
current BSON document
16251
*/
16252
void write_bson_element(const string_t& name,
16253
const BasicJsonType& j)
16254
{
16255
switch (j.type())
16256
{
16257
case value_t::object:
16258
return write_bson_object_entry(name, *j.m_data.m_value.object);
16259
16260
case value_t::array:
16261
return write_bson_array(name, *j.m_data.m_value.array);
16262
16263
case value_t::binary:
16264
return write_bson_binary(name, *j.m_data.m_value.binary);
16265
16266
case value_t::boolean:
16267
return write_bson_boolean(name, j.m_data.m_value.boolean);
16268
16269
case value_t::number_float:
16270
return write_bson_double(name, j.m_data.m_value.number_float);
16271
16272
case value_t::number_integer:
16273
return write_bson_integer(name, j.m_data.m_value.number_integer);
16274
16275
case value_t::number_unsigned:
16276
return write_bson_unsigned(name, j);
16277
16278
case value_t::string:
16279
return write_bson_string(name, *j.m_data.m_value.string);
16280
16281
case value_t::null:
16282
return write_bson_null(name);
16283
16284
// LCOV_EXCL_START
16285
case value_t::discarded:
16286
default:
16287
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16288
return;
16289
// LCOV_EXCL_STOP
16290
}
16291
}
16292
16293
/*!
16294
@brief Calculates the size of the BSON serialization of the given
16295
JSON-object @a j.
16296
@param[in] value JSON value to serialize
16297
@pre value.type() == value_t::object
16298
*/
16299
static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
16300
{
16301
const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
16302
[](size_t result, const typename BasicJsonType::object_t::value_type & el)
16303
{
16304
return result += calc_bson_element_size(el.first, el.second);
16305
});
16306
16307
return sizeof(std::int32_t) + document_size + 1ul;
16308
}
16309
16310
/*!
16311
@param[in] value JSON value to serialize
16312
@pre value.type() == value_t::object
16313
*/
16314
void write_bson_object(const typename BasicJsonType::object_t& value)
16315
{
16316
write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
16317
16318
for (const auto& el : value)
16319
{
16320
write_bson_element(el.first, el.second);
16321
}
16322
16323
oa->write_character(to_char_type(0x00));
16324
}
16325
16326
//////////
16327
// CBOR //
16328
//////////
16329
16330
static constexpr CharType get_cbor_float_prefix(float /*unused*/)
16331
{
16332
return to_char_type(0xFA); // Single-Precision Float
16333
}
16334
16335
static constexpr CharType get_cbor_float_prefix(double /*unused*/)
16336
{
16337
return to_char_type(0xFB); // Double-Precision Float
16338
}
16339
16340
/////////////
16341
// MsgPack //
16342
/////////////
16343
16344
static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
16345
{
16346
return to_char_type(0xCA); // float 32
16347
}
16348
16349
static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
16350
{
16351
return to_char_type(0xCB); // float 64
16352
}
16353
16354
////////////
16355
// UBJSON //
16356
////////////
16357
16358
// UBJSON: write number (floating point)
16359
template<typename NumberType, typename std::enable_if<
16360
std::is_floating_point<NumberType>::value, int>::type = 0>
16361
void write_number_with_ubjson_prefix(const NumberType n,
16362
const bool add_prefix,
16363
const bool use_bjdata)
16364
{
16365
if (add_prefix)
16366
{
16367
oa->write_character(get_ubjson_float_prefix(n));
16368
}
16369
write_number(n, use_bjdata);
16370
}
16371
16372
// UBJSON: write number (unsigned integer)
16373
template<typename NumberType, typename std::enable_if<
16374
std::is_unsigned<NumberType>::value, int>::type = 0>
16375
void write_number_with_ubjson_prefix(const NumberType n,
16376
const bool add_prefix,
16377
const bool use_bjdata)
16378
{
16379
if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16380
{
16381
if (add_prefix)
16382
{
16383
oa->write_character(to_char_type('i')); // int8
16384
}
16385
write_number(static_cast<std::uint8_t>(n), use_bjdata);
16386
}
16387
else if (n <= (std::numeric_limits<std::uint8_t>::max)())
16388
{
16389
if (add_prefix)
16390
{
16391
oa->write_character(to_char_type('U')); // uint8
16392
}
16393
write_number(static_cast<std::uint8_t>(n), use_bjdata);
16394
}
16395
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16396
{
16397
if (add_prefix)
16398
{
16399
oa->write_character(to_char_type('I')); // int16
16400
}
16401
write_number(static_cast<std::int16_t>(n), use_bjdata);
16402
}
16403
else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
16404
{
16405
if (add_prefix)
16406
{
16407
oa->write_character(to_char_type('u')); // uint16 - bjdata only
16408
}
16409
write_number(static_cast<std::uint16_t>(n), use_bjdata);
16410
}
16411
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16412
{
16413
if (add_prefix)
16414
{
16415
oa->write_character(to_char_type('l')); // int32
16416
}
16417
write_number(static_cast<std::int32_t>(n), use_bjdata);
16418
}
16419
else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
16420
{
16421
if (add_prefix)
16422
{
16423
oa->write_character(to_char_type('m')); // uint32 - bjdata only
16424
}
16425
write_number(static_cast<std::uint32_t>(n), use_bjdata);
16426
}
16427
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16428
{
16429
if (add_prefix)
16430
{
16431
oa->write_character(to_char_type('L')); // int64
16432
}
16433
write_number(static_cast<std::int64_t>(n), use_bjdata);
16434
}
16435
else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
16436
{
16437
if (add_prefix)
16438
{
16439
oa->write_character(to_char_type('M')); // uint64 - bjdata only
16440
}
16441
write_number(static_cast<std::uint64_t>(n), use_bjdata);
16442
}
16443
else
16444
{
16445
if (add_prefix)
16446
{
16447
oa->write_character(to_char_type('H')); // high-precision number
16448
}
16449
16450
const auto number = BasicJsonType(n).dump();
16451
write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16452
for (std::size_t i = 0; i < number.size(); ++i)
16453
{
16454
oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16455
}
16456
}
16457
}
16458
16459
// UBJSON: write number (signed integer)
16460
template < typename NumberType, typename std::enable_if <
16461
std::is_signed<NumberType>::value&&
16462
!std::is_floating_point<NumberType>::value, int >::type = 0 >
16463
void write_number_with_ubjson_prefix(const NumberType n,
16464
const bool add_prefix,
16465
const bool use_bjdata)
16466
{
16467
if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
16468
{
16469
if (add_prefix)
16470
{
16471
oa->write_character(to_char_type('i')); // int8
16472
}
16473
write_number(static_cast<std::int8_t>(n), use_bjdata);
16474
}
16475
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)()))
16476
{
16477
if (add_prefix)
16478
{
16479
oa->write_character(to_char_type('U')); // uint8
16480
}
16481
write_number(static_cast<std::uint8_t>(n), use_bjdata);
16482
}
16483
else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
16484
{
16485
if (add_prefix)
16486
{
16487
oa->write_character(to_char_type('I')); // int16
16488
}
16489
write_number(static_cast<std::int16_t>(n), use_bjdata);
16490
}
16491
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)())))
16492
{
16493
if (add_prefix)
16494
{
16495
oa->write_character(to_char_type('u')); // uint16 - bjdata only
16496
}
16497
write_number(static_cast<uint16_t>(n), use_bjdata);
16498
}
16499
else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
16500
{
16501
if (add_prefix)
16502
{
16503
oa->write_character(to_char_type('l')); // int32
16504
}
16505
write_number(static_cast<std::int32_t>(n), use_bjdata);
16506
}
16507
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)())))
16508
{
16509
if (add_prefix)
16510
{
16511
oa->write_character(to_char_type('m')); // uint32 - bjdata only
16512
}
16513
write_number(static_cast<uint32_t>(n), use_bjdata);
16514
}
16515
else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
16516
{
16517
if (add_prefix)
16518
{
16519
oa->write_character(to_char_type('L')); // int64
16520
}
16521
write_number(static_cast<std::int64_t>(n), use_bjdata);
16522
}
16523
// LCOV_EXCL_START
16524
else
16525
{
16526
if (add_prefix)
16527
{
16528
oa->write_character(to_char_type('H')); // high-precision number
16529
}
16530
16531
const auto number = BasicJsonType(n).dump();
16532
write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16533
for (std::size_t i = 0; i < number.size(); ++i)
16534
{
16535
oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16536
}
16537
}
16538
// LCOV_EXCL_STOP
16539
}
16540
16541
/*!
16542
@brief determine the type prefix of container values
16543
*/
16544
CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
16545
{
16546
switch (j.type())
16547
{
16548
case value_t::null:
16549
return 'Z';
16550
16551
case value_t::boolean:
16552
return j.m_data.m_value.boolean ? 'T' : 'F';
16553
16554
case value_t::number_integer:
16555
{
16556
if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16557
{
16558
return 'i';
16559
}
16560
if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
16561
{
16562
return 'U';
16563
}
16564
if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16565
{
16566
return 'I';
16567
}
16568
if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
16569
{
16570
return 'u';
16571
}
16572
if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16573
{
16574
return 'l';
16575
}
16576
if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
16577
{
16578
return 'm';
16579
}
16580
if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16581
{
16582
return 'L';
16583
}
16584
// anything else is treated as high-precision number
16585
return 'H'; // LCOV_EXCL_LINE
16586
}
16587
16588
case value_t::number_unsigned:
16589
{
16590
if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16591
{
16592
return 'i';
16593
}
16594
if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
16595
{
16596
return 'U';
16597
}
16598
if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16599
{
16600
return 'I';
16601
}
16602
if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
16603
{
16604
return 'u';
16605
}
16606
if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16607
{
16608
return 'l';
16609
}
16610
if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
16611
{
16612
return 'm';
16613
}
16614
if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16615
{
16616
return 'L';
16617
}
16618
if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16619
{
16620
return 'M';
16621
}
16622
// anything else is treated as high-precision number
16623
return 'H'; // LCOV_EXCL_LINE
16624
}
16625
16626
case value_t::number_float:
16627
return get_ubjson_float_prefix(j.m_data.m_value.number_float);
16628
16629
case value_t::string:
16630
return 'S';
16631
16632
case value_t::array: // fallthrough
16633
case value_t::binary:
16634
return '[';
16635
16636
case value_t::object:
16637
return '{';
16638
16639
case value_t::discarded:
16640
default: // discarded values
16641
return 'N';
16642
}
16643
}
16644
16645
static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
16646
{
16647
return 'd'; // float 32
16648
}
16649
16650
static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
16651
{
16652
return 'D'; // float 64
16653
}
16654
16655
/*!
16656
@return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid
16657
*/
16658
bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
16659
{
16660
std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
16661
{"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
16662
};
16663
16664
string_t key = "_ArrayType_";
16665
auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
16666
if (it == bjdtype.end())
16667
{
16668
return true;
16669
}
16670
CharType dtype = it->second;
16671
16672
key = "_ArraySize_";
16673
std::size_t len = (value.at(key).empty() ? 0 : 1);
16674
for (const auto& el : value.at(key))
16675
{
16676
len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
16677
}
16678
16679
key = "_ArrayData_";
16680
if (value.at(key).size() != len)
16681
{
16682
return true;
16683
}
16684
16685
oa->write_character('[');
16686
oa->write_character('$');
16687
oa->write_character(dtype);
16688
oa->write_character('#');
16689
16690
key = "_ArraySize_";
16691
write_ubjson(value.at(key), use_count, use_type, true, true);
16692
16693
key = "_ArrayData_";
16694
if (dtype == 'U' || dtype == 'C')
16695
{
16696
for (const auto& el : value.at(key))
16697
{
16698
write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
16699
}
16700
}
16701
else if (dtype == 'i')
16702
{
16703
for (const auto& el : value.at(key))
16704
{
16705
write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
16706
}
16707
}
16708
else if (dtype == 'u')
16709
{
16710
for (const auto& el : value.at(key))
16711
{
16712
write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
16713
}
16714
}
16715
else if (dtype == 'I')
16716
{
16717
for (const auto& el : value.at(key))
16718
{
16719
write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
16720
}
16721
}
16722
else if (dtype == 'm')
16723
{
16724
for (const auto& el : value.at(key))
16725
{
16726
write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
16727
}
16728
}
16729
else if (dtype == 'l')
16730
{
16731
for (const auto& el : value.at(key))
16732
{
16733
write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
16734
}
16735
}
16736
else if (dtype == 'M')
16737
{
16738
for (const auto& el : value.at(key))
16739
{
16740
write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
16741
}
16742
}
16743
else if (dtype == 'L')
16744
{
16745
for (const auto& el : value.at(key))
16746
{
16747
write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
16748
}
16749
}
16750
else if (dtype == 'd')
16751
{
16752
for (const auto& el : value.at(key))
16753
{
16754
write_number(static_cast<float>(el.m_data.m_value.number_float), true);
16755
}
16756
}
16757
else if (dtype == 'D')
16758
{
16759
for (const auto& el : value.at(key))
16760
{
16761
write_number(static_cast<double>(el.m_data.m_value.number_float), true);
16762
}
16763
}
16764
return false;
16765
}
16766
16767
///////////////////////
16768
// Utility functions //
16769
///////////////////////
16770
16771
/*
16772
@brief write a number to output input
16773
@param[in] n number of type @a NumberType
16774
@param[in] OutputIsLittleEndian Set to true if output data is
16775
required to be little endian
16776
@tparam NumberType the type of the number
16777
16778
@note This function needs to respect the system's endianness, because bytes
16779
in CBOR, MessagePack, and UBJSON are stored in network order (big
16780
endian) and therefore need reordering on little endian systems.
16781
On the other hand, BSON and BJData use little endian and should reorder
16782
on big endian systems.
16783
*/
16784
template<typename NumberType>
16785
void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
16786
{
16787
// step 1: write number to array of length NumberType
16788
std::array<CharType, sizeof(NumberType)> vec{};
16789
std::memcpy(vec.data(), &n, sizeof(NumberType));
16790
16791
// step 2: write array to output (with possible reordering)
16792
if (is_little_endian != OutputIsLittleEndian)
16793
{
16794
// reverse byte order prior to conversion if necessary
16795
std::reverse(vec.begin(), vec.end());
16796
}
16797
16798
oa->write_characters(vec.data(), sizeof(NumberType));
16799
}
16800
16801
void write_compact_float(const number_float_t n, detail::input_format_t format)
16802
{
16803
#ifdef __GNUC__
16804
#pragma GCC diagnostic push
16805
#pragma GCC diagnostic ignored "-Wfloat-equal"
16806
#endif
16807
if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
16808
static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
16809
static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
16810
{
16811
oa->write_character(format == detail::input_format_t::cbor
16812
? get_cbor_float_prefix(static_cast<float>(n))
16813
: get_msgpack_float_prefix(static_cast<float>(n)));
16814
write_number(static_cast<float>(n));
16815
}
16816
else
16817
{
16818
oa->write_character(format == detail::input_format_t::cbor
16819
? get_cbor_float_prefix(n)
16820
: get_msgpack_float_prefix(n));
16821
write_number(n);
16822
}
16823
#ifdef __GNUC__
16824
#pragma GCC diagnostic pop
16825
#endif
16826
}
16827
16828
public:
16829
// The following to_char_type functions are implement the conversion
16830
// between uint8_t and CharType. In case CharType is not unsigned,
16831
// such a conversion is required to allow values greater than 128.
16832
// See <https://github.com/nlohmann/json/issues/1286> for a discussion.
16833
template < typename C = CharType,
16834
enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
16835
static constexpr CharType to_char_type(std::uint8_t x) noexcept
16836
{
16837
return *reinterpret_cast<char*>(&x);
16838
}
16839
16840
template < typename C = CharType,
16841
enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
16842
static CharType to_char_type(std::uint8_t x) noexcept
16843
{
16844
static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
16845
static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
16846
CharType result;
16847
std::memcpy(&result, &x, sizeof(x));
16848
return result;
16849
}
16850
16851
template<typename C = CharType,
16852
enable_if_t<std::is_unsigned<C>::value>* = nullptr>
16853
static constexpr CharType to_char_type(std::uint8_t x) noexcept
16854
{
16855
return x;
16856
}
16857
16858
template < typename InputCharType, typename C = CharType,
16859
enable_if_t <
16860
std::is_signed<C>::value &&
16861
std::is_signed<char>::value &&
16862
std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
16863
> * = nullptr >
16864
static constexpr CharType to_char_type(InputCharType x) noexcept
16865
{
16866
return x;
16867
}
16868
16869
private:
16870
/// whether we can assume little endianness
16871
const bool is_little_endian = little_endianness();
16872
16873
/// the output
16874
output_adapter_t<CharType> oa = nullptr;
16875
};
16876
16877
} // namespace detail
16878
NLOHMANN_JSON_NAMESPACE_END
16879
16880
// #include <nlohmann/detail/output/output_adapters.hpp>
16881
16882
// #include <nlohmann/detail/output/serializer.hpp>
16883
// __ _____ _____ _____
16884
// __| | __| | | | JSON for Modern C++
16885
// | | |__ | | | | | | version 3.11.3
16886
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16887
//
16888
// SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <[email protected]>
16889
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
16890
// SPDX-License-Identifier: MIT
16891
16892
16893
16894
#include <algorithm> // reverse, remove, fill, find, none_of
16895
#include <array> // array
16896
#include <clocale> // localeconv, lconv
16897
#include <cmath> // labs, isfinite, isnan, signbit
16898
#include <cstddef> // size_t, ptrdiff_t
16899
#include <cstdint> // uint8_t
16900
#include <cstdio> // snprintf
16901
#include <limits> // numeric_limits
16902
#include <string> // string, char_traits
16903
#include <iomanip> // setfill, setw
16904
#include <type_traits> // is_same
16905
#include <utility> // move
16906
16907
// #include <nlohmann/detail/conversions/to_chars.hpp>
16908
// __ _____ _____ _____
16909
// __| | __| | | | JSON for Modern C++
16910
// | | |__ | | | | | | version 3.11.3
16911
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16912
//
16913
// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
16914
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
16915
// SPDX-License-Identifier: MIT
16916
16917
16918
16919
#include <array> // array
16920
#include <cmath> // signbit, isfinite
16921
#include <cstdint> // intN_t, uintN_t
16922
#include <cstring> // memcpy, memmove
16923
#include <limits> // numeric_limits
16924
#include <type_traits> // conditional
16925
16926
// #include <nlohmann/detail/macro_scope.hpp>
16927
16928
16929
NLOHMANN_JSON_NAMESPACE_BEGIN
16930
namespace detail
16931
{
16932
16933
/*!
16934
@brief implements the Grisu2 algorithm for binary to decimal floating-point
16935
conversion.
16936
16937
This implementation is a slightly modified version of the reference
16938
implementation which may be obtained from
16939
http://florian.loitsch.com/publications (bench.tar.gz).
16940
16941
The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
16942
16943
For a detailed description of the algorithm see:
16944
16945
[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
16946
Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
16947
Language Design and Implementation, PLDI 2010
16948
[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
16949
Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
16950
Design and Implementation, PLDI 1996
16951
*/
16952
namespace dtoa_impl
16953
{
16954
16955
template<typename Target, typename Source>
16956
Target reinterpret_bits(const Source source)
16957
{
16958
static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
16959
16960
Target target;
16961
std::memcpy(&target, &source, sizeof(Source));
16962
return target;
16963
}
16964
16965
struct diyfp // f * 2^e
16966
{
16967
static constexpr int kPrecision = 64; // = q
16968
16969
std::uint64_t f = 0;
16970
int e = 0;
16971
16972
constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
16973
16974
/*!
16975
@brief returns x - y
16976
@pre x.e == y.e and x.f >= y.f
16977
*/
16978
static diyfp sub(const diyfp& x, const diyfp& y) noexcept
16979
{
16980
JSON_ASSERT(x.e == y.e);
16981
JSON_ASSERT(x.f >= y.f);
16982
16983
return {x.f - y.f, x.e};
16984
}
16985
16986
/*!
16987
@brief returns x * y
16988
@note The result is rounded. (Only the upper q bits are returned.)
16989
*/
16990
static diyfp mul(const diyfp& x, const diyfp& y) noexcept
16991
{
16992
static_assert(kPrecision == 64, "internal error");
16993
16994
// Computes:
16995
// f = round((x.f * y.f) / 2^q)
16996
// e = x.e + y.e + q
16997
16998
// Emulate the 64-bit * 64-bit multiplication:
16999
//
17000
// p = u * v
17001
// = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17002
// = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
17003
// = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
17004
// = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
17005
// = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
17006
// = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
17007
// = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
17008
//
17009
// (Since Q might be larger than 2^32 - 1)
17010
//
17011
// = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17012
//
17013
// (Q_hi + H does not overflow a 64-bit int)
17014
//
17015
// = p_lo + 2^64 p_hi
17016
17017
const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17018
const std::uint64_t u_hi = x.f >> 32u;
17019
const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17020
const std::uint64_t v_hi = y.f >> 32u;
17021
17022
const std::uint64_t p0 = u_lo * v_lo;
17023
const std::uint64_t p1 = u_lo * v_hi;
17024
const std::uint64_t p2 = u_hi * v_lo;
17025
const std::uint64_t p3 = u_hi * v_hi;
17026
17027
const std::uint64_t p0_hi = p0 >> 32u;
17028
const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17029
const std::uint64_t p1_hi = p1 >> 32u;
17030
const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17031
const std::uint64_t p2_hi = p2 >> 32u;
17032
17033
std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17034
17035
// The full product might now be computed as
17036
//
17037
// p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17038
// p_lo = p0_lo + (Q << 32)
17039
//
17040
// But in this particular case here, the full p_lo is not required.
17041
// Effectively we only need to add the highest bit in p_lo to p_hi (and
17042
// Q_hi + 1 does not overflow).
17043
17044
Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17045
17046
const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17047
17048
return {h, x.e + y.e + 64};
17049
}
17050
17051
/*!
17052
@brief normalize x such that the significand is >= 2^(q-1)
17053
@pre x.f != 0
17054
*/
17055
static diyfp normalize(diyfp x) noexcept
17056
{
17057
JSON_ASSERT(x.f != 0);
17058
17059
while ((x.f >> 63u) == 0)
17060
{
17061
x.f <<= 1u;
17062
x.e--;
17063
}
17064
17065
return x;
17066
}
17067
17068
/*!
17069
@brief normalize x such that the result has the exponent E
17070
@pre e >= x.e and the upper e - x.e bits of x.f must be zero.
17071
*/
17072
static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17073
{
17074
const int delta = x.e - target_exponent;
17075
17076
JSON_ASSERT(delta >= 0);
17077
JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17078
17079
return {x.f << delta, target_exponent};
17080
}
17081
};
17082
17083
struct boundaries
17084
{
17085
diyfp w;
17086
diyfp minus;
17087
diyfp plus;
17088
};
17089
17090
/*!
17091
Compute the (normalized) diyfp representing the input number 'value' and its
17092
boundaries.
17093
17094
@pre value must be finite and positive
17095
*/
17096
template<typename FloatType>
17097
boundaries compute_boundaries(FloatType value)
17098
{
17099
JSON_ASSERT(std::isfinite(value));
17100
JSON_ASSERT(value > 0);
17101
17102
// Convert the IEEE representation into a diyfp.
17103
//
17104
// If v is denormal:
17105
// value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17106
// If v is normalized:
17107
// value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17108
17109
static_assert(std::numeric_limits<FloatType>::is_iec559,
17110
"internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17111
17112
constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17113
constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17114
constexpr int kMinExp = 1 - kBias;
17115
constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17116
17117
using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17118
17119
const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17120
const std::uint64_t E = bits >> (kPrecision - 1);
17121
const std::uint64_t F = bits & (kHiddenBit - 1);
17122
17123
const bool is_denormal = E == 0;
17124
const diyfp v = is_denormal
17125
? diyfp(F, kMinExp)
17126
: diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17127
17128
// Compute the boundaries m- and m+ of the floating-point value
17129
// v = f * 2^e.
17130
//
17131
// Determine v- and v+, the floating-point predecessor and successor if v,
17132
// respectively.
17133
//
17134
// v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17135
// = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17136
//
17137
// v+ = v + 2^e
17138
//
17139
// Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17140
// between m- and m+ round to v, regardless of how the input rounding
17141
// algorithm breaks ties.
17142
//
17143
// ---+-------------+-------------+-------------+-------------+--- (A)
17144
// v- m- v m+ v+
17145
//
17146
// -----------------+------+------+-------------+-------------+--- (B)
17147
// v- m- v m+ v+
17148
17149
const bool lower_boundary_is_closer = F == 0 && E > 1;
17150
const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
17151
const diyfp m_minus = lower_boundary_is_closer
17152
? diyfp(4 * v.f - 1, v.e - 2) // (B)
17153
: diyfp(2 * v.f - 1, v.e - 1); // (A)
17154
17155
// Determine the normalized w+ = m+.
17156
const diyfp w_plus = diyfp::normalize(m_plus);
17157
17158
// Determine w- = m- such that e_(w-) = e_(w+).
17159
const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17160
17161
return {diyfp::normalize(v), w_minus, w_plus};
17162
}
17163
17164
// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17165
// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17166
// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17167
//
17168
// alpha <= e = e_c + e_w + q <= gamma
17169
//
17170
// or
17171
//
17172
// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17173
// <= f_c * f_w * 2^gamma
17174
//
17175
// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17176
//
17177
// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17178
//
17179
// or
17180
//
17181
// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17182
//
17183
// The choice of (alpha,gamma) determines the size of the table and the form of
17184
// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17185
// in practice:
17186
//
17187
// The idea is to cut the number c * w = f * 2^e into two parts, which can be
17188
// processed independently: An integral part p1, and a fractional part p2:
17189
//
17190
// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17191
// = (f div 2^-e) + (f mod 2^-e) * 2^e
17192
// = p1 + p2 * 2^e
17193
//
17194
// The conversion of p1 into decimal form requires a series of divisions and
17195
// modulos by (a power of) 10. These operations are faster for 32-bit than for
17196
// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17197
// achieved by choosing
17198
//
17199
// -e >= 32 or e <= -32 := gamma
17200
//
17201
// In order to convert the fractional part
17202
//
17203
// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
17204
//
17205
// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
17206
// d[-i] are extracted in order:
17207
//
17208
// (10 * p2) div 2^-e = d[-1]
17209
// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
17210
//
17211
// The multiplication by 10 must not overflow. It is sufficient to choose
17212
//
17213
// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
17214
//
17215
// Since p2 = f mod 2^-e < 2^-e,
17216
//
17217
// -e <= 60 or e >= -60 := alpha
17218
17219
constexpr int kAlpha = -60;
17220
constexpr int kGamma = -32;
17221
17222
struct cached_power // c = f * 2^e ~= 10^k
17223
{
17224
std::uint64_t f;
17225
int e;
17226
int k;
17227
};
17228
17229
/*!
17230
For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
17231
power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
17232
satisfies (Definition 3.2 from [1])
17233
17234
alpha <= e_c + e + q <= gamma.
17235
*/
17236
inline cached_power get_cached_power_for_binary_exponent(int e)
17237
{
17238
// Now
17239
//
17240
// alpha <= e_c + e + q <= gamma (1)
17241
// ==> f_c * 2^alpha <= c * 2^e * 2^q
17242
//
17243
// and since the c's are normalized, 2^(q-1) <= f_c,
17244
//
17245
// ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
17246
// ==> 2^(alpha - e - 1) <= c
17247
//
17248
// If c were an exact power of ten, i.e. c = 10^k, one may determine k as
17249
//
17250
// k = ceil( log_10( 2^(alpha - e - 1) ) )
17251
// = ceil( (alpha - e - 1) * log_10(2) )
17252
//
17253
// From the paper:
17254
// "In theory the result of the procedure could be wrong since c is rounded,
17255
// and the computation itself is approximated [...]. In practice, however,
17256
// this simple function is sufficient."
17257
//
17258
// For IEEE double precision floating-point numbers converted into
17259
// normalized diyfp's w = f * 2^e, with q = 64,
17260
//
17261
// e >= -1022 (min IEEE exponent)
17262
// -52 (p - 1)
17263
// -52 (p - 1, possibly normalize denormal IEEE numbers)
17264
// -11 (normalize the diyfp)
17265
// = -1137
17266
//
17267
// and
17268
//
17269
// e <= +1023 (max IEEE exponent)
17270
// -52 (p - 1)
17271
// -11 (normalize the diyfp)
17272
// = 960
17273
//
17274
// This binary exponent range [-1137,960] results in a decimal exponent
17275
// range [-307,324]. One does not need to store a cached power for each
17276
// k in this range. For each such k it suffices to find a cached power
17277
// such that the exponent of the product lies in [alpha,gamma].
17278
// This implies that the difference of the decimal exponents of adjacent
17279
// table entries must be less than or equal to
17280
//
17281
// floor( (gamma - alpha) * log_10(2) ) = 8.
17282
//
17283
// (A smaller distance gamma-alpha would require a larger table.)
17284
17285
// NB:
17286
// Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
17287
17288
constexpr int kCachedPowersMinDecExp = -300;
17289
constexpr int kCachedPowersDecStep = 8;
17290
17291
static constexpr std::array<cached_power, 79> kCachedPowers =
17292
{
17293
{
17294
{ 0xAB70FE17C79AC6CA, -1060, -300 },
17295
{ 0xFF77B1FCBEBCDC4F, -1034, -292 },
17296
{ 0xBE5691EF416BD60C, -1007, -284 },
17297
{ 0x8DD01FAD907FFC3C, -980, -276 },
17298
{ 0xD3515C2831559A83, -954, -268 },
17299
{ 0x9D71AC8FADA6C9B5, -927, -260 },
17300
{ 0xEA9C227723EE8BCB, -901, -252 },
17301
{ 0xAECC49914078536D, -874, -244 },
17302
{ 0x823C12795DB6CE57, -847, -236 },
17303
{ 0xC21094364DFB5637, -821, -228 },
17304
{ 0x9096EA6F3848984F, -794, -220 },
17305
{ 0xD77485CB25823AC7, -768, -212 },
17306
{ 0xA086CFCD97BF97F4, -741, -204 },
17307
{ 0xEF340A98172AACE5, -715, -196 },
17308
{ 0xB23867FB2A35B28E, -688, -188 },
17309
{ 0x84C8D4DFD2C63F3B, -661, -180 },
17310
{ 0xC5DD44271AD3CDBA, -635, -172 },
17311
{ 0x936B9FCEBB25C996, -608, -164 },
17312
{ 0xDBAC6C247D62A584, -582, -156 },
17313
{ 0xA3AB66580D5FDAF6, -555, -148 },
17314
{ 0xF3E2F893DEC3F126, -529, -140 },
17315
{ 0xB5B5ADA8AAFF80B8, -502, -132 },
17316
{ 0x87625F056C7C4A8B, -475, -124 },
17317
{ 0xC9BCFF6034C13053, -449, -116 },
17318
{ 0x964E858C91BA2655, -422, -108 },
17319
{ 0xDFF9772470297EBD, -396, -100 },
17320
{ 0xA6DFBD9FB8E5B88F, -369, -92 },
17321
{ 0xF8A95FCF88747D94, -343, -84 },
17322
{ 0xB94470938FA89BCF, -316, -76 },
17323
{ 0x8A08F0F8BF0F156B, -289, -68 },
17324
{ 0xCDB02555653131B6, -263, -60 },
17325
{ 0x993FE2C6D07B7FAC, -236, -52 },
17326
{ 0xE45C10C42A2B3B06, -210, -44 },
17327
{ 0xAA242499697392D3, -183, -36 },
17328
{ 0xFD87B5F28300CA0E, -157, -28 },
17329
{ 0xBCE5086492111AEB, -130, -20 },
17330
{ 0x8CBCCC096F5088CC, -103, -12 },
17331
{ 0xD1B71758E219652C, -77, -4 },
17332
{ 0x9C40000000000000, -50, 4 },
17333
{ 0xE8D4A51000000000, -24, 12 },
17334
{ 0xAD78EBC5AC620000, 3, 20 },
17335
{ 0x813F3978F8940984, 30, 28 },
17336
{ 0xC097CE7BC90715B3, 56, 36 },
17337
{ 0x8F7E32CE7BEA5C70, 83, 44 },
17338
{ 0xD5D238A4ABE98068, 109, 52 },
17339
{ 0x9F4F2726179A2245, 136, 60 },
17340
{ 0xED63A231D4C4FB27, 162, 68 },
17341
{ 0xB0DE65388CC8ADA8, 189, 76 },
17342
{ 0x83C7088E1AAB65DB, 216, 84 },
17343
{ 0xC45D1DF942711D9A, 242, 92 },
17344
{ 0x924D692CA61BE758, 269, 100 },
17345
{ 0xDA01EE641A708DEA, 295, 108 },
17346
{ 0xA26DA3999AEF774A, 322, 116 },
17347
{ 0xF209787BB47D6B85, 348, 124 },
17348
{ 0xB454E4A179DD1877, 375, 132 },
17349
{ 0x865B86925B9BC5C2, 402, 140 },
17350
{ 0xC83553C5C8965D3D, 428, 148 },
17351
{ 0x952AB45CFA97A0B3, 455, 156 },
17352
{ 0xDE469FBD99A05FE3, 481, 164 },
17353
{ 0xA59BC234DB398C25, 508, 172 },
17354
{ 0xF6C69A72A3989F5C, 534, 180 },
17355
{ 0xB7DCBF5354E9BECE, 561, 188 },
17356
{ 0x88FCF317F22241E2, 588, 196 },
17357
{ 0xCC20CE9BD35C78A5, 614, 204 },
17358
{ 0x98165AF37B2153DF, 641, 212 },
17359
{ 0xE2A0B5DC971F303A, 667, 220 },
17360
{ 0xA8D9D1535CE3B396, 694, 228 },
17361
{ 0xFB9B7CD9A4A7443C, 720, 236 },
17362
{ 0xBB764C4CA7A44410, 747, 244 },
17363
{ 0x8BAB8EEFB6409C1A, 774, 252 },
17364
{ 0xD01FEF10A657842C, 800, 260 },
17365
{ 0x9B10A4E5E9913129, 827, 268 },
17366
{ 0xE7109BFBA19C0C9D, 853, 276 },
17367
{ 0xAC2820D9623BF429, 880, 284 },
17368
{ 0x80444B5E7AA7CF85, 907, 292 },
17369
{ 0xBF21E44003ACDD2D, 933, 300 },
17370
{ 0x8E679C2F5E44FF8F, 960, 308 },
17371
{ 0xD433179D9C8CB841, 986, 316 },
17372
{ 0x9E19DB92B4E31BA9, 1013, 324 },
17373
}
17374
};
17375
17376
// This computation gives exactly the same results for k as
17377
// k = ceil((kAlpha - e - 1) * 0.30102999566398114)
17378
// for |e| <= 1500, but doesn't require floating-point operations.
17379
// NB: log_10(2) ~= 78913 / 2^18
17380
JSON_ASSERT(e >= -1500);
17381
JSON_ASSERT(e <= 1500);
17382
const int f = kAlpha - e - 1;
17383
const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
17384
17385
const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
17386
JSON_ASSERT(index >= 0);
17387
JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
17388
17389
const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
17390
JSON_ASSERT(kAlpha <= cached.e + e + 64);
17391
JSON_ASSERT(kGamma >= cached.e + e + 64);
17392
17393
return cached;
17394
}
17395
17396
/*!
17397
For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
17398
For n == 0, returns 1 and sets pow10 := 1.
17399
*/
17400
inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
17401
{
17402
// LCOV_EXCL_START
17403
if (n >= 1000000000)
17404
{
17405
pow10 = 1000000000;
17406
return 10;
17407
}
17408
// LCOV_EXCL_STOP
17409
if (n >= 100000000)
17410
{
17411
pow10 = 100000000;
17412
return 9;
17413
}
17414
if (n >= 10000000)
17415
{
17416
pow10 = 10000000;
17417
return 8;
17418
}
17419
if (n >= 1000000)
17420
{
17421
pow10 = 1000000;
17422
return 7;
17423
}
17424
if (n >= 100000)
17425
{
17426
pow10 = 100000;
17427
return 6;
17428
}
17429
if (n >= 10000)
17430
{
17431
pow10 = 10000;
17432
return 5;
17433
}
17434
if (n >= 1000)
17435
{
17436
pow10 = 1000;
17437
return 4;
17438
}
17439
if (n >= 100)
17440
{
17441
pow10 = 100;
17442
return 3;
17443
}
17444
if (n >= 10)
17445
{
17446
pow10 = 10;
17447
return 2;
17448
}
17449
17450
pow10 = 1;
17451
return 1;
17452
}
17453
17454
inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
17455
std::uint64_t rest, std::uint64_t ten_k)
17456
{
17457
JSON_ASSERT(len >= 1);
17458
JSON_ASSERT(dist <= delta);
17459
JSON_ASSERT(rest <= delta);
17460
JSON_ASSERT(ten_k > 0);
17461
17462
// <--------------------------- delta ---->
17463
// <---- dist --------->
17464
// --------------[------------------+-------------------]--------------
17465
// M- w M+
17466
//
17467
// ten_k
17468
// <------>
17469
// <---- rest ---->
17470
// --------------[------------------+----+--------------]--------------
17471
// w V
17472
// = buf * 10^k
17473
//
17474
// ten_k represents a unit-in-the-last-place in the decimal representation
17475
// stored in buf.
17476
// Decrement buf by ten_k while this takes buf closer to w.
17477
17478
// The tests are written in this order to avoid overflow in unsigned
17479
// integer arithmetic.
17480
17481
while (rest < dist
17482
&& delta - rest >= ten_k
17483
&& (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
17484
{
17485
JSON_ASSERT(buf[len - 1] != '0');
17486
buf[len - 1]--;
17487
rest += ten_k;
17488
}
17489
}
17490
17491
/*!
17492
Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
17493
M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
17494
*/
17495
inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
17496
diyfp M_minus, diyfp w, diyfp M_plus)
17497
{
17498
static_assert(kAlpha >= -60, "internal error");
17499
static_assert(kGamma <= -32, "internal error");
17500
17501
// Generates the digits (and the exponent) of a decimal floating-point
17502
// number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
17503
// w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
17504
//
17505
// <--------------------------- delta ---->
17506
// <---- dist --------->
17507
// --------------[------------------+-------------------]--------------
17508
// M- w M+
17509
//
17510
// Grisu2 generates the digits of M+ from left to right and stops as soon as
17511
// V is in [M-,M+].
17512
17513
JSON_ASSERT(M_plus.e >= kAlpha);
17514
JSON_ASSERT(M_plus.e <= kGamma);
17515
17516
std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
17517
std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
17518
17519
// Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
17520
//
17521
// M+ = f * 2^e
17522
// = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
17523
// = ((p1 ) * 2^-e + (p2 )) * 2^e
17524
// = p1 + p2 * 2^e
17525
17526
const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
17527
17528
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.)
17529
std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
17530
17531
// 1)
17532
//
17533
// Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
17534
17535
JSON_ASSERT(p1 > 0);
17536
17537
std::uint32_t pow10{};
17538
const int k = find_largest_pow10(p1, pow10);
17539
17540
// 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
17541
//
17542
// p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
17543
// = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
17544
//
17545
// M+ = p1 + p2 * 2^e
17546
// = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
17547
// = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
17548
// = d[k-1] * 10^(k-1) + ( rest) * 2^e
17549
//
17550
// Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
17551
//
17552
// p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
17553
//
17554
// but stop as soon as
17555
//
17556
// rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
17557
17558
int n = k;
17559
while (n > 0)
17560
{
17561
// Invariants:
17562
// M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
17563
// pow10 = 10^(n-1) <= p1 < 10^n
17564
//
17565
const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
17566
const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
17567
//
17568
// M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
17569
// = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
17570
//
17571
JSON_ASSERT(d <= 9);
17572
buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17573
//
17574
// M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
17575
//
17576
p1 = r;
17577
n--;
17578
//
17579
// M+ = buffer * 10^n + (p1 + p2 * 2^e)
17580
// pow10 = 10^n
17581
//
17582
17583
// Now check if enough digits have been generated.
17584
// Compute
17585
//
17586
// p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
17587
//
17588
// Note:
17589
// Since rest and delta share the same exponent e, it suffices to
17590
// compare the significands.
17591
const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
17592
if (rest <= delta)
17593
{
17594
// V = buffer * 10^n, with M- <= V <= M+.
17595
17596
decimal_exponent += n;
17597
17598
// We may now just stop. But instead look if the buffer could be
17599
// decremented to bring V closer to w.
17600
//
17601
// pow10 = 10^n is now 1 ulp in the decimal representation V.
17602
// The rounding procedure works with diyfp's with an implicit
17603
// exponent of e.
17604
//
17605
// 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
17606
//
17607
const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
17608
grisu2_round(buffer, length, dist, delta, rest, ten_n);
17609
17610
return;
17611
}
17612
17613
pow10 /= 10;
17614
//
17615
// pow10 = 10^(n-1) <= p1 < 10^n
17616
// Invariants restored.
17617
}
17618
17619
// 2)
17620
//
17621
// The digits of the integral part have been generated:
17622
//
17623
// M+ = d[k-1]...d[1]d[0] + p2 * 2^e
17624
// = buffer + p2 * 2^e
17625
//
17626
// Now generate the digits of the fractional part p2 * 2^e.
17627
//
17628
// Note:
17629
// No decimal point is generated: the exponent is adjusted instead.
17630
//
17631
// p2 actually represents the fraction
17632
//
17633
// p2 * 2^e
17634
// = p2 / 2^-e
17635
// = d[-1] / 10^1 + d[-2] / 10^2 + ...
17636
//
17637
// Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
17638
//
17639
// p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
17640
// + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
17641
//
17642
// using
17643
//
17644
// 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
17645
// = ( d) * 2^-e + ( r)
17646
//
17647
// or
17648
// 10^m * p2 * 2^e = d + r * 2^e
17649
//
17650
// i.e.
17651
//
17652
// M+ = buffer + p2 * 2^e
17653
// = buffer + 10^-m * (d + r * 2^e)
17654
// = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
17655
//
17656
// and stop as soon as 10^-m * r * 2^e <= delta * 2^e
17657
17658
JSON_ASSERT(p2 > delta);
17659
17660
int m = 0;
17661
for (;;)
17662
{
17663
// Invariant:
17664
// M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
17665
// = buffer * 10^-m + 10^-m * (p2 ) * 2^e
17666
// = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
17667
// = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
17668
//
17669
JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
17670
p2 *= 10;
17671
const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
17672
const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
17673
//
17674
// M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
17675
// = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
17676
// = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
17677
//
17678
JSON_ASSERT(d <= 9);
17679
buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17680
//
17681
// M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
17682
//
17683
p2 = r;
17684
m++;
17685
//
17686
// M+ = buffer * 10^-m + 10^-m * p2 * 2^e
17687
// Invariant restored.
17688
17689
// Check if enough digits have been generated.
17690
//
17691
// 10^-m * p2 * 2^e <= delta * 2^e
17692
// p2 * 2^e <= 10^m * delta * 2^e
17693
// p2 <= 10^m * delta
17694
delta *= 10;
17695
dist *= 10;
17696
if (p2 <= delta)
17697
{
17698
break;
17699
}
17700
}
17701
17702
// V = buffer * 10^-m, with M- <= V <= M+.
17703
17704
decimal_exponent -= m;
17705
17706
// 1 ulp in the decimal representation is now 10^-m.
17707
// Since delta and dist are now scaled by 10^m, we need to do the
17708
// same with ulp in order to keep the units in sync.
17709
//
17710
// 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
17711
//
17712
const std::uint64_t ten_m = one.f;
17713
grisu2_round(buffer, length, dist, delta, p2, ten_m);
17714
17715
// By construction this algorithm generates the shortest possible decimal
17716
// number (Loitsch, Theorem 6.2) which rounds back to w.
17717
// For an input number of precision p, at least
17718
//
17719
// N = 1 + ceil(p * log_10(2))
17720
//
17721
// decimal digits are sufficient to identify all binary floating-point
17722
// numbers (Matula, "In-and-Out conversions").
17723
// This implies that the algorithm does not produce more than N decimal
17724
// digits.
17725
//
17726
// N = 17 for p = 53 (IEEE double precision)
17727
// N = 9 for p = 24 (IEEE single precision)
17728
}
17729
17730
/*!
17731
v = buf * 10^decimal_exponent
17732
len is the length of the buffer (number of decimal digits)
17733
The buffer must be large enough, i.e. >= max_digits10.
17734
*/
17735
JSON_HEDLEY_NON_NULL(1)
17736
inline void grisu2(char* buf, int& len, int& decimal_exponent,
17737
diyfp m_minus, diyfp v, diyfp m_plus)
17738
{
17739
JSON_ASSERT(m_plus.e == m_minus.e);
17740
JSON_ASSERT(m_plus.e == v.e);
17741
17742
// --------(-----------------------+-----------------------)-------- (A)
17743
// m- v m+
17744
//
17745
// --------------------(-----------+-----------------------)-------- (B)
17746
// m- v m+
17747
//
17748
// First scale v (and m- and m+) such that the exponent is in the range
17749
// [alpha, gamma].
17750
17751
const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
17752
17753
const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
17754
17755
// The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
17756
const diyfp w = diyfp::mul(v, c_minus_k);
17757
const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
17758
const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
17759
17760
// ----(---+---)---------------(---+---)---------------(---+---)----
17761
// w- w w+
17762
// = c*m- = c*v = c*m+
17763
//
17764
// diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
17765
// w+ are now off by a small amount.
17766
// In fact:
17767
//
17768
// w - v * 10^k < 1 ulp
17769
//
17770
// To account for this inaccuracy, add resp. subtract 1 ulp.
17771
//
17772
// --------+---[---------------(---+---)---------------]---+--------
17773
// w- M- w M+ w+
17774
//
17775
// Now any number in [M-, M+] (bounds included) will round to w when input,
17776
// regardless of how the input rounding algorithm breaks ties.
17777
//
17778
// And digit_gen generates the shortest possible such number in [M-, M+].
17779
// Note that this does not mean that Grisu2 always generates the shortest
17780
// possible number in the interval (m-, m+).
17781
const diyfp M_minus(w_minus.f + 1, w_minus.e);
17782
const diyfp M_plus (w_plus.f - 1, w_plus.e );
17783
17784
decimal_exponent = -cached.k; // = -(-k) = k
17785
17786
grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
17787
}
17788
17789
/*!
17790
v = buf * 10^decimal_exponent
17791
len is the length of the buffer (number of decimal digits)
17792
The buffer must be large enough, i.e. >= max_digits10.
17793
*/
17794
template<typename FloatType>
17795
JSON_HEDLEY_NON_NULL(1)
17796
void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
17797
{
17798
static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
17799
"internal error: not enough precision");
17800
17801
JSON_ASSERT(std::isfinite(value));
17802
JSON_ASSERT(value > 0);
17803
17804
// If the neighbors (and boundaries) of 'value' are always computed for double-precision
17805
// numbers, all float's can be recovered using strtod (and strtof). However, the resulting
17806
// decimal representations are not exactly "short".
17807
//
17808
// The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
17809
// says "value is converted to a string as if by std::sprintf in the default ("C") locale"
17810
// and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
17811
// does.
17812
// On the other hand, the documentation for 'std::to_chars' requires that "parsing the
17813
// representation using the corresponding std::from_chars function recovers value exactly". That
17814
// indicates that single precision floating-point numbers should be recovered using
17815
// 'std::strtof'.
17816
//
17817
// NB: If the neighbors are computed for single-precision numbers, there is a single float
17818
// (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
17819
// value is off by 1 ulp.
17820
#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
17821
const boundaries w = compute_boundaries(static_cast<double>(value));
17822
#else
17823
const boundaries w = compute_boundaries(value);
17824
#endif
17825
17826
grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
17827
}
17828
17829
/*!
17830
@brief appends a decimal representation of e to buf
17831
@return a pointer to the element following the exponent.
17832
@pre -1000 < e < 1000
17833
*/
17834
JSON_HEDLEY_NON_NULL(1)
17835
JSON_HEDLEY_RETURNS_NON_NULL
17836
inline char* append_exponent(char* buf, int e)
17837
{
17838
JSON_ASSERT(e > -1000);
17839
JSON_ASSERT(e < 1000);
17840
17841
if (e < 0)
17842
{
17843
e = -e;
17844
*buf++ = '-';
17845
}
17846
else
17847
{
17848
*buf++ = '+';
17849
}
17850
17851
auto k = static_cast<std::uint32_t>(e);
17852
if (k < 10)
17853
{
17854
// Always print at least two digits in the exponent.
17855
// This is for compatibility with printf("%g").
17856
*buf++ = '0';
17857
*buf++ = static_cast<char>('0' + k);
17858
}
17859
else if (k < 100)
17860
{
17861
*buf++ = static_cast<char>('0' + k / 10);
17862
k %= 10;
17863
*buf++ = static_cast<char>('0' + k);
17864
}
17865
else
17866
{
17867
*buf++ = static_cast<char>('0' + k / 100);
17868
k %= 100;
17869
*buf++ = static_cast<char>('0' + k / 10);
17870
k %= 10;
17871
*buf++ = static_cast<char>('0' + k);
17872
}
17873
17874
return buf;
17875
}
17876
17877
/*!
17878
@brief prettify v = buf * 10^decimal_exponent
17879
17880
If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
17881
notation. Otherwise it will be printed in exponential notation.
17882
17883
@pre min_exp < 0
17884
@pre max_exp > 0
17885
*/
17886
JSON_HEDLEY_NON_NULL(1)
17887
JSON_HEDLEY_RETURNS_NON_NULL
17888
inline char* format_buffer(char* buf, int len, int decimal_exponent,
17889
int min_exp, int max_exp)
17890
{
17891
JSON_ASSERT(min_exp < 0);
17892
JSON_ASSERT(max_exp > 0);
17893
17894
const int k = len;
17895
const int n = len + decimal_exponent;
17896
17897
// v = buf * 10^(n-k)
17898
// k is the length of the buffer (number of decimal digits)
17899
// n is the position of the decimal point relative to the start of the buffer.
17900
17901
if (k <= n && n <= max_exp)
17902
{
17903
// digits[000]
17904
// len <= max_exp + 2
17905
17906
std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
17907
// Make it look like a floating-point number (#362, #378)
17908
buf[n + 0] = '.';
17909
buf[n + 1] = '0';
17910
return buf + (static_cast<size_t>(n) + 2);
17911
}
17912
17913
if (0 < n && n <= max_exp)
17914
{
17915
// dig.its
17916
// len <= max_digits10 + 1
17917
17918
JSON_ASSERT(k > n);
17919
17920
std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
17921
buf[n] = '.';
17922
return buf + (static_cast<size_t>(k) + 1U);
17923
}
17924
17925
if (min_exp < n && n <= 0)
17926
{
17927
// 0.[000]digits
17928
// len <= 2 + (-min_exp - 1) + max_digits10
17929
17930
std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
17931
buf[0] = '0';
17932
buf[1] = '.';
17933
std::memset(buf + 2, '0', static_cast<size_t>(-n));
17934
return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
17935
}
17936
17937
if (k == 1)
17938
{
17939
// dE+123
17940
// len <= 1 + 5
17941
17942
buf += 1;
17943
}
17944
else
17945
{
17946
// d.igitsE+123
17947
// len <= max_digits10 + 1 + 5
17948
17949
std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
17950
buf[1] = '.';
17951
buf += 1 + static_cast<size_t>(k);
17952
}
17953
17954
*buf++ = 'e';
17955
return append_exponent(buf, n - 1);
17956
}
17957
17958
} // namespace dtoa_impl
17959
17960
/*!
17961
@brief generates a decimal representation of the floating-point number value in [first, last).
17962
17963
The format of the resulting decimal representation is similar to printf's %g
17964
format. Returns an iterator pointing past-the-end of the decimal representation.
17965
17966
@note The input number must be finite, i.e. NaN's and Inf's are not supported.
17967
@note The buffer must be large enough.
17968
@note The result is NOT null-terminated.
17969
*/
17970
template<typename FloatType>
17971
JSON_HEDLEY_NON_NULL(1, 2)
17972
JSON_HEDLEY_RETURNS_NON_NULL
17973
char* to_chars(char* first, const char* last, FloatType value)
17974
{
17975
static_cast<void>(last); // maybe unused - fix warning
17976
JSON_ASSERT(std::isfinite(value));
17977
17978
// Use signbit(value) instead of (value < 0) since signbit works for -0.
17979
if (std::signbit(value))
17980
{
17981
value = -value;
17982
*first++ = '-';
17983
}
17984
17985
#ifdef __GNUC__
17986
#pragma GCC diagnostic push
17987
#pragma GCC diagnostic ignored "-Wfloat-equal"
17988
#endif
17989
if (value == 0) // +-0
17990
{
17991
*first++ = '0';
17992
// Make it look like a floating-point number (#362, #378)
17993
*first++ = '.';
17994
*first++ = '0';
17995
return first;
17996
}
17997
#ifdef __GNUC__
17998
#pragma GCC diagnostic pop
17999
#endif
18000
18001
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18002
18003
// Compute v = buffer * 10^decimal_exponent.
18004
// The decimal digits are stored in the buffer, which needs to be interpreted
18005
// as an unsigned decimal integer.
18006
// len is the length of the buffer, i.e. the number of decimal digits.
18007
int len = 0;
18008
int decimal_exponent = 0;
18009
dtoa_impl::grisu2(first, len, decimal_exponent, value);
18010
18011
JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18012
18013
// Format the buffer like printf("%.*g", prec, value)
18014
constexpr int kMinExp = -4;
18015
// Use digits10 here to increase compatibility with version 2.
18016
constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18017
18018
JSON_ASSERT(last - first >= kMaxExp + 2);
18019
JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18020
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18021
18022
return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18023
}
18024
18025
} // namespace detail
18026
NLOHMANN_JSON_NAMESPACE_END
18027
18028
// #include <nlohmann/detail/exceptions.hpp>
18029
18030
// #include <nlohmann/detail/macro_scope.hpp>
18031
18032
// #include <nlohmann/detail/meta/cpp_future.hpp>
18033
18034
// #include <nlohmann/detail/output/binary_writer.hpp>
18035
18036
// #include <nlohmann/detail/output/output_adapters.hpp>
18037
18038
// #include <nlohmann/detail/string_concat.hpp>
18039
18040
// #include <nlohmann/detail/value_t.hpp>
18041
18042
18043
NLOHMANN_JSON_NAMESPACE_BEGIN
18044
namespace detail
18045
{
18046
18047
///////////////////
18048
// serialization //
18049
///////////////////
18050
18051
/// how to treat decoding errors
18052
enum class error_handler_t
18053
{
18054
strict, ///< throw a type_error exception in case of invalid UTF-8
18055
replace, ///< replace invalid UTF-8 sequences with U+FFFD
18056
ignore ///< ignore invalid UTF-8 sequences
18057
};
18058
18059
template<typename BasicJsonType>
18060
class serializer
18061
{
18062
using string_t = typename BasicJsonType::string_t;
18063
using number_float_t = typename BasicJsonType::number_float_t;
18064
using number_integer_t = typename BasicJsonType::number_integer_t;
18065
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18066
using binary_char_t = typename BasicJsonType::binary_t::value_type;
18067
static constexpr std::uint8_t UTF8_ACCEPT = 0;
18068
static constexpr std::uint8_t UTF8_REJECT = 1;
18069
18070
public:
18071
/*!
18072
@param[in] s output stream to serialize to
18073
@param[in] ichar indentation character to use
18074
@param[in] error_handler_ how to react on decoding errors
18075
*/
18076
serializer(output_adapter_t<char> s, const char ichar,
18077
error_handler_t error_handler_ = error_handler_t::strict)
18078
: o(std::move(s))
18079
, loc(std::localeconv())
18080
, thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
18081
, decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
18082
, indent_char(ichar)
18083
, indent_string(512, indent_char)
18084
, error_handler(error_handler_)
18085
{}
18086
18087
// delete because of pointer members
18088
serializer(const serializer&) = delete;
18089
serializer& operator=(const serializer&) = delete;
18090
serializer(serializer&&) = delete;
18091
serializer& operator=(serializer&&) = delete;
18092
~serializer() = default;
18093
18094
/*!
18095
@brief internal implementation of the serialization function
18096
18097
This function is called by the public member function dump and organizes
18098
the serialization internally. The indentation level is propagated as
18099
additional parameter. In case of arrays and objects, the function is
18100
called recursively.
18101
18102
- strings and object keys are escaped using `escape_string()`
18103
- integer numbers are converted implicitly via `operator<<`
18104
- floating-point numbers are converted to a string using `"%g"` format
18105
- binary values are serialized as objects containing the subtype and the
18106
byte array
18107
18108
@param[in] val value to serialize
18109
@param[in] pretty_print whether the output shall be pretty-printed
18110
@param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
18111
in the output are escaped with `\uXXXX` sequences, and the result consists
18112
of ASCII characters only.
18113
@param[in] indent_step the indent level
18114
@param[in] current_indent the current indent level (only used internally)
18115
*/
18116
void dump(const BasicJsonType& val,
18117
const bool pretty_print,
18118
const bool ensure_ascii,
18119
const unsigned int indent_step,
18120
const unsigned int current_indent = 0)
18121
{
18122
switch (val.m_data.m_type)
18123
{
18124
case value_t::object:
18125
{
18126
if (val.m_data.m_value.object->empty())
18127
{
18128
o->write_characters("{}", 2);
18129
return;
18130
}
18131
18132
if (pretty_print)
18133
{
18134
o->write_characters("{\n", 2);
18135
18136
// variable to hold indentation for recursive calls
18137
const auto new_indent = current_indent + indent_step;
18138
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18139
{
18140
indent_string.resize(indent_string.size() * 2, ' ');
18141
}
18142
18143
// first n-1 elements
18144
auto i = val.m_data.m_value.object->cbegin();
18145
for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18146
{
18147
o->write_characters(indent_string.c_str(), new_indent);
18148
o->write_character('\"');
18149
dump_escaped(i->first, ensure_ascii);
18150
o->write_characters("\": ", 3);
18151
dump(i->second, true, ensure_ascii, indent_step, new_indent);
18152
o->write_characters(",\n", 2);
18153
}
18154
18155
// last element
18156
JSON_ASSERT(i != val.m_data.m_value.object->cend());
18157
JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18158
o->write_characters(indent_string.c_str(), new_indent);
18159
o->write_character('\"');
18160
dump_escaped(i->first, ensure_ascii);
18161
o->write_characters("\": ", 3);
18162
dump(i->second, true, ensure_ascii, indent_step, new_indent);
18163
18164
o->write_character('\n');
18165
o->write_characters(indent_string.c_str(), current_indent);
18166
o->write_character('}');
18167
}
18168
else
18169
{
18170
o->write_character('{');
18171
18172
// first n-1 elements
18173
auto i = val.m_data.m_value.object->cbegin();
18174
for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18175
{
18176
o->write_character('\"');
18177
dump_escaped(i->first, ensure_ascii);
18178
o->write_characters("\":", 2);
18179
dump(i->second, false, ensure_ascii, indent_step, current_indent);
18180
o->write_character(',');
18181
}
18182
18183
// last element
18184
JSON_ASSERT(i != val.m_data.m_value.object->cend());
18185
JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18186
o->write_character('\"');
18187
dump_escaped(i->first, ensure_ascii);
18188
o->write_characters("\":", 2);
18189
dump(i->second, false, ensure_ascii, indent_step, current_indent);
18190
18191
o->write_character('}');
18192
}
18193
18194
return;
18195
}
18196
18197
case value_t::array:
18198
{
18199
if (val.m_data.m_value.array->empty())
18200
{
18201
o->write_characters("[]", 2);
18202
return;
18203
}
18204
18205
if (pretty_print)
18206
{
18207
o->write_characters("[\n", 2);
18208
18209
// variable to hold indentation for recursive calls
18210
const auto new_indent = current_indent + indent_step;
18211
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18212
{
18213
indent_string.resize(indent_string.size() * 2, ' ');
18214
}
18215
18216
// first n-1 elements
18217
for (auto i = val.m_data.m_value.array->cbegin();
18218
i != val.m_data.m_value.array->cend() - 1; ++i)
18219
{
18220
o->write_characters(indent_string.c_str(), new_indent);
18221
dump(*i, true, ensure_ascii, indent_step, new_indent);
18222
o->write_characters(",\n", 2);
18223
}
18224
18225
// last element
18226
JSON_ASSERT(!val.m_data.m_value.array->empty());
18227
o->write_characters(indent_string.c_str(), new_indent);
18228
dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
18229
18230
o->write_character('\n');
18231
o->write_characters(indent_string.c_str(), current_indent);
18232
o->write_character(']');
18233
}
18234
else
18235
{
18236
o->write_character('[');
18237
18238
// first n-1 elements
18239
for (auto i = val.m_data.m_value.array->cbegin();
18240
i != val.m_data.m_value.array->cend() - 1; ++i)
18241
{
18242
dump(*i, false, ensure_ascii, indent_step, current_indent);
18243
o->write_character(',');
18244
}
18245
18246
// last element
18247
JSON_ASSERT(!val.m_data.m_value.array->empty());
18248
dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
18249
18250
o->write_character(']');
18251
}
18252
18253
return;
18254
}
18255
18256
case value_t::string:
18257
{
18258
o->write_character('\"');
18259
dump_escaped(*val.m_data.m_value.string, ensure_ascii);
18260
o->write_character('\"');
18261
return;
18262
}
18263
18264
case value_t::binary:
18265
{
18266
if (pretty_print)
18267
{
18268
o->write_characters("{\n", 2);
18269
18270
// variable to hold indentation for recursive calls
18271
const auto new_indent = current_indent + indent_step;
18272
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18273
{
18274
indent_string.resize(indent_string.size() * 2, ' ');
18275
}
18276
18277
o->write_characters(indent_string.c_str(), new_indent);
18278
18279
o->write_characters("\"bytes\": [", 10);
18280
18281
if (!val.m_data.m_value.binary->empty())
18282
{
18283
for (auto i = val.m_data.m_value.binary->cbegin();
18284
i != val.m_data.m_value.binary->cend() - 1; ++i)
18285
{
18286
dump_integer(*i);
18287
o->write_characters(", ", 2);
18288
}
18289
dump_integer(val.m_data.m_value.binary->back());
18290
}
18291
18292
o->write_characters("],\n", 3);
18293
o->write_characters(indent_string.c_str(), new_indent);
18294
18295
o->write_characters("\"subtype\": ", 11);
18296
if (val.m_data.m_value.binary->has_subtype())
18297
{
18298
dump_integer(val.m_data.m_value.binary->subtype());
18299
}
18300
else
18301
{
18302
o->write_characters("null", 4);
18303
}
18304
o->write_character('\n');
18305
o->write_characters(indent_string.c_str(), current_indent);
18306
o->write_character('}');
18307
}
18308
else
18309
{
18310
o->write_characters("{\"bytes\":[", 10);
18311
18312
if (!val.m_data.m_value.binary->empty())
18313
{
18314
for (auto i = val.m_data.m_value.binary->cbegin();
18315
i != val.m_data.m_value.binary->cend() - 1; ++i)
18316
{
18317
dump_integer(*i);
18318
o->write_character(',');
18319
}
18320
dump_integer(val.m_data.m_value.binary->back());
18321
}
18322
18323
o->write_characters("],\"subtype\":", 12);
18324
if (val.m_data.m_value.binary->has_subtype())
18325
{
18326
dump_integer(val.m_data.m_value.binary->subtype());
18327
o->write_character('}');
18328
}
18329
else
18330
{
18331
o->write_characters("null}", 5);
18332
}
18333
}
18334
return;
18335
}
18336
18337
case value_t::boolean:
18338
{
18339
if (val.m_data.m_value.boolean)
18340
{
18341
o->write_characters("true", 4);
18342
}
18343
else
18344
{
18345
o->write_characters("false", 5);
18346
}
18347
return;
18348
}
18349
18350
case value_t::number_integer:
18351
{
18352
dump_integer(val.m_data.m_value.number_integer);
18353
return;
18354
}
18355
18356
case value_t::number_unsigned:
18357
{
18358
dump_integer(val.m_data.m_value.number_unsigned);
18359
return;
18360
}
18361
18362
case value_t::number_float:
18363
{
18364
dump_float(val.m_data.m_value.number_float);
18365
return;
18366
}
18367
18368
case value_t::discarded:
18369
{
18370
o->write_characters("<discarded>", 11);
18371
return;
18372
}
18373
18374
case value_t::null:
18375
{
18376
o->write_characters("null", 4);
18377
return;
18378
}
18379
18380
default: // LCOV_EXCL_LINE
18381
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18382
}
18383
}
18384
18385
JSON_PRIVATE_UNLESS_TESTED:
18386
/*!
18387
@brief dump escaped string
18388
18389
Escape a string by replacing certain special characters by a sequence of an
18390
escape character (backslash) and another character and other control
18391
characters by a sequence of "\u" followed by a four-digit hex
18392
representation. The escaped string is written to output stream @a o.
18393
18394
@param[in] s the string to escape
18395
@param[in] ensure_ascii whether to escape non-ASCII characters with
18396
\uXXXX sequences
18397
18398
@complexity Linear in the length of string @a s.
18399
*/
18400
void dump_escaped(const string_t& s, const bool ensure_ascii)
18401
{
18402
std::uint32_t codepoint{};
18403
std::uint8_t state = UTF8_ACCEPT;
18404
std::size_t bytes = 0; // number of bytes written to string_buffer
18405
18406
// number of bytes written at the point of the last valid byte
18407
std::size_t bytes_after_last_accept = 0;
18408
std::size_t undumped_chars = 0;
18409
18410
for (std::size_t i = 0; i < s.size(); ++i)
18411
{
18412
const auto byte = static_cast<std::uint8_t>(s[i]);
18413
18414
switch (decode(state, codepoint, byte))
18415
{
18416
case UTF8_ACCEPT: // decode found a new code point
18417
{
18418
switch (codepoint)
18419
{
18420
case 0x08: // backspace
18421
{
18422
string_buffer[bytes++] = '\\';
18423
string_buffer[bytes++] = 'b';
18424
break;
18425
}
18426
18427
case 0x09: // horizontal tab
18428
{
18429
string_buffer[bytes++] = '\\';
18430
string_buffer[bytes++] = 't';
18431
break;
18432
}
18433
18434
case 0x0A: // newline
18435
{
18436
string_buffer[bytes++] = '\\';
18437
string_buffer[bytes++] = 'n';
18438
break;
18439
}
18440
18441
case 0x0C: // formfeed
18442
{
18443
string_buffer[bytes++] = '\\';
18444
string_buffer[bytes++] = 'f';
18445
break;
18446
}
18447
18448
case 0x0D: // carriage return
18449
{
18450
string_buffer[bytes++] = '\\';
18451
string_buffer[bytes++] = 'r';
18452
break;
18453
}
18454
18455
case 0x22: // quotation mark
18456
{
18457
string_buffer[bytes++] = '\\';
18458
string_buffer[bytes++] = '\"';
18459
break;
18460
}
18461
18462
case 0x5C: // reverse solidus
18463
{
18464
string_buffer[bytes++] = '\\';
18465
string_buffer[bytes++] = '\\';
18466
break;
18467
}
18468
18469
default:
18470
{
18471
// escape control characters (0x00..0x1F) or, if
18472
// ensure_ascii parameter is used, non-ASCII characters
18473
if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
18474
{
18475
if (codepoint <= 0xFFFF)
18476
{
18477
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18478
static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
18479
static_cast<std::uint16_t>(codepoint)));
18480
bytes += 6;
18481
}
18482
else
18483
{
18484
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18485
static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
18486
static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
18487
static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
18488
bytes += 12;
18489
}
18490
}
18491
else
18492
{
18493
// copy byte to buffer (all previous bytes
18494
// been copied have in default case above)
18495
string_buffer[bytes++] = s[i];
18496
}
18497
break;
18498
}
18499
}
18500
18501
// write buffer and reset index; there must be 13 bytes
18502
// left, as this is the maximal number of bytes to be
18503
// written ("\uxxxx\uxxxx\0") for one code point
18504
if (string_buffer.size() - bytes < 13)
18505
{
18506
o->write_characters(string_buffer.data(), bytes);
18507
bytes = 0;
18508
}
18509
18510
// remember the byte position of this accept
18511
bytes_after_last_accept = bytes;
18512
undumped_chars = 0;
18513
break;
18514
}
18515
18516
case UTF8_REJECT: // decode found invalid UTF-8 byte
18517
{
18518
switch (error_handler)
18519
{
18520
case error_handler_t::strict:
18521
{
18522
JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
18523
}
18524
18525
case error_handler_t::ignore:
18526
case error_handler_t::replace:
18527
{
18528
// in case we saw this character the first time, we
18529
// would like to read it again, because the byte
18530
// may be OK for itself, but just not OK for the
18531
// previous sequence
18532
if (undumped_chars > 0)
18533
{
18534
--i;
18535
}
18536
18537
// reset length buffer to the last accepted index;
18538
// thus removing/ignoring the invalid characters
18539
bytes = bytes_after_last_accept;
18540
18541
if (error_handler == error_handler_t::replace)
18542
{
18543
// add a replacement character
18544
if (ensure_ascii)
18545
{
18546
string_buffer[bytes++] = '\\';
18547
string_buffer[bytes++] = 'u';
18548
string_buffer[bytes++] = 'f';
18549
string_buffer[bytes++] = 'f';
18550
string_buffer[bytes++] = 'f';
18551
string_buffer[bytes++] = 'd';
18552
}
18553
else
18554
{
18555
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
18556
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
18557
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
18558
}
18559
18560
// write buffer and reset index; there must be 13 bytes
18561
// left, as this is the maximal number of bytes to be
18562
// written ("\uxxxx\uxxxx\0") for one code point
18563
if (string_buffer.size() - bytes < 13)
18564
{
18565
o->write_characters(string_buffer.data(), bytes);
18566
bytes = 0;
18567
}
18568
18569
bytes_after_last_accept = bytes;
18570
}
18571
18572
undumped_chars = 0;
18573
18574
// continue processing the string
18575
state = UTF8_ACCEPT;
18576
break;
18577
}
18578
18579
default: // LCOV_EXCL_LINE
18580
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18581
}
18582
break;
18583
}
18584
18585
default: // decode found yet incomplete multi-byte code point
18586
{
18587
if (!ensure_ascii)
18588
{
18589
// code point will not be escaped - copy byte to buffer
18590
string_buffer[bytes++] = s[i];
18591
}
18592
++undumped_chars;
18593
break;
18594
}
18595
}
18596
}
18597
18598
// we finished processing the string
18599
if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
18600
{
18601
// write buffer
18602
if (bytes > 0)
18603
{
18604
o->write_characters(string_buffer.data(), bytes);
18605
}
18606
}
18607
else
18608
{
18609
// we finish reading, but do not accept: string was incomplete
18610
switch (error_handler)
18611
{
18612
case error_handler_t::strict:
18613
{
18614
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));
18615
}
18616
18617
case error_handler_t::ignore:
18618
{
18619
// write all accepted bytes
18620
o->write_characters(string_buffer.data(), bytes_after_last_accept);
18621
break;
18622
}
18623
18624
case error_handler_t::replace:
18625
{
18626
// write all accepted bytes
18627
o->write_characters(string_buffer.data(), bytes_after_last_accept);
18628
// add a replacement character
18629
if (ensure_ascii)
18630
{
18631
o->write_characters("\\ufffd", 6);
18632
}
18633
else
18634
{
18635
o->write_characters("\xEF\xBF\xBD", 3);
18636
}
18637
break;
18638
}
18639
18640
default: // LCOV_EXCL_LINE
18641
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18642
}
18643
}
18644
}
18645
18646
private:
18647
/*!
18648
@brief count digits
18649
18650
Count the number of decimal (base 10) digits for an input unsigned integer.
18651
18652
@param[in] x unsigned integer number to count its digits
18653
@return number of decimal digits
18654
*/
18655
inline unsigned int count_digits(number_unsigned_t x) noexcept
18656
{
18657
unsigned int n_digits = 1;
18658
for (;;)
18659
{
18660
if (x < 10)
18661
{
18662
return n_digits;
18663
}
18664
if (x < 100)
18665
{
18666
return n_digits + 1;
18667
}
18668
if (x < 1000)
18669
{
18670
return n_digits + 2;
18671
}
18672
if (x < 10000)
18673
{
18674
return n_digits + 3;
18675
}
18676
x = x / 10000u;
18677
n_digits += 4;
18678
}
18679
}
18680
18681
/*!
18682
* @brief convert a byte to a uppercase hex representation
18683
* @param[in] byte byte to represent
18684
* @return representation ("00".."FF")
18685
*/
18686
static std::string hex_bytes(std::uint8_t byte)
18687
{
18688
std::string result = "FF";
18689
constexpr const char* nibble_to_hex = "0123456789ABCDEF";
18690
result[0] = nibble_to_hex[byte / 16];
18691
result[1] = nibble_to_hex[byte % 16];
18692
return result;
18693
}
18694
18695
// templates to avoid warnings about useless casts
18696
template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
18697
bool is_negative_number(NumberType x)
18698
{
18699
return x < 0;
18700
}
18701
18702
template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
18703
bool is_negative_number(NumberType /*unused*/)
18704
{
18705
return false;
18706
}
18707
18708
/*!
18709
@brief dump an integer
18710
18711
Dump a given integer to output stream @a o. Works internally with
18712
@a number_buffer.
18713
18714
@param[in] x integer number (signed or unsigned) to dump
18715
@tparam NumberType either @a number_integer_t or @a number_unsigned_t
18716
*/
18717
template < typename NumberType, detail::enable_if_t <
18718
std::is_integral<NumberType>::value ||
18719
std::is_same<NumberType, number_unsigned_t>::value ||
18720
std::is_same<NumberType, number_integer_t>::value ||
18721
std::is_same<NumberType, binary_char_t>::value,
18722
int > = 0 >
18723
void dump_integer(NumberType x)
18724
{
18725
static constexpr std::array<std::array<char, 2>, 100> digits_to_99
18726
{
18727
{
18728
{{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
18729
{{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
18730
{{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
18731
{{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
18732
{{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
18733
{{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
18734
{{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
18735
{{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
18736
{{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
18737
{{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
18738
}
18739
};
18740
18741
// special case for "0"
18742
if (x == 0)
18743
{
18744
o->write_character('0');
18745
return;
18746
}
18747
18748
// use a pointer to fill the buffer
18749
auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18750
18751
number_unsigned_t abs_value;
18752
18753
unsigned int n_chars{};
18754
18755
if (is_negative_number(x))
18756
{
18757
*buffer_ptr = '-';
18758
abs_value = remove_sign(static_cast<number_integer_t>(x));
18759
18760
// account one more byte for the minus sign
18761
n_chars = 1 + count_digits(abs_value);
18762
}
18763
else
18764
{
18765
abs_value = static_cast<number_unsigned_t>(x);
18766
n_chars = count_digits(abs_value);
18767
}
18768
18769
// spare 1 byte for '\0'
18770
JSON_ASSERT(n_chars < number_buffer.size() - 1);
18771
18772
// jump to the end to generate the string from backward,
18773
// so we later avoid reversing the result
18774
buffer_ptr += n_chars;
18775
18776
// Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
18777
// See: https://www.youtube.com/watch?v=o4-CwDo2zpg
18778
while (abs_value >= 100)
18779
{
18780
const auto digits_index = static_cast<unsigned>((abs_value % 100));
18781
abs_value /= 100;
18782
*(--buffer_ptr) = digits_to_99[digits_index][1];
18783
*(--buffer_ptr) = digits_to_99[digits_index][0];
18784
}
18785
18786
if (abs_value >= 10)
18787
{
18788
const auto digits_index = static_cast<unsigned>(abs_value);
18789
*(--buffer_ptr) = digits_to_99[digits_index][1];
18790
*(--buffer_ptr) = digits_to_99[digits_index][0];
18791
}
18792
else
18793
{
18794
*(--buffer_ptr) = static_cast<char>('0' + abs_value);
18795
}
18796
18797
o->write_characters(number_buffer.data(), n_chars);
18798
}
18799
18800
/*!
18801
@brief dump a floating-point number
18802
18803
Dump a given floating-point number to output stream @a o. Works internally
18804
with @a number_buffer.
18805
18806
@param[in] x floating-point number to dump
18807
*/
18808
void dump_float(number_float_t x)
18809
{
18810
// NaN / inf
18811
if (!std::isfinite(x))
18812
{
18813
o->write_characters("null", 4);
18814
return;
18815
}
18816
18817
// If number_float_t is an IEEE-754 single or double precision number,
18818
// use the Grisu2 algorithm to produce short numbers which are
18819
// guaranteed to round-trip, using strtof and strtod, resp.
18820
//
18821
// NB: The test below works if <long double> == <double>.
18822
static constexpr bool is_ieee_single_or_double
18823
= (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) ||
18824
(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);
18825
18826
dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
18827
}
18828
18829
void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
18830
{
18831
auto* begin = number_buffer.data();
18832
auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
18833
18834
o->write_characters(begin, static_cast<size_t>(end - begin));
18835
}
18836
18837
void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
18838
{
18839
// get number of digits for a float -> text -> float round-trip
18840
static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
18841
18842
// the actual conversion
18843
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18844
std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
18845
18846
// negative value indicates an error
18847
JSON_ASSERT(len > 0);
18848
// check if buffer was large enough
18849
JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
18850
18851
// erase thousands separator
18852
if (thousands_sep != '\0')
18853
{
18854
// NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
18855
const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
18856
std::fill(end, number_buffer.end(), '\0');
18857
JSON_ASSERT((end - number_buffer.begin()) <= len);
18858
len = (end - number_buffer.begin());
18859
}
18860
18861
// convert decimal point to '.'
18862
if (decimal_point != '\0' && decimal_point != '.')
18863
{
18864
// NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
18865
const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
18866
if (dec_pos != number_buffer.end())
18867
{
18868
*dec_pos = '.';
18869
}
18870
}
18871
18872
o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
18873
18874
// determine if we need to append ".0"
18875
const bool value_is_int_like =
18876
std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
18877
[](char c)
18878
{
18879
return c == '.' || c == 'e';
18880
});
18881
18882
if (value_is_int_like)
18883
{
18884
o->write_characters(".0", 2);
18885
}
18886
}
18887
18888
/*!
18889
@brief check whether a string is UTF-8 encoded
18890
18891
The function checks each byte of a string whether it is UTF-8 encoded. The
18892
result of the check is stored in the @a state parameter. The function must
18893
be called initially with state 0 (accept). State 1 means the string must
18894
be rejected, because the current byte is not allowed. If the string is
18895
completely processed, but the state is non-zero, the string ended
18896
prematurely; that is, the last byte indicated more bytes should have
18897
followed.
18898
18899
@param[in,out] state the state of the decoding
18900
@param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
18901
@param[in] byte next byte to decode
18902
@return new state
18903
18904
@note The function has been edited: a std::array is used.
18905
18906
@copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <[email protected]>
18907
@sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
18908
*/
18909
static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
18910
{
18911
static const std::array<std::uint8_t, 400> utf8d =
18912
{
18913
{
18914
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
18915
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
18916
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
18917
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
18918
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
18919
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
18920
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
18921
0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
18922
0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
18923
0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
18924
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
18925
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
18926
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
18927
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
18928
}
18929
};
18930
18931
JSON_ASSERT(byte < utf8d.size());
18932
const std::uint8_t type = utf8d[byte];
18933
18934
codep = (state != UTF8_ACCEPT)
18935
? (byte & 0x3fu) | (codep << 6u)
18936
: (0xFFu >> type) & (byte);
18937
18938
const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
18939
JSON_ASSERT(index < utf8d.size());
18940
state = utf8d[index];
18941
return state;
18942
}
18943
18944
/*
18945
* Overload to make the compiler happy while it is instantiating
18946
* dump_integer for number_unsigned_t.
18947
* Must never be called.
18948
*/
18949
number_unsigned_t remove_sign(number_unsigned_t x)
18950
{
18951
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18952
return x; // LCOV_EXCL_LINE
18953
}
18954
18955
/*
18956
* Helper function for dump_integer
18957
*
18958
* This function takes a negative signed integer and returns its absolute
18959
* value as unsigned integer. The plus/minus shuffling is necessary as we can
18960
* not directly remove the sign of an arbitrary signed integer as the
18961
* absolute values of INT_MIN and INT_MAX are usually not the same. See
18962
* #1708 for details.
18963
*/
18964
inline number_unsigned_t remove_sign(number_integer_t x) noexcept
18965
{
18966
JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
18967
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
18968
}
18969
18970
private:
18971
/// the output of the serializer
18972
output_adapter_t<char> o = nullptr;
18973
18974
/// a (hopefully) large enough character buffer
18975
std::array<char, 64> number_buffer{{}};
18976
18977
/// the locale
18978
const std::lconv* loc = nullptr;
18979
/// the locale's thousand separator character
18980
const char thousands_sep = '\0';
18981
/// the locale's decimal point character
18982
const char decimal_point = '\0';
18983
18984
/// string buffer
18985
std::array<char, 512> string_buffer{{}};
18986
18987
/// the indentation character
18988
const char indent_char;
18989
/// the indentation string
18990
string_t indent_string;
18991
18992
/// error_handler how to react on decoding errors
18993
const error_handler_t error_handler;
18994
};
18995
18996
} // namespace detail
18997
NLOHMANN_JSON_NAMESPACE_END
18998
18999
// #include <nlohmann/detail/value_t.hpp>
19000
19001
// #include <nlohmann/json_fwd.hpp>
19002
19003
// #include <nlohmann/ordered_map.hpp>
19004
// __ _____ _____ _____
19005
// __| | __| | | | JSON for Modern C++
19006
// | | |__ | | | | | | version 3.11.3
19007
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
19008
//
19009
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
19010
// SPDX-License-Identifier: MIT
19011
19012
19013
19014
#include <functional> // equal_to, less
19015
#include <initializer_list> // initializer_list
19016
#include <iterator> // input_iterator_tag, iterator_traits
19017
#include <memory> // allocator
19018
#include <stdexcept> // for out_of_range
19019
#include <type_traits> // enable_if, is_convertible
19020
#include <utility> // pair
19021
#include <vector> // vector
19022
19023
// #include <nlohmann/detail/macro_scope.hpp>
19024
19025
// #include <nlohmann/detail/meta/type_traits.hpp>
19026
19027
19028
NLOHMANN_JSON_NAMESPACE_BEGIN
19029
19030
/// ordered_map: a minimal map-like container that preserves insertion order
19031
/// for use within nlohmann::basic_json<ordered_map>
19032
template <class Key, class T, class IgnoredLess = std::less<Key>,
19033
class Allocator = std::allocator<std::pair<const Key, T>>>
19034
struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19035
{
19036
using key_type = Key;
19037
using mapped_type = T;
19038
using Container = std::vector<std::pair<const Key, T>, Allocator>;
19039
using iterator = typename Container::iterator;
19040
using const_iterator = typename Container::const_iterator;
19041
using size_type = typename Container::size_type;
19042
using value_type = typename Container::value_type;
19043
#ifdef JSON_HAS_CPP_14
19044
using key_compare = std::equal_to<>;
19045
#else
19046
using key_compare = std::equal_to<Key>;
19047
#endif
19048
19049
// Explicit constructors instead of `using Container::Container`
19050
// otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19051
ordered_map() noexcept(noexcept(Container())) : Container{} {}
19052
explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19053
template <class It>
19054
ordered_map(It first, It last, const Allocator& alloc = Allocator())
19055
: Container{first, last, alloc} {}
19056
ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19057
: Container{init, alloc} {}
19058
19059
std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19060
{
19061
for (auto it = this->begin(); it != this->end(); ++it)
19062
{
19063
if (m_compare(it->first, key))
19064
{
19065
return {it, false};
19066
}
19067
}
19068
Container::emplace_back(key, std::forward<T>(t));
19069
return {std::prev(this->end()), true};
19070
}
19071
19072
template<class KeyType, detail::enable_if_t<
19073
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19074
std::pair<iterator, bool> emplace(KeyType && key, T && t)
19075
{
19076
for (auto it = this->begin(); it != this->end(); ++it)
19077
{
19078
if (m_compare(it->first, key))
19079
{
19080
return {it, false};
19081
}
19082
}
19083
Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19084
return {std::prev(this->end()), true};
19085
}
19086
19087
T& operator[](const key_type& key)
19088
{
19089
return emplace(key, T{}).first->second;
19090
}
19091
19092
template<class KeyType, detail::enable_if_t<
19093
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19094
T & operator[](KeyType && key)
19095
{
19096
return emplace(std::forward<KeyType>(key), T{}).first->second;
19097
}
19098
19099
const T& operator[](const key_type& key) const
19100
{
19101
return at(key);
19102
}
19103
19104
template<class KeyType, detail::enable_if_t<
19105
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19106
const T & operator[](KeyType && key) const
19107
{
19108
return at(std::forward<KeyType>(key));
19109
}
19110
19111
T& at(const key_type& key)
19112
{
19113
for (auto it = this->begin(); it != this->end(); ++it)
19114
{
19115
if (m_compare(it->first, key))
19116
{
19117
return it->second;
19118
}
19119
}
19120
19121
JSON_THROW(std::out_of_range("key not found"));
19122
}
19123
19124
template<class KeyType, detail::enable_if_t<
19125
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19126
T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19127
{
19128
for (auto it = this->begin(); it != this->end(); ++it)
19129
{
19130
if (m_compare(it->first, key))
19131
{
19132
return it->second;
19133
}
19134
}
19135
19136
JSON_THROW(std::out_of_range("key not found"));
19137
}
19138
19139
const T& at(const key_type& key) const
19140
{
19141
for (auto it = this->begin(); it != this->end(); ++it)
19142
{
19143
if (m_compare(it->first, key))
19144
{
19145
return it->second;
19146
}
19147
}
19148
19149
JSON_THROW(std::out_of_range("key not found"));
19150
}
19151
19152
template<class KeyType, detail::enable_if_t<
19153
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19154
const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19155
{
19156
for (auto it = this->begin(); it != this->end(); ++it)
19157
{
19158
if (m_compare(it->first, key))
19159
{
19160
return it->second;
19161
}
19162
}
19163
19164
JSON_THROW(std::out_of_range("key not found"));
19165
}
19166
19167
size_type erase(const key_type& key)
19168
{
19169
for (auto it = this->begin(); it != this->end(); ++it)
19170
{
19171
if (m_compare(it->first, key))
19172
{
19173
// Since we cannot move const Keys, re-construct them in place
19174
for (auto next = it; ++next != this->end(); ++it)
19175
{
19176
it->~value_type(); // Destroy but keep allocation
19177
new (&*it) value_type{std::move(*next)};
19178
}
19179
Container::pop_back();
19180
return 1;
19181
}
19182
}
19183
return 0;
19184
}
19185
19186
template<class KeyType, detail::enable_if_t<
19187
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19188
size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19189
{
19190
for (auto it = this->begin(); it != this->end(); ++it)
19191
{
19192
if (m_compare(it->first, key))
19193
{
19194
// Since we cannot move const Keys, re-construct them in place
19195
for (auto next = it; ++next != this->end(); ++it)
19196
{
19197
it->~value_type(); // Destroy but keep allocation
19198
new (&*it) value_type{std::move(*next)};
19199
}
19200
Container::pop_back();
19201
return 1;
19202
}
19203
}
19204
return 0;
19205
}
19206
19207
iterator erase(iterator pos)
19208
{
19209
return erase(pos, std::next(pos));
19210
}
19211
19212
iterator erase(iterator first, iterator last)
19213
{
19214
if (first == last)
19215
{
19216
return first;
19217
}
19218
19219
const auto elements_affected = std::distance(first, last);
19220
const auto offset = std::distance(Container::begin(), first);
19221
19222
// This is the start situation. We need to delete elements_affected
19223
// elements (3 in this example: e, f, g), and need to return an
19224
// iterator past the last deleted element (h in this example).
19225
// Note that offset is the distance from the start of the vector
19226
// to first. We will need this later.
19227
19228
// [ a, b, c, d, e, f, g, h, i, j ]
19229
// ^ ^
19230
// first last
19231
19232
// Since we cannot move const Keys, we re-construct them in place.
19233
// We start at first and re-construct (viz. copy) the elements from
19234
// the back of the vector. Example for first iteration:
19235
19236
// ,--------.
19237
// v | destroy e and re-construct with h
19238
// [ a, b, c, d, e, f, g, h, i, j ]
19239
// ^ ^
19240
// it it + elements_affected
19241
19242
for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
19243
{
19244
it->~value_type(); // destroy but keep allocation
19245
new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
19246
}
19247
19248
// [ a, b, c, d, h, i, j, h, i, j ]
19249
// ^ ^
19250
// first last
19251
19252
// remove the unneeded elements at the end of the vector
19253
Container::resize(this->size() - static_cast<size_type>(elements_affected));
19254
19255
// [ a, b, c, d, h, i, j ]
19256
// ^ ^
19257
// first last
19258
19259
// first is now pointing past the last deleted element, but we cannot
19260
// use this iterator, because it may have been invalidated by the
19261
// resize call. Instead, we can return begin() + offset.
19262
return Container::begin() + offset;
19263
}
19264
19265
size_type count(const key_type& key) const
19266
{
19267
for (auto it = this->begin(); it != this->end(); ++it)
19268
{
19269
if (m_compare(it->first, key))
19270
{
19271
return 1;
19272
}
19273
}
19274
return 0;
19275
}
19276
19277
template<class KeyType, detail::enable_if_t<
19278
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19279
size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19280
{
19281
for (auto it = this->begin(); it != this->end(); ++it)
19282
{
19283
if (m_compare(it->first, key))
19284
{
19285
return 1;
19286
}
19287
}
19288
return 0;
19289
}
19290
19291
iterator find(const key_type& key)
19292
{
19293
for (auto it = this->begin(); it != this->end(); ++it)
19294
{
19295
if (m_compare(it->first, key))
19296
{
19297
return it;
19298
}
19299
}
19300
return Container::end();
19301
}
19302
19303
template<class KeyType, detail::enable_if_t<
19304
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19305
iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19306
{
19307
for (auto it = this->begin(); it != this->end(); ++it)
19308
{
19309
if (m_compare(it->first, key))
19310
{
19311
return it;
19312
}
19313
}
19314
return Container::end();
19315
}
19316
19317
const_iterator find(const key_type& key) const
19318
{
19319
for (auto it = this->begin(); it != this->end(); ++it)
19320
{
19321
if (m_compare(it->first, key))
19322
{
19323
return it;
19324
}
19325
}
19326
return Container::end();
19327
}
19328
19329
std::pair<iterator, bool> insert( value_type&& value )
19330
{
19331
return emplace(value.first, std::move(value.second));
19332
}
19333
19334
std::pair<iterator, bool> insert( const value_type& value )
19335
{
19336
for (auto it = this->begin(); it != this->end(); ++it)
19337
{
19338
if (m_compare(it->first, value.first))
19339
{
19340
return {it, false};
19341
}
19342
}
19343
Container::push_back(value);
19344
return {--this->end(), true};
19345
}
19346
19347
template<typename InputIt>
19348
using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
19349
std::input_iterator_tag>::value>::type;
19350
19351
template<typename InputIt, typename = require_input_iter<InputIt>>
19352
void insert(InputIt first, InputIt last)
19353
{
19354
for (auto it = first; it != last; ++it)
19355
{
19356
insert(*it);
19357
}
19358
}
19359
19360
private:
19361
JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
19362
};
19363
19364
NLOHMANN_JSON_NAMESPACE_END
19365
19366
19367
#if defined(JSON_HAS_CPP_17)
19368
#if JSON_HAS_STATIC_RTTI
19369
#include <any>
19370
#endif
19371
#include <string_view>
19372
#endif
19373
19374
/*!
19375
@brief namespace for Niels Lohmann
19376
@see https://github.com/nlohmann
19377
@since version 1.0.0
19378
*/
19379
NLOHMANN_JSON_NAMESPACE_BEGIN
19380
19381
/*!
19382
@brief a class to store JSON values
19383
19384
@internal
19385
@invariant The member variables @a m_value and @a m_type have the following
19386
relationship:
19387
- If `m_type == value_t::object`, then `m_value.object != nullptr`.
19388
- If `m_type == value_t::array`, then `m_value.array != nullptr`.
19389
- If `m_type == value_t::string`, then `m_value.string != nullptr`.
19390
The invariants are checked by member function assert_invariant().
19391
19392
@note ObjectType trick from https://stackoverflow.com/a/9860911
19393
@endinternal
19394
19395
@since version 1.0.0
19396
19397
@nosubgrouping
19398
*/
19399
NLOHMANN_BASIC_JSON_TPL_DECLARATION
19400
class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
19401
: public ::nlohmann::detail::json_base_class<CustomBaseClass>
19402
{
19403
private:
19404
template<detail::value_t> friend struct detail::external_constructor;
19405
19406
template<typename>
19407
friend class ::nlohmann::json_pointer;
19408
// can be restored when json_pointer backwards compatibility is removed
19409
// friend ::nlohmann::json_pointer<StringType>;
19410
19411
template<typename BasicJsonType, typename InputType>
19412
friend class ::nlohmann::detail::parser;
19413
friend ::nlohmann::detail::serializer<basic_json>;
19414
template<typename BasicJsonType>
19415
friend class ::nlohmann::detail::iter_impl;
19416
template<typename BasicJsonType, typename CharType>
19417
friend class ::nlohmann::detail::binary_writer;
19418
template<typename BasicJsonType, typename InputType, typename SAX>
19419
friend class ::nlohmann::detail::binary_reader;
19420
template<typename BasicJsonType>
19421
friend class ::nlohmann::detail::json_sax_dom_parser;
19422
template<typename BasicJsonType>
19423
friend class ::nlohmann::detail::json_sax_dom_callback_parser;
19424
friend class ::nlohmann::detail::exception;
19425
19426
/// workaround type for MSVC
19427
using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
19428
using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
19429
19430
JSON_PRIVATE_UNLESS_TESTED:
19431
// convenience aliases for types residing in namespace detail;
19432
using lexer = ::nlohmann::detail::lexer_base<basic_json>;
19433
19434
template<typename InputAdapterType>
19435
static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
19436
InputAdapterType adapter,
19437
detail::parser_callback_t<basic_json>cb = nullptr,
19438
const bool allow_exceptions = true,
19439
const bool ignore_comments = false
19440
)
19441
{
19442
return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
19443
std::move(cb), allow_exceptions, ignore_comments);
19444
}
19445
19446
private:
19447
using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
19448
template<typename BasicJsonType>
19449
using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
19450
template<typename BasicJsonType>
19451
using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
19452
template<typename Iterator>
19453
using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
19454
template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
19455
19456
template<typename CharType>
19457
using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
19458
19459
template<typename InputType>
19460
using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
19461
template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
19462
19463
JSON_PRIVATE_UNLESS_TESTED:
19464
using serializer = ::nlohmann::detail::serializer<basic_json>;
19465
19466
public:
19467
using value_t = detail::value_t;
19468
/// JSON Pointer, see @ref nlohmann::json_pointer
19469
using json_pointer = ::nlohmann::json_pointer<StringType>;
19470
template<typename T, typename SFINAE>
19471
using json_serializer = JSONSerializer<T, SFINAE>;
19472
/// how to treat decoding errors
19473
using error_handler_t = detail::error_handler_t;
19474
/// how to treat CBOR tags
19475
using cbor_tag_handler_t = detail::cbor_tag_handler_t;
19476
/// helper type for initializer lists of basic_json values
19477
using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
19478
19479
using input_format_t = detail::input_format_t;
19480
/// SAX interface type, see @ref nlohmann::json_sax
19481
using json_sax_t = json_sax<basic_json>;
19482
19483
////////////////
19484
// exceptions //
19485
////////////////
19486
19487
/// @name exceptions
19488
/// Classes to implement user-defined exceptions.
19489
/// @{
19490
19491
using exception = detail::exception;
19492
using parse_error = detail::parse_error;
19493
using invalid_iterator = detail::invalid_iterator;
19494
using type_error = detail::type_error;
19495
using out_of_range = detail::out_of_range;
19496
using other_error = detail::other_error;
19497
19498
/// @}
19499
19500
/////////////////////
19501
// container types //
19502
/////////////////////
19503
19504
/// @name container types
19505
/// The canonic container types to use @ref basic_json like any other STL
19506
/// container.
19507
/// @{
19508
19509
/// the type of elements in a basic_json container
19510
using value_type = basic_json;
19511
19512
/// the type of an element reference
19513
using reference = value_type&;
19514
/// the type of an element const reference
19515
using const_reference = const value_type&;
19516
19517
/// a type to represent differences between iterators
19518
using difference_type = std::ptrdiff_t;
19519
/// a type to represent container sizes
19520
using size_type = std::size_t;
19521
19522
/// the allocator type
19523
using allocator_type = AllocatorType<basic_json>;
19524
19525
/// the type of an element pointer
19526
using pointer = typename std::allocator_traits<allocator_type>::pointer;
19527
/// the type of an element const pointer
19528
using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
19529
19530
/// an iterator for a basic_json container
19531
using iterator = iter_impl<basic_json>;
19532
/// a const iterator for a basic_json container
19533
using const_iterator = iter_impl<const basic_json>;
19534
/// a reverse iterator for a basic_json container
19535
using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
19536
/// a const reverse iterator for a basic_json container
19537
using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
19538
19539
/// @}
19540
19541
/// @brief returns the allocator associated with the container
19542
/// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
19543
static allocator_type get_allocator()
19544
{
19545
return allocator_type();
19546
}
19547
19548
/// @brief returns version information on the library
19549
/// @sa https://json.nlohmann.me/api/basic_json/meta/
19550
JSON_HEDLEY_WARN_UNUSED_RESULT
19551
static basic_json meta()
19552
{
19553
basic_json result;
19554
19555
result["copyright"] = "(C) 2013-2023 Niels Lohmann";
19556
result["name"] = "JSON for Modern C++";
19557
result["url"] = "https://github.com/nlohmann/json";
19558
result["version"]["string"] =
19559
detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
19560
std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
19561
std::to_string(NLOHMANN_JSON_VERSION_PATCH));
19562
result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
19563
result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
19564
result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
19565
19566
#ifdef _WIN32
19567
result["platform"] = "win32";
19568
#elif defined __linux__
19569
result["platform"] = "linux";
19570
#elif defined __APPLE__
19571
result["platform"] = "apple";
19572
#elif defined __unix__
19573
result["platform"] = "unix";
19574
#else
19575
result["platform"] = "unknown";
19576
#endif
19577
19578
#if defined(__ICC) || defined(__INTEL_COMPILER)
19579
result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
19580
#elif defined(__clang__)
19581
result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
19582
#elif defined(__GNUC__) || defined(__GNUG__)
19583
result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
19584
std::to_string(__GNUC__), '.',
19585
std::to_string(__GNUC_MINOR__), '.',
19586
std::to_string(__GNUC_PATCHLEVEL__))
19587
}
19588
};
19589
#elif defined(__HP_cc) || defined(__HP_aCC)
19590
result["compiler"] = "hp"
19591
#elif defined(__IBMCPP__)
19592
result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
19593
#elif defined(_MSC_VER)
19594
result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
19595
#elif defined(__PGI)
19596
result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
19597
#elif defined(__SUNPRO_CC)
19598
result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
19599
#else
19600
result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
19601
#endif
19602
19603
#if defined(_MSVC_LANG)
19604
result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
19605
#elif defined(__cplusplus)
19606
result["compiler"]["c++"] = std::to_string(__cplusplus);
19607
#else
19608
result["compiler"]["c++"] = "unknown";
19609
#endif
19610
return result;
19611
}
19612
19613
///////////////////////////
19614
// JSON value data types //
19615
///////////////////////////
19616
19617
/// @name JSON value data types
19618
/// The data types to store a JSON value. These types are derived from
19619
/// the template arguments passed to class @ref basic_json.
19620
/// @{
19621
19622
/// @brief default object key comparator type
19623
/// The actual object key comparator type (@ref object_comparator_t) may be
19624
/// different.
19625
/// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
19626
#if defined(JSON_HAS_CPP_14)
19627
// use of transparent comparator avoids unnecessary repeated construction of temporaries
19628
// in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
19629
using default_object_comparator_t = std::less<>;
19630
#else
19631
using default_object_comparator_t = std::less<StringType>;
19632
#endif
19633
19634
/// @brief a type for an object
19635
/// @sa https://json.nlohmann.me/api/basic_json/object_t/
19636
using object_t = ObjectType<StringType,
19637
basic_json,
19638
default_object_comparator_t,
19639
AllocatorType<std::pair<const StringType,
19640
basic_json>>>;
19641
19642
/// @brief a type for an array
19643
/// @sa https://json.nlohmann.me/api/basic_json/array_t/
19644
using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
19645
19646
/// @brief a type for a string
19647
/// @sa https://json.nlohmann.me/api/basic_json/string_t/
19648
using string_t = StringType;
19649
19650
/// @brief a type for a boolean
19651
/// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
19652
using boolean_t = BooleanType;
19653
19654
/// @brief a type for a number (integer)
19655
/// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
19656
using number_integer_t = NumberIntegerType;
19657
19658
/// @brief a type for a number (unsigned)
19659
/// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
19660
using number_unsigned_t = NumberUnsignedType;
19661
19662
/// @brief a type for a number (floating-point)
19663
/// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
19664
using number_float_t = NumberFloatType;
19665
19666
/// @brief a type for a packed binary type
19667
/// @sa https://json.nlohmann.me/api/basic_json/binary_t/
19668
using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
19669
19670
/// @brief object key comparator type
19671
/// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
19672
using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
19673
19674
/// @}
19675
19676
private:
19677
19678
/// helper for exception-safe object creation
19679
template<typename T, typename... Args>
19680
JSON_HEDLEY_RETURNS_NON_NULL
19681
static T* create(Args&& ... args)
19682
{
19683
AllocatorType<T> alloc;
19684
using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
19685
19686
auto deleter = [&](T * obj)
19687
{
19688
AllocatorTraits::deallocate(alloc, obj, 1);
19689
};
19690
std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
19691
AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
19692
JSON_ASSERT(obj != nullptr);
19693
return obj.release();
19694
}
19695
19696
////////////////////////
19697
// JSON value storage //
19698
////////////////////////
19699
19700
JSON_PRIVATE_UNLESS_TESTED:
19701
/*!
19702
@brief a JSON value
19703
19704
The actual storage for a JSON value of the @ref basic_json class. This
19705
union combines the different storage types for the JSON value types
19706
defined in @ref value_t.
19707
19708
JSON type | value_t type | used type
19709
--------- | --------------- | ------------------------
19710
object | object | pointer to @ref object_t
19711
array | array | pointer to @ref array_t
19712
string | string | pointer to @ref string_t
19713
boolean | boolean | @ref boolean_t
19714
number | number_integer | @ref number_integer_t
19715
number | number_unsigned | @ref number_unsigned_t
19716
number | number_float | @ref number_float_t
19717
binary | binary | pointer to @ref binary_t
19718
null | null | *no value is stored*
19719
19720
@note Variable-length types (objects, arrays, and strings) are stored as
19721
pointers. The size of the union should not exceed 64 bits if the default
19722
value types are used.
19723
19724
@since version 1.0.0
19725
*/
19726
union json_value
19727
{
19728
/// object (stored with pointer to save storage)
19729
object_t* object;
19730
/// array (stored with pointer to save storage)
19731
array_t* array;
19732
/// string (stored with pointer to save storage)
19733
string_t* string;
19734
/// binary (stored with pointer to save storage)
19735
binary_t* binary;
19736
/// boolean
19737
boolean_t boolean;
19738
/// number (integer)
19739
number_integer_t number_integer;
19740
/// number (unsigned integer)
19741
number_unsigned_t number_unsigned;
19742
/// number (floating-point)
19743
number_float_t number_float;
19744
19745
/// default constructor (for null values)
19746
json_value() = default;
19747
/// constructor for booleans
19748
json_value(boolean_t v) noexcept : boolean(v) {}
19749
/// constructor for numbers (integer)
19750
json_value(number_integer_t v) noexcept : number_integer(v) {}
19751
/// constructor for numbers (unsigned)
19752
json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
19753
/// constructor for numbers (floating-point)
19754
json_value(number_float_t v) noexcept : number_float(v) {}
19755
/// constructor for empty values of a given type
19756
json_value(value_t t)
19757
{
19758
switch (t)
19759
{
19760
case value_t::object:
19761
{
19762
object = create<object_t>();
19763
break;
19764
}
19765
19766
case value_t::array:
19767
{
19768
array = create<array_t>();
19769
break;
19770
}
19771
19772
case value_t::string:
19773
{
19774
string = create<string_t>("");
19775
break;
19776
}
19777
19778
case value_t::binary:
19779
{
19780
binary = create<binary_t>();
19781
break;
19782
}
19783
19784
case value_t::boolean:
19785
{
19786
boolean = static_cast<boolean_t>(false);
19787
break;
19788
}
19789
19790
case value_t::number_integer:
19791
{
19792
number_integer = static_cast<number_integer_t>(0);
19793
break;
19794
}
19795
19796
case value_t::number_unsigned:
19797
{
19798
number_unsigned = static_cast<number_unsigned_t>(0);
19799
break;
19800
}
19801
19802
case value_t::number_float:
19803
{
19804
number_float = static_cast<number_float_t>(0.0);
19805
break;
19806
}
19807
19808
case value_t::null:
19809
{
19810
object = nullptr; // silence warning, see #821
19811
break;
19812
}
19813
19814
case value_t::discarded:
19815
default:
19816
{
19817
object = nullptr; // silence warning, see #821
19818
if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
19819
{
19820
JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE
19821
}
19822
break;
19823
}
19824
}
19825
}
19826
19827
/// constructor for strings
19828
json_value(const string_t& value) : string(create<string_t>(value)) {}
19829
19830
/// constructor for rvalue strings
19831
json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
19832
19833
/// constructor for objects
19834
json_value(const object_t& value) : object(create<object_t>(value)) {}
19835
19836
/// constructor for rvalue objects
19837
json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
19838
19839
/// constructor for arrays
19840
json_value(const array_t& value) : array(create<array_t>(value)) {}
19841
19842
/// constructor for rvalue arrays
19843
json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
19844
19845
/// constructor for binary arrays
19846
json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
19847
19848
/// constructor for rvalue binary arrays
19849
json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
19850
19851
/// constructor for binary arrays (internal type)
19852
json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
19853
19854
/// constructor for rvalue binary arrays (internal type)
19855
json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
19856
19857
void destroy(value_t t)
19858
{
19859
if (
19860
(t == value_t::object && object == nullptr) ||
19861
(t == value_t::array && array == nullptr) ||
19862
(t == value_t::string && string == nullptr) ||
19863
(t == value_t::binary && binary == nullptr)
19864
)
19865
{
19866
//not initialized (e.g. due to exception in the ctor)
19867
return;
19868
}
19869
if (t == value_t::array || t == value_t::object)
19870
{
19871
// flatten the current json_value to a heap-allocated stack
19872
std::vector<basic_json> stack;
19873
19874
// move the top-level items to stack
19875
if (t == value_t::array)
19876
{
19877
stack.reserve(array->size());
19878
std::move(array->begin(), array->end(), std::back_inserter(stack));
19879
}
19880
else
19881
{
19882
stack.reserve(object->size());
19883
for (auto&& it : *object)
19884
{
19885
stack.push_back(std::move(it.second));
19886
}
19887
}
19888
19889
while (!stack.empty())
19890
{
19891
// move the last item to local variable to be processed
19892
basic_json current_item(std::move(stack.back()));
19893
stack.pop_back();
19894
19895
// if current_item is array/object, move
19896
// its children to the stack to be processed later
19897
if (current_item.is_array())
19898
{
19899
std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
19900
19901
current_item.m_data.m_value.array->clear();
19902
}
19903
else if (current_item.is_object())
19904
{
19905
for (auto&& it : *current_item.m_data.m_value.object)
19906
{
19907
stack.push_back(std::move(it.second));
19908
}
19909
19910
current_item.m_data.m_value.object->clear();
19911
}
19912
19913
// it's now safe that current_item get destructed
19914
// since it doesn't have any children
19915
}
19916
}
19917
19918
switch (t)
19919
{
19920
case value_t::object:
19921
{
19922
AllocatorType<object_t> alloc;
19923
std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
19924
std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
19925
break;
19926
}
19927
19928
case value_t::array:
19929
{
19930
AllocatorType<array_t> alloc;
19931
std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
19932
std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
19933
break;
19934
}
19935
19936
case value_t::string:
19937
{
19938
AllocatorType<string_t> alloc;
19939
std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
19940
std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
19941
break;
19942
}
19943
19944
case value_t::binary:
19945
{
19946
AllocatorType<binary_t> alloc;
19947
std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
19948
std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
19949
break;
19950
}
19951
19952
case value_t::null:
19953
case value_t::boolean:
19954
case value_t::number_integer:
19955
case value_t::number_unsigned:
19956
case value_t::number_float:
19957
case value_t::discarded:
19958
default:
19959
{
19960
break;
19961
}
19962
}
19963
}
19964
};
19965
19966
private:
19967
/*!
19968
@brief checks the class invariants
19969
19970
This function asserts the class invariants. It needs to be called at the
19971
end of every constructor to make sure that created objects respect the
19972
invariant. Furthermore, it has to be called each time the type of a JSON
19973
value is changed, because the invariant expresses a relationship between
19974
@a m_type and @a m_value.
19975
19976
Furthermore, the parent relation is checked for arrays and objects: If
19977
@a check_parents true and the value is an array or object, then the
19978
container's elements must have the current value as parent.
19979
19980
@param[in] check_parents whether the parent relation should be checked.
19981
The value is true by default and should only be set to false
19982
during destruction of objects when the invariant does not
19983
need to hold.
19984
*/
19985
void assert_invariant(bool check_parents = true) const noexcept
19986
{
19987
JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
19988
JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
19989
JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
19990
JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
19991
19992
#if JSON_DIAGNOSTICS
19993
JSON_TRY
19994
{
19995
// cppcheck-suppress assertWithSideEffect
19996
JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
19997
{
19998
return j.m_parent == this;
19999
}));
20000
}
20001
JSON_CATCH(...) {} // LCOV_EXCL_LINE
20002
#endif
20003
static_cast<void>(check_parents);
20004
}
20005
20006
void set_parents()
20007
{
20008
#if JSON_DIAGNOSTICS
20009
switch (m_data.m_type)
20010
{
20011
case value_t::array:
20012
{
20013
for (auto& element : *m_data.m_value.array)
20014
{
20015
element.m_parent = this;
20016
}
20017
break;
20018
}
20019
20020
case value_t::object:
20021
{
20022
for (auto& element : *m_data.m_value.object)
20023
{
20024
element.second.m_parent = this;
20025
}
20026
break;
20027
}
20028
20029
case value_t::null:
20030
case value_t::string:
20031
case value_t::boolean:
20032
case value_t::number_integer:
20033
case value_t::number_unsigned:
20034
case value_t::number_float:
20035
case value_t::binary:
20036
case value_t::discarded:
20037
default:
20038
break;
20039
}
20040
#endif
20041
}
20042
20043
iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20044
{
20045
#if JSON_DIAGNOSTICS
20046
for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20047
{
20048
(it + i)->m_parent = this;
20049
}
20050
#else
20051
static_cast<void>(count_set_parents);
20052
#endif
20053
return it;
20054
}
20055
20056
reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
20057
{
20058
#if JSON_DIAGNOSTICS
20059
if (old_capacity != static_cast<std::size_t>(-1))
20060
{
20061
// see https://github.com/nlohmann/json/issues/2838
20062
JSON_ASSERT(type() == value_t::array);
20063
if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20064
{
20065
// capacity has changed: update all parents
20066
set_parents();
20067
return j;
20068
}
20069
}
20070
20071
// ordered_json uses a vector internally, so pointers could have
20072
// been invalidated; see https://github.com/nlohmann/json/issues/2962
20073
#ifdef JSON_HEDLEY_MSVC_VERSION
20074
#pragma warning(push )
20075
#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20076
#endif
20077
if (detail::is_ordered_map<object_t>::value)
20078
{
20079
set_parents();
20080
return j;
20081
}
20082
#ifdef JSON_HEDLEY_MSVC_VERSION
20083
#pragma warning( pop )
20084
#endif
20085
20086
j.m_parent = this;
20087
#else
20088
static_cast<void>(j);
20089
static_cast<void>(old_capacity);
20090
#endif
20091
return j;
20092
}
20093
20094
public:
20095
//////////////////////////
20096
// JSON parser callback //
20097
//////////////////////////
20098
20099
/// @brief parser event types
20100
/// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
20101
using parse_event_t = detail::parse_event_t;
20102
20103
/// @brief per-element parser callback type
20104
/// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
20105
using parser_callback_t = detail::parser_callback_t<basic_json>;
20106
20107
//////////////////
20108
// constructors //
20109
//////////////////
20110
20111
/// @name constructors and destructors
20112
/// Constructors of class @ref basic_json, copy/move constructor, copy
20113
/// assignment, static functions creating objects, and the destructor.
20114
/// @{
20115
20116
/// @brief create an empty value with a given type
20117
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20118
basic_json(const value_t v)
20119
: m_data(v)
20120
{
20121
assert_invariant();
20122
}
20123
20124
/// @brief create a null object
20125
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20126
basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20127
: basic_json(value_t::null)
20128
{
20129
assert_invariant();
20130
}
20131
20132
/// @brief create a JSON value from compatible types
20133
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20134
template < typename CompatibleType,
20135
typename U = detail::uncvref_t<CompatibleType>,
20136
detail::enable_if_t <
20137
!detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
20138
basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20139
JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20140
std::forward<CompatibleType>(val))))
20141
{
20142
JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20143
set_parents();
20144
assert_invariant();
20145
}
20146
20147
/// @brief create a JSON value from an existing one
20148
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20149
template < typename BasicJsonType,
20150
detail::enable_if_t <
20151
detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20152
basic_json(const BasicJsonType& val)
20153
{
20154
using other_boolean_t = typename BasicJsonType::boolean_t;
20155
using other_number_float_t = typename BasicJsonType::number_float_t;
20156
using other_number_integer_t = typename BasicJsonType::number_integer_t;
20157
using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20158
using other_string_t = typename BasicJsonType::string_t;
20159
using other_object_t = typename BasicJsonType::object_t;
20160
using other_array_t = typename BasicJsonType::array_t;
20161
using other_binary_t = typename BasicJsonType::binary_t;
20162
20163
switch (val.type())
20164
{
20165
case value_t::boolean:
20166
JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20167
break;
20168
case value_t::number_float:
20169
JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20170
break;
20171
case value_t::number_integer:
20172
JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20173
break;
20174
case value_t::number_unsigned:
20175
JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20176
break;
20177
case value_t::string:
20178
JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20179
break;
20180
case value_t::object:
20181
JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20182
break;
20183
case value_t::array:
20184
JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20185
break;
20186
case value_t::binary:
20187
JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20188
break;
20189
case value_t::null:
20190
*this = nullptr;
20191
break;
20192
case value_t::discarded:
20193
m_data.m_type = value_t::discarded;
20194
break;
20195
default: // LCOV_EXCL_LINE
20196
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
20197
}
20198
JSON_ASSERT(m_data.m_type == val.type());
20199
set_parents();
20200
assert_invariant();
20201
}
20202
20203
/// @brief create a container (array or object) from an initializer list
20204
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20205
basic_json(initializer_list_t init,
20206
bool type_deduction = true,
20207
value_t manual_type = value_t::array)
20208
{
20209
// check if each element is an array with two elements whose first
20210
// element is a string
20211
bool is_an_object = std::all_of(init.begin(), init.end(),
20212
[](const detail::json_ref<basic_json>& element_ref)
20213
{
20214
// The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
20215
// (many string types can be constructed from 0 via its null-pointer guise, so we get a
20216
// broken call to op[key_type], the wrong semantics and a 4804 warning on Windows)
20217
return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
20218
});
20219
20220
// adjust type if type deduction is not wanted
20221
if (!type_deduction)
20222
{
20223
// if array is wanted, do not create an object though possible
20224
if (manual_type == value_t::array)
20225
{
20226
is_an_object = false;
20227
}
20228
20229
// if object is wanted but impossible, throw an exception
20230
if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
20231
{
20232
JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
20233
}
20234
}
20235
20236
if (is_an_object)
20237
{
20238
// the initializer list is a list of pairs -> create object
20239
m_data.m_type = value_t::object;
20240
m_data.m_value = value_t::object;
20241
20242
for (auto& element_ref : init)
20243
{
20244
auto element = element_ref.moved_or_copied();
20245
m_data.m_value.object->emplace(
20246
std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
20247
std::move((*element.m_data.m_value.array)[1]));
20248
}
20249
}
20250
else
20251
{
20252
// the initializer list describes an array -> create array
20253
m_data.m_type = value_t::array;
20254
m_data.m_value.array = create<array_t>(init.begin(), init.end());
20255
}
20256
20257
set_parents();
20258
assert_invariant();
20259
}
20260
20261
/// @brief explicitly create a binary array (without subtype)
20262
/// @sa https://json.nlohmann.me/api/basic_json/binary/
20263
JSON_HEDLEY_WARN_UNUSED_RESULT
20264
static basic_json binary(const typename binary_t::container_type& init)
20265
{
20266
auto res = basic_json();
20267
res.m_data.m_type = value_t::binary;
20268
res.m_data.m_value = init;
20269
return res;
20270
}
20271
20272
/// @brief explicitly create a binary array (with subtype)
20273
/// @sa https://json.nlohmann.me/api/basic_json/binary/
20274
JSON_HEDLEY_WARN_UNUSED_RESULT
20275
static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
20276
{
20277
auto res = basic_json();
20278
res.m_data.m_type = value_t::binary;
20279
res.m_data.m_value = binary_t(init, subtype);
20280
return res;
20281
}
20282
20283
/// @brief explicitly create a binary array
20284
/// @sa https://json.nlohmann.me/api/basic_json/binary/
20285
JSON_HEDLEY_WARN_UNUSED_RESULT
20286
static basic_json binary(typename binary_t::container_type&& init)
20287
{
20288
auto res = basic_json();
20289
res.m_data.m_type = value_t::binary;
20290
res.m_data.m_value = std::move(init);
20291
return res;
20292
}
20293
20294
/// @brief explicitly create a binary array (with subtype)
20295
/// @sa https://json.nlohmann.me/api/basic_json/binary/
20296
JSON_HEDLEY_WARN_UNUSED_RESULT
20297
static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
20298
{
20299
auto res = basic_json();
20300
res.m_data.m_type = value_t::binary;
20301
res.m_data.m_value = binary_t(std::move(init), subtype);
20302
return res;
20303
}
20304
20305
/// @brief explicitly create an array from an initializer list
20306
/// @sa https://json.nlohmann.me/api/basic_json/array/
20307
JSON_HEDLEY_WARN_UNUSED_RESULT
20308
static basic_json array(initializer_list_t init = {})
20309
{
20310
return basic_json(init, false, value_t::array);
20311
}
20312
20313
/// @brief explicitly create an object from an initializer list
20314
/// @sa https://json.nlohmann.me/api/basic_json/object/
20315
JSON_HEDLEY_WARN_UNUSED_RESULT
20316
static basic_json object(initializer_list_t init = {})
20317
{
20318
return basic_json(init, false, value_t::object);
20319
}
20320
20321
/// @brief construct an array with count copies of given value
20322
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20323
basic_json(size_type cnt, const basic_json& val):
20324
m_data{cnt, val}
20325
{
20326
set_parents();
20327
assert_invariant();
20328
}
20329
20330
/// @brief construct a JSON container given an iterator range
20331
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20332
template < class InputIT, typename std::enable_if <
20333
std::is_same<InputIT, typename basic_json_t::iterator>::value ||
20334
std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
20335
basic_json(InputIT first, InputIT last)
20336
{
20337
JSON_ASSERT(first.m_object != nullptr);
20338
JSON_ASSERT(last.m_object != nullptr);
20339
20340
// make sure iterator fits the current value
20341
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20342
{
20343
JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
20344
}
20345
20346
// copy type from first iterator
20347
m_data.m_type = first.m_object->m_data.m_type;
20348
20349
// check if iterator range is complete for primitive values
20350
switch (m_data.m_type)
20351
{
20352
case value_t::boolean:
20353
case value_t::number_float:
20354
case value_t::number_integer:
20355
case value_t::number_unsigned:
20356
case value_t::string:
20357
{
20358
if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
20359
|| !last.m_it.primitive_iterator.is_end()))
20360
{
20361
JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
20362
}
20363
break;
20364
}
20365
20366
case value_t::null:
20367
case value_t::object:
20368
case value_t::array:
20369
case value_t::binary:
20370
case value_t::discarded:
20371
default:
20372
break;
20373
}
20374
20375
switch (m_data.m_type)
20376
{
20377
case value_t::number_integer:
20378
{
20379
m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
20380
break;
20381
}
20382
20383
case value_t::number_unsigned:
20384
{
20385
m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
20386
break;
20387
}
20388
20389
case value_t::number_float:
20390
{
20391
m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
20392
break;
20393
}
20394
20395
case value_t::boolean:
20396
{
20397
m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
20398
break;
20399
}
20400
20401
case value_t::string:
20402
{
20403
m_data.m_value = *first.m_object->m_data.m_value.string;
20404
break;
20405
}
20406
20407
case value_t::object:
20408
{
20409
m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
20410
last.m_it.object_iterator);
20411
break;
20412
}
20413
20414
case value_t::array:
20415
{
20416
m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
20417
last.m_it.array_iterator);
20418
break;
20419
}
20420
20421
case value_t::binary:
20422
{
20423
m_data.m_value = *first.m_object->m_data.m_value.binary;
20424
break;
20425
}
20426
20427
case value_t::null:
20428
case value_t::discarded:
20429
default:
20430
JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
20431
}
20432
20433
set_parents();
20434
assert_invariant();
20435
}
20436
20437
///////////////////////////////////////
20438
// other constructors and destructor //
20439
///////////////////////////////////////
20440
20441
template<typename JsonRef,
20442
detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
20443
std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
20444
basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
20445
20446
/// @brief copy constructor
20447
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20448
basic_json(const basic_json& other)
20449
: json_base_class_t(other)
20450
{
20451
m_data.m_type = other.m_data.m_type;
20452
// check of passed value is valid
20453
other.assert_invariant();
20454
20455
switch (m_data.m_type)
20456
{
20457
case value_t::object:
20458
{
20459
m_data.m_value = *other.m_data.m_value.object;
20460
break;
20461
}
20462
20463
case value_t::array:
20464
{
20465
m_data.m_value = *other.m_data.m_value.array;
20466
break;
20467
}
20468
20469
case value_t::string:
20470
{
20471
m_data.m_value = *other.m_data.m_value.string;
20472
break;
20473
}
20474
20475
case value_t::boolean:
20476
{
20477
m_data.m_value = other.m_data.m_value.boolean;
20478
break;
20479
}
20480
20481
case value_t::number_integer:
20482
{
20483
m_data.m_value = other.m_data.m_value.number_integer;
20484
break;
20485
}
20486
20487
case value_t::number_unsigned:
20488
{
20489
m_data.m_value = other.m_data.m_value.number_unsigned;
20490
break;
20491
}
20492
20493
case value_t::number_float:
20494
{
20495
m_data.m_value = other.m_data.m_value.number_float;
20496
break;
20497
}
20498
20499
case value_t::binary:
20500
{
20501
m_data.m_value = *other.m_data.m_value.binary;
20502
break;
20503
}
20504
20505
case value_t::null:
20506
case value_t::discarded:
20507
default:
20508
break;
20509
}
20510
20511
set_parents();
20512
assert_invariant();
20513
}
20514
20515
/// @brief move constructor
20516
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20517
basic_json(basic_json&& other) noexcept
20518
: json_base_class_t(std::forward<json_base_class_t>(other)),
20519
m_data(std::move(other.m_data))
20520
{
20521
// check that passed value is valid
20522
other.assert_invariant(false);
20523
20524
// invalidate payload
20525
other.m_data.m_type = value_t::null;
20526
other.m_data.m_value = {};
20527
20528
set_parents();
20529
assert_invariant();
20530
}
20531
20532
/// @brief copy assignment
20533
/// @sa https://json.nlohmann.me/api/basic_json/operator=/
20534
basic_json& operator=(basic_json other) noexcept (
20535
std::is_nothrow_move_constructible<value_t>::value&&
20536
std::is_nothrow_move_assignable<value_t>::value&&
20537
std::is_nothrow_move_constructible<json_value>::value&&
20538
std::is_nothrow_move_assignable<json_value>::value&&
20539
std::is_nothrow_move_assignable<json_base_class_t>::value
20540
)
20541
{
20542
// check that passed value is valid
20543
other.assert_invariant();
20544
20545
using std::swap;
20546
swap(m_data.m_type, other.m_data.m_type);
20547
swap(m_data.m_value, other.m_data.m_value);
20548
json_base_class_t::operator=(std::move(other));
20549
20550
set_parents();
20551
assert_invariant();
20552
return *this;
20553
}
20554
20555
/// @brief destructor
20556
/// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
20557
~basic_json() noexcept
20558
{
20559
assert_invariant(false);
20560
}
20561
20562
/// @}
20563
20564
public:
20565
///////////////////////
20566
// object inspection //
20567
///////////////////////
20568
20569
/// @name object inspection
20570
/// Functions to inspect the type of a JSON value.
20571
/// @{
20572
20573
/// @brief serialization
20574
/// @sa https://json.nlohmann.me/api/basic_json/dump/
20575
string_t dump(const int indent = -1,
20576
const char indent_char = ' ',
20577
const bool ensure_ascii = false,
20578
const error_handler_t error_handler = error_handler_t::strict) const
20579
{
20580
string_t result;
20581
serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
20582
20583
if (indent >= 0)
20584
{
20585
s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
20586
}
20587
else
20588
{
20589
s.dump(*this, false, ensure_ascii, 0);
20590
}
20591
20592
return result;
20593
}
20594
20595
/// @brief return the type of the JSON value (explicit)
20596
/// @sa https://json.nlohmann.me/api/basic_json/type/
20597
constexpr value_t type() const noexcept
20598
{
20599
return m_data.m_type;
20600
}
20601
20602
/// @brief return whether type is primitive
20603
/// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
20604
constexpr bool is_primitive() const noexcept
20605
{
20606
return is_null() || is_string() || is_boolean() || is_number() || is_binary();
20607
}
20608
20609
/// @brief return whether type is structured
20610
/// @sa https://json.nlohmann.me/api/basic_json/is_structured/
20611
constexpr bool is_structured() const noexcept
20612
{
20613
return is_array() || is_object();
20614
}
20615
20616
/// @brief return whether value is null
20617
/// @sa https://json.nlohmann.me/api/basic_json/is_null/
20618
constexpr bool is_null() const noexcept
20619
{
20620
return m_data.m_type == value_t::null;
20621
}
20622
20623
/// @brief return whether value is a boolean
20624
/// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
20625
constexpr bool is_boolean() const noexcept
20626
{
20627
return m_data.m_type == value_t::boolean;
20628
}
20629
20630
/// @brief return whether value is a number
20631
/// @sa https://json.nlohmann.me/api/basic_json/is_number/
20632
constexpr bool is_number() const noexcept
20633
{
20634
return is_number_integer() || is_number_float();
20635
}
20636
20637
/// @brief return whether value is an integer number
20638
/// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
20639
constexpr bool is_number_integer() const noexcept
20640
{
20641
return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
20642
}
20643
20644
/// @brief return whether value is an unsigned integer number
20645
/// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
20646
constexpr bool is_number_unsigned() const noexcept
20647
{
20648
return m_data.m_type == value_t::number_unsigned;
20649
}
20650
20651
/// @brief return whether value is a floating-point number
20652
/// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
20653
constexpr bool is_number_float() const noexcept
20654
{
20655
return m_data.m_type == value_t::number_float;
20656
}
20657
20658
/// @brief return whether value is an object
20659
/// @sa https://json.nlohmann.me/api/basic_json/is_object/
20660
constexpr bool is_object() const noexcept
20661
{
20662
return m_data.m_type == value_t::object;
20663
}
20664
20665
/// @brief return whether value is an array
20666
/// @sa https://json.nlohmann.me/api/basic_json/is_array/
20667
constexpr bool is_array() const noexcept
20668
{
20669
return m_data.m_type == value_t::array;
20670
}
20671
20672
/// @brief return whether value is a string
20673
/// @sa https://json.nlohmann.me/api/basic_json/is_string/
20674
constexpr bool is_string() const noexcept
20675
{
20676
return m_data.m_type == value_t::string;
20677
}
20678
20679
/// @brief return whether value is a binary array
20680
/// @sa https://json.nlohmann.me/api/basic_json/is_binary/
20681
constexpr bool is_binary() const noexcept
20682
{
20683
return m_data.m_type == value_t::binary;
20684
}
20685
20686
/// @brief return whether value is discarded
20687
/// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
20688
constexpr bool is_discarded() const noexcept
20689
{
20690
return m_data.m_type == value_t::discarded;
20691
}
20692
20693
/// @brief return the type of the JSON value (implicit)
20694
/// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
20695
constexpr operator value_t() const noexcept
20696
{
20697
return m_data.m_type;
20698
}
20699
20700
/// @}
20701
20702
private:
20703
//////////////////
20704
// value access //
20705
//////////////////
20706
20707
/// get a boolean (explicit)
20708
boolean_t get_impl(boolean_t* /*unused*/) const
20709
{
20710
if (JSON_HEDLEY_LIKELY(is_boolean()))
20711
{
20712
return m_data.m_value.boolean;
20713
}
20714
20715
JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
20716
}
20717
20718
/// get a pointer to the value (object)
20719
object_t* get_impl_ptr(object_t* /*unused*/) noexcept
20720
{
20721
return is_object() ? m_data.m_value.object : nullptr;
20722
}
20723
20724
/// get a pointer to the value (object)
20725
constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
20726
{
20727
return is_object() ? m_data.m_value.object : nullptr;
20728
}
20729
20730
/// get a pointer to the value (array)
20731
array_t* get_impl_ptr(array_t* /*unused*/) noexcept
20732
{
20733
return is_array() ? m_data.m_value.array : nullptr;
20734
}
20735
20736
/// get a pointer to the value (array)
20737
constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
20738
{
20739
return is_array() ? m_data.m_value.array : nullptr;
20740
}
20741
20742
/// get a pointer to the value (string)
20743
string_t* get_impl_ptr(string_t* /*unused*/) noexcept
20744
{
20745
return is_string() ? m_data.m_value.string : nullptr;
20746
}
20747
20748
/// get a pointer to the value (string)
20749
constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
20750
{
20751
return is_string() ? m_data.m_value.string : nullptr;
20752
}
20753
20754
/// get a pointer to the value (boolean)
20755
boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
20756
{
20757
return is_boolean() ? &m_data.m_value.boolean : nullptr;
20758
}
20759
20760
/// get a pointer to the value (boolean)
20761
constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
20762
{
20763
return is_boolean() ? &m_data.m_value.boolean : nullptr;
20764
}
20765
20766
/// get a pointer to the value (integer number)
20767
number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
20768
{
20769
return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20770
}
20771
20772
/// get a pointer to the value (integer number)
20773
constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
20774
{
20775
return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20776
}
20777
20778
/// get a pointer to the value (unsigned number)
20779
number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
20780
{
20781
return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20782
}
20783
20784
/// get a pointer to the value (unsigned number)
20785
constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
20786
{
20787
return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20788
}
20789
20790
/// get a pointer to the value (floating-point number)
20791
number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
20792
{
20793
return is_number_float() ? &m_data.m_value.number_float : nullptr;
20794
}
20795
20796
/// get a pointer to the value (floating-point number)
20797
constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
20798
{
20799
return is_number_float() ? &m_data.m_value.number_float : nullptr;
20800
}
20801
20802
/// get a pointer to the value (binary)
20803
binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
20804
{
20805
return is_binary() ? m_data.m_value.binary : nullptr;
20806
}
20807
20808
/// get a pointer to the value (binary)
20809
constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
20810
{
20811
return is_binary() ? m_data.m_value.binary : nullptr;
20812
}
20813
20814
/*!
20815
@brief helper function to implement get_ref()
20816
20817
This function helps to implement get_ref() without code duplication for
20818
const and non-const overloads
20819
20820
@tparam ThisType will be deduced as `basic_json` or `const basic_json`
20821
20822
@throw type_error.303 if ReferenceType does not match underlying value
20823
type of the current JSON
20824
*/
20825
template<typename ReferenceType, typename ThisType>
20826
static ReferenceType get_ref_impl(ThisType& obj)
20827
{
20828
// delegate the call to get_ptr<>()
20829
auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
20830
20831
if (JSON_HEDLEY_LIKELY(ptr != nullptr))
20832
{
20833
return *ptr;
20834
}
20835
20836
JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
20837
}
20838
20839
public:
20840
/// @name value access
20841
/// Direct access to the stored value of a JSON value.
20842
/// @{
20843
20844
/// @brief get a pointer value (implicit)
20845
/// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
20846
template<typename PointerType, typename std::enable_if<
20847
std::is_pointer<PointerType>::value, int>::type = 0>
20848
auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20849
{
20850
// delegate the call to get_impl_ptr<>()
20851
return get_impl_ptr(static_cast<PointerType>(nullptr));
20852
}
20853
20854
/// @brief get a pointer value (implicit)
20855
/// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
20856
template < typename PointerType, typename std::enable_if <
20857
std::is_pointer<PointerType>::value&&
20858
std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
20859
constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20860
{
20861
// delegate the call to get_impl_ptr<>() const
20862
return get_impl_ptr(static_cast<PointerType>(nullptr));
20863
}
20864
20865
private:
20866
/*!
20867
@brief get a value (explicit)
20868
20869
Explicit type conversion between the JSON value and a compatible value
20870
which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
20871
and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
20872
The value is converted by calling the @ref json_serializer<ValueType>
20873
`from_json()` method.
20874
20875
The function is equivalent to executing
20876
@code {.cpp}
20877
ValueType ret;
20878
JSONSerializer<ValueType>::from_json(*this, ret);
20879
return ret;
20880
@endcode
20881
20882
This overloads is chosen if:
20883
- @a ValueType is not @ref basic_json,
20884
- @ref json_serializer<ValueType> has a `from_json()` method of the form
20885
`void from_json(const basic_json&, ValueType&)`, and
20886
- @ref json_serializer<ValueType> does not have a `from_json()` method of
20887
the form `ValueType from_json(const basic_json&)`
20888
20889
@tparam ValueType the returned value type
20890
20891
@return copy of the JSON value, converted to @a ValueType
20892
20893
@throw what @ref json_serializer<ValueType> `from_json()` method throws
20894
20895
@liveexample{The example below shows several conversions from JSON values
20896
to other types. There a few things to note: (1) Floating-point numbers can
20897
be converted to integers\, (2) A JSON array can be converted to a standard
20898
`std::vector<short>`\, (3) A JSON object can be converted to C++
20899
associative containers such as `std::unordered_map<std::string\,
20900
json>`.,get__ValueType_const}
20901
20902
@since version 2.1.0
20903
*/
20904
template < typename ValueType,
20905
detail::enable_if_t <
20906
detail::is_default_constructible<ValueType>::value&&
20907
detail::has_from_json<basic_json_t, ValueType>::value,
20908
int > = 0 >
20909
ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
20910
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
20911
{
20912
auto ret = ValueType();
20913
JSONSerializer<ValueType>::from_json(*this, ret);
20914
return ret;
20915
}
20916
20917
/*!
20918
@brief get a value (explicit); special case
20919
20920
Explicit type conversion between the JSON value and a compatible value
20921
which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
20922
and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
20923
The value is converted by calling the @ref json_serializer<ValueType>
20924
`from_json()` method.
20925
20926
The function is equivalent to executing
20927
@code {.cpp}
20928
return JSONSerializer<ValueType>::from_json(*this);
20929
@endcode
20930
20931
This overloads is chosen if:
20932
- @a ValueType is not @ref basic_json and
20933
- @ref json_serializer<ValueType> has a `from_json()` method of the form
20934
`ValueType from_json(const basic_json&)`
20935
20936
@note If @ref json_serializer<ValueType> has both overloads of
20937
`from_json()`, this one is chosen.
20938
20939
@tparam ValueType the returned value type
20940
20941
@return copy of the JSON value, converted to @a ValueType
20942
20943
@throw what @ref json_serializer<ValueType> `from_json()` method throws
20944
20945
@since version 2.1.0
20946
*/
20947
template < typename ValueType,
20948
detail::enable_if_t <
20949
detail::has_non_default_from_json<basic_json_t, ValueType>::value,
20950
int > = 0 >
20951
ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
20952
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
20953
{
20954
return JSONSerializer<ValueType>::from_json(*this);
20955
}
20956
20957
/*!
20958
@brief get special-case overload
20959
20960
This overloads converts the current @ref basic_json in a different
20961
@ref basic_json type
20962
20963
@tparam BasicJsonType == @ref basic_json
20964
20965
@return a copy of *this, converted into @a BasicJsonType
20966
20967
@complexity Depending on the implementation of the called `from_json()`
20968
method.
20969
20970
@since version 3.2.0
20971
*/
20972
template < typename BasicJsonType,
20973
detail::enable_if_t <
20974
detail::is_basic_json<BasicJsonType>::value,
20975
int > = 0 >
20976
BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
20977
{
20978
return *this;
20979
}
20980
20981
/*!
20982
@brief get special-case overload
20983
20984
This overloads avoids a lot of template boilerplate, it can be seen as the
20985
identity method
20986
20987
@tparam BasicJsonType == @ref basic_json
20988
20989
@return a copy of *this
20990
20991
@complexity Constant.
20992
20993
@since version 2.1.0
20994
*/
20995
template<typename BasicJsonType,
20996
detail::enable_if_t<
20997
std::is_same<BasicJsonType, basic_json_t>::value,
20998
int> = 0>
20999
basic_json get_impl(detail::priority_tag<3> /*unused*/) const
21000
{
21001
return *this;
21002
}
21003
21004
/*!
21005
@brief get a pointer value (explicit)
21006
@copydoc get()
21007
*/
21008
template<typename PointerType,
21009
detail::enable_if_t<
21010
std::is_pointer<PointerType>::value,
21011
int> = 0>
21012
constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21013
-> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21014
{
21015
// delegate the call to get_ptr
21016
return get_ptr<PointerType>();
21017
}
21018
21019
public:
21020
/*!
21021
@brief get a (pointer) value (explicit)
21022
21023
Performs explicit type conversion between the JSON value and a compatible value if required.
21024
21025
- If the requested type is a pointer to the internally stored JSON value that pointer is returned.
21026
No copies are made.
21027
21028
- If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
21029
from the current @ref basic_json.
21030
21031
- Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
21032
method.
21033
21034
@tparam ValueTypeCV the provided value type
21035
@tparam ValueType the returned value type
21036
21037
@return copy of the JSON value, converted to @tparam ValueType if necessary
21038
21039
@throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
21040
21041
@since version 2.1.0
21042
*/
21043
template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21044
#if defined(JSON_HAS_CPP_14)
21045
constexpr
21046
#endif
21047
auto get() const noexcept(
21048
noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21049
-> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21050
{
21051
// we cannot static_assert on ValueTypeCV being non-const, because
21052
// there is support for get<const basic_json_t>(), which is why we
21053
// still need the uncvref
21054
static_assert(!std::is_reference<ValueTypeCV>::value,
21055
"get() cannot be used with reference types, you might want to use get_ref()");
21056
return get_impl<ValueType>(detail::priority_tag<4> {});
21057
}
21058
21059
/*!
21060
@brief get a pointer value (explicit)
21061
21062
Explicit pointer access to the internally stored JSON value. No copies are
21063
made.
21064
21065
@warning The pointer becomes invalid if the underlying JSON object
21066
changes.
21067
21068
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
21069
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
21070
@ref number_unsigned_t, or @ref number_float_t.
21071
21072
@return pointer to the internally stored JSON value if the requested
21073
pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
21074
21075
@complexity Constant.
21076
21077
@liveexample{The example below shows how pointers to internal values of a
21078
JSON value can be requested. Note that no type conversions are made and a
21079
`nullptr` is returned if the value and the requested pointer type does not
21080
match.,get__PointerType}
21081
21082
@sa see @ref get_ptr() for explicit pointer-member access
21083
21084
@since version 1.0.0
21085
*/
21086
template<typename PointerType, typename std::enable_if<
21087
std::is_pointer<PointerType>::value, int>::type = 0>
21088
auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21089
{
21090
// delegate the call to get_ptr
21091
return get_ptr<PointerType>();
21092
}
21093
21094
/// @brief get a value (explicit)
21095
/// @sa https://json.nlohmann.me/api/basic_json/get_to/
21096
template < typename ValueType,
21097
detail::enable_if_t <
21098
!detail::is_basic_json<ValueType>::value&&
21099
detail::has_from_json<basic_json_t, ValueType>::value,
21100
int > = 0 >
21101
ValueType & get_to(ValueType& v) const noexcept(noexcept(
21102
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21103
{
21104
JSONSerializer<ValueType>::from_json(*this, v);
21105
return v;
21106
}
21107
21108
// specialization to allow calling get_to with a basic_json value
21109
// see https://github.com/nlohmann/json/issues/2175
21110
template<typename ValueType,
21111
detail::enable_if_t <
21112
detail::is_basic_json<ValueType>::value,
21113
int> = 0>
21114
ValueType & get_to(ValueType& v) const
21115
{
21116
v = *this;
21117
return v;
21118
}
21119
21120
template <
21121
typename T, std::size_t N,
21122
typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21123
detail::enable_if_t <
21124
detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
21125
Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21126
noexcept(noexcept(JSONSerializer<Array>::from_json(
21127
std::declval<const basic_json_t&>(), v)))
21128
{
21129
JSONSerializer<Array>::from_json(*this, v);
21130
return v;
21131
}
21132
21133
/// @brief get a reference value (implicit)
21134
/// @sa https://json.nlohmann.me/api/basic_json/get_ref/
21135
template<typename ReferenceType, typename std::enable_if<
21136
std::is_reference<ReferenceType>::value, int>::type = 0>
21137
ReferenceType get_ref()
21138
{
21139
// delegate call to get_ref_impl
21140
return get_ref_impl<ReferenceType>(*this);
21141
}
21142
21143
/// @brief get a reference value (implicit)
21144
/// @sa https://json.nlohmann.me/api/basic_json/get_ref/
21145
template < typename ReferenceType, typename std::enable_if <
21146
std::is_reference<ReferenceType>::value&&
21147
std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21148
ReferenceType get_ref() const
21149
{
21150
// delegate call to get_ref_impl
21151
return get_ref_impl<ReferenceType>(*this);
21152
}
21153
21154
/*!
21155
@brief get a value (implicit)
21156
21157
Implicit type conversion between the JSON value and a compatible value.
21158
The call is realized by calling @ref get() const.
21159
21160
@tparam ValueType non-pointer type compatible to the JSON value, for
21161
instance `int` for JSON integer numbers, `bool` for JSON booleans, or
21162
`std::vector` types for JSON arrays. The character type of @ref string_t
21163
as well as an initializer list of this type is excluded to avoid
21164
ambiguities as these types implicitly convert to `std::string`.
21165
21166
@return copy of the JSON value, converted to type @a ValueType
21167
21168
@throw type_error.302 in case passed type @a ValueType is incompatible
21169
to the JSON value type (e.g., the JSON value is of type boolean, but a
21170
string is requested); see example below
21171
21172
@complexity Linear in the size of the JSON value.
21173
21174
@liveexample{The example below shows several conversions from JSON values
21175
to other types. There a few things to note: (1) Floating-point numbers can
21176
be converted to integers\, (2) A JSON array can be converted to a standard
21177
`std::vector<short>`\, (3) A JSON object can be converted to C++
21178
associative containers such as `std::unordered_map<std::string\,
21179
json>`.,operator__ValueType}
21180
21181
@since version 1.0.0
21182
*/
21183
template < typename ValueType, typename std::enable_if <
21184
detail::conjunction <
21185
detail::negation<std::is_pointer<ValueType>>,
21186
detail::negation<std::is_same<ValueType, std::nullptr_t>>,
21187
detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
21188
detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
21189
detail::negation<detail::is_basic_json<ValueType>>,
21190
detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
21191
#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
21192
detail::negation<std::is_same<ValueType, std::string_view>>,
21193
#endif
21194
#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
21195
detail::negation<std::is_same<ValueType, std::any>>,
21196
#endif
21197
detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
21198
>::value, int >::type = 0 >
21199
JSON_EXPLICIT operator ValueType() const
21200
{
21201
// delegate the call to get<>() const
21202
return get<ValueType>();
21203
}
21204
21205
/// @brief get a binary value
21206
/// @sa https://json.nlohmann.me/api/basic_json/get_binary/
21207
binary_t& get_binary()
21208
{
21209
if (!is_binary())
21210
{
21211
JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21212
}
21213
21214
return *get_ptr<binary_t*>();
21215
}
21216
21217
/// @brief get a binary value
21218
/// @sa https://json.nlohmann.me/api/basic_json/get_binary/
21219
const binary_t& get_binary() const
21220
{
21221
if (!is_binary())
21222
{
21223
JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21224
}
21225
21226
return *get_ptr<const binary_t*>();
21227
}
21228
21229
/// @}
21230
21231
////////////////////
21232
// element access //
21233
////////////////////
21234
21235
/// @name element access
21236
/// Access to the JSON value.
21237
/// @{
21238
21239
/// @brief access specified array element with bounds checking
21240
/// @sa https://json.nlohmann.me/api/basic_json/at/
21241
reference at(size_type idx)
21242
{
21243
// at only works for arrays
21244
if (JSON_HEDLEY_LIKELY(is_array()))
21245
{
21246
JSON_TRY
21247
{
21248
return set_parent(m_data.m_value.array->at(idx));
21249
}
21250
JSON_CATCH (std::out_of_range&)
21251
{
21252
// create better exception explanation
21253
JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21254
}
21255
}
21256
else
21257
{
21258
JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21259
}
21260
}
21261
21262
/// @brief access specified array element with bounds checking
21263
/// @sa https://json.nlohmann.me/api/basic_json/at/
21264
const_reference at(size_type idx) const
21265
{
21266
// at only works for arrays
21267
if (JSON_HEDLEY_LIKELY(is_array()))
21268
{
21269
JSON_TRY
21270
{
21271
return m_data.m_value.array->at(idx);
21272
}
21273
JSON_CATCH (std::out_of_range&)
21274
{
21275
// create better exception explanation
21276
JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21277
}
21278
}
21279
else
21280
{
21281
JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21282
}
21283
}
21284
21285
/// @brief access specified object element with bounds checking
21286
/// @sa https://json.nlohmann.me/api/basic_json/at/
21287
reference at(const typename object_t::key_type& key)
21288
{
21289
// at only works for objects
21290
if (JSON_HEDLEY_UNLIKELY(!is_object()))
21291
{
21292
JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21293
}
21294
21295
auto it = m_data.m_value.object->find(key);
21296
if (it == m_data.m_value.object->end())
21297
{
21298
JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21299
}
21300
return set_parent(it->second);
21301
}
21302
21303
/// @brief access specified object element with bounds checking
21304
/// @sa https://json.nlohmann.me/api/basic_json/at/
21305
template<class KeyType, detail::enable_if_t<
21306
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21307
reference at(KeyType && key)
21308
{
21309
// at only works for objects
21310
if (JSON_HEDLEY_UNLIKELY(!is_object()))
21311
{
21312
JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21313
}
21314
21315
auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21316
if (it == m_data.m_value.object->end())
21317
{
21318
JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21319
}
21320
return set_parent(it->second);
21321
}
21322
21323
/// @brief access specified object element with bounds checking
21324
/// @sa https://json.nlohmann.me/api/basic_json/at/
21325
const_reference at(const typename object_t::key_type& key) const
21326
{
21327
// at only works for objects
21328
if (JSON_HEDLEY_UNLIKELY(!is_object()))
21329
{
21330
JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21331
}
21332
21333
auto it = m_data.m_value.object->find(key);
21334
if (it == m_data.m_value.object->end())
21335
{
21336
JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21337
}
21338
return it->second;
21339
}
21340
21341
/// @brief access specified object element with bounds checking
21342
/// @sa https://json.nlohmann.me/api/basic_json/at/
21343
template<class KeyType, detail::enable_if_t<
21344
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21345
const_reference at(KeyType && key) const
21346
{
21347
// at only works for objects
21348
if (JSON_HEDLEY_UNLIKELY(!is_object()))
21349
{
21350
JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21351
}
21352
21353
auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21354
if (it == m_data.m_value.object->end())
21355
{
21356
JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21357
}
21358
return it->second;
21359
}
21360
21361
/// @brief access specified array element
21362
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21363
reference operator[](size_type idx)
21364
{
21365
// implicitly convert null value to an empty array
21366
if (is_null())
21367
{
21368
m_data.m_type = value_t::array;
21369
m_data.m_value.array = create<array_t>();
21370
assert_invariant();
21371
}
21372
21373
// operator[] only works for arrays
21374
if (JSON_HEDLEY_LIKELY(is_array()))
21375
{
21376
// fill up array with null values if given idx is outside range
21377
if (idx >= m_data.m_value.array->size())
21378
{
21379
#if JSON_DIAGNOSTICS
21380
// remember array size & capacity before resizing
21381
const auto old_size = m_data.m_value.array->size();
21382
const auto old_capacity = m_data.m_value.array->capacity();
21383
#endif
21384
m_data.m_value.array->resize(idx + 1);
21385
21386
#if JSON_DIAGNOSTICS
21387
if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
21388
{
21389
// capacity has changed: update all parents
21390
set_parents();
21391
}
21392
else
21393
{
21394
// set parent for values added above
21395
set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
21396
}
21397
#endif
21398
assert_invariant();
21399
}
21400
21401
return m_data.m_value.array->operator[](idx);
21402
}
21403
21404
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21405
}
21406
21407
/// @brief access specified array element
21408
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21409
const_reference operator[](size_type idx) const
21410
{
21411
// const operator[] only works for arrays
21412
if (JSON_HEDLEY_LIKELY(is_array()))
21413
{
21414
return m_data.m_value.array->operator[](idx);
21415
}
21416
21417
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21418
}
21419
21420
/// @brief access specified object element
21421
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21422
reference operator[](typename object_t::key_type key)
21423
{
21424
// implicitly convert null value to an empty object
21425
if (is_null())
21426
{
21427
m_data.m_type = value_t::object;
21428
m_data.m_value.object = create<object_t>();
21429
assert_invariant();
21430
}
21431
21432
// operator[] only works for objects
21433
if (JSON_HEDLEY_LIKELY(is_object()))
21434
{
21435
auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
21436
return set_parent(result.first->second);
21437
}
21438
21439
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21440
}
21441
21442
/// @brief access specified object element
21443
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21444
const_reference operator[](const typename object_t::key_type& key) const
21445
{
21446
// const operator[] only works for objects
21447
if (JSON_HEDLEY_LIKELY(is_object()))
21448
{
21449
auto it = m_data.m_value.object->find(key);
21450
JSON_ASSERT(it != m_data.m_value.object->end());
21451
return it->second;
21452
}
21453
21454
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21455
}
21456
21457
// these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
21458
// (they seemingly cannot be constrained to resolve the ambiguity)
21459
template<typename T>
21460
reference operator[](T* key)
21461
{
21462
return operator[](typename object_t::key_type(key));
21463
}
21464
21465
template<typename T>
21466
const_reference operator[](T* key) const
21467
{
21468
return operator[](typename object_t::key_type(key));
21469
}
21470
21471
/// @brief access specified object element
21472
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21473
template<class KeyType, detail::enable_if_t<
21474
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
21475
reference operator[](KeyType && key)
21476
{
21477
// implicitly convert null value to an empty object
21478
if (is_null())
21479
{
21480
m_data.m_type = value_t::object;
21481
m_data.m_value.object = create<object_t>();
21482
assert_invariant();
21483
}
21484
21485
// operator[] only works for objects
21486
if (JSON_HEDLEY_LIKELY(is_object()))
21487
{
21488
auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
21489
return set_parent(result.first->second);
21490
}
21491
21492
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21493
}
21494
21495
/// @brief access specified object element
21496
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21497
template<class KeyType, detail::enable_if_t<
21498
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
21499
const_reference operator[](KeyType && key) const
21500
{
21501
// const operator[] only works for objects
21502
if (JSON_HEDLEY_LIKELY(is_object()))
21503
{
21504
auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21505
JSON_ASSERT(it != m_data.m_value.object->end());
21506
return it->second;
21507
}
21508
21509
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21510
}
21511
21512
private:
21513
template<typename KeyType>
21514
using is_comparable_with_object_key = detail::is_comparable <
21515
object_comparator_t, const typename object_t::key_type&, KeyType >;
21516
21517
template<typename ValueType>
21518
using value_return_type = std::conditional <
21519
detail::is_c_string_uncvref<ValueType>::value,
21520
string_t, typename std::decay<ValueType>::type >;
21521
21522
public:
21523
/// @brief access specified object element with default value
21524
/// @sa https://json.nlohmann.me/api/basic_json/value/
21525
template < class ValueType, detail::enable_if_t <
21526
!detail::is_transparent<object_comparator_t>::value
21527
&& detail::is_getable<basic_json_t, ValueType>::value
21528
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21529
ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
21530
{
21531
// value only works for objects
21532
if (JSON_HEDLEY_LIKELY(is_object()))
21533
{
21534
// if key is found, return value and given default value otherwise
21535
const auto it = find(key);
21536
if (it != end())
21537
{
21538
return it->template get<ValueType>();
21539
}
21540
21541
return default_value;
21542
}
21543
21544
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21545
}
21546
21547
/// @brief access specified object element with default value
21548
/// @sa https://json.nlohmann.me/api/basic_json/value/
21549
template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21550
detail::enable_if_t <
21551
!detail::is_transparent<object_comparator_t>::value
21552
&& detail::is_getable<basic_json_t, ReturnType>::value
21553
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21554
ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
21555
{
21556
// value only works for objects
21557
if (JSON_HEDLEY_LIKELY(is_object()))
21558
{
21559
// if key is found, return value and given default value otherwise
21560
const auto it = find(key);
21561
if (it != end())
21562
{
21563
return it->template get<ReturnType>();
21564
}
21565
21566
return std::forward<ValueType>(default_value);
21567
}
21568
21569
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21570
}
21571
21572
/// @brief access specified object element with default value
21573
/// @sa https://json.nlohmann.me/api/basic_json/value/
21574
template < class ValueType, class KeyType, detail::enable_if_t <
21575
detail::is_transparent<object_comparator_t>::value
21576
&& !detail::is_json_pointer<KeyType>::value
21577
&& is_comparable_with_object_key<KeyType>::value
21578
&& detail::is_getable<basic_json_t, ValueType>::value
21579
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21580
ValueType value(KeyType && key, const ValueType& default_value) const
21581
{
21582
// value only works for objects
21583
if (JSON_HEDLEY_LIKELY(is_object()))
21584
{
21585
// if key is found, return value and given default value otherwise
21586
const auto it = find(std::forward<KeyType>(key));
21587
if (it != end())
21588
{
21589
return it->template get<ValueType>();
21590
}
21591
21592
return default_value;
21593
}
21594
21595
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21596
}
21597
21598
/// @brief access specified object element via JSON Pointer with default value
21599
/// @sa https://json.nlohmann.me/api/basic_json/value/
21600
template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
21601
detail::enable_if_t <
21602
detail::is_transparent<object_comparator_t>::value
21603
&& !detail::is_json_pointer<KeyType>::value
21604
&& is_comparable_with_object_key<KeyType>::value
21605
&& detail::is_getable<basic_json_t, ReturnType>::value
21606
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21607
ReturnType value(KeyType && key, ValueType && default_value) const
21608
{
21609
// value only works for objects
21610
if (JSON_HEDLEY_LIKELY(is_object()))
21611
{
21612
// if key is found, return value and given default value otherwise
21613
const auto it = find(std::forward<KeyType>(key));
21614
if (it != end())
21615
{
21616
return it->template get<ReturnType>();
21617
}
21618
21619
return std::forward<ValueType>(default_value);
21620
}
21621
21622
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21623
}
21624
21625
/// @brief access specified object element via JSON Pointer with default value
21626
/// @sa https://json.nlohmann.me/api/basic_json/value/
21627
template < class ValueType, detail::enable_if_t <
21628
detail::is_getable<basic_json_t, ValueType>::value
21629
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21630
ValueType value(const json_pointer& ptr, const ValueType& default_value) const
21631
{
21632
// value only works for objects
21633
if (JSON_HEDLEY_LIKELY(is_object()))
21634
{
21635
// if pointer resolves a value, return it or use default value
21636
JSON_TRY
21637
{
21638
return ptr.get_checked(this).template get<ValueType>();
21639
}
21640
JSON_INTERNAL_CATCH (out_of_range&)
21641
{
21642
return default_value;
21643
}
21644
}
21645
21646
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21647
}
21648
21649
/// @brief access specified object element via JSON Pointer with default value
21650
/// @sa https://json.nlohmann.me/api/basic_json/value/
21651
template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21652
detail::enable_if_t <
21653
detail::is_getable<basic_json_t, ReturnType>::value
21654
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21655
ReturnType value(const json_pointer& ptr, ValueType && default_value) const
21656
{
21657
// value only works for objects
21658
if (JSON_HEDLEY_LIKELY(is_object()))
21659
{
21660
// if pointer resolves a value, return it or use default value
21661
JSON_TRY
21662
{
21663
return ptr.get_checked(this).template get<ReturnType>();
21664
}
21665
JSON_INTERNAL_CATCH (out_of_range&)
21666
{
21667
return std::forward<ValueType>(default_value);
21668
}
21669
}
21670
21671
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21672
}
21673
21674
template < class ValueType, class BasicJsonType, detail::enable_if_t <
21675
detail::is_basic_json<BasicJsonType>::value
21676
&& detail::is_getable<basic_json_t, ValueType>::value
21677
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21678
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21679
ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
21680
{
21681
return value(ptr.convert(), default_value);
21682
}
21683
21684
template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
21685
detail::enable_if_t <
21686
detail::is_basic_json<BasicJsonType>::value
21687
&& detail::is_getable<basic_json_t, ReturnType>::value
21688
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21689
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21690
ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
21691
{
21692
return value(ptr.convert(), std::forward<ValueType>(default_value));
21693
}
21694
21695
/// @brief access the first element
21696
/// @sa https://json.nlohmann.me/api/basic_json/front/
21697
reference front()
21698
{
21699
return *begin();
21700
}
21701
21702
/// @brief access the first element
21703
/// @sa https://json.nlohmann.me/api/basic_json/front/
21704
const_reference front() const
21705
{
21706
return *cbegin();
21707
}
21708
21709
/// @brief access the last element
21710
/// @sa https://json.nlohmann.me/api/basic_json/back/
21711
reference back()
21712
{
21713
auto tmp = end();
21714
--tmp;
21715
return *tmp;
21716
}
21717
21718
/// @brief access the last element
21719
/// @sa https://json.nlohmann.me/api/basic_json/back/
21720
const_reference back() const
21721
{
21722
auto tmp = cend();
21723
--tmp;
21724
return *tmp;
21725
}
21726
21727
/// @brief remove element given an iterator
21728
/// @sa https://json.nlohmann.me/api/basic_json/erase/
21729
template < class IteratorType, detail::enable_if_t <
21730
std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21731
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21732
IteratorType erase(IteratorType pos)
21733
{
21734
// make sure iterator fits the current value
21735
if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
21736
{
21737
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21738
}
21739
21740
IteratorType result = end();
21741
21742
switch (m_data.m_type)
21743
{
21744
case value_t::boolean:
21745
case value_t::number_float:
21746
case value_t::number_integer:
21747
case value_t::number_unsigned:
21748
case value_t::string:
21749
case value_t::binary:
21750
{
21751
if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
21752
{
21753
JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
21754
}
21755
21756
if (is_string())
21757
{
21758
AllocatorType<string_t> alloc;
21759
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21760
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21761
m_data.m_value.string = nullptr;
21762
}
21763
else if (is_binary())
21764
{
21765
AllocatorType<binary_t> alloc;
21766
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21767
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21768
m_data.m_value.binary = nullptr;
21769
}
21770
21771
m_data.m_type = value_t::null;
21772
assert_invariant();
21773
break;
21774
}
21775
21776
case value_t::object:
21777
{
21778
result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
21779
break;
21780
}
21781
21782
case value_t::array:
21783
{
21784
result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
21785
break;
21786
}
21787
21788
case value_t::null:
21789
case value_t::discarded:
21790
default:
21791
JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21792
}
21793
21794
return result;
21795
}
21796
21797
/// @brief remove elements given an iterator range
21798
/// @sa https://json.nlohmann.me/api/basic_json/erase/
21799
template < class IteratorType, detail::enable_if_t <
21800
std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21801
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21802
IteratorType erase(IteratorType first, IteratorType last)
21803
{
21804
// make sure iterator fits the current value
21805
if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
21806
{
21807
JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
21808
}
21809
21810
IteratorType result = end();
21811
21812
switch (m_data.m_type)
21813
{
21814
case value_t::boolean:
21815
case value_t::number_float:
21816
case value_t::number_integer:
21817
case value_t::number_unsigned:
21818
case value_t::string:
21819
case value_t::binary:
21820
{
21821
if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
21822
|| !last.m_it.primitive_iterator.is_end()))
21823
{
21824
JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
21825
}
21826
21827
if (is_string())
21828
{
21829
AllocatorType<string_t> alloc;
21830
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21831
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21832
m_data.m_value.string = nullptr;
21833
}
21834
else if (is_binary())
21835
{
21836
AllocatorType<binary_t> alloc;
21837
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21838
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21839
m_data.m_value.binary = nullptr;
21840
}
21841
21842
m_data.m_type = value_t::null;
21843
assert_invariant();
21844
break;
21845
}
21846
21847
case value_t::object:
21848
{
21849
result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
21850
last.m_it.object_iterator);
21851
break;
21852
}
21853
21854
case value_t::array:
21855
{
21856
result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
21857
last.m_it.array_iterator);
21858
break;
21859
}
21860
21861
case value_t::null:
21862
case value_t::discarded:
21863
default:
21864
JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21865
}
21866
21867
return result;
21868
}
21869
21870
private:
21871
template < typename KeyType, detail::enable_if_t <
21872
detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
21873
size_type erase_internal(KeyType && key)
21874
{
21875
// this erase only works for objects
21876
if (JSON_HEDLEY_UNLIKELY(!is_object()))
21877
{
21878
JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21879
}
21880
21881
return m_data.m_value.object->erase(std::forward<KeyType>(key));
21882
}
21883
21884
template < typename KeyType, detail::enable_if_t <
21885
!detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
21886
size_type erase_internal(KeyType && key)
21887
{
21888
// this erase only works for objects
21889
if (JSON_HEDLEY_UNLIKELY(!is_object()))
21890
{
21891
JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21892
}
21893
21894
const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21895
if (it != m_data.m_value.object->end())
21896
{
21897
m_data.m_value.object->erase(it);
21898
return 1;
21899
}
21900
return 0;
21901
}
21902
21903
public:
21904
21905
/// @brief remove element from a JSON object given a key
21906
/// @sa https://json.nlohmann.me/api/basic_json/erase/
21907
size_type erase(const typename object_t::key_type& key)
21908
{
21909
// the indirection via erase_internal() is added to avoid making this
21910
// function a template and thus de-rank it during overload resolution
21911
return erase_internal(key);
21912
}
21913
21914
/// @brief remove element from a JSON object given a key
21915
/// @sa https://json.nlohmann.me/api/basic_json/erase/
21916
template<class KeyType, detail::enable_if_t<
21917
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21918
size_type erase(KeyType && key)
21919
{
21920
return erase_internal(std::forward<KeyType>(key));
21921
}
21922
21923
/// @brief remove element from a JSON array given an index
21924
/// @sa https://json.nlohmann.me/api/basic_json/erase/
21925
void erase(const size_type idx)
21926
{
21927
// this erase only works for arrays
21928
if (JSON_HEDLEY_LIKELY(is_array()))
21929
{
21930
if (JSON_HEDLEY_UNLIKELY(idx >= size()))
21931
{
21932
JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21933
}
21934
21935
m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
21936
}
21937
else
21938
{
21939
JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21940
}
21941
}
21942
21943
/// @}
21944
21945
////////////
21946
// lookup //
21947
////////////
21948
21949
/// @name lookup
21950
/// @{
21951
21952
/// @brief find an element in a JSON object
21953
/// @sa https://json.nlohmann.me/api/basic_json/find/
21954
iterator find(const typename object_t::key_type& key)
21955
{
21956
auto result = end();
21957
21958
if (is_object())
21959
{
21960
result.m_it.object_iterator = m_data.m_value.object->find(key);
21961
}
21962
21963
return result;
21964
}
21965
21966
/// @brief find an element in a JSON object
21967
/// @sa https://json.nlohmann.me/api/basic_json/find/
21968
const_iterator find(const typename object_t::key_type& key) const
21969
{
21970
auto result = cend();
21971
21972
if (is_object())
21973
{
21974
result.m_it.object_iterator = m_data.m_value.object->find(key);
21975
}
21976
21977
return result;
21978
}
21979
21980
/// @brief find an element in a JSON object
21981
/// @sa https://json.nlohmann.me/api/basic_json/find/
21982
template<class KeyType, detail::enable_if_t<
21983
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21984
iterator find(KeyType && key)
21985
{
21986
auto result = end();
21987
21988
if (is_object())
21989
{
21990
result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
21991
}
21992
21993
return result;
21994
}
21995
21996
/// @brief find an element in a JSON object
21997
/// @sa https://json.nlohmann.me/api/basic_json/find/
21998
template<class KeyType, detail::enable_if_t<
21999
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22000
const_iterator find(KeyType && key) const
22001
{
22002
auto result = cend();
22003
22004
if (is_object())
22005
{
22006
result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22007
}
22008
22009
return result;
22010
}
22011
22012
/// @brief returns the number of occurrences of a key in a JSON object
22013
/// @sa https://json.nlohmann.me/api/basic_json/count/
22014
size_type count(const typename object_t::key_type& key) const
22015
{
22016
// return 0 for all nonobject types
22017
return is_object() ? m_data.m_value.object->count(key) : 0;
22018
}
22019
22020
/// @brief returns the number of occurrences of a key in a JSON object
22021
/// @sa https://json.nlohmann.me/api/basic_json/count/
22022
template<class KeyType, detail::enable_if_t<
22023
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22024
size_type count(KeyType && key) const
22025
{
22026
// return 0 for all nonobject types
22027
return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22028
}
22029
22030
/// @brief check the existence of an element in a JSON object
22031
/// @sa https://json.nlohmann.me/api/basic_json/contains/
22032
bool contains(const typename object_t::key_type& key) const
22033
{
22034
return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22035
}
22036
22037
/// @brief check the existence of an element in a JSON object
22038
/// @sa https://json.nlohmann.me/api/basic_json/contains/
22039
template<class KeyType, detail::enable_if_t<
22040
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22041
bool contains(KeyType && key) const
22042
{
22043
return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22044
}
22045
22046
/// @brief check the existence of an element in a JSON object given a JSON pointer
22047
/// @sa https://json.nlohmann.me/api/basic_json/contains/
22048
bool contains(const json_pointer& ptr) const
22049
{
22050
return ptr.contains(this);
22051
}
22052
22053
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22054
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22055
bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22056
{
22057
return ptr.contains(this);
22058
}
22059
22060
/// @}
22061
22062
///////////////
22063
// iterators //
22064
///////////////
22065
22066
/// @name iterators
22067
/// @{
22068
22069
/// @brief returns an iterator to the first element
22070
/// @sa https://json.nlohmann.me/api/basic_json/begin/
22071
iterator begin() noexcept
22072
{
22073
iterator result(this);
22074
result.set_begin();
22075
return result;
22076
}
22077
22078
/// @brief returns an iterator to the first element
22079
/// @sa https://json.nlohmann.me/api/basic_json/begin/
22080
const_iterator begin() const noexcept
22081
{
22082
return cbegin();
22083
}
22084
22085
/// @brief returns a const iterator to the first element
22086
/// @sa https://json.nlohmann.me/api/basic_json/cbegin/
22087
const_iterator cbegin() const noexcept
22088
{
22089
const_iterator result(this);
22090
result.set_begin();
22091
return result;
22092
}
22093
22094
/// @brief returns an iterator to one past the last element
22095
/// @sa https://json.nlohmann.me/api/basic_json/end/
22096
iterator end() noexcept
22097
{
22098
iterator result(this);
22099
result.set_end();
22100
return result;
22101
}
22102
22103
/// @brief returns an iterator to one past the last element
22104
/// @sa https://json.nlohmann.me/api/basic_json/end/
22105
const_iterator end() const noexcept
22106
{
22107
return cend();
22108
}
22109
22110
/// @brief returns an iterator to one past the last element
22111
/// @sa https://json.nlohmann.me/api/basic_json/cend/
22112
const_iterator cend() const noexcept
22113
{
22114
const_iterator result(this);
22115
result.set_end();
22116
return result;
22117
}
22118
22119
/// @brief returns an iterator to the reverse-beginning
22120
/// @sa https://json.nlohmann.me/api/basic_json/rbegin/
22121
reverse_iterator rbegin() noexcept
22122
{
22123
return reverse_iterator(end());
22124
}
22125
22126
/// @brief returns an iterator to the reverse-beginning
22127
/// @sa https://json.nlohmann.me/api/basic_json/rbegin/
22128
const_reverse_iterator rbegin() const noexcept
22129
{
22130
return crbegin();
22131
}
22132
22133
/// @brief returns an iterator to the reverse-end
22134
/// @sa https://json.nlohmann.me/api/basic_json/rend/
22135
reverse_iterator rend() noexcept
22136
{
22137
return reverse_iterator(begin());
22138
}
22139
22140
/// @brief returns an iterator to the reverse-end
22141
/// @sa https://json.nlohmann.me/api/basic_json/rend/
22142
const_reverse_iterator rend() const noexcept
22143
{
22144
return crend();
22145
}
22146
22147
/// @brief returns a const reverse iterator to the last element
22148
/// @sa https://json.nlohmann.me/api/basic_json/crbegin/
22149
const_reverse_iterator crbegin() const noexcept
22150
{
22151
return const_reverse_iterator(cend());
22152
}
22153
22154
/// @brief returns a const reverse iterator to one before the first
22155
/// @sa https://json.nlohmann.me/api/basic_json/crend/
22156
const_reverse_iterator crend() const noexcept
22157
{
22158
return const_reverse_iterator(cbegin());
22159
}
22160
22161
public:
22162
/// @brief wrapper to access iterator member functions in range-based for
22163
/// @sa https://json.nlohmann.me/api/basic_json/items/
22164
/// @deprecated This function is deprecated since 3.1.0 and will be removed in
22165
/// version 4.0.0 of the library. Please use @ref items() instead;
22166
/// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
22167
JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22168
static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
22169
{
22170
return ref.items();
22171
}
22172
22173
/// @brief wrapper to access iterator member functions in range-based for
22174
/// @sa https://json.nlohmann.me/api/basic_json/items/
22175
/// @deprecated This function is deprecated since 3.1.0 and will be removed in
22176
/// version 4.0.0 of the library. Please use @ref items() instead;
22177
/// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
22178
JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22179
static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
22180
{
22181
return ref.items();
22182
}
22183
22184
/// @brief helper to access iterator member functions in range-based for
22185
/// @sa https://json.nlohmann.me/api/basic_json/items/
22186
iteration_proxy<iterator> items() noexcept
22187
{
22188
return iteration_proxy<iterator>(*this);
22189
}
22190
22191
/// @brief helper to access iterator member functions in range-based for
22192
/// @sa https://json.nlohmann.me/api/basic_json/items/
22193
iteration_proxy<const_iterator> items() const noexcept
22194
{
22195
return iteration_proxy<const_iterator>(*this);
22196
}
22197
22198
/// @}
22199
22200
//////////////
22201
// capacity //
22202
//////////////
22203
22204
/// @name capacity
22205
/// @{
22206
22207
/// @brief checks whether the container is empty.
22208
/// @sa https://json.nlohmann.me/api/basic_json/empty/
22209
bool empty() const noexcept
22210
{
22211
switch (m_data.m_type)
22212
{
22213
case value_t::null:
22214
{
22215
// null values are empty
22216
return true;
22217
}
22218
22219
case value_t::array:
22220
{
22221
// delegate call to array_t::empty()
22222
return m_data.m_value.array->empty();
22223
}
22224
22225
case value_t::object:
22226
{
22227
// delegate call to object_t::empty()
22228
return m_data.m_value.object->empty();
22229
}
22230
22231
case value_t::string:
22232
case value_t::boolean:
22233
case value_t::number_integer:
22234
case value_t::number_unsigned:
22235
case value_t::number_float:
22236
case value_t::binary:
22237
case value_t::discarded:
22238
default:
22239
{
22240
// all other types are nonempty
22241
return false;
22242
}
22243
}
22244
}
22245
22246
/// @brief returns the number of elements
22247
/// @sa https://json.nlohmann.me/api/basic_json/size/
22248
size_type size() const noexcept
22249
{
22250
switch (m_data.m_type)
22251
{
22252
case value_t::null:
22253
{
22254
// null values are empty
22255
return 0;
22256
}
22257
22258
case value_t::array:
22259
{
22260
// delegate call to array_t::size()
22261
return m_data.m_value.array->size();
22262
}
22263
22264
case value_t::object:
22265
{
22266
// delegate call to object_t::size()
22267
return m_data.m_value.object->size();
22268
}
22269
22270
case value_t::string:
22271
case value_t::boolean:
22272
case value_t::number_integer:
22273
case value_t::number_unsigned:
22274
case value_t::number_float:
22275
case value_t::binary:
22276
case value_t::discarded:
22277
default:
22278
{
22279
// all other types have size 1
22280
return 1;
22281
}
22282
}
22283
}
22284
22285
/// @brief returns the maximum possible number of elements
22286
/// @sa https://json.nlohmann.me/api/basic_json/max_size/
22287
size_type max_size() const noexcept
22288
{
22289
switch (m_data.m_type)
22290
{
22291
case value_t::array:
22292
{
22293
// delegate call to array_t::max_size()
22294
return m_data.m_value.array->max_size();
22295
}
22296
22297
case value_t::object:
22298
{
22299
// delegate call to object_t::max_size()
22300
return m_data.m_value.object->max_size();
22301
}
22302
22303
case value_t::null:
22304
case value_t::string:
22305
case value_t::boolean:
22306
case value_t::number_integer:
22307
case value_t::number_unsigned:
22308
case value_t::number_float:
22309
case value_t::binary:
22310
case value_t::discarded:
22311
default:
22312
{
22313
// all other types have max_size() == size()
22314
return size();
22315
}
22316
}
22317
}
22318
22319
/// @}
22320
22321
///////////////
22322
// modifiers //
22323
///////////////
22324
22325
/// @name modifiers
22326
/// @{
22327
22328
/// @brief clears the contents
22329
/// @sa https://json.nlohmann.me/api/basic_json/clear/
22330
void clear() noexcept
22331
{
22332
switch (m_data.m_type)
22333
{
22334
case value_t::number_integer:
22335
{
22336
m_data.m_value.number_integer = 0;
22337
break;
22338
}
22339
22340
case value_t::number_unsigned:
22341
{
22342
m_data.m_value.number_unsigned = 0;
22343
break;
22344
}
22345
22346
case value_t::number_float:
22347
{
22348
m_data.m_value.number_float = 0.0;
22349
break;
22350
}
22351
22352
case value_t::boolean:
22353
{
22354
m_data.m_value.boolean = false;
22355
break;
22356
}
22357
22358
case value_t::string:
22359
{
22360
m_data.m_value.string->clear();
22361
break;
22362
}
22363
22364
case value_t::binary:
22365
{
22366
m_data.m_value.binary->clear();
22367
break;
22368
}
22369
22370
case value_t::array:
22371
{
22372
m_data.m_value.array->clear();
22373
break;
22374
}
22375
22376
case value_t::object:
22377
{
22378
m_data.m_value.object->clear();
22379
break;
22380
}
22381
22382
case value_t::null:
22383
case value_t::discarded:
22384
default:
22385
break;
22386
}
22387
}
22388
22389
/// @brief add an object to an array
22390
/// @sa https://json.nlohmann.me/api/basic_json/push_back/
22391
void push_back(basic_json&& val)
22392
{
22393
// push_back only works for null objects or arrays
22394
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22395
{
22396
JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22397
}
22398
22399
// transform null object into an array
22400
if (is_null())
22401
{
22402
m_data.m_type = value_t::array;
22403
m_data.m_value = value_t::array;
22404
assert_invariant();
22405
}
22406
22407
// add element to array (move semantics)
22408
const auto old_capacity = m_data.m_value.array->capacity();
22409
m_data.m_value.array->push_back(std::move(val));
22410
set_parent(m_data.m_value.array->back(), old_capacity);
22411
// if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
22412
}
22413
22414
/// @brief add an object to an array
22415
/// @sa https://json.nlohmann.me/api/basic_json/operator+=/
22416
reference operator+=(basic_json&& val)
22417
{
22418
push_back(std::move(val));
22419
return *this;
22420
}
22421
22422
/// @brief add an object to an array
22423
/// @sa https://json.nlohmann.me/api/basic_json/push_back/
22424
void push_back(const basic_json& val)
22425
{
22426
// push_back only works for null objects or arrays
22427
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22428
{
22429
JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22430
}
22431
22432
// transform null object into an array
22433
if (is_null())
22434
{
22435
m_data.m_type = value_t::array;
22436
m_data.m_value = value_t::array;
22437
assert_invariant();
22438
}
22439
22440
// add element to array
22441
const auto old_capacity = m_data.m_value.array->capacity();
22442
m_data.m_value.array->push_back(val);
22443
set_parent(m_data.m_value.array->back(), old_capacity);
22444
}
22445
22446
/// @brief add an object to an array
22447
/// @sa https://json.nlohmann.me/api/basic_json/operator+=/
22448
reference operator+=(const basic_json& val)
22449
{
22450
push_back(val);
22451
return *this;
22452
}
22453
22454
/// @brief add an object to an object
22455
/// @sa https://json.nlohmann.me/api/basic_json/push_back/
22456
void push_back(const typename object_t::value_type& val)
22457
{
22458
// push_back only works for null objects or objects
22459
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22460
{
22461
JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22462
}
22463
22464
// transform null object into an object
22465
if (is_null())
22466
{
22467
m_data.m_type = value_t::object;
22468
m_data.m_value = value_t::object;
22469
assert_invariant();
22470
}
22471
22472
// add element to object
22473
auto res = m_data.m_value.object->insert(val);
22474
set_parent(res.first->second);
22475
}
22476
22477
/// @brief add an object to an object
22478
/// @sa https://json.nlohmann.me/api/basic_json/operator+=/
22479
reference operator+=(const typename object_t::value_type& val)
22480
{
22481
push_back(val);
22482
return *this;
22483
}
22484
22485
/// @brief add an object to an object
22486
/// @sa https://json.nlohmann.me/api/basic_json/push_back/
22487
void push_back(initializer_list_t init)
22488
{
22489
if (is_object() && init.size() == 2 && (*init.begin())->is_string())
22490
{
22491
basic_json&& key = init.begin()->moved_or_copied();
22492
push_back(typename object_t::value_type(
22493
std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
22494
}
22495
else
22496
{
22497
push_back(basic_json(init));
22498
}
22499
}
22500
22501
/// @brief add an object to an object
22502
/// @sa https://json.nlohmann.me/api/basic_json/operator+=/
22503
reference operator+=(initializer_list_t init)
22504
{
22505
push_back(init);
22506
return *this;
22507
}
22508
22509
/// @brief add an object to an array
22510
/// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
22511
template<class... Args>
22512
reference emplace_back(Args&& ... args)
22513
{
22514
// emplace_back only works for null objects or arrays
22515
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22516
{
22517
JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
22518
}
22519
22520
// transform null object into an array
22521
if (is_null())
22522
{
22523
m_data.m_type = value_t::array;
22524
m_data.m_value = value_t::array;
22525
assert_invariant();
22526
}
22527
22528
// add element to array (perfect forwarding)
22529
const auto old_capacity = m_data.m_value.array->capacity();
22530
m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
22531
return set_parent(m_data.m_value.array->back(), old_capacity);
22532
}
22533
22534
/// @brief add an object to an object if key does not exist
22535
/// @sa https://json.nlohmann.me/api/basic_json/emplace/
22536
template<class... Args>
22537
std::pair<iterator, bool> emplace(Args&& ... args)
22538
{
22539
// emplace only works for null objects or arrays
22540
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22541
{
22542
JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
22543
}
22544
22545
// transform null object into an object
22546
if (is_null())
22547
{
22548
m_data.m_type = value_t::object;
22549
m_data.m_value = value_t::object;
22550
assert_invariant();
22551
}
22552
22553
// add element to array (perfect forwarding)
22554
auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
22555
set_parent(res.first->second);
22556
22557
// create result iterator and set iterator to the result of emplace
22558
auto it = begin();
22559
it.m_it.object_iterator = res.first;
22560
22561
// return pair of iterator and boolean
22562
return {it, res.second};
22563
}
22564
22565
/// Helper for insertion of an iterator
22566
/// @note: This uses std::distance to support GCC 4.8,
22567
/// see https://github.com/nlohmann/json/pull/1257
22568
template<typename... Args>
22569
iterator insert_iterator(const_iterator pos, Args&& ... args)
22570
{
22571
iterator result(this);
22572
JSON_ASSERT(m_data.m_value.array != nullptr);
22573
22574
auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
22575
m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
22576
result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
22577
22578
// This could have been written as:
22579
// result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
22580
// but the return value of insert is missing in GCC 4.8, so it is written this way instead.
22581
22582
set_parents();
22583
return result;
22584
}
22585
22586
/// @brief inserts element into array
22587
/// @sa https://json.nlohmann.me/api/basic_json/insert/
22588
iterator insert(const_iterator pos, const basic_json& val)
22589
{
22590
// insert only works for arrays
22591
if (JSON_HEDLEY_LIKELY(is_array()))
22592
{
22593
// check if iterator pos fits to this JSON value
22594
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22595
{
22596
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22597
}
22598
22599
// insert to array and return iterator
22600
return insert_iterator(pos, val);
22601
}
22602
22603
JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22604
}
22605
22606
/// @brief inserts element into array
22607
/// @sa https://json.nlohmann.me/api/basic_json/insert/
22608
iterator insert(const_iterator pos, basic_json&& val)
22609
{
22610
return insert(pos, val);
22611
}
22612
22613
/// @brief inserts copies of element into array
22614
/// @sa https://json.nlohmann.me/api/basic_json/insert/
22615
iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
22616
{
22617
// insert only works for arrays
22618
if (JSON_HEDLEY_LIKELY(is_array()))
22619
{
22620
// check if iterator pos fits to this JSON value
22621
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22622
{
22623
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22624
}
22625
22626
// insert to array and return iterator
22627
return insert_iterator(pos, cnt, val);
22628
}
22629
22630
JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22631
}
22632
22633
/// @brief inserts range of elements into array
22634
/// @sa https://json.nlohmann.me/api/basic_json/insert/
22635
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
22636
{
22637
// insert only works for arrays
22638
if (JSON_HEDLEY_UNLIKELY(!is_array()))
22639
{
22640
JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22641
}
22642
22643
// check if iterator pos fits to this JSON value
22644
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22645
{
22646
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22647
}
22648
22649
// check if range iterators belong to the same JSON object
22650
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22651
{
22652
JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22653
}
22654
22655
if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
22656
{
22657
JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
22658
}
22659
22660
// insert to array and return iterator
22661
return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
22662
}
22663
22664
/// @brief inserts elements from initializer list into array
22665
/// @sa https://json.nlohmann.me/api/basic_json/insert/
22666
iterator insert(const_iterator pos, initializer_list_t ilist)
22667
{
22668
// insert only works for arrays
22669
if (JSON_HEDLEY_UNLIKELY(!is_array()))
22670
{
22671
JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22672
}
22673
22674
// check if iterator pos fits to this JSON value
22675
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22676
{
22677
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22678
}
22679
22680
// insert to array and return iterator
22681
return insert_iterator(pos, ilist.begin(), ilist.end());
22682
}
22683
22684
/// @brief inserts range of elements into object
22685
/// @sa https://json.nlohmann.me/api/basic_json/insert/
22686
void insert(const_iterator first, const_iterator last)
22687
{
22688
// insert only works for objects
22689
if (JSON_HEDLEY_UNLIKELY(!is_object()))
22690
{
22691
JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22692
}
22693
22694
// check if range iterators belong to the same JSON object
22695
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22696
{
22697
JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22698
}
22699
22700
// passed iterators must belong to objects
22701
if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22702
{
22703
JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
22704
}
22705
22706
m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
22707
}
22708
22709
/// @brief updates a JSON object from another object, overwriting existing keys
22710
/// @sa https://json.nlohmann.me/api/basic_json/update/
22711
void update(const_reference j, bool merge_objects = false)
22712
{
22713
update(j.begin(), j.end(), merge_objects);
22714
}
22715
22716
/// @brief updates a JSON object from another object, overwriting existing keys
22717
/// @sa https://json.nlohmann.me/api/basic_json/update/
22718
void update(const_iterator first, const_iterator last, bool merge_objects = false)
22719
{
22720
// implicitly convert null value to an empty object
22721
if (is_null())
22722
{
22723
m_data.m_type = value_t::object;
22724
m_data.m_value.object = create<object_t>();
22725
assert_invariant();
22726
}
22727
22728
if (JSON_HEDLEY_UNLIKELY(!is_object()))
22729
{
22730
JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
22731
}
22732
22733
// check if range iterators belong to the same JSON object
22734
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22735
{
22736
JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22737
}
22738
22739
// passed iterators must belong to objects
22740
if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22741
{
22742
JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
22743
}
22744
22745
for (auto it = first; it != last; ++it)
22746
{
22747
if (merge_objects && it.value().is_object())
22748
{
22749
auto it2 = m_data.m_value.object->find(it.key());
22750
if (it2 != m_data.m_value.object->end())
22751
{
22752
it2->second.update(it.value(), true);
22753
continue;
22754
}
22755
}
22756
m_data.m_value.object->operator[](it.key()) = it.value();
22757
#if JSON_DIAGNOSTICS
22758
m_data.m_value.object->operator[](it.key()).m_parent = this;
22759
#endif
22760
}
22761
}
22762
22763
/// @brief exchanges the values
22764
/// @sa https://json.nlohmann.me/api/basic_json/swap/
22765
void swap(reference other) noexcept (
22766
std::is_nothrow_move_constructible<value_t>::value&&
22767
std::is_nothrow_move_assignable<value_t>::value&&
22768
std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22769
std::is_nothrow_move_assignable<json_value>::value
22770
)
22771
{
22772
std::swap(m_data.m_type, other.m_data.m_type);
22773
std::swap(m_data.m_value, other.m_data.m_value);
22774
22775
set_parents();
22776
other.set_parents();
22777
assert_invariant();
22778
}
22779
22780
/// @brief exchanges the values
22781
/// @sa https://json.nlohmann.me/api/basic_json/swap/
22782
friend void swap(reference left, reference right) noexcept (
22783
std::is_nothrow_move_constructible<value_t>::value&&
22784
std::is_nothrow_move_assignable<value_t>::value&&
22785
std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22786
std::is_nothrow_move_assignable<json_value>::value
22787
)
22788
{
22789
left.swap(right);
22790
}
22791
22792
/// @brief exchanges the values
22793
/// @sa https://json.nlohmann.me/api/basic_json/swap/
22794
void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22795
{
22796
// swap only works for arrays
22797
if (JSON_HEDLEY_LIKELY(is_array()))
22798
{
22799
using std::swap;
22800
swap(*(m_data.m_value.array), other);
22801
}
22802
else
22803
{
22804
JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
22805
}
22806
}
22807
22808
/// @brief exchanges the values
22809
/// @sa https://json.nlohmann.me/api/basic_json/swap/
22810
void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22811
{
22812
// swap only works for objects
22813
if (JSON_HEDLEY_LIKELY(is_object()))
22814
{
22815
using std::swap;
22816
swap(*(m_data.m_value.object), other);
22817
}
22818
else
22819
{
22820
JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
22821
}
22822
}
22823
22824
/// @brief exchanges the values
22825
/// @sa https://json.nlohmann.me/api/basic_json/swap/
22826
void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22827
{
22828
// swap only works for strings
22829
if (JSON_HEDLEY_LIKELY(is_string()))
22830
{
22831
using std::swap;
22832
swap(*(m_data.m_value.string), other);
22833
}
22834
else
22835
{
22836
JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
22837
}
22838
}
22839
22840
/// @brief exchanges the values
22841
/// @sa https://json.nlohmann.me/api/basic_json/swap/
22842
void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22843
{
22844
// swap only works for strings
22845
if (JSON_HEDLEY_LIKELY(is_binary()))
22846
{
22847
using std::swap;
22848
swap(*(m_data.m_value.binary), other);
22849
}
22850
else
22851
{
22852
JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
22853
}
22854
}
22855
22856
/// @brief exchanges the values
22857
/// @sa https://json.nlohmann.me/api/basic_json/swap/
22858
void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
22859
{
22860
// swap only works for strings
22861
if (JSON_HEDLEY_LIKELY(is_binary()))
22862
{
22863
using std::swap;
22864
swap(*(m_data.m_value.binary), other);
22865
}
22866
else
22867
{
22868
JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
22869
}
22870
}
22871
22872
/// @}
22873
22874
//////////////////////////////////////////
22875
// lexicographical comparison operators //
22876
//////////////////////////////////////////
22877
22878
/// @name lexicographical comparison operators
22879
/// @{
22880
22881
// note parentheses around operands are necessary; see
22882
// https://github.com/nlohmann/json/issues/1530
22883
#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
22884
const auto lhs_type = lhs.type(); \
22885
const auto rhs_type = rhs.type(); \
22886
\
22887
if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
22888
{ \
22889
switch (lhs_type) \
22890
{ \
22891
case value_t::array: \
22892
return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
22893
\
22894
case value_t::object: \
22895
return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
22896
\
22897
case value_t::null: \
22898
return (null_result); \
22899
\
22900
case value_t::string: \
22901
return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
22902
\
22903
case value_t::boolean: \
22904
return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
22905
\
22906
case value_t::number_integer: \
22907
return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
22908
\
22909
case value_t::number_unsigned: \
22910
return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
22911
\
22912
case value_t::number_float: \
22913
return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
22914
\
22915
case value_t::binary: \
22916
return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
22917
\
22918
case value_t::discarded: \
22919
default: \
22920
return (unordered_result); \
22921
} \
22922
} \
22923
else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
22924
{ \
22925
return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
22926
} \
22927
else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
22928
{ \
22929
return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
22930
} \
22931
else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
22932
{ \
22933
return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
22934
} \
22935
else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
22936
{ \
22937
return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
22938
} \
22939
else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
22940
{ \
22941
return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
22942
} \
22943
else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
22944
{ \
22945
return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
22946
} \
22947
else if(compares_unordered(lhs, rhs))\
22948
{\
22949
return (unordered_result);\
22950
}\
22951
\
22952
return (default_result);
22953
22954
JSON_PRIVATE_UNLESS_TESTED:
22955
// returns true if:
22956
// - any operand is NaN and the other operand is of number type
22957
// - any operand is discarded
22958
// in legacy mode, discarded values are considered ordered if
22959
// an operation is computed as an odd number of inverses of others
22960
static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
22961
{
22962
if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
22963
|| (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
22964
{
22965
return true;
22966
}
22967
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22968
return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
22969
#else
22970
static_cast<void>(inverse);
22971
return lhs.is_discarded() || rhs.is_discarded();
22972
#endif
22973
}
22974
22975
private:
22976
bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
22977
{
22978
return compares_unordered(*this, rhs, inverse);
22979
}
22980
22981
public:
22982
#if JSON_HAS_THREE_WAY_COMPARISON
22983
/// @brief comparison: equal
22984
/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
22985
bool operator==(const_reference rhs) const noexcept
22986
{
22987
#ifdef __GNUC__
22988
#pragma GCC diagnostic push
22989
#pragma GCC diagnostic ignored "-Wfloat-equal"
22990
#endif
22991
const_reference lhs = *this;
22992
JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
22993
#ifdef __GNUC__
22994
#pragma GCC diagnostic pop
22995
#endif
22996
}
22997
22998
/// @brief comparison: equal
22999
/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23000
template<typename ScalarType>
23001
requires std::is_scalar_v<ScalarType>
23002
bool operator==(ScalarType rhs) const noexcept
23003
{
23004
return *this == basic_json(rhs);
23005
}
23006
23007
/// @brief comparison: not equal
23008
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23009
bool operator!=(const_reference rhs) const noexcept
23010
{
23011
if (compares_unordered(rhs, true))
23012
{
23013
return false;
23014
}
23015
return !operator==(rhs);
23016
}
23017
23018
/// @brief comparison: 3-way
23019
/// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
23020
std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23021
{
23022
const_reference lhs = *this;
23023
// default_result is used if we cannot compare values. In that case,
23024
// we compare types.
23025
JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23026
std::partial_ordering::equivalent,
23027
std::partial_ordering::unordered,
23028
lhs_type <=> rhs_type) // *NOPAD*
23029
}
23030
23031
/// @brief comparison: 3-way
23032
/// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
23033
template<typename ScalarType>
23034
requires std::is_scalar_v<ScalarType>
23035
std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23036
{
23037
return *this <=> basic_json(rhs); // *NOPAD*
23038
}
23039
23040
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23041
// all operators that are computed as an odd number of inverses of others
23042
// need to be overloaded to emulate the legacy comparison behavior
23043
23044
/// @brief comparison: less than or equal
23045
/// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23046
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23047
bool operator<=(const_reference rhs) const noexcept
23048
{
23049
if (compares_unordered(rhs, true))
23050
{
23051
return false;
23052
}
23053
return !(rhs < *this);
23054
}
23055
23056
/// @brief comparison: less than or equal
23057
/// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23058
template<typename ScalarType>
23059
requires std::is_scalar_v<ScalarType>
23060
bool operator<=(ScalarType rhs) const noexcept
23061
{
23062
return *this <= basic_json(rhs);
23063
}
23064
23065
/// @brief comparison: greater than or equal
23066
/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23067
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23068
bool operator>=(const_reference rhs) const noexcept
23069
{
23070
if (compares_unordered(rhs, true))
23071
{
23072
return false;
23073
}
23074
return !(*this < rhs);
23075
}
23076
23077
/// @brief comparison: greater than or equal
23078
/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23079
template<typename ScalarType>
23080
requires std::is_scalar_v<ScalarType>
23081
bool operator>=(ScalarType rhs) const noexcept
23082
{
23083
return *this >= basic_json(rhs);
23084
}
23085
#endif
23086
#else
23087
/// @brief comparison: equal
23088
/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23089
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23090
{
23091
#ifdef __GNUC__
23092
#pragma GCC diagnostic push
23093
#pragma GCC diagnostic ignored "-Wfloat-equal"
23094
#endif
23095
JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23096
#ifdef __GNUC__
23097
#pragma GCC diagnostic pop
23098
#endif
23099
}
23100
23101
/// @brief comparison: equal
23102
/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23103
template<typename ScalarType, typename std::enable_if<
23104
std::is_scalar<ScalarType>::value, int>::type = 0>
23105
friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23106
{
23107
return lhs == basic_json(rhs);
23108
}
23109
23110
/// @brief comparison: equal
23111
/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23112
template<typename ScalarType, typename std::enable_if<
23113
std::is_scalar<ScalarType>::value, int>::type = 0>
23114
friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23115
{
23116
return basic_json(lhs) == rhs;
23117
}
23118
23119
/// @brief comparison: not equal
23120
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23121
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23122
{
23123
if (compares_unordered(lhs, rhs, true))
23124
{
23125
return false;
23126
}
23127
return !(lhs == rhs);
23128
}
23129
23130
/// @brief comparison: not equal
23131
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23132
template<typename ScalarType, typename std::enable_if<
23133
std::is_scalar<ScalarType>::value, int>::type = 0>
23134
friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23135
{
23136
return lhs != basic_json(rhs);
23137
}
23138
23139
/// @brief comparison: not equal
23140
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23141
template<typename ScalarType, typename std::enable_if<
23142
std::is_scalar<ScalarType>::value, int>::type = 0>
23143
friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23144
{
23145
return basic_json(lhs) != rhs;
23146
}
23147
23148
/// @brief comparison: less than
23149
/// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23150
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23151
{
23152
// default_result is used if we cannot compare values. In that case,
23153
// we compare types. Note we have to call the operator explicitly,
23154
// because MSVC has problems otherwise.
23155
JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23156
}
23157
23158
/// @brief comparison: less than
23159
/// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23160
template<typename ScalarType, typename std::enable_if<
23161
std::is_scalar<ScalarType>::value, int>::type = 0>
23162
friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23163
{
23164
return lhs < basic_json(rhs);
23165
}
23166
23167
/// @brief comparison: less than
23168
/// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23169
template<typename ScalarType, typename std::enable_if<
23170
std::is_scalar<ScalarType>::value, int>::type = 0>
23171
friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
23172
{
23173
return basic_json(lhs) < rhs;
23174
}
23175
23176
/// @brief comparison: less than or equal
23177
/// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23178
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
23179
{
23180
if (compares_unordered(lhs, rhs, true))
23181
{
23182
return false;
23183
}
23184
return !(rhs < lhs);
23185
}
23186
23187
/// @brief comparison: less than or equal
23188
/// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23189
template<typename ScalarType, typename std::enable_if<
23190
std::is_scalar<ScalarType>::value, int>::type = 0>
23191
friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
23192
{
23193
return lhs <= basic_json(rhs);
23194
}
23195
23196
/// @brief comparison: less than or equal
23197
/// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23198
template<typename ScalarType, typename std::enable_if<
23199
std::is_scalar<ScalarType>::value, int>::type = 0>
23200
friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
23201
{
23202
return basic_json(lhs) <= rhs;
23203
}
23204
23205
/// @brief comparison: greater than
23206
/// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23207
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
23208
{
23209
// double inverse
23210
if (compares_unordered(lhs, rhs))
23211
{
23212
return false;
23213
}
23214
return !(lhs <= rhs);
23215
}
23216
23217
/// @brief comparison: greater than
23218
/// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23219
template<typename ScalarType, typename std::enable_if<
23220
std::is_scalar<ScalarType>::value, int>::type = 0>
23221
friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
23222
{
23223
return lhs > basic_json(rhs);
23224
}
23225
23226
/// @brief comparison: greater than
23227
/// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23228
template<typename ScalarType, typename std::enable_if<
23229
std::is_scalar<ScalarType>::value, int>::type = 0>
23230
friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
23231
{
23232
return basic_json(lhs) > rhs;
23233
}
23234
23235
/// @brief comparison: greater than or equal
23236
/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23237
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
23238
{
23239
if (compares_unordered(lhs, rhs, true))
23240
{
23241
return false;
23242
}
23243
return !(lhs < rhs);
23244
}
23245
23246
/// @brief comparison: greater than or equal
23247
/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23248
template<typename ScalarType, typename std::enable_if<
23249
std::is_scalar<ScalarType>::value, int>::type = 0>
23250
friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
23251
{
23252
return lhs >= basic_json(rhs);
23253
}
23254
23255
/// @brief comparison: greater than or equal
23256
/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23257
template<typename ScalarType, typename std::enable_if<
23258
std::is_scalar<ScalarType>::value, int>::type = 0>
23259
friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
23260
{
23261
return basic_json(lhs) >= rhs;
23262
}
23263
#endif
23264
23265
#undef JSON_IMPLEMENT_OPERATOR
23266
23267
/// @}
23268
23269
///////////////////
23270
// serialization //
23271
///////////////////
23272
23273
/// @name serialization
23274
/// @{
23275
#ifndef JSON_NO_IO
23276
/// @brief serialize to stream
23277
/// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
23278
friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
23279
{
23280
// read width member and use it as indentation parameter if nonzero
23281
const bool pretty_print = o.width() > 0;
23282
const auto indentation = pretty_print ? o.width() : 0;
23283
23284
// reset width to 0 for subsequent calls to this stream
23285
o.width(0);
23286
23287
// do the actual serialization
23288
serializer s(detail::output_adapter<char>(o), o.fill());
23289
s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
23290
return o;
23291
}
23292
23293
/// @brief serialize to stream
23294
/// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
23295
/// @deprecated This function is deprecated since 3.0.0 and will be removed in
23296
/// version 4.0.0 of the library. Please use
23297
/// operator<<(std::ostream&, const basic_json&) instead; that is,
23298
/// replace calls like `j >> o;` with `o << j;`.
23299
JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
23300
friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
23301
{
23302
return o << j;
23303
}
23304
#endif // JSON_NO_IO
23305
/// @}
23306
23307
/////////////////////
23308
// deserialization //
23309
/////////////////////
23310
23311
/// @name deserialization
23312
/// @{
23313
23314
/// @brief deserialize from a compatible input
23315
/// @sa https://json.nlohmann.me/api/basic_json/parse/
23316
template<typename InputType>
23317
JSON_HEDLEY_WARN_UNUSED_RESULT
23318
static basic_json parse(InputType&& i,
23319
const parser_callback_t cb = nullptr,
23320
const bool allow_exceptions = true,
23321
const bool ignore_comments = false)
23322
{
23323
basic_json result;
23324
parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
23325
return result;
23326
}
23327
23328
/// @brief deserialize from a pair of character iterators
23329
/// @sa https://json.nlohmann.me/api/basic_json/parse/
23330
template<typename IteratorType>
23331
JSON_HEDLEY_WARN_UNUSED_RESULT
23332
static basic_json parse(IteratorType first,
23333
IteratorType last,
23334
const parser_callback_t cb = nullptr,
23335
const bool allow_exceptions = true,
23336
const bool ignore_comments = false)
23337
{
23338
basic_json result;
23339
parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
23340
return result;
23341
}
23342
23343
JSON_HEDLEY_WARN_UNUSED_RESULT
23344
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
23345
static basic_json parse(detail::span_input_adapter&& i,
23346
const parser_callback_t cb = nullptr,
23347
const bool allow_exceptions = true,
23348
const bool ignore_comments = false)
23349
{
23350
basic_json result;
23351
parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
23352
return result;
23353
}
23354
23355
/// @brief check if the input is valid JSON
23356
/// @sa https://json.nlohmann.me/api/basic_json/accept/
23357
template<typename InputType>
23358
static bool accept(InputType&& i,
23359
const bool ignore_comments = false)
23360
{
23361
return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
23362
}
23363
23364
/// @brief check if the input is valid JSON
23365
/// @sa https://json.nlohmann.me/api/basic_json/accept/
23366
template<typename IteratorType>
23367
static bool accept(IteratorType first, IteratorType last,
23368
const bool ignore_comments = false)
23369
{
23370
return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
23371
}
23372
23373
JSON_HEDLEY_WARN_UNUSED_RESULT
23374
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
23375
static bool accept(detail::span_input_adapter&& i,
23376
const bool ignore_comments = false)
23377
{
23378
return parser(i.get(), nullptr, false, ignore_comments).accept(true);
23379
}
23380
23381
/// @brief generate SAX events
23382
/// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
23383
template <typename InputType, typename SAX>
23384
JSON_HEDLEY_NON_NULL(2)
23385
static bool sax_parse(InputType&& i, SAX* sax,
23386
input_format_t format = input_format_t::json,
23387
const bool strict = true,
23388
const bool ignore_comments = false)
23389
{
23390
auto ia = detail::input_adapter(std::forward<InputType>(i));
23391
return format == input_format_t::json
23392
? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23393
: detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23394
}
23395
23396
/// @brief generate SAX events
23397
/// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
23398
template<class IteratorType, class SAX>
23399
JSON_HEDLEY_NON_NULL(3)
23400
static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
23401
input_format_t format = input_format_t::json,
23402
const bool strict = true,
23403
const bool ignore_comments = false)
23404
{
23405
auto ia = detail::input_adapter(std::move(first), std::move(last));
23406
return format == input_format_t::json
23407
? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23408
: detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23409
}
23410
23411
/// @brief generate SAX events
23412
/// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
23413
/// @deprecated This function is deprecated since 3.8.0 and will be removed in
23414
/// version 4.0.0 of the library. Please use
23415
/// sax_parse(ptr, ptr + len) instead.
23416
template <typename SAX>
23417
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
23418
JSON_HEDLEY_NON_NULL(2)
23419
static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
23420
input_format_t format = input_format_t::json,
23421
const bool strict = true,
23422
const bool ignore_comments = false)
23423
{
23424
auto ia = i.get();
23425
return format == input_format_t::json
23426
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23427
? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23428
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23429
: detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23430
}
23431
#ifndef JSON_NO_IO
23432
/// @brief deserialize from stream
23433
/// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
23434
/// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
23435
/// version 4.0.0 of the library. Please use
23436
/// operator>>(std::istream&, basic_json&) instead; that is,
23437
/// replace calls like `j << i;` with `i >> j;`.
23438
JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
23439
friend std::istream& operator<<(basic_json& j, std::istream& i)
23440
{
23441
return operator>>(i, j);
23442
}
23443
23444
/// @brief deserialize from stream
23445
/// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
23446
friend std::istream& operator>>(std::istream& i, basic_json& j)
23447
{
23448
parser(detail::input_adapter(i)).parse(false, j);
23449
return i;
23450
}
23451
#endif // JSON_NO_IO
23452
/// @}
23453
23454
///////////////////////////
23455
// convenience functions //
23456
///////////////////////////
23457
23458
/// @brief return the type as string
23459
/// @sa https://json.nlohmann.me/api/basic_json/type_name/
23460
JSON_HEDLEY_RETURNS_NON_NULL
23461
const char* type_name() const noexcept
23462
{
23463
switch (m_data.m_type)
23464
{
23465
case value_t::null:
23466
return "null";
23467
case value_t::object:
23468
return "object";
23469
case value_t::array:
23470
return "array";
23471
case value_t::string:
23472
return "string";
23473
case value_t::boolean:
23474
return "boolean";
23475
case value_t::binary:
23476
return "binary";
23477
case value_t::discarded:
23478
return "discarded";
23479
case value_t::number_integer:
23480
case value_t::number_unsigned:
23481
case value_t::number_float:
23482
default:
23483
return "number";
23484
}
23485
}
23486
23487
JSON_PRIVATE_UNLESS_TESTED:
23488
//////////////////////
23489
// member variables //
23490
//////////////////////
23491
23492
struct data
23493
{
23494
/// the type of the current element
23495
value_t m_type = value_t::null;
23496
23497
/// the value of the current element
23498
json_value m_value = {};
23499
23500
data(const value_t v)
23501
: m_type(v), m_value(v)
23502
{
23503
}
23504
23505
data(size_type cnt, const basic_json& val)
23506
: m_type(value_t::array)
23507
{
23508
m_value.array = create<array_t>(cnt, val);
23509
}
23510
23511
data() noexcept = default;
23512
data(data&&) noexcept = default;
23513
data(const data&) noexcept = delete;
23514
data& operator=(data&&) noexcept = delete;
23515
data& operator=(const data&) noexcept = delete;
23516
23517
~data() noexcept
23518
{
23519
m_value.destroy(m_type);
23520
}
23521
};
23522
23523
data m_data = {};
23524
23525
#if JSON_DIAGNOSTICS
23526
/// a pointer to a parent value (for debugging purposes)
23527
basic_json* m_parent = nullptr;
23528
#endif
23529
23530
//////////////////////////////////////////
23531
// binary serialization/deserialization //
23532
//////////////////////////////////////////
23533
23534
/// @name binary serialization/deserialization support
23535
/// @{
23536
23537
public:
23538
/// @brief create a CBOR serialization of a given JSON value
23539
/// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
23540
static std::vector<std::uint8_t> to_cbor(const basic_json& j)
23541
{
23542
std::vector<std::uint8_t> result;
23543
to_cbor(j, result);
23544
return result;
23545
}
23546
23547
/// @brief create a CBOR serialization of a given JSON value
23548
/// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
23549
static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23550
{
23551
binary_writer<std::uint8_t>(o).write_cbor(j);
23552
}
23553
23554
/// @brief create a CBOR serialization of a given JSON value
23555
/// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
23556
static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
23557
{
23558
binary_writer<char>(o).write_cbor(j);
23559
}
23560
23561
/// @brief create a MessagePack serialization of a given JSON value
23562
/// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
23563
static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
23564
{
23565
std::vector<std::uint8_t> result;
23566
to_msgpack(j, result);
23567
return result;
23568
}
23569
23570
/// @brief create a MessagePack serialization of a given JSON value
23571
/// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
23572
static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23573
{
23574
binary_writer<std::uint8_t>(o).write_msgpack(j);
23575
}
23576
23577
/// @brief create a MessagePack serialization of a given JSON value
23578
/// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
23579
static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
23580
{
23581
binary_writer<char>(o).write_msgpack(j);
23582
}
23583
23584
/// @brief create a UBJSON serialization of a given JSON value
23585
/// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
23586
static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
23587
const bool use_size = false,
23588
const bool use_type = false)
23589
{
23590
std::vector<std::uint8_t> result;
23591
to_ubjson(j, result, use_size, use_type);
23592
return result;
23593
}
23594
23595
/// @brief create a UBJSON serialization of a given JSON value
23596
/// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
23597
static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
23598
const bool use_size = false, const bool use_type = false)
23599
{
23600
binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
23601
}
23602
23603
/// @brief create a UBJSON serialization of a given JSON value
23604
/// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
23605
static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
23606
const bool use_size = false, const bool use_type = false)
23607
{
23608
binary_writer<char>(o).write_ubjson(j, use_size, use_type);
23609
}
23610
23611
/// @brief create a BJData serialization of a given JSON value
23612
/// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
23613
static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
23614
const bool use_size = false,
23615
const bool use_type = false)
23616
{
23617
std::vector<std::uint8_t> result;
23618
to_bjdata(j, result, use_size, use_type);
23619
return result;
23620
}
23621
23622
/// @brief create a BJData serialization of a given JSON value
23623
/// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
23624
static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
23625
const bool use_size = false, const bool use_type = false)
23626
{
23627
binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
23628
}
23629
23630
/// @brief create a BJData serialization of a given JSON value
23631
/// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
23632
static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
23633
const bool use_size = false, const bool use_type = false)
23634
{
23635
binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
23636
}
23637
23638
/// @brief create a BSON serialization of a given JSON value
23639
/// @sa https://json.nlohmann.me/api/basic_json/to_bson/
23640
static std::vector<std::uint8_t> to_bson(const basic_json& j)
23641
{
23642
std::vector<std::uint8_t> result;
23643
to_bson(j, result);
23644
return result;
23645
}
23646
23647
/// @brief create a BSON serialization of a given JSON value
23648
/// @sa https://json.nlohmann.me/api/basic_json/to_bson/
23649
static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23650
{
23651
binary_writer<std::uint8_t>(o).write_bson(j);
23652
}
23653
23654
/// @brief create a BSON serialization of a given JSON value
23655
/// @sa https://json.nlohmann.me/api/basic_json/to_bson/
23656
static void to_bson(const basic_json& j, detail::output_adapter<char> o)
23657
{
23658
binary_writer<char>(o).write_bson(j);
23659
}
23660
23661
/// @brief create a JSON value from an input in CBOR format
23662
/// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
23663
template<typename InputType>
23664
JSON_HEDLEY_WARN_UNUSED_RESULT
23665
static basic_json from_cbor(InputType&& i,
23666
const bool strict = true,
23667
const bool allow_exceptions = true,
23668
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23669
{
23670
basic_json result;
23671
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23672
auto ia = detail::input_adapter(std::forward<InputType>(i));
23673
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23674
return res ? result : basic_json(value_t::discarded);
23675
}
23676
23677
/// @brief create a JSON value from an input in CBOR format
23678
/// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
23679
template<typename IteratorType>
23680
JSON_HEDLEY_WARN_UNUSED_RESULT
23681
static basic_json from_cbor(IteratorType first, IteratorType last,
23682
const bool strict = true,
23683
const bool allow_exceptions = true,
23684
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23685
{
23686
basic_json result;
23687
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23688
auto ia = detail::input_adapter(std::move(first), std::move(last));
23689
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23690
return res ? result : basic_json(value_t::discarded);
23691
}
23692
23693
template<typename T>
23694
JSON_HEDLEY_WARN_UNUSED_RESULT
23695
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23696
static basic_json from_cbor(const T* ptr, std::size_t len,
23697
const bool strict = true,
23698
const bool allow_exceptions = true,
23699
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23700
{
23701
return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
23702
}
23703
23704
JSON_HEDLEY_WARN_UNUSED_RESULT
23705
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23706
static basic_json from_cbor(detail::span_input_adapter&& i,
23707
const bool strict = true,
23708
const bool allow_exceptions = true,
23709
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23710
{
23711
basic_json result;
23712
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23713
auto ia = i.get();
23714
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23715
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23716
return res ? result : basic_json(value_t::discarded);
23717
}
23718
23719
/// @brief create a JSON value from an input in MessagePack format
23720
/// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
23721
template<typename InputType>
23722
JSON_HEDLEY_WARN_UNUSED_RESULT
23723
static basic_json from_msgpack(InputType&& i,
23724
const bool strict = true,
23725
const bool allow_exceptions = true)
23726
{
23727
basic_json result;
23728
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23729
auto ia = detail::input_adapter(std::forward<InputType>(i));
23730
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23731
return res ? result : basic_json(value_t::discarded);
23732
}
23733
23734
/// @brief create a JSON value from an input in MessagePack format
23735
/// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
23736
template<typename IteratorType>
23737
JSON_HEDLEY_WARN_UNUSED_RESULT
23738
static basic_json from_msgpack(IteratorType first, IteratorType last,
23739
const bool strict = true,
23740
const bool allow_exceptions = true)
23741
{
23742
basic_json result;
23743
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23744
auto ia = detail::input_adapter(std::move(first), std::move(last));
23745
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23746
return res ? result : basic_json(value_t::discarded);
23747
}
23748
23749
template<typename T>
23750
JSON_HEDLEY_WARN_UNUSED_RESULT
23751
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23752
static basic_json from_msgpack(const T* ptr, std::size_t len,
23753
const bool strict = true,
23754
const bool allow_exceptions = true)
23755
{
23756
return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
23757
}
23758
23759
JSON_HEDLEY_WARN_UNUSED_RESULT
23760
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23761
static basic_json from_msgpack(detail::span_input_adapter&& i,
23762
const bool strict = true,
23763
const bool allow_exceptions = true)
23764
{
23765
basic_json result;
23766
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23767
auto ia = i.get();
23768
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23769
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23770
return res ? result : basic_json(value_t::discarded);
23771
}
23772
23773
/// @brief create a JSON value from an input in UBJSON format
23774
/// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
23775
template<typename InputType>
23776
JSON_HEDLEY_WARN_UNUSED_RESULT
23777
static basic_json from_ubjson(InputType&& i,
23778
const bool strict = true,
23779
const bool allow_exceptions = true)
23780
{
23781
basic_json result;
23782
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23783
auto ia = detail::input_adapter(std::forward<InputType>(i));
23784
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23785
return res ? result : basic_json(value_t::discarded);
23786
}
23787
23788
/// @brief create a JSON value from an input in UBJSON format
23789
/// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
23790
template<typename IteratorType>
23791
JSON_HEDLEY_WARN_UNUSED_RESULT
23792
static basic_json from_ubjson(IteratorType first, IteratorType last,
23793
const bool strict = true,
23794
const bool allow_exceptions = true)
23795
{
23796
basic_json result;
23797
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23798
auto ia = detail::input_adapter(std::move(first), std::move(last));
23799
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23800
return res ? result : basic_json(value_t::discarded);
23801
}
23802
23803
template<typename T>
23804
JSON_HEDLEY_WARN_UNUSED_RESULT
23805
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23806
static basic_json from_ubjson(const T* ptr, std::size_t len,
23807
const bool strict = true,
23808
const bool allow_exceptions = true)
23809
{
23810
return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
23811
}
23812
23813
JSON_HEDLEY_WARN_UNUSED_RESULT
23814
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23815
static basic_json from_ubjson(detail::span_input_adapter&& i,
23816
const bool strict = true,
23817
const bool allow_exceptions = true)
23818
{
23819
basic_json result;
23820
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23821
auto ia = i.get();
23822
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23823
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23824
return res ? result : basic_json(value_t::discarded);
23825
}
23826
23827
/// @brief create a JSON value from an input in BJData format
23828
/// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
23829
template<typename InputType>
23830
JSON_HEDLEY_WARN_UNUSED_RESULT
23831
static basic_json from_bjdata(InputType&& i,
23832
const bool strict = true,
23833
const bool allow_exceptions = true)
23834
{
23835
basic_json result;
23836
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23837
auto ia = detail::input_adapter(std::forward<InputType>(i));
23838
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23839
return res ? result : basic_json(value_t::discarded);
23840
}
23841
23842
/// @brief create a JSON value from an input in BJData format
23843
/// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
23844
template<typename IteratorType>
23845
JSON_HEDLEY_WARN_UNUSED_RESULT
23846
static basic_json from_bjdata(IteratorType first, IteratorType last,
23847
const bool strict = true,
23848
const bool allow_exceptions = true)
23849
{
23850
basic_json result;
23851
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23852
auto ia = detail::input_adapter(std::move(first), std::move(last));
23853
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23854
return res ? result : basic_json(value_t::discarded);
23855
}
23856
23857
/// @brief create a JSON value from an input in BSON format
23858
/// @sa https://json.nlohmann.me/api/basic_json/from_bson/
23859
template<typename InputType>
23860
JSON_HEDLEY_WARN_UNUSED_RESULT
23861
static basic_json from_bson(InputType&& i,
23862
const bool strict = true,
23863
const bool allow_exceptions = true)
23864
{
23865
basic_json result;
23866
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23867
auto ia = detail::input_adapter(std::forward<InputType>(i));
23868
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23869
return res ? result : basic_json(value_t::discarded);
23870
}
23871
23872
/// @brief create a JSON value from an input in BSON format
23873
/// @sa https://json.nlohmann.me/api/basic_json/from_bson/
23874
template<typename IteratorType>
23875
JSON_HEDLEY_WARN_UNUSED_RESULT
23876
static basic_json from_bson(IteratorType first, IteratorType last,
23877
const bool strict = true,
23878
const bool allow_exceptions = true)
23879
{
23880
basic_json result;
23881
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23882
auto ia = detail::input_adapter(std::move(first), std::move(last));
23883
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23884
return res ? result : basic_json(value_t::discarded);
23885
}
23886
23887
template<typename T>
23888
JSON_HEDLEY_WARN_UNUSED_RESULT
23889
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23890
static basic_json from_bson(const T* ptr, std::size_t len,
23891
const bool strict = true,
23892
const bool allow_exceptions = true)
23893
{
23894
return from_bson(ptr, ptr + len, strict, allow_exceptions);
23895
}
23896
23897
JSON_HEDLEY_WARN_UNUSED_RESULT
23898
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23899
static basic_json from_bson(detail::span_input_adapter&& i,
23900
const bool strict = true,
23901
const bool allow_exceptions = true)
23902
{
23903
basic_json result;
23904
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23905
auto ia = i.get();
23906
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23907
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23908
return res ? result : basic_json(value_t::discarded);
23909
}
23910
/// @}
23911
23912
//////////////////////////
23913
// JSON Pointer support //
23914
//////////////////////////
23915
23916
/// @name JSON Pointer functions
23917
/// @{
23918
23919
/// @brief access specified element via JSON Pointer
23920
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
23921
reference operator[](const json_pointer& ptr)
23922
{
23923
return ptr.get_unchecked(this);
23924
}
23925
23926
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23927
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23928
reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23929
{
23930
return ptr.get_unchecked(this);
23931
}
23932
23933
/// @brief access specified element via JSON Pointer
23934
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
23935
const_reference operator[](const json_pointer& ptr) const
23936
{
23937
return ptr.get_unchecked(this);
23938
}
23939
23940
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23941
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23942
const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23943
{
23944
return ptr.get_unchecked(this);
23945
}
23946
23947
/// @brief access specified element via JSON Pointer
23948
/// @sa https://json.nlohmann.me/api/basic_json/at/
23949
reference at(const json_pointer& ptr)
23950
{
23951
return ptr.get_checked(this);
23952
}
23953
23954
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23955
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23956
reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23957
{
23958
return ptr.get_checked(this);
23959
}
23960
23961
/// @brief access specified element via JSON Pointer
23962
/// @sa https://json.nlohmann.me/api/basic_json/at/
23963
const_reference at(const json_pointer& ptr) const
23964
{
23965
return ptr.get_checked(this);
23966
}
23967
23968
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23969
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23970
const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23971
{
23972
return ptr.get_checked(this);
23973
}
23974
23975
/// @brief return flattened JSON value
23976
/// @sa https://json.nlohmann.me/api/basic_json/flatten/
23977
basic_json flatten() const
23978
{
23979
basic_json result(value_t::object);
23980
json_pointer::flatten("", *this, result);
23981
return result;
23982
}
23983
23984
/// @brief unflatten a previously flattened JSON value
23985
/// @sa https://json.nlohmann.me/api/basic_json/unflatten/
23986
basic_json unflatten() const
23987
{
23988
return json_pointer::unflatten(*this);
23989
}
23990
23991
/// @}
23992
23993
//////////////////////////
23994
// JSON Patch functions //
23995
//////////////////////////
23996
23997
/// @name JSON Patch functions
23998
/// @{
23999
24000
/// @brief applies a JSON patch in-place without copying the object
24001
/// @sa https://json.nlohmann.me/api/basic_json/patch/
24002
void patch_inplace(const basic_json& json_patch)
24003
{
24004
basic_json& result = *this;
24005
// the valid JSON Patch operations
24006
enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24007
24008
const auto get_op = [](const std::string & op)
24009
{
24010
if (op == "add")
24011
{
24012
return patch_operations::add;
24013
}
24014
if (op == "remove")
24015
{
24016
return patch_operations::remove;
24017
}
24018
if (op == "replace")
24019
{
24020
return patch_operations::replace;
24021
}
24022
if (op == "move")
24023
{
24024
return patch_operations::move;
24025
}
24026
if (op == "copy")
24027
{
24028
return patch_operations::copy;
24029
}
24030
if (op == "test")
24031
{
24032
return patch_operations::test;
24033
}
24034
24035
return patch_operations::invalid;
24036
};
24037
24038
// wrapper for "add" operation; add value at ptr
24039
const auto operation_add = [&result](json_pointer & ptr, basic_json val)
24040
{
24041
// adding to the root of the target document means replacing it
24042
if (ptr.empty())
24043
{
24044
result = val;
24045
return;
24046
}
24047
24048
// make sure the top element of the pointer exists
24049
json_pointer const top_pointer = ptr.top();
24050
if (top_pointer != ptr)
24051
{
24052
result.at(top_pointer);
24053
}
24054
24055
// get reference to parent of JSON pointer ptr
24056
const auto last_path = ptr.back();
24057
ptr.pop_back();
24058
// parent must exist when performing patch add per RFC6902 specs
24059
basic_json& parent = result.at(ptr);
24060
24061
switch (parent.m_data.m_type)
24062
{
24063
case value_t::null:
24064
case value_t::object:
24065
{
24066
// use operator[] to add value
24067
parent[last_path] = val;
24068
break;
24069
}
24070
24071
case value_t::array:
24072
{
24073
if (last_path == "-")
24074
{
24075
// special case: append to back
24076
parent.push_back(val);
24077
}
24078
else
24079
{
24080
const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24081
if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24082
{
24083
// avoid undefined behavior
24084
JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24085
}
24086
24087
// default case: insert add offset
24088
parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24089
}
24090
break;
24091
}
24092
24093
// if there exists a parent it cannot be primitive
24094
case value_t::string: // LCOV_EXCL_LINE
24095
case value_t::boolean: // LCOV_EXCL_LINE
24096
case value_t::number_integer: // LCOV_EXCL_LINE
24097
case value_t::number_unsigned: // LCOV_EXCL_LINE
24098
case value_t::number_float: // LCOV_EXCL_LINE
24099
case value_t::binary: // LCOV_EXCL_LINE
24100
case value_t::discarded: // LCOV_EXCL_LINE
24101
default: // LCOV_EXCL_LINE
24102
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24103
}
24104
};
24105
24106
// wrapper for "remove" operation; remove value at ptr
24107
const auto operation_remove = [this, & result](json_pointer & ptr)
24108
{
24109
// get reference to parent of JSON pointer ptr
24110
const auto last_path = ptr.back();
24111
ptr.pop_back();
24112
basic_json& parent = result.at(ptr);
24113
24114
// remove child
24115
if (parent.is_object())
24116
{
24117
// perform range check
24118
auto it = parent.find(last_path);
24119
if (JSON_HEDLEY_LIKELY(it != parent.end()))
24120
{
24121
parent.erase(it);
24122
}
24123
else
24124
{
24125
JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24126
}
24127
}
24128
else if (parent.is_array())
24129
{
24130
// note erase performs range check
24131
parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24132
}
24133
};
24134
24135
// type check: top level value must be an array
24136
if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24137
{
24138
JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
24139
}
24140
24141
// iterate and apply the operations
24142
for (const auto& val : json_patch)
24143
{
24144
// wrapper to get a value for an operation
24145
const auto get_value = [&val](const std::string & op,
24146
const std::string & member,
24147
bool string_type) -> basic_json &
24148
{
24149
// find value
24150
auto it = val.m_data.m_value.object->find(member);
24151
24152
// context-sensitive error message
24153
const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
24154
24155
// check if desired value is present
24156
if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
24157
{
24158
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24159
JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
24160
}
24161
24162
// check if result is of type string
24163
if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24164
{
24165
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24166
JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
24167
}
24168
24169
// no error: return value
24170
return it->second;
24171
};
24172
24173
// type check: every element of the array must be an object
24174
if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24175
{
24176
JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
24177
}
24178
24179
// collect mandatory members
24180
const auto op = get_value("op", "op", true).template get<std::string>();
24181
const auto path = get_value(op, "path", true).template get<std::string>();
24182
json_pointer ptr(path);
24183
24184
switch (get_op(op))
24185
{
24186
case patch_operations::add:
24187
{
24188
operation_add(ptr, get_value("add", "value", false));
24189
break;
24190
}
24191
24192
case patch_operations::remove:
24193
{
24194
operation_remove(ptr);
24195
break;
24196
}
24197
24198
case patch_operations::replace:
24199
{
24200
// the "path" location must exist - use at()
24201
result.at(ptr) = get_value("replace", "value", false);
24202
break;
24203
}
24204
24205
case patch_operations::move:
24206
{
24207
const auto from_path = get_value("move", "from", true).template get<std::string>();
24208
json_pointer from_ptr(from_path);
24209
24210
// the "from" location must exist - use at()
24211
basic_json const v = result.at(from_ptr);
24212
24213
// The move operation is functionally identical to a
24214
// "remove" operation on the "from" location, followed
24215
// immediately by an "add" operation at the target
24216
// location with the value that was just removed.
24217
operation_remove(from_ptr);
24218
operation_add(ptr, v);
24219
break;
24220
}
24221
24222
case patch_operations::copy:
24223
{
24224
const auto from_path = get_value("copy", "from", true).template get<std::string>();
24225
const json_pointer from_ptr(from_path);
24226
24227
// the "from" location must exist - use at()
24228
basic_json const v = result.at(from_ptr);
24229
24230
// The copy is functionally identical to an "add"
24231
// operation at the target location using the value
24232
// specified in the "from" member.
24233
operation_add(ptr, v);
24234
break;
24235
}
24236
24237
case patch_operations::test:
24238
{
24239
bool success = false;
24240
JSON_TRY
24241
{
24242
// check if "value" matches the one at "path"
24243
// the "path" location must exist - use at()
24244
success = (result.at(ptr) == get_value("test", "value", false));
24245
}
24246
JSON_INTERNAL_CATCH (out_of_range&)
24247
{
24248
// ignore out of range errors: success remains false
24249
}
24250
24251
// throw an exception if test fails
24252
if (JSON_HEDLEY_UNLIKELY(!success))
24253
{
24254
JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
24255
}
24256
24257
break;
24258
}
24259
24260
case patch_operations::invalid:
24261
default:
24262
{
24263
// op must be "add", "remove", "replace", "move", "copy", or
24264
// "test"
24265
JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
24266
}
24267
}
24268
}
24269
}
24270
24271
/// @brief applies a JSON patch to a copy of the current object
24272
/// @sa https://json.nlohmann.me/api/basic_json/patch/
24273
basic_json patch(const basic_json& json_patch) const
24274
{
24275
basic_json result = *this;
24276
result.patch_inplace(json_patch);
24277
return result;
24278
}
24279
24280
/// @brief creates a diff as a JSON patch
24281
/// @sa https://json.nlohmann.me/api/basic_json/diff/
24282
JSON_HEDLEY_WARN_UNUSED_RESULT
24283
static basic_json diff(const basic_json& source, const basic_json& target,
24284
const std::string& path = "")
24285
{
24286
// the patch
24287
basic_json result(value_t::array);
24288
24289
// if the values are the same, return empty patch
24290
if (source == target)
24291
{
24292
return result;
24293
}
24294
24295
if (source.type() != target.type())
24296
{
24297
// different types: replace value
24298
result.push_back(
24299
{
24300
{"op", "replace"}, {"path", path}, {"value", target}
24301
});
24302
return result;
24303
}
24304
24305
switch (source.type())
24306
{
24307
case value_t::array:
24308
{
24309
// first pass: traverse common elements
24310
std::size_t i = 0;
24311
while (i < source.size() && i < target.size())
24312
{
24313
// recursive call to compare array values at index i
24314
auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
24315
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24316
++i;
24317
}
24318
24319
// We now reached the end of at least one array
24320
// in a second pass, traverse the remaining elements
24321
24322
// remove my remaining elements
24323
const auto end_index = static_cast<difference_type>(result.size());
24324
while (i < source.size())
24325
{
24326
// add operations in reverse order to avoid invalid
24327
// indices
24328
result.insert(result.begin() + end_index, object(
24329
{
24330
{"op", "remove"},
24331
{"path", detail::concat(path, '/', std::to_string(i))}
24332
}));
24333
++i;
24334
}
24335
24336
// add other remaining elements
24337
while (i < target.size())
24338
{
24339
result.push_back(
24340
{
24341
{"op", "add"},
24342
{"path", detail::concat(path, "/-")},
24343
{"value", target[i]}
24344
});
24345
++i;
24346
}
24347
24348
break;
24349
}
24350
24351
case value_t::object:
24352
{
24353
// first pass: traverse this object's elements
24354
for (auto it = source.cbegin(); it != source.cend(); ++it)
24355
{
24356
// escape the key name to be used in a JSON patch
24357
const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24358
24359
if (target.find(it.key()) != target.end())
24360
{
24361
// recursive call to compare object values at key it
24362
auto temp_diff = diff(it.value(), target[it.key()], path_key);
24363
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24364
}
24365
else
24366
{
24367
// found a key that is not in o -> remove it
24368
result.push_back(object(
24369
{
24370
{"op", "remove"}, {"path", path_key}
24371
}));
24372
}
24373
}
24374
24375
// second pass: traverse other object's elements
24376
for (auto it = target.cbegin(); it != target.cend(); ++it)
24377
{
24378
if (source.find(it.key()) == source.end())
24379
{
24380
// found a key that is not in this -> add it
24381
const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24382
result.push_back(
24383
{
24384
{"op", "add"}, {"path", path_key},
24385
{"value", it.value()}
24386
});
24387
}
24388
}
24389
24390
break;
24391
}
24392
24393
case value_t::null:
24394
case value_t::string:
24395
case value_t::boolean:
24396
case value_t::number_integer:
24397
case value_t::number_unsigned:
24398
case value_t::number_float:
24399
case value_t::binary:
24400
case value_t::discarded:
24401
default:
24402
{
24403
// both primitive type: replace value
24404
result.push_back(
24405
{
24406
{"op", "replace"}, {"path", path}, {"value", target}
24407
});
24408
break;
24409
}
24410
}
24411
24412
return result;
24413
}
24414
/// @}
24415
24416
////////////////////////////////
24417
// JSON Merge Patch functions //
24418
////////////////////////////////
24419
24420
/// @name JSON Merge Patch functions
24421
/// @{
24422
24423
/// @brief applies a JSON Merge Patch
24424
/// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
24425
void merge_patch(const basic_json& apply_patch)
24426
{
24427
if (apply_patch.is_object())
24428
{
24429
if (!is_object())
24430
{
24431
*this = object();
24432
}
24433
for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
24434
{
24435
if (it.value().is_null())
24436
{
24437
erase(it.key());
24438
}
24439
else
24440
{
24441
operator[](it.key()).merge_patch(it.value());
24442
}
24443
}
24444
}
24445
else
24446
{
24447
*this = apply_patch;
24448
}
24449
}
24450
24451
/// @}
24452
};
24453
24454
/// @brief user-defined to_string function for JSON values
24455
/// @sa https://json.nlohmann.me/api/basic_json/to_string/
24456
NLOHMANN_BASIC_JSON_TPL_DECLARATION
24457
std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
24458
{
24459
return j.dump();
24460
}
24461
24462
inline namespace literals
24463
{
24464
inline namespace json_literals
24465
{
24466
24467
/// @brief user-defined string literal for JSON values
24468
/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
24469
JSON_HEDLEY_NON_NULL(1)
24470
#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24471
inline nlohmann::json operator ""_json(const char* s, std::size_t n)
24472
#else
24473
inline nlohmann::json operator "" _json(const char* s, std::size_t n)
24474
#endif
24475
{
24476
return nlohmann::json::parse(s, s + n);
24477
}
24478
24479
/// @brief user-defined string literal for JSON pointer
24480
/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
24481
JSON_HEDLEY_NON_NULL(1)
24482
#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24483
inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
24484
#else
24485
inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
24486
#endif
24487
{
24488
return nlohmann::json::json_pointer(std::string(s, n));
24489
}
24490
24491
} // namespace json_literals
24492
} // namespace literals
24493
NLOHMANN_JSON_NAMESPACE_END
24494
24495
///////////////////////
24496
// nonmember support //
24497
///////////////////////
24498
24499
namespace std // NOLINT(cert-dcl58-cpp)
24500
{
24501
24502
/// @brief hash value for JSON objects
24503
/// @sa https://json.nlohmann.me/api/basic_json/std_hash/
24504
NLOHMANN_BASIC_JSON_TPL_DECLARATION
24505
struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
24506
{
24507
std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
24508
{
24509
return nlohmann::detail::hash(j);
24510
}
24511
};
24512
24513
// specialization for std::less<value_t>
24514
template<>
24515
struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
24516
{
24517
/*!
24518
@brief compare two value_t enum values
24519
@since version 3.0.0
24520
*/
24521
bool operator()(::nlohmann::detail::value_t lhs,
24522
::nlohmann::detail::value_t rhs) const noexcept
24523
{
24524
#if JSON_HAS_THREE_WAY_COMPARISON
24525
return std::is_lt(lhs <=> rhs); // *NOPAD*
24526
#else
24527
return ::nlohmann::detail::operator<(lhs, rhs);
24528
#endif
24529
}
24530
};
24531
24532
// C++20 prohibit function specialization in the std namespace.
24533
#ifndef JSON_HAS_CPP_20
24534
24535
/// @brief exchanges the values of two JSON objects
24536
/// @sa https://json.nlohmann.me/api/basic_json/std_swap/
24537
NLOHMANN_BASIC_JSON_TPL_DECLARATION
24538
inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
24539
is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
24540
is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
24541
{
24542
j1.swap(j2);
24543
}
24544
24545
#endif
24546
24547
} // namespace std
24548
24549
#if JSON_USE_GLOBAL_UDLS
24550
#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24551
using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24552
using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24553
#else
24554
using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24555
using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24556
#endif
24557
#endif
24558
24559
// #include <nlohmann/detail/macro_unscope.hpp>
24560
// __ _____ _____ _____
24561
// __| | __| | | | JSON for Modern C++
24562
// | | |__ | | | | | | version 3.11.3
24563
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24564
//
24565
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
24566
// SPDX-License-Identifier: MIT
24567
24568
24569
24570
// restore clang diagnostic settings
24571
#if defined(__clang__)
24572
#pragma clang diagnostic pop
24573
#endif
24574
24575
// clean up
24576
#undef JSON_ASSERT
24577
#undef JSON_INTERNAL_CATCH
24578
#undef JSON_THROW
24579
#undef JSON_PRIVATE_UNLESS_TESTED
24580
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
24581
#undef NLOHMANN_BASIC_JSON_TPL
24582
#undef JSON_EXPLICIT
24583
#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
24584
#undef JSON_INLINE_VARIABLE
24585
#undef JSON_NO_UNIQUE_ADDRESS
24586
#undef JSON_DISABLE_ENUM_SERIALIZATION
24587
#undef JSON_USE_GLOBAL_UDLS
24588
24589
#ifndef JSON_TEST_KEEP_MACROS
24590
#undef JSON_CATCH
24591
#undef JSON_TRY
24592
#undef JSON_HAS_CPP_11
24593
#undef JSON_HAS_CPP_14
24594
#undef JSON_HAS_CPP_17
24595
#undef JSON_HAS_CPP_20
24596
#undef JSON_HAS_FILESYSTEM
24597
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
24598
#undef JSON_HAS_THREE_WAY_COMPARISON
24599
#undef JSON_HAS_RANGES
24600
#undef JSON_HAS_STATIC_RTTI
24601
#undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
24602
#endif
24603
24604
// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
24605
// __ _____ _____ _____
24606
// __| | __| | | | JSON for Modern C++
24607
// | | |__ | | | | | | version 3.11.3
24608
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24609
//
24610
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
24611
// SPDX-License-Identifier: MIT
24612
24613
24614
24615
#undef JSON_HEDLEY_ALWAYS_INLINE
24616
#undef JSON_HEDLEY_ARM_VERSION
24617
#undef JSON_HEDLEY_ARM_VERSION_CHECK
24618
#undef JSON_HEDLEY_ARRAY_PARAM
24619
#undef JSON_HEDLEY_ASSUME
24620
#undef JSON_HEDLEY_BEGIN_C_DECLS
24621
#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
24622
#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
24623
#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
24624
#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
24625
#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
24626
#undef JSON_HEDLEY_CLANG_HAS_FEATURE
24627
#undef JSON_HEDLEY_CLANG_HAS_WARNING
24628
#undef JSON_HEDLEY_COMPCERT_VERSION
24629
#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
24630
#undef JSON_HEDLEY_CONCAT
24631
#undef JSON_HEDLEY_CONCAT3
24632
#undef JSON_HEDLEY_CONCAT3_EX
24633
#undef JSON_HEDLEY_CONCAT_EX
24634
#undef JSON_HEDLEY_CONST
24635
#undef JSON_HEDLEY_CONSTEXPR
24636
#undef JSON_HEDLEY_CONST_CAST
24637
#undef JSON_HEDLEY_CPP_CAST
24638
#undef JSON_HEDLEY_CRAY_VERSION
24639
#undef JSON_HEDLEY_CRAY_VERSION_CHECK
24640
#undef JSON_HEDLEY_C_DECL
24641
#undef JSON_HEDLEY_DEPRECATED
24642
#undef JSON_HEDLEY_DEPRECATED_FOR
24643
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
24644
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
24645
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
24646
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
24647
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
24648
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
24649
#undef JSON_HEDLEY_DIAGNOSTIC_POP
24650
#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
24651
#undef JSON_HEDLEY_DMC_VERSION
24652
#undef JSON_HEDLEY_DMC_VERSION_CHECK
24653
#undef JSON_HEDLEY_EMPTY_BASES
24654
#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
24655
#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
24656
#undef JSON_HEDLEY_END_C_DECLS
24657
#undef JSON_HEDLEY_FLAGS
24658
#undef JSON_HEDLEY_FLAGS_CAST
24659
#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
24660
#undef JSON_HEDLEY_GCC_HAS_BUILTIN
24661
#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
24662
#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
24663
#undef JSON_HEDLEY_GCC_HAS_EXTENSION
24664
#undef JSON_HEDLEY_GCC_HAS_FEATURE
24665
#undef JSON_HEDLEY_GCC_HAS_WARNING
24666
#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
24667
#undef JSON_HEDLEY_GCC_VERSION
24668
#undef JSON_HEDLEY_GCC_VERSION_CHECK
24669
#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
24670
#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
24671
#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
24672
#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
24673
#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
24674
#undef JSON_HEDLEY_GNUC_HAS_FEATURE
24675
#undef JSON_HEDLEY_GNUC_HAS_WARNING
24676
#undef JSON_HEDLEY_GNUC_VERSION
24677
#undef JSON_HEDLEY_GNUC_VERSION_CHECK
24678
#undef JSON_HEDLEY_HAS_ATTRIBUTE
24679
#undef JSON_HEDLEY_HAS_BUILTIN
24680
#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
24681
#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
24682
#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
24683
#undef JSON_HEDLEY_HAS_EXTENSION
24684
#undef JSON_HEDLEY_HAS_FEATURE
24685
#undef JSON_HEDLEY_HAS_WARNING
24686
#undef JSON_HEDLEY_IAR_VERSION
24687
#undef JSON_HEDLEY_IAR_VERSION_CHECK
24688
#undef JSON_HEDLEY_IBM_VERSION
24689
#undef JSON_HEDLEY_IBM_VERSION_CHECK
24690
#undef JSON_HEDLEY_IMPORT
24691
#undef JSON_HEDLEY_INLINE
24692
#undef JSON_HEDLEY_INTEL_CL_VERSION
24693
#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
24694
#undef JSON_HEDLEY_INTEL_VERSION
24695
#undef JSON_HEDLEY_INTEL_VERSION_CHECK
24696
#undef JSON_HEDLEY_IS_CONSTANT
24697
#undef JSON_HEDLEY_IS_CONSTEXPR_
24698
#undef JSON_HEDLEY_LIKELY
24699
#undef JSON_HEDLEY_MALLOC
24700
#undef JSON_HEDLEY_MCST_LCC_VERSION
24701
#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
24702
#undef JSON_HEDLEY_MESSAGE
24703
#undef JSON_HEDLEY_MSVC_VERSION
24704
#undef JSON_HEDLEY_MSVC_VERSION_CHECK
24705
#undef JSON_HEDLEY_NEVER_INLINE
24706
#undef JSON_HEDLEY_NON_NULL
24707
#undef JSON_HEDLEY_NO_ESCAPE
24708
#undef JSON_HEDLEY_NO_RETURN
24709
#undef JSON_HEDLEY_NO_THROW
24710
#undef JSON_HEDLEY_NULL
24711
#undef JSON_HEDLEY_PELLES_VERSION
24712
#undef JSON_HEDLEY_PELLES_VERSION_CHECK
24713
#undef JSON_HEDLEY_PGI_VERSION
24714
#undef JSON_HEDLEY_PGI_VERSION_CHECK
24715
#undef JSON_HEDLEY_PREDICT
24716
#undef JSON_HEDLEY_PRINTF_FORMAT
24717
#undef JSON_HEDLEY_PRIVATE
24718
#undef JSON_HEDLEY_PUBLIC
24719
#undef JSON_HEDLEY_PURE
24720
#undef JSON_HEDLEY_REINTERPRET_CAST
24721
#undef JSON_HEDLEY_REQUIRE
24722
#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
24723
#undef JSON_HEDLEY_REQUIRE_MSG
24724
#undef JSON_HEDLEY_RESTRICT
24725
#undef JSON_HEDLEY_RETURNS_NON_NULL
24726
#undef JSON_HEDLEY_SENTINEL
24727
#undef JSON_HEDLEY_STATIC_ASSERT
24728
#undef JSON_HEDLEY_STATIC_CAST
24729
#undef JSON_HEDLEY_STRINGIFY
24730
#undef JSON_HEDLEY_STRINGIFY_EX
24731
#undef JSON_HEDLEY_SUNPRO_VERSION
24732
#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
24733
#undef JSON_HEDLEY_TINYC_VERSION
24734
#undef JSON_HEDLEY_TINYC_VERSION_CHECK
24735
#undef JSON_HEDLEY_TI_ARMCL_VERSION
24736
#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
24737
#undef JSON_HEDLEY_TI_CL2000_VERSION
24738
#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
24739
#undef JSON_HEDLEY_TI_CL430_VERSION
24740
#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
24741
#undef JSON_HEDLEY_TI_CL6X_VERSION
24742
#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
24743
#undef JSON_HEDLEY_TI_CL7X_VERSION
24744
#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
24745
#undef JSON_HEDLEY_TI_CLPRU_VERSION
24746
#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
24747
#undef JSON_HEDLEY_TI_VERSION
24748
#undef JSON_HEDLEY_TI_VERSION_CHECK
24749
#undef JSON_HEDLEY_UNAVAILABLE
24750
#undef JSON_HEDLEY_UNLIKELY
24751
#undef JSON_HEDLEY_UNPREDICTABLE
24752
#undef JSON_HEDLEY_UNREACHABLE
24753
#undef JSON_HEDLEY_UNREACHABLE_RETURN
24754
#undef JSON_HEDLEY_VERSION
24755
#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
24756
#undef JSON_HEDLEY_VERSION_DECODE_MINOR
24757
#undef JSON_HEDLEY_VERSION_DECODE_REVISION
24758
#undef JSON_HEDLEY_VERSION_ENCODE
24759
#undef JSON_HEDLEY_WARNING
24760
#undef JSON_HEDLEY_WARN_UNUSED_RESULT
24761
#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
24762
#undef JSON_HEDLEY_FALL_THROUGH
24763
24764
24765
24766
#endif // INCLUDE_NLOHMANN_JSON_HPP_
24767
24768