Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/foreign/nlohmann/json.hpp
169678 views
1
/*
2
__ _____ _____ _____
3
__| | __| | | | JSON for Modern C++
4
| | |__ | | | | | | version 3.10.5
5
|_____|_____|_____|_|___| https://github.com/nlohmann/json
6
7
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8
SPDX-License-Identifier: MIT
9
Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
10
11
Permission is hereby granted, free of charge, to any person obtaining a copy
12
of this software and associated documentation files (the "Software"), to deal
13
in the Software without restriction, including without limitation the rights
14
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
copies of the Software, and to permit persons to whom the Software is
16
furnished to do so, subject to the following conditions:
17
18
The above copyright notice and this permission notice shall be included in all
19
copies or substantial portions of the Software.
20
21
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
SOFTWARE.
28
*/
29
30
/****************************************************************************\
31
* Note on documentation: The source files contain links to the online *
32
* documentation of the public API at https://json.nlohmann.me. This URL *
33
* contains the most recent documentation and should also be applicable to *
34
* previous versions; documentation for deprecated functions is not *
35
* removed, but marked deprecated. See "Generate documentation" section in *
36
* file doc/README.md. *
37
\****************************************************************************/
38
39
#ifndef INCLUDE_NLOHMANN_JSON_HPP_
40
#define INCLUDE_NLOHMANN_JSON_HPP_
41
42
#define NLOHMANN_JSON_VERSION_MAJOR 3
43
#define NLOHMANN_JSON_VERSION_MINOR 10
44
#define NLOHMANN_JSON_VERSION_PATCH 5
45
46
#include <algorithm> // all_of, find, for_each
47
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
48
#include <functional> // hash, less
49
#include <initializer_list> // initializer_list
50
#ifndef JSON_NO_IO
51
#include <iosfwd> // istream, ostream
52
#endif // JSON_NO_IO
53
#include <iterator> // random_access_iterator_tag
54
#include <memory> // unique_ptr
55
#include <numeric> // accumulate
56
#include <string> // string, stoi, to_string
57
#include <utility> // declval, forward, move, pair, swap
58
#include <vector> // vector
59
60
// #include <nlohmann/adl_serializer.hpp>
61
62
63
#include <type_traits>
64
#include <utility>
65
66
// #include <nlohmann/detail/conversions/from_json.hpp>
67
68
69
#include <algorithm> // transform
70
#include <array> // array
71
#include <forward_list> // forward_list
72
#include <iterator> // inserter, front_inserter, end
73
#include <map> // map
74
#include <string> // string
75
#include <tuple> // tuple, make_tuple
76
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
77
#include <unordered_map> // unordered_map
78
#include <utility> // pair, declval
79
#include <valarray> // valarray
80
81
// #include <nlohmann/detail/exceptions.hpp>
82
83
84
#include <exception> // exception
85
#include <stdexcept> // runtime_error
86
#include <string> // to_string
87
#include <vector> // vector
88
89
// #include <nlohmann/detail/value_t.hpp>
90
91
92
#include <array> // array
93
#include <cstddef> // size_t
94
#include <cstdint> // uint8_t
95
#include <string> // string
96
97
namespace nlohmann
98
{
99
namespace detail
100
{
101
///////////////////////////
102
// JSON type enumeration //
103
///////////////////////////
104
105
/*!
106
@brief the JSON type enumeration
107
108
This enumeration collects the different JSON types. It is internally used to
109
distinguish the stored values, and the functions @ref basic_json::is_null(),
110
@ref basic_json::is_object(), @ref basic_json::is_array(),
111
@ref basic_json::is_string(), @ref basic_json::is_boolean(),
112
@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
113
@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
114
@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
115
@ref basic_json::is_structured() rely on it.
116
117
@note There are three enumeration entries (number_integer, number_unsigned, and
118
number_float), because the library distinguishes these three types for numbers:
119
@ref basic_json::number_unsigned_t is used for unsigned integers,
120
@ref basic_json::number_integer_t is used for signed integers, and
121
@ref basic_json::number_float_t is used for floating-point numbers or to
122
approximate integers which do not fit in the limits of their respective type.
123
124
@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
125
value with the default value for a given type
126
127
@since version 1.0.0
128
*/
129
enum class value_t : std::uint8_t
130
{
131
null, ///< null value
132
object, ///< object (unordered set of name/value pairs)
133
array, ///< array (ordered collection of values)
134
string, ///< string value
135
boolean, ///< boolean value
136
number_integer, ///< number value (signed integer)
137
number_unsigned, ///< number value (unsigned integer)
138
number_float, ///< number value (floating-point)
139
binary, ///< binary array (ordered collection of bytes)
140
discarded ///< discarded by the parser callback function
141
};
142
143
/*!
144
@brief comparison operator for JSON types
145
146
Returns an ordering that is similar to Python:
147
- order: null < boolean < number < object < array < string < binary
148
- furthermore, each type is not smaller than itself
149
- discarded values are not comparable
150
- binary is represented as a b"" string in python and directly comparable to a
151
string; however, making a binary array directly comparable with a string would
152
be surprising behavior in a JSON file.
153
154
@since version 1.0.0
155
*/
156
inline bool operator<(const value_t lhs, const value_t rhs) noexcept
157
{
158
static constexpr std::array<std::uint8_t, 9> order = {{
159
0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
160
1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
161
6 /* binary */
162
}
163
};
164
165
const auto l_index = static_cast<std::size_t>(lhs);
166
const auto r_index = static_cast<std::size_t>(rhs);
167
return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
168
}
169
} // namespace detail
170
} // namespace nlohmann
171
172
// #include <nlohmann/detail/string_escape.hpp>
173
174
175
#include <string>
176
// #include <nlohmann/detail/macro_scope.hpp>
177
178
179
#include <utility> // declval, pair
180
// #include <nlohmann/thirdparty/hedley/hedley.hpp>
181
182
183
/* Hedley - https://nemequ.github.io/hedley
184
* Created by Evan Nemerson <[email protected]>
185
*
186
* To the extent possible under law, the author(s) have dedicated all
187
* copyright and related and neighboring rights to this software to
188
* the public domain worldwide. This software is distributed without
189
* any warranty.
190
*
191
* For details, see <http://creativecommons.org/publicdomain/zero/1.0/>.
192
* SPDX-License-Identifier: CC0-1.0
193
*/
194
195
#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
196
#if defined(JSON_HEDLEY_VERSION)
197
#undef JSON_HEDLEY_VERSION
198
#endif
199
#define JSON_HEDLEY_VERSION 15
200
201
#if defined(JSON_HEDLEY_STRINGIFY_EX)
202
#undef JSON_HEDLEY_STRINGIFY_EX
203
#endif
204
#define JSON_HEDLEY_STRINGIFY_EX(x) #x
205
206
#if defined(JSON_HEDLEY_STRINGIFY)
207
#undef JSON_HEDLEY_STRINGIFY
208
#endif
209
#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
210
211
#if defined(JSON_HEDLEY_CONCAT_EX)
212
#undef JSON_HEDLEY_CONCAT_EX
213
#endif
214
#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
215
216
#if defined(JSON_HEDLEY_CONCAT)
217
#undef JSON_HEDLEY_CONCAT
218
#endif
219
#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
220
221
#if defined(JSON_HEDLEY_CONCAT3_EX)
222
#undef JSON_HEDLEY_CONCAT3_EX
223
#endif
224
#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
225
226
#if defined(JSON_HEDLEY_CONCAT3)
227
#undef JSON_HEDLEY_CONCAT3
228
#endif
229
#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
230
231
#if defined(JSON_HEDLEY_VERSION_ENCODE)
232
#undef JSON_HEDLEY_VERSION_ENCODE
233
#endif
234
#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
235
236
#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
237
#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
238
#endif
239
#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
240
241
#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
242
#undef JSON_HEDLEY_VERSION_DECODE_MINOR
243
#endif
244
#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
245
246
#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
247
#undef JSON_HEDLEY_VERSION_DECODE_REVISION
248
#endif
249
#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
250
251
#if defined(JSON_HEDLEY_GNUC_VERSION)
252
#undef JSON_HEDLEY_GNUC_VERSION
253
#endif
254
#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
255
#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
256
#elif defined(__GNUC__)
257
#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
258
#endif
259
260
#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
261
#undef JSON_HEDLEY_GNUC_VERSION_CHECK
262
#endif
263
#if defined(JSON_HEDLEY_GNUC_VERSION)
264
#define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
265
#else
266
#define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
267
#endif
268
269
#if defined(JSON_HEDLEY_MSVC_VERSION)
270
#undef JSON_HEDLEY_MSVC_VERSION
271
#endif
272
#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
273
#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
274
#elif defined(_MSC_FULL_VER) && !defined(__ICL)
275
#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
276
#elif defined(_MSC_VER) && !defined(__ICL)
277
#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
278
#endif
279
280
#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
281
#undef JSON_HEDLEY_MSVC_VERSION_CHECK
282
#endif
283
#if !defined(JSON_HEDLEY_MSVC_VERSION)
284
#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
285
#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
286
#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
287
#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
288
#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
289
#else
290
#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
291
#endif
292
293
#if defined(JSON_HEDLEY_INTEL_VERSION)
294
#undef JSON_HEDLEY_INTEL_VERSION
295
#endif
296
#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
297
#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
298
#elif defined(__INTEL_COMPILER) && !defined(__ICL)
299
#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
300
#endif
301
302
#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
303
#undef JSON_HEDLEY_INTEL_VERSION_CHECK
304
#endif
305
#if defined(JSON_HEDLEY_INTEL_VERSION)
306
#define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
307
#else
308
#define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
309
#endif
310
311
#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
312
#undef JSON_HEDLEY_INTEL_CL_VERSION
313
#endif
314
#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
315
#define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
316
#endif
317
318
#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
319
#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
320
#endif
321
#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
322
#define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
323
#else
324
#define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
325
#endif
326
327
#if defined(JSON_HEDLEY_PGI_VERSION)
328
#undef JSON_HEDLEY_PGI_VERSION
329
#endif
330
#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
331
#define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
332
#endif
333
334
#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
335
#undef JSON_HEDLEY_PGI_VERSION_CHECK
336
#endif
337
#if defined(JSON_HEDLEY_PGI_VERSION)
338
#define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
339
#else
340
#define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
341
#endif
342
343
#if defined(JSON_HEDLEY_SUNPRO_VERSION)
344
#undef JSON_HEDLEY_SUNPRO_VERSION
345
#endif
346
#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
347
#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
348
#elif defined(__SUNPRO_C)
349
#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
350
#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
351
#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
352
#elif defined(__SUNPRO_CC)
353
#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
354
#endif
355
356
#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
357
#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
358
#endif
359
#if defined(JSON_HEDLEY_SUNPRO_VERSION)
360
#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
361
#else
362
#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
363
#endif
364
365
#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
366
#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
367
#endif
368
#if defined(__EMSCRIPTEN__)
369
#define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
370
#endif
371
372
#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
373
#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
374
#endif
375
#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
376
#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
377
#else
378
#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
379
#endif
380
381
#if defined(JSON_HEDLEY_ARM_VERSION)
382
#undef JSON_HEDLEY_ARM_VERSION
383
#endif
384
#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
385
#define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
386
#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
387
#define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
388
#endif
389
390
#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
391
#undef JSON_HEDLEY_ARM_VERSION_CHECK
392
#endif
393
#if defined(JSON_HEDLEY_ARM_VERSION)
394
#define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
395
#else
396
#define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
397
#endif
398
399
#if defined(JSON_HEDLEY_IBM_VERSION)
400
#undef JSON_HEDLEY_IBM_VERSION
401
#endif
402
#if defined(__ibmxl__)
403
#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
404
#elif defined(__xlC__) && defined(__xlC_ver__)
405
#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
406
#elif defined(__xlC__)
407
#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
408
#endif
409
410
#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
411
#undef JSON_HEDLEY_IBM_VERSION_CHECK
412
#endif
413
#if defined(JSON_HEDLEY_IBM_VERSION)
414
#define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
415
#else
416
#define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
417
#endif
418
419
#if defined(JSON_HEDLEY_TI_VERSION)
420
#undef JSON_HEDLEY_TI_VERSION
421
#endif
422
#if \
423
defined(__TI_COMPILER_VERSION__) && \
424
( \
425
defined(__TMS470__) || defined(__TI_ARM__) || \
426
defined(__MSP430__) || \
427
defined(__TMS320C2000__) \
428
)
429
#if (__TI_COMPILER_VERSION__ >= 16000000)
430
#define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
431
#endif
432
#endif
433
434
#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
435
#undef JSON_HEDLEY_TI_VERSION_CHECK
436
#endif
437
#if defined(JSON_HEDLEY_TI_VERSION)
438
#define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
439
#else
440
#define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
441
#endif
442
443
#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
444
#undef JSON_HEDLEY_TI_CL2000_VERSION
445
#endif
446
#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
447
#define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
448
#endif
449
450
#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
451
#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
452
#endif
453
#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
454
#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
455
#else
456
#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
457
#endif
458
459
#if defined(JSON_HEDLEY_TI_CL430_VERSION)
460
#undef JSON_HEDLEY_TI_CL430_VERSION
461
#endif
462
#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
463
#define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
464
#endif
465
466
#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
467
#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
468
#endif
469
#if defined(JSON_HEDLEY_TI_CL430_VERSION)
470
#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
471
#else
472
#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
473
#endif
474
475
#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
476
#undef JSON_HEDLEY_TI_ARMCL_VERSION
477
#endif
478
#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
479
#define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
480
#endif
481
482
#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
483
#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
484
#endif
485
#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
486
#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
487
#else
488
#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
489
#endif
490
491
#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
492
#undef JSON_HEDLEY_TI_CL6X_VERSION
493
#endif
494
#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
495
#define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
496
#endif
497
498
#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
499
#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
500
#endif
501
#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
502
#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
503
#else
504
#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
505
#endif
506
507
#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
508
#undef JSON_HEDLEY_TI_CL7X_VERSION
509
#endif
510
#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
511
#define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
512
#endif
513
514
#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
515
#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
516
#endif
517
#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
518
#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
519
#else
520
#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
521
#endif
522
523
#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
524
#undef JSON_HEDLEY_TI_CLPRU_VERSION
525
#endif
526
#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
527
#define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
528
#endif
529
530
#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
531
#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
532
#endif
533
#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
534
#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
535
#else
536
#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
537
#endif
538
539
#if defined(JSON_HEDLEY_CRAY_VERSION)
540
#undef JSON_HEDLEY_CRAY_VERSION
541
#endif
542
#if defined(_CRAYC)
543
#if defined(_RELEASE_PATCHLEVEL)
544
#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
545
#else
546
#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
547
#endif
548
#endif
549
550
#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
551
#undef JSON_HEDLEY_CRAY_VERSION_CHECK
552
#endif
553
#if defined(JSON_HEDLEY_CRAY_VERSION)
554
#define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
555
#else
556
#define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
557
#endif
558
559
#if defined(JSON_HEDLEY_IAR_VERSION)
560
#undef JSON_HEDLEY_IAR_VERSION
561
#endif
562
#if defined(__IAR_SYSTEMS_ICC__)
563
#if __VER__ > 1000
564
#define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
565
#else
566
#define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
567
#endif
568
#endif
569
570
#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
571
#undef JSON_HEDLEY_IAR_VERSION_CHECK
572
#endif
573
#if defined(JSON_HEDLEY_IAR_VERSION)
574
#define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
575
#else
576
#define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
577
#endif
578
579
#if defined(JSON_HEDLEY_TINYC_VERSION)
580
#undef JSON_HEDLEY_TINYC_VERSION
581
#endif
582
#if defined(__TINYC__)
583
#define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
584
#endif
585
586
#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
587
#undef JSON_HEDLEY_TINYC_VERSION_CHECK
588
#endif
589
#if defined(JSON_HEDLEY_TINYC_VERSION)
590
#define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
591
#else
592
#define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
593
#endif
594
595
#if defined(JSON_HEDLEY_DMC_VERSION)
596
#undef JSON_HEDLEY_DMC_VERSION
597
#endif
598
#if defined(__DMC__)
599
#define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
600
#endif
601
602
#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
603
#undef JSON_HEDLEY_DMC_VERSION_CHECK
604
#endif
605
#if defined(JSON_HEDLEY_DMC_VERSION)
606
#define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
607
#else
608
#define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
609
#endif
610
611
#if defined(JSON_HEDLEY_COMPCERT_VERSION)
612
#undef JSON_HEDLEY_COMPCERT_VERSION
613
#endif
614
#if defined(__COMPCERT_VERSION__)
615
#define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
616
#endif
617
618
#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
619
#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
620
#endif
621
#if defined(JSON_HEDLEY_COMPCERT_VERSION)
622
#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
623
#else
624
#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
625
#endif
626
627
#if defined(JSON_HEDLEY_PELLES_VERSION)
628
#undef JSON_HEDLEY_PELLES_VERSION
629
#endif
630
#if defined(__POCC__)
631
#define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
632
#endif
633
634
#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
635
#undef JSON_HEDLEY_PELLES_VERSION_CHECK
636
#endif
637
#if defined(JSON_HEDLEY_PELLES_VERSION)
638
#define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
639
#else
640
#define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
641
#endif
642
643
#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
644
#undef JSON_HEDLEY_MCST_LCC_VERSION
645
#endif
646
#if defined(__LCC__) && defined(__LCC_MINOR__)
647
#define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
648
#endif
649
650
#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
651
#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
652
#endif
653
#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
654
#define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
655
#else
656
#define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
657
#endif
658
659
#if defined(JSON_HEDLEY_GCC_VERSION)
660
#undef JSON_HEDLEY_GCC_VERSION
661
#endif
662
#if \
663
defined(JSON_HEDLEY_GNUC_VERSION) && \
664
!defined(__clang__) && \
665
!defined(JSON_HEDLEY_INTEL_VERSION) && \
666
!defined(JSON_HEDLEY_PGI_VERSION) && \
667
!defined(JSON_HEDLEY_ARM_VERSION) && \
668
!defined(JSON_HEDLEY_CRAY_VERSION) && \
669
!defined(JSON_HEDLEY_TI_VERSION) && \
670
!defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
671
!defined(JSON_HEDLEY_TI_CL430_VERSION) && \
672
!defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
673
!defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
674
!defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
675
!defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
676
!defined(__COMPCERT__) && \
677
!defined(JSON_HEDLEY_MCST_LCC_VERSION)
678
#define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
679
#endif
680
681
#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
682
#undef JSON_HEDLEY_GCC_VERSION_CHECK
683
#endif
684
#if defined(JSON_HEDLEY_GCC_VERSION)
685
#define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
686
#else
687
#define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
688
#endif
689
690
#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
691
#undef JSON_HEDLEY_HAS_ATTRIBUTE
692
#endif
693
#if \
694
defined(__has_attribute) && \
695
( \
696
(!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
697
)
698
# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
699
#else
700
# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
701
#endif
702
703
#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
704
#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
705
#endif
706
#if defined(__has_attribute)
707
#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
708
#else
709
#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
710
#endif
711
712
#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
713
#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
714
#endif
715
#if defined(__has_attribute)
716
#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
717
#else
718
#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
719
#endif
720
721
#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
722
#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
723
#endif
724
#if \
725
defined(__has_cpp_attribute) && \
726
defined(__cplusplus) && \
727
(!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
728
#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
729
#else
730
#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
731
#endif
732
733
#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
734
#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
735
#endif
736
#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
737
#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
738
#elif \
739
!defined(JSON_HEDLEY_PGI_VERSION) && \
740
!defined(JSON_HEDLEY_IAR_VERSION) && \
741
(!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
742
(!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
743
#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
744
#else
745
#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
746
#endif
747
748
#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
749
#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
750
#endif
751
#if defined(__has_cpp_attribute) && defined(__cplusplus)
752
#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
753
#else
754
#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
755
#endif
756
757
#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
758
#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
759
#endif
760
#if defined(__has_cpp_attribute) && defined(__cplusplus)
761
#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
762
#else
763
#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
764
#endif
765
766
#if defined(JSON_HEDLEY_HAS_BUILTIN)
767
#undef JSON_HEDLEY_HAS_BUILTIN
768
#endif
769
#if defined(__has_builtin)
770
#define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
771
#else
772
#define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
773
#endif
774
775
#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
776
#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
777
#endif
778
#if defined(__has_builtin)
779
#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
780
#else
781
#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
782
#endif
783
784
#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
785
#undef JSON_HEDLEY_GCC_HAS_BUILTIN
786
#endif
787
#if defined(__has_builtin)
788
#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
789
#else
790
#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
791
#endif
792
793
#if defined(JSON_HEDLEY_HAS_FEATURE)
794
#undef JSON_HEDLEY_HAS_FEATURE
795
#endif
796
#if defined(__has_feature)
797
#define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
798
#else
799
#define JSON_HEDLEY_HAS_FEATURE(feature) (0)
800
#endif
801
802
#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
803
#undef JSON_HEDLEY_GNUC_HAS_FEATURE
804
#endif
805
#if defined(__has_feature)
806
#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
807
#else
808
#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
809
#endif
810
811
#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
812
#undef JSON_HEDLEY_GCC_HAS_FEATURE
813
#endif
814
#if defined(__has_feature)
815
#define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
816
#else
817
#define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
818
#endif
819
820
#if defined(JSON_HEDLEY_HAS_EXTENSION)
821
#undef JSON_HEDLEY_HAS_EXTENSION
822
#endif
823
#if defined(__has_extension)
824
#define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
825
#else
826
#define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
827
#endif
828
829
#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
830
#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
831
#endif
832
#if defined(__has_extension)
833
#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
834
#else
835
#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
836
#endif
837
838
#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
839
#undef JSON_HEDLEY_GCC_HAS_EXTENSION
840
#endif
841
#if defined(__has_extension)
842
#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
843
#else
844
#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
845
#endif
846
847
#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
848
#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
849
#endif
850
#if defined(__has_declspec_attribute)
851
#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
852
#else
853
#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
854
#endif
855
856
#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
857
#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
858
#endif
859
#if defined(__has_declspec_attribute)
860
#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
861
#else
862
#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
863
#endif
864
865
#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
866
#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
867
#endif
868
#if defined(__has_declspec_attribute)
869
#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
870
#else
871
#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
872
#endif
873
874
#if defined(JSON_HEDLEY_HAS_WARNING)
875
#undef JSON_HEDLEY_HAS_WARNING
876
#endif
877
#if defined(__has_warning)
878
#define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
879
#else
880
#define JSON_HEDLEY_HAS_WARNING(warning) (0)
881
#endif
882
883
#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
884
#undef JSON_HEDLEY_GNUC_HAS_WARNING
885
#endif
886
#if defined(__has_warning)
887
#define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
888
#else
889
#define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
890
#endif
891
892
#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
893
#undef JSON_HEDLEY_GCC_HAS_WARNING
894
#endif
895
#if defined(__has_warning)
896
#define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
897
#else
898
#define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
899
#endif
900
901
#if \
902
(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
903
defined(__clang__) || \
904
JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
905
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
906
JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
907
JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
908
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
909
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
910
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
911
JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
912
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
913
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
914
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
915
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
916
JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
917
JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
918
JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
919
(JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
920
#define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
921
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
922
#define JSON_HEDLEY_PRAGMA(value) __pragma(value)
923
#else
924
#define JSON_HEDLEY_PRAGMA(value)
925
#endif
926
927
#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
928
#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
929
#endif
930
#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
931
#undef JSON_HEDLEY_DIAGNOSTIC_POP
932
#endif
933
#if defined(__clang__)
934
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
935
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
936
#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
937
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
938
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
939
#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
940
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
941
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
942
#elif \
943
JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
944
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
945
#define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
946
#define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
947
#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
948
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
949
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
950
#elif \
951
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
952
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
953
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
954
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
955
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
956
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
957
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
958
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
959
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
960
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
961
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
962
#else
963
#define JSON_HEDLEY_DIAGNOSTIC_PUSH
964
#define JSON_HEDLEY_DIAGNOSTIC_POP
965
#endif
966
967
/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
968
HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
969
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
970
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
971
#endif
972
#if defined(__cplusplus)
973
# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
974
# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
975
# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
976
# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
977
JSON_HEDLEY_DIAGNOSTIC_PUSH \
978
_Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
979
_Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
980
_Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
981
xpr \
982
JSON_HEDLEY_DIAGNOSTIC_POP
983
# else
984
# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
985
JSON_HEDLEY_DIAGNOSTIC_PUSH \
986
_Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
987
_Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
988
xpr \
989
JSON_HEDLEY_DIAGNOSTIC_POP
990
# endif
991
# else
992
# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
993
JSON_HEDLEY_DIAGNOSTIC_PUSH \
994
_Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
995
xpr \
996
JSON_HEDLEY_DIAGNOSTIC_POP
997
# endif
998
# endif
999
#endif
1000
#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1001
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1002
#endif
1003
1004
#if defined(JSON_HEDLEY_CONST_CAST)
1005
#undef JSON_HEDLEY_CONST_CAST
1006
#endif
1007
#if defined(__cplusplus)
1008
# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1009
#elif \
1010
JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1011
JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1012
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1013
# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1014
JSON_HEDLEY_DIAGNOSTIC_PUSH \
1015
JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1016
((T) (expr)); \
1017
JSON_HEDLEY_DIAGNOSTIC_POP \
1018
}))
1019
#else
1020
# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1021
#endif
1022
1023
#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1024
#undef JSON_HEDLEY_REINTERPRET_CAST
1025
#endif
1026
#if defined(__cplusplus)
1027
#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1028
#else
1029
#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1030
#endif
1031
1032
#if defined(JSON_HEDLEY_STATIC_CAST)
1033
#undef JSON_HEDLEY_STATIC_CAST
1034
#endif
1035
#if defined(__cplusplus)
1036
#define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1037
#else
1038
#define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1039
#endif
1040
1041
#if defined(JSON_HEDLEY_CPP_CAST)
1042
#undef JSON_HEDLEY_CPP_CAST
1043
#endif
1044
#if defined(__cplusplus)
1045
# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1046
# define JSON_HEDLEY_CPP_CAST(T, expr) \
1047
JSON_HEDLEY_DIAGNOSTIC_PUSH \
1048
_Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1049
((T) (expr)) \
1050
JSON_HEDLEY_DIAGNOSTIC_POP
1051
# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1052
# define JSON_HEDLEY_CPP_CAST(T, expr) \
1053
JSON_HEDLEY_DIAGNOSTIC_PUSH \
1054
_Pragma("diag_suppress=Pe137") \
1055
JSON_HEDLEY_DIAGNOSTIC_POP
1056
# else
1057
# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1058
# endif
1059
#else
1060
# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1061
#endif
1062
1063
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1064
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1065
#endif
1066
#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1067
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1068
#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1069
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1070
#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1071
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1072
#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1073
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1074
#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1075
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1076
#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1077
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1078
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1079
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1080
#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1081
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1082
#elif \
1083
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1084
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1085
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1086
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1087
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1088
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1089
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1090
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1091
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1092
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1093
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1094
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1095
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1096
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1097
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1098
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1099
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1100
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1101
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1102
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1103
#else
1104
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1105
#endif
1106
1107
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1108
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1109
#endif
1110
#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1111
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1112
#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1113
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1114
#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1115
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1116
#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1117
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1118
#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1119
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1120
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1121
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1122
#elif \
1123
JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1124
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1125
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1126
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1127
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1128
#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1129
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1130
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1131
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1132
#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1133
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1134
#else
1135
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1136
#endif
1137
1138
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1139
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1140
#endif
1141
#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1142
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1143
#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1144
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1145
#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1146
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1147
#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1148
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1149
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1150
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1151
#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1152
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1153
#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1154
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1155
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1156
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1157
#elif \
1158
JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1159
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1160
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1161
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1162
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1163
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1164
#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1165
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1166
#else
1167
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1168
#endif
1169
1170
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1171
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1172
#endif
1173
#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1174
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1175
#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1176
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1177
#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1178
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1179
#else
1180
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1181
#endif
1182
1183
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1184
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1185
#endif
1186
#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1187
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1188
#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1189
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1190
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1191
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1192
#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1193
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1194
#else
1195
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1196
#endif
1197
1198
#if defined(JSON_HEDLEY_DEPRECATED)
1199
#undef JSON_HEDLEY_DEPRECATED
1200
#endif
1201
#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1202
#undef JSON_HEDLEY_DEPRECATED_FOR
1203
#endif
1204
#if \
1205
JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1206
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1207
#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1208
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1209
#elif \
1210
(JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1211
JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1212
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1213
JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1214
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1215
JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1216
JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1217
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1218
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1219
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1220
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1221
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1222
#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1223
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1224
#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1225
#define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1226
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1227
#elif \
1228
JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1229
JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1230
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1231
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1232
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1233
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1234
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1235
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1236
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1237
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1238
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1239
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1240
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1241
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1242
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1243
JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1244
#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1245
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1246
#elif \
1247
JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1248
JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1249
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1250
#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1251
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1252
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1253
#define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1254
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1255
#else
1256
#define JSON_HEDLEY_DEPRECATED(since)
1257
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1258
#endif
1259
1260
#if defined(JSON_HEDLEY_UNAVAILABLE)
1261
#undef JSON_HEDLEY_UNAVAILABLE
1262
#endif
1263
#if \
1264
JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1265
JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1266
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1267
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1268
#define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1269
#else
1270
#define JSON_HEDLEY_UNAVAILABLE(available_since)
1271
#endif
1272
1273
#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1274
#undef JSON_HEDLEY_WARN_UNUSED_RESULT
1275
#endif
1276
#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1277
#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1278
#endif
1279
#if \
1280
JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1281
JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1282
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1283
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1284
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1285
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1286
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1287
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1288
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1289
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1290
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1291
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1292
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1293
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1294
(JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1295
JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1296
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1297
#define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1298
#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1299
#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1300
#define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1301
#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1302
#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1303
#define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1304
#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1305
#elif defined(_Check_return_) /* SAL */
1306
#define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1307
#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1308
#else
1309
#define JSON_HEDLEY_WARN_UNUSED_RESULT
1310
#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1311
#endif
1312
1313
#if defined(JSON_HEDLEY_SENTINEL)
1314
#undef JSON_HEDLEY_SENTINEL
1315
#endif
1316
#if \
1317
JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1318
JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1319
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1320
JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1321
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1322
#define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1323
#else
1324
#define JSON_HEDLEY_SENTINEL(position)
1325
#endif
1326
1327
#if defined(JSON_HEDLEY_NO_RETURN)
1328
#undef JSON_HEDLEY_NO_RETURN
1329
#endif
1330
#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1331
#define JSON_HEDLEY_NO_RETURN __noreturn
1332
#elif \
1333
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1334
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1335
#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1336
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1337
#define JSON_HEDLEY_NO_RETURN _Noreturn
1338
#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1339
#define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1340
#elif \
1341
JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1342
JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1343
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1344
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1345
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1346
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1347
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1348
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1349
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1350
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1351
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1352
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1353
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1354
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1355
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1356
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1357
JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1358
#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1359
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1360
#define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1361
#elif \
1362
JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1363
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1364
#define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1365
#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1366
#define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1367
#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1368
#define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1369
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1370
#define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1371
#else
1372
#define JSON_HEDLEY_NO_RETURN
1373
#endif
1374
1375
#if defined(JSON_HEDLEY_NO_ESCAPE)
1376
#undef JSON_HEDLEY_NO_ESCAPE
1377
#endif
1378
#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1379
#define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1380
#else
1381
#define JSON_HEDLEY_NO_ESCAPE
1382
#endif
1383
1384
#if defined(JSON_HEDLEY_UNREACHABLE)
1385
#undef JSON_HEDLEY_UNREACHABLE
1386
#endif
1387
#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1388
#undef JSON_HEDLEY_UNREACHABLE_RETURN
1389
#endif
1390
#if defined(JSON_HEDLEY_ASSUME)
1391
#undef JSON_HEDLEY_ASSUME
1392
#endif
1393
#if \
1394
JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1395
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1396
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1397
#define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1398
#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1399
#define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1400
#elif \
1401
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1402
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1403
#if defined(__cplusplus)
1404
#define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1405
#else
1406
#define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1407
#endif
1408
#endif
1409
#if \
1410
(JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1411
JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1412
JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1413
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1414
JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1415
JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1416
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1417
#define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1418
#elif defined(JSON_HEDLEY_ASSUME)
1419
#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1420
#endif
1421
#if !defined(JSON_HEDLEY_ASSUME)
1422
#if defined(JSON_HEDLEY_UNREACHABLE)
1423
#define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1424
#else
1425
#define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1426
#endif
1427
#endif
1428
#if defined(JSON_HEDLEY_UNREACHABLE)
1429
#if \
1430
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1431
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1432
#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1433
#else
1434
#define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1435
#endif
1436
#else
1437
#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1438
#endif
1439
#if !defined(JSON_HEDLEY_UNREACHABLE)
1440
#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1441
#endif
1442
1443
JSON_HEDLEY_DIAGNOSTIC_PUSH
1444
#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1445
#pragma clang diagnostic ignored "-Wpedantic"
1446
#endif
1447
#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1448
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1449
#endif
1450
#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1451
#if defined(__clang__)
1452
#pragma clang diagnostic ignored "-Wvariadic-macros"
1453
#elif defined(JSON_HEDLEY_GCC_VERSION)
1454
#pragma GCC diagnostic ignored "-Wvariadic-macros"
1455
#endif
1456
#endif
1457
#if defined(JSON_HEDLEY_NON_NULL)
1458
#undef JSON_HEDLEY_NON_NULL
1459
#endif
1460
#if \
1461
JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1462
JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1463
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1464
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1465
#define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1466
#else
1467
#define JSON_HEDLEY_NON_NULL(...)
1468
#endif
1469
JSON_HEDLEY_DIAGNOSTIC_POP
1470
1471
#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1472
#undef JSON_HEDLEY_PRINTF_FORMAT
1473
#endif
1474
#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1475
#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1476
#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1477
#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1478
#elif \
1479
JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1480
JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1481
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1482
JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1483
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1484
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1485
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1486
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1487
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1488
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1489
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1490
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1491
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1492
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1493
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1494
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1495
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1496
#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1497
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1498
#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1499
#else
1500
#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1501
#endif
1502
1503
#if defined(JSON_HEDLEY_CONSTEXPR)
1504
#undef JSON_HEDLEY_CONSTEXPR
1505
#endif
1506
#if defined(__cplusplus)
1507
#if __cplusplus >= 201103L
1508
#define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1509
#endif
1510
#endif
1511
#if !defined(JSON_HEDLEY_CONSTEXPR)
1512
#define JSON_HEDLEY_CONSTEXPR
1513
#endif
1514
1515
#if defined(JSON_HEDLEY_PREDICT)
1516
#undef JSON_HEDLEY_PREDICT
1517
#endif
1518
#if defined(JSON_HEDLEY_LIKELY)
1519
#undef JSON_HEDLEY_LIKELY
1520
#endif
1521
#if defined(JSON_HEDLEY_UNLIKELY)
1522
#undef JSON_HEDLEY_UNLIKELY
1523
#endif
1524
#if defined(JSON_HEDLEY_UNPREDICTABLE)
1525
#undef JSON_HEDLEY_UNPREDICTABLE
1526
#endif
1527
#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1528
#define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1529
#endif
1530
#if \
1531
(JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1532
JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1533
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1534
# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1535
# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1536
# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1537
# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1538
# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1539
#elif \
1540
(JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1541
JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1542
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1543
(JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1544
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1545
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1546
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1547
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1548
JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1549
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1550
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1551
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1552
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1553
JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1554
JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1555
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1556
# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1557
(((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1558
# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1559
(__extension__ ({ \
1560
double hedley_probability_ = (probability); \
1561
((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1562
}))
1563
# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1564
(__extension__ ({ \
1565
double hedley_probability_ = (probability); \
1566
((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1567
}))
1568
# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1569
# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1570
#else
1571
# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1572
# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1573
# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1574
# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1575
# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1576
#endif
1577
#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1578
#define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1579
#endif
1580
1581
#if defined(JSON_HEDLEY_MALLOC)
1582
#undef JSON_HEDLEY_MALLOC
1583
#endif
1584
#if \
1585
JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1586
JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1587
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1588
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1589
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1590
JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1591
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1592
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1593
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1594
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1595
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1596
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1597
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1598
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1599
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1600
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1601
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1602
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1603
#define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1604
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1605
#define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1606
#elif \
1607
JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1608
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1609
#define JSON_HEDLEY_MALLOC __declspec(restrict)
1610
#else
1611
#define JSON_HEDLEY_MALLOC
1612
#endif
1613
1614
#if defined(JSON_HEDLEY_PURE)
1615
#undef JSON_HEDLEY_PURE
1616
#endif
1617
#if \
1618
JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1619
JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1620
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1621
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1622
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1623
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1624
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1625
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1626
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1627
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1628
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1629
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1630
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1631
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1632
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1633
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1634
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1635
JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1636
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1637
# define JSON_HEDLEY_PURE __attribute__((__pure__))
1638
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1639
# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1640
#elif defined(__cplusplus) && \
1641
( \
1642
JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1643
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1644
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1645
)
1646
# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1647
#else
1648
# define JSON_HEDLEY_PURE
1649
#endif
1650
1651
#if defined(JSON_HEDLEY_CONST)
1652
#undef JSON_HEDLEY_CONST
1653
#endif
1654
#if \
1655
JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1656
JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1657
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1658
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1659
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1660
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1661
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1662
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1663
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1664
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1665
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1666
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1667
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1668
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1669
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1670
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1671
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1672
JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1673
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1674
#define JSON_HEDLEY_CONST __attribute__((__const__))
1675
#elif \
1676
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1677
#define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1678
#else
1679
#define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1680
#endif
1681
1682
#if defined(JSON_HEDLEY_RESTRICT)
1683
#undef JSON_HEDLEY_RESTRICT
1684
#endif
1685
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1686
#define JSON_HEDLEY_RESTRICT restrict
1687
#elif \
1688
JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1689
JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1690
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1691
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1692
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1693
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1694
JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1695
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1696
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1697
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1698
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1699
(JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1700
JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1701
defined(__clang__) || \
1702
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1703
#define JSON_HEDLEY_RESTRICT __restrict
1704
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1705
#define JSON_HEDLEY_RESTRICT _Restrict
1706
#else
1707
#define JSON_HEDLEY_RESTRICT
1708
#endif
1709
1710
#if defined(JSON_HEDLEY_INLINE)
1711
#undef JSON_HEDLEY_INLINE
1712
#endif
1713
#if \
1714
(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1715
(defined(__cplusplus) && (__cplusplus >= 199711L))
1716
#define JSON_HEDLEY_INLINE inline
1717
#elif \
1718
defined(JSON_HEDLEY_GCC_VERSION) || \
1719
JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1720
#define JSON_HEDLEY_INLINE __inline__
1721
#elif \
1722
JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1723
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1724
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1725
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1726
JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1727
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1728
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1729
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1730
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1731
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1732
#define JSON_HEDLEY_INLINE __inline
1733
#else
1734
#define JSON_HEDLEY_INLINE
1735
#endif
1736
1737
#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1738
#undef JSON_HEDLEY_ALWAYS_INLINE
1739
#endif
1740
#if \
1741
JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1742
JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1743
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1744
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1745
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1746
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1747
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1748
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1749
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1750
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1751
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1752
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1753
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1754
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1755
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1756
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1757
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1758
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1759
JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1760
# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1761
#elif \
1762
JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1763
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1764
# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1765
#elif defined(__cplusplus) && \
1766
( \
1767
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1768
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1769
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1770
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1771
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1772
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1773
)
1774
# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1775
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1776
# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1777
#else
1778
# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1779
#endif
1780
1781
#if defined(JSON_HEDLEY_NEVER_INLINE)
1782
#undef JSON_HEDLEY_NEVER_INLINE
1783
#endif
1784
#if \
1785
JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1786
JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1787
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1788
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1789
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1790
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1791
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1792
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1793
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1794
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1795
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1796
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1797
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1798
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1799
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1800
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1801
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1802
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1803
JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1804
#define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1805
#elif \
1806
JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1807
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1808
#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1809
#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1810
#define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1811
#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1812
#define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1813
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1814
#define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1815
#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1816
#define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1817
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1818
#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1819
#else
1820
#define JSON_HEDLEY_NEVER_INLINE
1821
#endif
1822
1823
#if defined(JSON_HEDLEY_PRIVATE)
1824
#undef JSON_HEDLEY_PRIVATE
1825
#endif
1826
#if defined(JSON_HEDLEY_PUBLIC)
1827
#undef JSON_HEDLEY_PUBLIC
1828
#endif
1829
#if defined(JSON_HEDLEY_IMPORT)
1830
#undef JSON_HEDLEY_IMPORT
1831
#endif
1832
#if defined(_WIN32) || defined(__CYGWIN__)
1833
# define JSON_HEDLEY_PRIVATE
1834
# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1835
# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1836
#else
1837
# if \
1838
JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1839
JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1840
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1841
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1842
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1843
JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1844
( \
1845
defined(__TI_EABI__) && \
1846
( \
1847
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1848
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1849
) \
1850
) || \
1851
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1852
# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1853
# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1854
# else
1855
# define JSON_HEDLEY_PRIVATE
1856
# define JSON_HEDLEY_PUBLIC
1857
# endif
1858
# define JSON_HEDLEY_IMPORT extern
1859
#endif
1860
1861
#if defined(JSON_HEDLEY_NO_THROW)
1862
#undef JSON_HEDLEY_NO_THROW
1863
#endif
1864
#if \
1865
JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
1866
JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1867
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1868
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1869
#define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
1870
#elif \
1871
JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
1872
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1873
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1874
#define JSON_HEDLEY_NO_THROW __declspec(nothrow)
1875
#else
1876
#define JSON_HEDLEY_NO_THROW
1877
#endif
1878
1879
#if defined(JSON_HEDLEY_FALL_THROUGH)
1880
#undef JSON_HEDLEY_FALL_THROUGH
1881
#endif
1882
#if \
1883
JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
1884
JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
1885
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1886
#define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
1887
#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
1888
#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
1889
#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
1890
#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
1891
#elif defined(__fallthrough) /* SAL */
1892
#define JSON_HEDLEY_FALL_THROUGH __fallthrough
1893
#else
1894
#define JSON_HEDLEY_FALL_THROUGH
1895
#endif
1896
1897
#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
1898
#undef JSON_HEDLEY_RETURNS_NON_NULL
1899
#endif
1900
#if \
1901
JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
1902
JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
1903
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1904
#define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
1905
#elif defined(_Ret_notnull_) /* SAL */
1906
#define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
1907
#else
1908
#define JSON_HEDLEY_RETURNS_NON_NULL
1909
#endif
1910
1911
#if defined(JSON_HEDLEY_ARRAY_PARAM)
1912
#undef JSON_HEDLEY_ARRAY_PARAM
1913
#endif
1914
#if \
1915
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
1916
!defined(__STDC_NO_VLA__) && \
1917
!defined(__cplusplus) && \
1918
!defined(JSON_HEDLEY_PGI_VERSION) && \
1919
!defined(JSON_HEDLEY_TINYC_VERSION)
1920
#define JSON_HEDLEY_ARRAY_PARAM(name) (name)
1921
#else
1922
#define JSON_HEDLEY_ARRAY_PARAM(name)
1923
#endif
1924
1925
#if defined(JSON_HEDLEY_IS_CONSTANT)
1926
#undef JSON_HEDLEY_IS_CONSTANT
1927
#endif
1928
#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
1929
#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
1930
#endif
1931
/* JSON_HEDLEY_IS_CONSTEXPR_ is for
1932
HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1933
#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1934
#undef JSON_HEDLEY_IS_CONSTEXPR_
1935
#endif
1936
#if \
1937
JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
1938
JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1939
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1940
JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
1941
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1942
JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1943
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1944
(JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
1945
JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1946
JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1947
#define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
1948
#endif
1949
#if !defined(__cplusplus)
1950
# if \
1951
JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
1952
JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1953
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1954
JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1955
JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1956
JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1957
JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
1958
#if defined(__INTPTR_TYPE__)
1959
#define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
1960
#else
1961
#include <stdint.h>
1962
#define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
1963
#endif
1964
# elif \
1965
( \
1966
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
1967
!defined(JSON_HEDLEY_SUNPRO_VERSION) && \
1968
!defined(JSON_HEDLEY_PGI_VERSION) && \
1969
!defined(JSON_HEDLEY_IAR_VERSION)) || \
1970
(JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1971
JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
1972
JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
1973
JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1974
JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
1975
#if defined(__INTPTR_TYPE__)
1976
#define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
1977
#else
1978
#include <stdint.h>
1979
#define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
1980
#endif
1981
# elif \
1982
defined(JSON_HEDLEY_GCC_VERSION) || \
1983
defined(JSON_HEDLEY_INTEL_VERSION) || \
1984
defined(JSON_HEDLEY_TINYC_VERSION) || \
1985
defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
1986
JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
1987
defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
1988
defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
1989
defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
1990
defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
1991
defined(__clang__)
1992
# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
1993
sizeof(void) != \
1994
sizeof(*( \
1995
1 ? \
1996
((void*) ((expr) * 0L) ) : \
1997
((struct { char v[sizeof(void) * 2]; } *) 1) \
1998
) \
1999
) \
2000
)
2001
# endif
2002
#endif
2003
#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2004
#if !defined(JSON_HEDLEY_IS_CONSTANT)
2005
#define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2006
#endif
2007
#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2008
#else
2009
#if !defined(JSON_HEDLEY_IS_CONSTANT)
2010
#define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2011
#endif
2012
#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2013
#endif
2014
2015
#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2016
#undef JSON_HEDLEY_BEGIN_C_DECLS
2017
#endif
2018
#if defined(JSON_HEDLEY_END_C_DECLS)
2019
#undef JSON_HEDLEY_END_C_DECLS
2020
#endif
2021
#if defined(JSON_HEDLEY_C_DECL)
2022
#undef JSON_HEDLEY_C_DECL
2023
#endif
2024
#if defined(__cplusplus)
2025
#define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2026
#define JSON_HEDLEY_END_C_DECLS }
2027
#define JSON_HEDLEY_C_DECL extern "C"
2028
#else
2029
#define JSON_HEDLEY_BEGIN_C_DECLS
2030
#define JSON_HEDLEY_END_C_DECLS
2031
#define JSON_HEDLEY_C_DECL
2032
#endif
2033
2034
#if defined(JSON_HEDLEY_STATIC_ASSERT)
2035
#undef JSON_HEDLEY_STATIC_ASSERT
2036
#endif
2037
#if \
2038
!defined(__cplusplus) && ( \
2039
(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2040
(JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2041
JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2042
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2043
defined(_Static_assert) \
2044
)
2045
# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2046
#elif \
2047
(defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2048
JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2049
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2050
# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2051
#else
2052
# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2053
#endif
2054
2055
#if defined(JSON_HEDLEY_NULL)
2056
#undef JSON_HEDLEY_NULL
2057
#endif
2058
#if defined(__cplusplus)
2059
#if __cplusplus >= 201103L
2060
#define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2061
#elif defined(NULL)
2062
#define JSON_HEDLEY_NULL NULL
2063
#else
2064
#define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2065
#endif
2066
#elif defined(NULL)
2067
#define JSON_HEDLEY_NULL NULL
2068
#else
2069
#define JSON_HEDLEY_NULL ((void*) 0)
2070
#endif
2071
2072
#if defined(JSON_HEDLEY_MESSAGE)
2073
#undef JSON_HEDLEY_MESSAGE
2074
#endif
2075
#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2076
# define JSON_HEDLEY_MESSAGE(msg) \
2077
JSON_HEDLEY_DIAGNOSTIC_PUSH \
2078
JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2079
JSON_HEDLEY_PRAGMA(message msg) \
2080
JSON_HEDLEY_DIAGNOSTIC_POP
2081
#elif \
2082
JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2083
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2084
# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2085
#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2086
# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2087
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2088
# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2089
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2090
# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2091
#else
2092
# define JSON_HEDLEY_MESSAGE(msg)
2093
#endif
2094
2095
#if defined(JSON_HEDLEY_WARNING)
2096
#undef JSON_HEDLEY_WARNING
2097
#endif
2098
#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2099
# define JSON_HEDLEY_WARNING(msg) \
2100
JSON_HEDLEY_DIAGNOSTIC_PUSH \
2101
JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2102
JSON_HEDLEY_PRAGMA(clang warning msg) \
2103
JSON_HEDLEY_DIAGNOSTIC_POP
2104
#elif \
2105
JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2106
JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2107
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2108
# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2109
#elif \
2110
JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2111
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2112
# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2113
#else
2114
# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2115
#endif
2116
2117
#if defined(JSON_HEDLEY_REQUIRE)
2118
#undef JSON_HEDLEY_REQUIRE
2119
#endif
2120
#if defined(JSON_HEDLEY_REQUIRE_MSG)
2121
#undef JSON_HEDLEY_REQUIRE_MSG
2122
#endif
2123
#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2124
# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2125
# define JSON_HEDLEY_REQUIRE(expr) \
2126
JSON_HEDLEY_DIAGNOSTIC_PUSH \
2127
_Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2128
__attribute__((diagnose_if(!(expr), #expr, "error"))) \
2129
JSON_HEDLEY_DIAGNOSTIC_POP
2130
# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2131
JSON_HEDLEY_DIAGNOSTIC_PUSH \
2132
_Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2133
__attribute__((diagnose_if(!(expr), msg, "error"))) \
2134
JSON_HEDLEY_DIAGNOSTIC_POP
2135
# else
2136
# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2137
# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2138
# endif
2139
#else
2140
# define JSON_HEDLEY_REQUIRE(expr)
2141
# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2142
#endif
2143
2144
#if defined(JSON_HEDLEY_FLAGS)
2145
#undef JSON_HEDLEY_FLAGS
2146
#endif
2147
#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2148
#define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2149
#else
2150
#define JSON_HEDLEY_FLAGS
2151
#endif
2152
2153
#if defined(JSON_HEDLEY_FLAGS_CAST)
2154
#undef JSON_HEDLEY_FLAGS_CAST
2155
#endif
2156
#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2157
# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2158
JSON_HEDLEY_DIAGNOSTIC_PUSH \
2159
_Pragma("warning(disable:188)") \
2160
((T) (expr)); \
2161
JSON_HEDLEY_DIAGNOSTIC_POP \
2162
}))
2163
#else
2164
# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2165
#endif
2166
2167
#if defined(JSON_HEDLEY_EMPTY_BASES)
2168
#undef JSON_HEDLEY_EMPTY_BASES
2169
#endif
2170
#if \
2171
(JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2172
JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2173
#define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2174
#else
2175
#define JSON_HEDLEY_EMPTY_BASES
2176
#endif
2177
2178
/* Remaining macros are deprecated. */
2179
2180
#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2181
#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2182
#endif
2183
#if defined(__clang__)
2184
#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2185
#else
2186
#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2187
#endif
2188
2189
#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2190
#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2191
#endif
2192
#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2193
2194
#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2195
#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2196
#endif
2197
#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2198
2199
#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2200
#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2201
#endif
2202
#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2203
2204
#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2205
#undef JSON_HEDLEY_CLANG_HAS_FEATURE
2206
#endif
2207
#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2208
2209
#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2210
#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2211
#endif
2212
#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2213
2214
#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2215
#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2216
#endif
2217
#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2218
2219
#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2220
#undef JSON_HEDLEY_CLANG_HAS_WARNING
2221
#endif
2222
#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2223
2224
#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2225
2226
// #include <nlohmann/detail/meta/detected.hpp>
2227
2228
2229
#include <type_traits>
2230
2231
// #include <nlohmann/detail/meta/void_t.hpp>
2232
2233
2234
namespace nlohmann
2235
{
2236
namespace detail
2237
{
2238
template<typename ...Ts> struct make_void
2239
{
2240
using type = void;
2241
};
2242
template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
2243
} // namespace detail
2244
} // namespace nlohmann
2245
2246
2247
// https://en.cppreference.com/w/cpp/experimental/is_detected
2248
namespace nlohmann
2249
{
2250
namespace detail
2251
{
2252
struct nonesuch
2253
{
2254
nonesuch() = delete;
2255
~nonesuch() = delete;
2256
nonesuch(nonesuch const&) = delete;
2257
nonesuch(nonesuch const&&) = delete;
2258
void operator=(nonesuch const&) = delete;
2259
void operator=(nonesuch&&) = delete;
2260
};
2261
2262
template<class Default,
2263
class AlwaysVoid,
2264
template<class...> class Op,
2265
class... Args>
2266
struct detector
2267
{
2268
using value_t = std::false_type;
2269
using type = Default;
2270
};
2271
2272
template<class Default, template<class...> class Op, class... Args>
2273
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
2274
{
2275
using value_t = std::true_type;
2276
using type = Op<Args...>;
2277
};
2278
2279
template<template<class...> class Op, class... Args>
2280
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
2281
2282
template<template<class...> class Op, class... Args>
2283
struct is_detected_lazy : is_detected<Op, Args...> { };
2284
2285
template<template<class...> class Op, class... Args>
2286
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
2287
2288
template<class Default, template<class...> class Op, class... Args>
2289
using detected_or = detector<Default, void, Op, Args...>;
2290
2291
template<class Default, template<class...> class Op, class... Args>
2292
using detected_or_t = typename detected_or<Default, Op, Args...>::type;
2293
2294
template<class Expected, template<class...> class Op, class... Args>
2295
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
2296
2297
template<class To, template<class...> class Op, class... Args>
2298
using is_detected_convertible =
2299
std::is_convertible<detected_t<Op, Args...>, To>;
2300
} // namespace detail
2301
} // namespace nlohmann
2302
2303
2304
// This file contains all internal macro definitions
2305
// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2306
2307
// exclude unsupported compilers
2308
#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2309
#if defined(__clang__)
2310
#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2311
#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2312
#endif
2313
#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2314
#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2315
#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2316
#endif
2317
#endif
2318
#endif
2319
2320
// C++ language standard detection
2321
// if the user manually specified the used c++ version this is skipped
2322
#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2323
#if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2324
#define JSON_HAS_CPP_20
2325
#define JSON_HAS_CPP_17
2326
#define JSON_HAS_CPP_14
2327
#elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2328
#define JSON_HAS_CPP_17
2329
#define JSON_HAS_CPP_14
2330
#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2331
#define JSON_HAS_CPP_14
2332
#endif
2333
// the cpp 11 flag is always specified because it is the minimal required version
2334
#define JSON_HAS_CPP_11
2335
#endif
2336
2337
#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2338
#ifdef JSON_HAS_CPP_17
2339
#if defined(__cpp_lib_filesystem)
2340
#define JSON_HAS_FILESYSTEM 1
2341
#elif defined(__cpp_lib_experimental_filesystem)
2342
#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2343
#elif !defined(__has_include)
2344
#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2345
#elif __has_include(<filesystem>)
2346
#define JSON_HAS_FILESYSTEM 1
2347
#elif __has_include(<experimental/filesystem>)
2348
#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2349
#endif
2350
2351
// std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2352
#if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2353
#undef JSON_HAS_FILESYSTEM
2354
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2355
#endif
2356
2357
// no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2358
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2359
#undef JSON_HAS_FILESYSTEM
2360
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2361
#endif
2362
2363
// no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2364
#if defined(__clang_major__) && __clang_major__ < 7
2365
#undef JSON_HAS_FILESYSTEM
2366
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2367
#endif
2368
2369
// no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2370
#if defined(_MSC_VER) && _MSC_VER < 1940
2371
#undef JSON_HAS_FILESYSTEM
2372
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2373
#endif
2374
2375
// no filesystem support before iOS 13
2376
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2377
#undef JSON_HAS_FILESYSTEM
2378
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2379
#endif
2380
2381
// no filesystem support before macOS Catalina
2382
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2383
#undef JSON_HAS_FILESYSTEM
2384
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2385
#endif
2386
#endif
2387
#endif
2388
2389
#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2390
#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2391
#endif
2392
2393
#ifndef JSON_HAS_FILESYSTEM
2394
#define JSON_HAS_FILESYSTEM 0
2395
#endif
2396
2397
// disable documentation warnings on clang
2398
#if defined(__clang__)
2399
#pragma clang diagnostic push
2400
#pragma clang diagnostic ignored "-Wdocumentation"
2401
#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2402
#endif
2403
2404
// allow disabling exceptions
2405
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2406
#define JSON_THROW(exception) throw exception
2407
#define JSON_TRY try
2408
#define JSON_CATCH(exception) catch(exception)
2409
#define JSON_INTERNAL_CATCH(exception) catch(exception)
2410
#else
2411
#include <cstdlib>
2412
#define JSON_THROW(exception) std::abort()
2413
#define JSON_TRY if(true)
2414
#define JSON_CATCH(exception) if(false)
2415
#define JSON_INTERNAL_CATCH(exception) if(false)
2416
#endif
2417
2418
// override exception macros
2419
#if defined(JSON_THROW_USER)
2420
#undef JSON_THROW
2421
#define JSON_THROW JSON_THROW_USER
2422
#endif
2423
#if defined(JSON_TRY_USER)
2424
#undef JSON_TRY
2425
#define JSON_TRY JSON_TRY_USER
2426
#endif
2427
#if defined(JSON_CATCH_USER)
2428
#undef JSON_CATCH
2429
#define JSON_CATCH JSON_CATCH_USER
2430
#undef JSON_INTERNAL_CATCH
2431
#define JSON_INTERNAL_CATCH JSON_CATCH_USER
2432
#endif
2433
#if defined(JSON_INTERNAL_CATCH_USER)
2434
#undef JSON_INTERNAL_CATCH
2435
#define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2436
#endif
2437
2438
// allow overriding assert
2439
#if !defined(JSON_ASSERT)
2440
#include <cassert> // assert
2441
#define JSON_ASSERT(x) assert(x)
2442
#endif
2443
2444
// allow to access some private functions (needed by the test suite)
2445
#if defined(JSON_TESTS_PRIVATE)
2446
#define JSON_PRIVATE_UNLESS_TESTED public
2447
#else
2448
#define JSON_PRIVATE_UNLESS_TESTED private
2449
#endif
2450
2451
/*!
2452
@brief macro to briefly define a mapping between an enum and JSON
2453
@def NLOHMANN_JSON_SERIALIZE_ENUM
2454
@since version 3.4.0
2455
*/
2456
#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2457
template<typename BasicJsonType> \
2458
inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2459
{ \
2460
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2461
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2462
auto it = std::find_if(std::begin(m), std::end(m), \
2463
[e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2464
{ \
2465
return ej_pair.first == e; \
2466
}); \
2467
j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2468
} \
2469
template<typename BasicJsonType> \
2470
inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2471
{ \
2472
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2473
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2474
auto it = std::find_if(std::begin(m), std::end(m), \
2475
[&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2476
{ \
2477
return ej_pair.second == j; \
2478
}); \
2479
e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2480
}
2481
2482
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2483
// may be removed in the future once the class is split.
2484
2485
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2486
template<template<typename, typename, typename...> class ObjectType, \
2487
template<typename, typename...> class ArrayType, \
2488
class StringType, class BooleanType, class NumberIntegerType, \
2489
class NumberUnsignedType, class NumberFloatType, \
2490
template<typename> class AllocatorType, \
2491
template<typename, typename = void> class JSONSerializer, \
2492
class BinaryType>
2493
2494
#define NLOHMANN_BASIC_JSON_TPL \
2495
basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2496
NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2497
AllocatorType, JSONSerializer, BinaryType>
2498
2499
// Macros to simplify conversion from/to types
2500
2501
#define NLOHMANN_JSON_EXPAND( x ) x
2502
#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
2503
#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2504
NLOHMANN_JSON_PASTE64, \
2505
NLOHMANN_JSON_PASTE63, \
2506
NLOHMANN_JSON_PASTE62, \
2507
NLOHMANN_JSON_PASTE61, \
2508
NLOHMANN_JSON_PASTE60, \
2509
NLOHMANN_JSON_PASTE59, \
2510
NLOHMANN_JSON_PASTE58, \
2511
NLOHMANN_JSON_PASTE57, \
2512
NLOHMANN_JSON_PASTE56, \
2513
NLOHMANN_JSON_PASTE55, \
2514
NLOHMANN_JSON_PASTE54, \
2515
NLOHMANN_JSON_PASTE53, \
2516
NLOHMANN_JSON_PASTE52, \
2517
NLOHMANN_JSON_PASTE51, \
2518
NLOHMANN_JSON_PASTE50, \
2519
NLOHMANN_JSON_PASTE49, \
2520
NLOHMANN_JSON_PASTE48, \
2521
NLOHMANN_JSON_PASTE47, \
2522
NLOHMANN_JSON_PASTE46, \
2523
NLOHMANN_JSON_PASTE45, \
2524
NLOHMANN_JSON_PASTE44, \
2525
NLOHMANN_JSON_PASTE43, \
2526
NLOHMANN_JSON_PASTE42, \
2527
NLOHMANN_JSON_PASTE41, \
2528
NLOHMANN_JSON_PASTE40, \
2529
NLOHMANN_JSON_PASTE39, \
2530
NLOHMANN_JSON_PASTE38, \
2531
NLOHMANN_JSON_PASTE37, \
2532
NLOHMANN_JSON_PASTE36, \
2533
NLOHMANN_JSON_PASTE35, \
2534
NLOHMANN_JSON_PASTE34, \
2535
NLOHMANN_JSON_PASTE33, \
2536
NLOHMANN_JSON_PASTE32, \
2537
NLOHMANN_JSON_PASTE31, \
2538
NLOHMANN_JSON_PASTE30, \
2539
NLOHMANN_JSON_PASTE29, \
2540
NLOHMANN_JSON_PASTE28, \
2541
NLOHMANN_JSON_PASTE27, \
2542
NLOHMANN_JSON_PASTE26, \
2543
NLOHMANN_JSON_PASTE25, \
2544
NLOHMANN_JSON_PASTE24, \
2545
NLOHMANN_JSON_PASTE23, \
2546
NLOHMANN_JSON_PASTE22, \
2547
NLOHMANN_JSON_PASTE21, \
2548
NLOHMANN_JSON_PASTE20, \
2549
NLOHMANN_JSON_PASTE19, \
2550
NLOHMANN_JSON_PASTE18, \
2551
NLOHMANN_JSON_PASTE17, \
2552
NLOHMANN_JSON_PASTE16, \
2553
NLOHMANN_JSON_PASTE15, \
2554
NLOHMANN_JSON_PASTE14, \
2555
NLOHMANN_JSON_PASTE13, \
2556
NLOHMANN_JSON_PASTE12, \
2557
NLOHMANN_JSON_PASTE11, \
2558
NLOHMANN_JSON_PASTE10, \
2559
NLOHMANN_JSON_PASTE9, \
2560
NLOHMANN_JSON_PASTE8, \
2561
NLOHMANN_JSON_PASTE7, \
2562
NLOHMANN_JSON_PASTE6, \
2563
NLOHMANN_JSON_PASTE5, \
2564
NLOHMANN_JSON_PASTE4, \
2565
NLOHMANN_JSON_PASTE3, \
2566
NLOHMANN_JSON_PASTE2, \
2567
NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2568
#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2569
#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2570
#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2571
#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2572
#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2573
#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2574
#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2575
#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2576
#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2577
#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2578
#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2579
#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2580
#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2581
#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2582
#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2583
#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2584
#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
2585
#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
2586
#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
2587
#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
2588
#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
2589
#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
2590
#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
2591
#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
2592
#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
2593
#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
2594
#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
2595
#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
2596
#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
2597
#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2598
#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
2599
#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
2600
#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
2601
#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
2602
#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
2603
#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
2604
#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
2605
#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
2606
#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
2607
#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
2608
#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
2609
#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
2610
#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
2611
#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
2612
#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
2613
#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
2614
#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
2615
#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
2616
#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
2617
#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
2618
#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
2619
#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
2620
#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
2621
#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2622
#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2623
#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2624
#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
2625
#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
2626
#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
2627
#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
2628
#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
2629
#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
2630
#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
2631
2632
#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2633
#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2634
2635
/*!
2636
@brief macro
2637
@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
2638
@since version 3.9.0
2639
*/
2640
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2641
friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2642
friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2643
2644
/*!
2645
@brief macro
2646
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
2647
@since version 3.9.0
2648
*/
2649
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2650
inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2651
inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2652
2653
2654
// inspired from https://stackoverflow.com/a/26745591
2655
// allows to call any std function as if (e.g. with begin):
2656
// using std::begin; begin(x);
2657
//
2658
// it allows using the detected idiom to retrieve the return type
2659
// of such an expression
2660
#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2661
namespace detail { \
2662
using std::std_name; \
2663
\
2664
template<typename... T> \
2665
using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2666
} \
2667
\
2668
namespace detail2 { \
2669
struct std_name##_tag \
2670
{ \
2671
}; \
2672
\
2673
template<typename... T> \
2674
std_name##_tag std_name(T&&...); \
2675
\
2676
template<typename... T> \
2677
using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2678
\
2679
template<typename... T> \
2680
struct would_call_std_##std_name \
2681
{ \
2682
static constexpr auto const value = ::nlohmann::detail:: \
2683
is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2684
}; \
2685
} /* namespace detail2 */ \
2686
\
2687
template<typename... T> \
2688
struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2689
{ \
2690
}
2691
2692
#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2693
#define JSON_USE_IMPLICIT_CONVERSIONS 1
2694
#endif
2695
2696
#if JSON_USE_IMPLICIT_CONVERSIONS
2697
#define JSON_EXPLICIT
2698
#else
2699
#define JSON_EXPLICIT explicit
2700
#endif
2701
2702
#ifndef JSON_DIAGNOSTICS
2703
#define JSON_DIAGNOSTICS 0
2704
#endif
2705
2706
2707
namespace nlohmann
2708
{
2709
namespace detail
2710
{
2711
2712
/*!
2713
@brief replace all occurrences of a substring by another string
2714
2715
@param[in,out] s the string to manipulate; changed so that all
2716
occurrences of @a f are replaced with @a t
2717
@param[in] f the substring to replace with @a t
2718
@param[in] t the string to replace @a f
2719
2720
@pre The search string @a f must not be empty. **This precondition is
2721
enforced with an assertion.**
2722
2723
@since version 2.0.0
2724
*/
2725
inline void replace_substring(std::string& s, const std::string& f,
2726
const std::string& t)
2727
{
2728
JSON_ASSERT(!f.empty());
2729
for (auto pos = s.find(f); // find first occurrence of f
2730
pos != std::string::npos; // make sure f was found
2731
s.replace(pos, f.size(), t), // replace with t, and
2732
pos = s.find(f, pos + t.size())) // find next occurrence of f
2733
{}
2734
}
2735
2736
/*!
2737
* @brief string escaping as described in RFC 6901 (Sect. 4)
2738
* @param[in] s string to escape
2739
* @return escaped string
2740
*
2741
* Note the order of escaping "~" to "~0" and "/" to "~1" is important.
2742
*/
2743
inline std::string escape(std::string s)
2744
{
2745
replace_substring(s, "~", "~0");
2746
replace_substring(s, "/", "~1");
2747
return s;
2748
}
2749
2750
/*!
2751
* @brief string unescaping as described in RFC 6901 (Sect. 4)
2752
* @param[in] s string to unescape
2753
* @return unescaped string
2754
*
2755
* Note the order of escaping "~1" to "/" and "~0" to "~" is important.
2756
*/
2757
static void unescape(std::string& s)
2758
{
2759
replace_substring(s, "~1", "/");
2760
replace_substring(s, "~0", "~");
2761
}
2762
2763
} // namespace detail
2764
} // namespace nlohmann
2765
2766
// #include <nlohmann/detail/input/position_t.hpp>
2767
2768
2769
#include <cstddef> // size_t
2770
2771
namespace nlohmann
2772
{
2773
namespace detail
2774
{
2775
/// struct to capture the start position of the current token
2776
struct position_t
2777
{
2778
/// the total number of characters read
2779
std::size_t chars_read_total = 0;
2780
/// the number of characters read in the current line
2781
std::size_t chars_read_current_line = 0;
2782
/// the number of lines read
2783
std::size_t lines_read = 0;
2784
2785
/// conversion to size_t to preserve SAX interface
2786
constexpr operator size_t() const
2787
{
2788
return chars_read_total;
2789
}
2790
};
2791
2792
} // namespace detail
2793
} // namespace nlohmann
2794
2795
// #include <nlohmann/detail/macro_scope.hpp>
2796
2797
2798
namespace nlohmann
2799
{
2800
namespace detail
2801
{
2802
////////////////
2803
// exceptions //
2804
////////////////
2805
2806
/// @brief general exception of the @ref basic_json class
2807
/// @sa https://json.nlohmann.me/api/basic_json/exception/
2808
class exception : public std::exception
2809
{
2810
public:
2811
/// returns the explanatory string
2812
const char* what() const noexcept override
2813
{
2814
return m.what();
2815
}
2816
2817
/// the id of the exception
2818
const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
2819
2820
protected:
2821
JSON_HEDLEY_NON_NULL(3)
2822
exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
2823
2824
static std::string name(const std::string& ename, int id_)
2825
{
2826
return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
2827
}
2828
2829
template<typename BasicJsonType>
2830
static std::string diagnostics(const BasicJsonType& leaf_element)
2831
{
2832
#if JSON_DIAGNOSTICS
2833
std::vector<std::string> tokens;
2834
for (const auto* current = &leaf_element; current->m_parent != nullptr; current = current->m_parent)
2835
{
2836
switch (current->m_parent->type())
2837
{
2838
case value_t::array:
2839
{
2840
for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
2841
{
2842
if (&current->m_parent->m_value.array->operator[](i) == current)
2843
{
2844
tokens.emplace_back(std::to_string(i));
2845
break;
2846
}
2847
}
2848
break;
2849
}
2850
2851
case value_t::object:
2852
{
2853
for (const auto& element : *current->m_parent->m_value.object)
2854
{
2855
if (&element.second == current)
2856
{
2857
tokens.emplace_back(element.first.c_str());
2858
break;
2859
}
2860
}
2861
break;
2862
}
2863
2864
case value_t::null: // LCOV_EXCL_LINE
2865
case value_t::string: // LCOV_EXCL_LINE
2866
case value_t::boolean: // LCOV_EXCL_LINE
2867
case value_t::number_integer: // LCOV_EXCL_LINE
2868
case value_t::number_unsigned: // LCOV_EXCL_LINE
2869
case value_t::number_float: // LCOV_EXCL_LINE
2870
case value_t::binary: // LCOV_EXCL_LINE
2871
case value_t::discarded: // LCOV_EXCL_LINE
2872
default: // LCOV_EXCL_LINE
2873
break; // LCOV_EXCL_LINE
2874
}
2875
}
2876
2877
if (tokens.empty())
2878
{
2879
return "";
2880
}
2881
2882
return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
2883
[](const std::string & a, const std::string & b)
2884
{
2885
return a + "/" + detail::escape(b);
2886
}) + ") ";
2887
#else
2888
static_cast<void>(leaf_element);
2889
return "";
2890
#endif
2891
}
2892
2893
private:
2894
/// an exception object as storage for error messages
2895
std::runtime_error m;
2896
};
2897
2898
/// @brief exception indicating a parse error
2899
/// @sa https://json.nlohmann.me/api/basic_json/parse_error/
2900
class parse_error : public exception
2901
{
2902
public:
2903
/*!
2904
@brief create a parse error exception
2905
@param[in] id_ the id of the exception
2906
@param[in] pos the position where the error occurred (or with
2907
chars_read_total=0 if the position cannot be
2908
determined)
2909
@param[in] what_arg the explanatory string
2910
@return parse_error object
2911
*/
2912
template<typename BasicJsonType>
2913
static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context)
2914
{
2915
std::string w = exception::name("parse_error", id_) + "parse error" +
2916
position_string(pos) + ": " + exception::diagnostics(context) + what_arg;
2917
return {id_, pos.chars_read_total, w.c_str()};
2918
}
2919
2920
template<typename BasicJsonType>
2921
static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context)
2922
{
2923
std::string w = exception::name("parse_error", id_) + "parse error" +
2924
(byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
2925
": " + exception::diagnostics(context) + what_arg;
2926
return {id_, byte_, w.c_str()};
2927
}
2928
2929
/*!
2930
@brief byte index of the parse error
2931
2932
The byte index of the last read character in the input file.
2933
2934
@note For an input with n bytes, 1 is the index of the first character and
2935
n+1 is the index of the terminating null byte or the end of file.
2936
This also holds true when reading a byte vector (CBOR or MessagePack).
2937
*/
2938
const std::size_t byte;
2939
2940
private:
2941
parse_error(int id_, std::size_t byte_, const char* what_arg)
2942
: exception(id_, what_arg), byte(byte_) {}
2943
2944
static std::string position_string(const position_t& pos)
2945
{
2946
return " at line " + std::to_string(pos.lines_read + 1) +
2947
", column " + std::to_string(pos.chars_read_current_line);
2948
}
2949
};
2950
2951
/// @brief exception indicating errors with iterators
2952
/// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
2953
class invalid_iterator : public exception
2954
{
2955
public:
2956
template<typename BasicJsonType>
2957
static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context)
2958
{
2959
std::string w = exception::name("invalid_iterator", id_) + exception::diagnostics(context) + what_arg;
2960
return {id_, w.c_str()};
2961
}
2962
2963
private:
2964
JSON_HEDLEY_NON_NULL(3)
2965
invalid_iterator(int id_, const char* what_arg)
2966
: exception(id_, what_arg) {}
2967
};
2968
2969
/// @brief exception indicating executing a member function with a wrong type
2970
/// @sa https://json.nlohmann.me/api/basic_json/type_error/
2971
class type_error : public exception
2972
{
2973
public:
2974
template<typename BasicJsonType>
2975
static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
2976
{
2977
std::string w = exception::name("type_error", id_) + exception::diagnostics(context) + what_arg;
2978
return {id_, w.c_str()};
2979
}
2980
2981
private:
2982
JSON_HEDLEY_NON_NULL(3)
2983
type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
2984
};
2985
2986
/// @brief exception indicating access out of the defined range
2987
/// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
2988
class out_of_range : public exception
2989
{
2990
public:
2991
template<typename BasicJsonType>
2992
static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context)
2993
{
2994
std::string w = exception::name("out_of_range", id_) + exception::diagnostics(context) + what_arg;
2995
return {id_, w.c_str()};
2996
}
2997
2998
private:
2999
JSON_HEDLEY_NON_NULL(3)
3000
out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
3001
};
3002
3003
/// @brief exception indicating other library errors
3004
/// @sa https://json.nlohmann.me/api/basic_json/other_error/
3005
class other_error : public exception
3006
{
3007
public:
3008
template<typename BasicJsonType>
3009
static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
3010
{
3011
std::string w = exception::name("other_error", id_) + exception::diagnostics(context) + what_arg;
3012
return {id_, w.c_str()};
3013
}
3014
3015
private:
3016
JSON_HEDLEY_NON_NULL(3)
3017
other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
3018
};
3019
3020
} // namespace detail
3021
} // namespace nlohmann
3022
3023
// #include <nlohmann/detail/macro_scope.hpp>
3024
3025
// #include <nlohmann/detail/meta/cpp_future.hpp>
3026
3027
3028
#include <cstddef> // size_t
3029
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3030
#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3031
3032
// #include <nlohmann/detail/macro_scope.hpp>
3033
3034
3035
namespace nlohmann
3036
{
3037
namespace detail
3038
{
3039
3040
template<typename T>
3041
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3042
3043
#ifdef JSON_HAS_CPP_14
3044
3045
// the following utilities are natively available in C++14
3046
using std::enable_if_t;
3047
using std::index_sequence;
3048
using std::make_index_sequence;
3049
using std::index_sequence_for;
3050
3051
#else
3052
3053
// alias templates to reduce boilerplate
3054
template<bool B, typename T = void>
3055
using enable_if_t = typename std::enable_if<B, T>::type;
3056
3057
// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3058
// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3059
3060
//// START OF CODE FROM GOOGLE ABSEIL
3061
3062
// integer_sequence
3063
//
3064
// Class template representing a compile-time integer sequence. An instantiation
3065
// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3066
// type through its template arguments (which is a common need when
3067
// working with C++11 variadic templates). `absl::integer_sequence` is designed
3068
// to be a drop-in replacement for C++14's `std::integer_sequence`.
3069
//
3070
// Example:
3071
//
3072
// template< class T, T... Ints >
3073
// void user_function(integer_sequence<T, Ints...>);
3074
//
3075
// int main()
3076
// {
3077
// // user_function's `T` will be deduced to `int` and `Ints...`
3078
// // will be deduced to `0, 1, 2, 3, 4`.
3079
// user_function(make_integer_sequence<int, 5>());
3080
// }
3081
template <typename T, T... Ints>
3082
struct integer_sequence
3083
{
3084
using value_type = T;
3085
static constexpr std::size_t size() noexcept
3086
{
3087
return sizeof...(Ints);
3088
}
3089
};
3090
3091
// index_sequence
3092
//
3093
// A helper template for an `integer_sequence` of `size_t`,
3094
// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3095
// `std::index_sequence`.
3096
template <size_t... Ints>
3097
using index_sequence = integer_sequence<size_t, Ints...>;
3098
3099
namespace utility_internal
3100
{
3101
3102
template <typename Seq, size_t SeqSize, size_t Rem>
3103
struct Extend;
3104
3105
// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3106
template <typename T, T... Ints, size_t SeqSize>
3107
struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3108
{
3109
using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3110
};
3111
3112
template <typename T, T... Ints, size_t SeqSize>
3113
struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3114
{
3115
using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3116
};
3117
3118
// Recursion helper for 'make_integer_sequence<T, N>'.
3119
// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3120
template <typename T, size_t N>
3121
struct Gen
3122
{
3123
using type =
3124
typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3125
};
3126
3127
template <typename T>
3128
struct Gen<T, 0>
3129
{
3130
using type = integer_sequence<T>;
3131
};
3132
3133
} // namespace utility_internal
3134
3135
// Compile-time sequences of integers
3136
3137
// make_integer_sequence
3138
//
3139
// This template alias is equivalent to
3140
// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3141
// replacement for C++14's `std::make_integer_sequence`.
3142
template <typename T, T N>
3143
using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
3144
3145
// make_index_sequence
3146
//
3147
// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3148
// and is designed to be a drop-in replacement for C++14's
3149
// `std::make_index_sequence`.
3150
template <size_t N>
3151
using make_index_sequence = make_integer_sequence<size_t, N>;
3152
3153
// index_sequence_for
3154
//
3155
// Converts a typename pack into an index sequence of the same length, and
3156
// is designed to be a drop-in replacement for C++14's
3157
// `std::index_sequence_for()`
3158
template <typename... Ts>
3159
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
3160
3161
//// END OF CODE FROM GOOGLE ABSEIL
3162
3163
#endif
3164
3165
// dispatch utility (taken from ranges-v3)
3166
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3167
template<> struct priority_tag<0> {};
3168
3169
// taken from ranges-v3
3170
template<typename T>
3171
struct static_const
3172
{
3173
static constexpr T value{};
3174
};
3175
3176
template<typename T>
3177
constexpr T static_const<T>::value; // NOLINT(readability-redundant-declaration)
3178
3179
} // namespace detail
3180
} // namespace nlohmann
3181
3182
// #include <nlohmann/detail/meta/identity_tag.hpp>
3183
3184
3185
namespace nlohmann
3186
{
3187
namespace detail
3188
{
3189
// dispatching helper struct
3190
template <class T> struct identity_tag {};
3191
} // namespace detail
3192
} // namespace nlohmann
3193
3194
// #include <nlohmann/detail/meta/type_traits.hpp>
3195
3196
3197
#include <limits> // numeric_limits
3198
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3199
#include <utility> // declval
3200
#include <tuple> // tuple
3201
3202
// #include <nlohmann/detail/macro_scope.hpp>
3203
3204
3205
// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3206
3207
3208
#include <iterator> // random_access_iterator_tag
3209
3210
// #include <nlohmann/detail/meta/void_t.hpp>
3211
3212
// #include <nlohmann/detail/meta/cpp_future.hpp>
3213
3214
3215
namespace nlohmann
3216
{
3217
namespace detail
3218
{
3219
template<typename It, typename = void>
3220
struct iterator_types {};
3221
3222
template<typename It>
3223
struct iterator_types <
3224
It,
3225
void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3226
typename It::reference, typename It::iterator_category >>
3227
{
3228
using difference_type = typename It::difference_type;
3229
using value_type = typename It::value_type;
3230
using pointer = typename It::pointer;
3231
using reference = typename It::reference;
3232
using iterator_category = typename It::iterator_category;
3233
};
3234
3235
// This is required as some compilers implement std::iterator_traits in a way that
3236
// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3237
template<typename T, typename = void>
3238
struct iterator_traits
3239
{
3240
};
3241
3242
template<typename T>
3243
struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3244
: iterator_types<T>
3245
{
3246
};
3247
3248
template<typename T>
3249
struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
3250
{
3251
using iterator_category = std::random_access_iterator_tag;
3252
using value_type = T;
3253
using difference_type = ptrdiff_t;
3254
using pointer = T*;
3255
using reference = T&;
3256
};
3257
} // namespace detail
3258
} // namespace nlohmann
3259
3260
// #include <nlohmann/detail/meta/call_std/begin.hpp>
3261
3262
3263
// #include <nlohmann/detail/macro_scope.hpp>
3264
3265
3266
namespace nlohmann
3267
{
3268
NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3269
} // namespace nlohmann
3270
3271
// #include <nlohmann/detail/meta/call_std/end.hpp>
3272
3273
3274
// #include <nlohmann/detail/macro_scope.hpp>
3275
3276
3277
namespace nlohmann
3278
{
3279
NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3280
} // namespace nlohmann
3281
3282
// #include <nlohmann/detail/meta/cpp_future.hpp>
3283
3284
// #include <nlohmann/detail/meta/detected.hpp>
3285
3286
// #include <nlohmann/json_fwd.hpp>
3287
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3288
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3289
3290
#include <cstdint> // int64_t, uint64_t
3291
#include <map> // map
3292
#include <memory> // allocator
3293
#include <string> // string
3294
#include <vector> // vector
3295
3296
/*!
3297
@brief namespace for Niels Lohmann
3298
@see https://github.com/nlohmann
3299
@since version 1.0.0
3300
*/
3301
namespace nlohmann
3302
{
3303
/*!
3304
@brief default JSONSerializer template argument
3305
3306
This serializer ignores the template arguments and uses ADL
3307
([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
3308
for serialization.
3309
*/
3310
template<typename T = void, typename SFINAE = void>
3311
struct adl_serializer;
3312
3313
/// a class to store JSON values
3314
/// @sa https://json.nlohmann.me/api/basic_json/
3315
template<template<typename U, typename V, typename... Args> class ObjectType =
3316
std::map,
3317
template<typename U, typename... Args> class ArrayType = std::vector,
3318
class StringType = std::string, class BooleanType = bool,
3319
class NumberIntegerType = std::int64_t,
3320
class NumberUnsignedType = std::uint64_t,
3321
class NumberFloatType = double,
3322
template<typename U> class AllocatorType = std::allocator,
3323
template<typename T, typename SFINAE = void> class JSONSerializer =
3324
adl_serializer,
3325
class BinaryType = std::vector<std::uint8_t>>
3326
class basic_json;
3327
3328
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
3329
/// @sa https://json.nlohmann.me/api/json_pointer/
3330
template<typename BasicJsonType>
3331
class json_pointer;
3332
3333
/*!
3334
@brief default specialization
3335
@sa https://json.nlohmann.me/api/json/
3336
*/
3337
using json = basic_json<>;
3338
3339
/// @brief a minimal map-like container that preserves insertion order
3340
/// @sa https://json.nlohmann.me/api/ordered_map/
3341
template<class Key, class T, class IgnoredLess, class Allocator>
3342
struct ordered_map;
3343
3344
/// @brief specialization that maintains the insertion order of object keys
3345
/// @sa https://json.nlohmann.me/api/ordered_json/
3346
using ordered_json = basic_json<nlohmann::ordered_map>;
3347
3348
} // namespace nlohmann
3349
3350
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3351
3352
3353
namespace nlohmann
3354
{
3355
/*!
3356
@brief detail namespace with internal helper functions
3357
3358
This namespace collects functions that should not be exposed,
3359
implementations of some @ref basic_json methods, and meta-programming helpers.
3360
3361
@since version 2.1.0
3362
*/
3363
namespace detail
3364
{
3365
/////////////
3366
// helpers //
3367
/////////////
3368
3369
// Note to maintainers:
3370
//
3371
// Every trait in this file expects a non CV-qualified type.
3372
// The only exceptions are in the 'aliases for detected' section
3373
// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3374
//
3375
// In this case, T has to be properly CV-qualified to constraint the function arguments
3376
// (e.g. to_json(BasicJsonType&, const T&))
3377
3378
template<typename> struct is_basic_json : std::false_type {};
3379
3380
NLOHMANN_BASIC_JSON_TPL_DECLARATION
3381
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3382
3383
//////////////////////
3384
// json_ref helpers //
3385
//////////////////////
3386
3387
template<typename>
3388
class json_ref;
3389
3390
template<typename>
3391
struct is_json_ref : std::false_type {};
3392
3393
template<typename T>
3394
struct is_json_ref<json_ref<T>> : std::true_type {};
3395
3396
//////////////////////////
3397
// aliases for detected //
3398
//////////////////////////
3399
3400
template<typename T>
3401
using mapped_type_t = typename T::mapped_type;
3402
3403
template<typename T>
3404
using key_type_t = typename T::key_type;
3405
3406
template<typename T>
3407
using value_type_t = typename T::value_type;
3408
3409
template<typename T>
3410
using difference_type_t = typename T::difference_type;
3411
3412
template<typename T>
3413
using pointer_t = typename T::pointer;
3414
3415
template<typename T>
3416
using reference_t = typename T::reference;
3417
3418
template<typename T>
3419
using iterator_category_t = typename T::iterator_category;
3420
3421
template<typename T, typename... Args>
3422
using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3423
3424
template<typename T, typename... Args>
3425
using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3426
3427
template<typename T, typename U>
3428
using get_template_function = decltype(std::declval<T>().template get<U>());
3429
3430
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3431
template<typename BasicJsonType, typename T, typename = void>
3432
struct has_from_json : std::false_type {};
3433
3434
// trait checking if j.get<T> is valid
3435
// use this trait instead of std::is_constructible or std::is_convertible,
3436
// both rely on, or make use of implicit conversions, and thus fail when T
3437
// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3438
template <typename BasicJsonType, typename T>
3439
struct is_getable
3440
{
3441
static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3442
};
3443
3444
template<typename BasicJsonType, typename T>
3445
struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3446
{
3447
using serializer = typename BasicJsonType::template json_serializer<T, void>;
3448
3449
static constexpr bool value =
3450
is_detected_exact<void, from_json_function, serializer,
3451
const BasicJsonType&, T&>::value;
3452
};
3453
3454
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3455
// this overload is used for non-default-constructible user-defined-types
3456
template<typename BasicJsonType, typename T, typename = void>
3457
struct has_non_default_from_json : std::false_type {};
3458
3459
template<typename BasicJsonType, typename T>
3460
struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3461
{
3462
using serializer = typename BasicJsonType::template json_serializer<T, void>;
3463
3464
static constexpr bool value =
3465
is_detected_exact<T, from_json_function, serializer,
3466
const BasicJsonType&>::value;
3467
};
3468
3469
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3470
// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3471
template<typename BasicJsonType, typename T, typename = void>
3472
struct has_to_json : std::false_type {};
3473
3474
template<typename BasicJsonType, typename T>
3475
struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3476
{
3477
using serializer = typename BasicJsonType::template json_serializer<T, void>;
3478
3479
static constexpr bool value =
3480
is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3481
T>::value;
3482
};
3483
3484
3485
///////////////////
3486
// is_ functions //
3487
///////////////////
3488
3489
// https://en.cppreference.com/w/cpp/types/conjunction
3490
template<class...> struct conjunction : std::true_type { };
3491
template<class B1> struct conjunction<B1> : B1 { };
3492
template<class B1, class... Bn>
3493
struct conjunction<B1, Bn...>
3494
: std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
3495
3496
// https://en.cppreference.com/w/cpp/types/negation
3497
template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3498
3499
// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3500
// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3501
// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3502
template <typename T>
3503
struct is_default_constructible : std::is_default_constructible<T> {};
3504
3505
template <typename T1, typename T2>
3506
struct is_default_constructible<std::pair<T1, T2>>
3507
: conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3508
3509
template <typename T1, typename T2>
3510
struct is_default_constructible<const std::pair<T1, T2>>
3511
: conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3512
3513
template <typename... Ts>
3514
struct is_default_constructible<std::tuple<Ts...>>
3515
: conjunction<is_default_constructible<Ts>...> {};
3516
3517
template <typename... Ts>
3518
struct is_default_constructible<const std::tuple<Ts...>>
3519
: conjunction<is_default_constructible<Ts>...> {};
3520
3521
3522
template <typename T, typename... Args>
3523
struct is_constructible : std::is_constructible<T, Args...> {};
3524
3525
template <typename T1, typename T2>
3526
struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3527
3528
template <typename T1, typename T2>
3529
struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3530
3531
template <typename... Ts>
3532
struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3533
3534
template <typename... Ts>
3535
struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3536
3537
3538
template<typename T, typename = void>
3539
struct is_iterator_traits : std::false_type {};
3540
3541
template<typename T>
3542
struct is_iterator_traits<iterator_traits<T>>
3543
{
3544
private:
3545
using traits = iterator_traits<T>;
3546
3547
public:
3548
static constexpr auto value =
3549
is_detected<value_type_t, traits>::value &&
3550
is_detected<difference_type_t, traits>::value &&
3551
is_detected<pointer_t, traits>::value &&
3552
is_detected<iterator_category_t, traits>::value &&
3553
is_detected<reference_t, traits>::value;
3554
};
3555
3556
template<typename T>
3557
struct is_range
3558
{
3559
private:
3560
using t_ref = typename std::add_lvalue_reference<T>::type;
3561
3562
using iterator = detected_t<result_of_begin, t_ref>;
3563
using sentinel = detected_t<result_of_end, t_ref>;
3564
3565
// to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3566
// and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3567
// but reimplementing these would be too much work, as a lot of other concepts are used underneath
3568
static constexpr auto is_iterator_begin =
3569
is_iterator_traits<iterator_traits<iterator>>::value;
3570
3571
public:
3572
static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3573
};
3574
3575
template<typename R>
3576
using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3577
3578
template<typename T>
3579
using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3580
3581
// The following implementation of is_complete_type is taken from
3582
// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3583
// and is written by Xiang Fan who agreed to using it in this library.
3584
3585
template<typename T, typename = void>
3586
struct is_complete_type : std::false_type {};
3587
3588
template<typename T>
3589
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3590
3591
template<typename BasicJsonType, typename CompatibleObjectType,
3592
typename = void>
3593
struct is_compatible_object_type_impl : std::false_type {};
3594
3595
template<typename BasicJsonType, typename CompatibleObjectType>
3596
struct is_compatible_object_type_impl <
3597
BasicJsonType, CompatibleObjectType,
3598
enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3599
is_detected<key_type_t, CompatibleObjectType>::value >>
3600
{
3601
using object_t = typename BasicJsonType::object_t;
3602
3603
// macOS's is_constructible does not play well with nonesuch...
3604
static constexpr bool value =
3605
is_constructible<typename object_t::key_type,
3606
typename CompatibleObjectType::key_type>::value &&
3607
is_constructible<typename object_t::mapped_type,
3608
typename CompatibleObjectType::mapped_type>::value;
3609
};
3610
3611
template<typename BasicJsonType, typename CompatibleObjectType>
3612
struct is_compatible_object_type
3613
: is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3614
3615
template<typename BasicJsonType, typename ConstructibleObjectType,
3616
typename = void>
3617
struct is_constructible_object_type_impl : std::false_type {};
3618
3619
template<typename BasicJsonType, typename ConstructibleObjectType>
3620
struct is_constructible_object_type_impl <
3621
BasicJsonType, ConstructibleObjectType,
3622
enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3623
is_detected<key_type_t, ConstructibleObjectType>::value >>
3624
{
3625
using object_t = typename BasicJsonType::object_t;
3626
3627
static constexpr bool value =
3628
(is_default_constructible<ConstructibleObjectType>::value &&
3629
(std::is_move_assignable<ConstructibleObjectType>::value ||
3630
std::is_copy_assignable<ConstructibleObjectType>::value) &&
3631
(is_constructible<typename ConstructibleObjectType::key_type,
3632
typename object_t::key_type>::value &&
3633
std::is_same <
3634
typename object_t::mapped_type,
3635
typename ConstructibleObjectType::mapped_type >::value)) ||
3636
(has_from_json<BasicJsonType,
3637
typename ConstructibleObjectType::mapped_type>::value ||
3638
has_non_default_from_json <
3639
BasicJsonType,
3640
typename ConstructibleObjectType::mapped_type >::value);
3641
};
3642
3643
template<typename BasicJsonType, typename ConstructibleObjectType>
3644
struct is_constructible_object_type
3645
: is_constructible_object_type_impl<BasicJsonType,
3646
ConstructibleObjectType> {};
3647
3648
template<typename BasicJsonType, typename CompatibleStringType>
3649
struct is_compatible_string_type
3650
{
3651
static constexpr auto value =
3652
is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
3653
};
3654
3655
template<typename BasicJsonType, typename ConstructibleStringType>
3656
struct is_constructible_string_type
3657
{
3658
static constexpr auto value =
3659
is_constructible<ConstructibleStringType,
3660
typename BasicJsonType::string_t>::value;
3661
};
3662
3663
template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3664
struct is_compatible_array_type_impl : std::false_type {};
3665
3666
template<typename BasicJsonType, typename CompatibleArrayType>
3667
struct is_compatible_array_type_impl <
3668
BasicJsonType, CompatibleArrayType,
3669
enable_if_t <
3670
is_detected<iterator_t, CompatibleArrayType>::value&&
3671
is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3672
// special case for types like std::filesystem::path whose iterator's value_type are themselves
3673
// c.f. https://github.com/nlohmann/json/pull/3073
3674
!std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3675
{
3676
static constexpr bool value =
3677
is_constructible<BasicJsonType,
3678
range_value_t<CompatibleArrayType>>::value;
3679
};
3680
3681
template<typename BasicJsonType, typename CompatibleArrayType>
3682
struct is_compatible_array_type
3683
: is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3684
3685
template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3686
struct is_constructible_array_type_impl : std::false_type {};
3687
3688
template<typename BasicJsonType, typename ConstructibleArrayType>
3689
struct is_constructible_array_type_impl <
3690
BasicJsonType, ConstructibleArrayType,
3691
enable_if_t<std::is_same<ConstructibleArrayType,
3692
typename BasicJsonType::value_type>::value >>
3693
: std::true_type {};
3694
3695
template<typename BasicJsonType, typename ConstructibleArrayType>
3696
struct is_constructible_array_type_impl <
3697
BasicJsonType, ConstructibleArrayType,
3698
enable_if_t < !std::is_same<ConstructibleArrayType,
3699
typename BasicJsonType::value_type>::value&&
3700
!is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3701
is_default_constructible<ConstructibleArrayType>::value&&
3702
(std::is_move_assignable<ConstructibleArrayType>::value ||
3703
std::is_copy_assignable<ConstructibleArrayType>::value)&&
3704
is_detected<iterator_t, ConstructibleArrayType>::value&&
3705
is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3706
is_detected<range_value_t, ConstructibleArrayType>::value&&
3707
// special case for types like std::filesystem::path whose iterator's value_type are themselves
3708
// c.f. https://github.com/nlohmann/json/pull/3073
3709
!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3710
is_complete_type <
3711
detected_t<range_value_t, ConstructibleArrayType >>::value >>
3712
{
3713
using value_type = range_value_t<ConstructibleArrayType>;
3714
3715
static constexpr bool value =
3716
std::is_same<value_type,
3717
typename BasicJsonType::array_t::value_type>::value ||
3718
has_from_json<BasicJsonType,
3719
value_type>::value ||
3720
has_non_default_from_json <
3721
BasicJsonType,
3722
value_type >::value;
3723
};
3724
3725
template<typename BasicJsonType, typename ConstructibleArrayType>
3726
struct is_constructible_array_type
3727
: is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3728
3729
template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3730
typename = void>
3731
struct is_compatible_integer_type_impl : std::false_type {};
3732
3733
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3734
struct is_compatible_integer_type_impl <
3735
RealIntegerType, CompatibleNumberIntegerType,
3736
enable_if_t < std::is_integral<RealIntegerType>::value&&
3737
std::is_integral<CompatibleNumberIntegerType>::value&&
3738
!std::is_same<bool, CompatibleNumberIntegerType>::value >>
3739
{
3740
// is there an assert somewhere on overflows?
3741
using RealLimits = std::numeric_limits<RealIntegerType>;
3742
using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3743
3744
static constexpr auto value =
3745
is_constructible<RealIntegerType,
3746
CompatibleNumberIntegerType>::value &&
3747
CompatibleLimits::is_integer &&
3748
RealLimits::is_signed == CompatibleLimits::is_signed;
3749
};
3750
3751
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3752
struct is_compatible_integer_type
3753
: is_compatible_integer_type_impl<RealIntegerType,
3754
CompatibleNumberIntegerType> {};
3755
3756
template<typename BasicJsonType, typename CompatibleType, typename = void>
3757
struct is_compatible_type_impl: std::false_type {};
3758
3759
template<typename BasicJsonType, typename CompatibleType>
3760
struct is_compatible_type_impl <
3761
BasicJsonType, CompatibleType,
3762
enable_if_t<is_complete_type<CompatibleType>::value >>
3763
{
3764
static constexpr bool value =
3765
has_to_json<BasicJsonType, CompatibleType>::value;
3766
};
3767
3768
template<typename BasicJsonType, typename CompatibleType>
3769
struct is_compatible_type
3770
: is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3771
3772
template<typename T1, typename T2>
3773
struct is_constructible_tuple : std::false_type {};
3774
3775
template<typename T1, typename... Args>
3776
struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3777
3778
// a naive helper to check if a type is an ordered_map (exploits the fact that
3779
// ordered_map inherits capacity() from std::vector)
3780
template <typename T>
3781
struct is_ordered_map
3782
{
3783
using one = char;
3784
3785
struct two
3786
{
3787
char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3788
};
3789
3790
template <typename C> static one test( decltype(&C::capacity) ) ;
3791
template <typename C> static two test(...);
3792
3793
enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
3794
};
3795
3796
// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
3797
template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
3798
T conditional_static_cast(U value)
3799
{
3800
return static_cast<T>(value);
3801
}
3802
3803
template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
3804
T conditional_static_cast(U value)
3805
{
3806
return value;
3807
}
3808
3809
} // namespace detail
3810
} // namespace nlohmann
3811
3812
// #include <nlohmann/detail/value_t.hpp>
3813
3814
3815
#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
3816
#include <experimental/filesystem>
3817
namespace nlohmann::detail
3818
{
3819
namespace std_fs = std::experimental::filesystem;
3820
} // namespace nlohmann::detail
3821
#elif JSON_HAS_FILESYSTEM
3822
#include <filesystem>
3823
namespace nlohmann::detail
3824
{
3825
namespace std_fs = std::filesystem;
3826
} // namespace nlohmann::detail
3827
#endif
3828
3829
namespace nlohmann
3830
{
3831
namespace detail
3832
{
3833
template<typename BasicJsonType>
3834
void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
3835
{
3836
if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
3837
{
3838
JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j));
3839
}
3840
n = nullptr;
3841
}
3842
3843
// overloads for basic_json template parameters
3844
template < typename BasicJsonType, typename ArithmeticType,
3845
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
3846
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
3847
int > = 0 >
3848
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
3849
{
3850
switch (static_cast<value_t>(j))
3851
{
3852
case value_t::number_unsigned:
3853
{
3854
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
3855
break;
3856
}
3857
case value_t::number_integer:
3858
{
3859
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
3860
break;
3861
}
3862
case value_t::number_float:
3863
{
3864
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
3865
break;
3866
}
3867
3868
case value_t::null:
3869
case value_t::object:
3870
case value_t::array:
3871
case value_t::string:
3872
case value_t::boolean:
3873
case value_t::binary:
3874
case value_t::discarded:
3875
default:
3876
JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
3877
}
3878
}
3879
3880
template<typename BasicJsonType>
3881
void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
3882
{
3883
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
3884
{
3885
JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j));
3886
}
3887
b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
3888
}
3889
3890
template<typename BasicJsonType>
3891
void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
3892
{
3893
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
3894
{
3895
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
3896
}
3897
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
3898
}
3899
3900
template <
3901
typename BasicJsonType, typename ConstructibleStringType,
3902
enable_if_t <
3903
is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value&&
3904
!std::is_same<typename BasicJsonType::string_t,
3905
ConstructibleStringType>::value,
3906
int > = 0 >
3907
void from_json(const BasicJsonType& j, ConstructibleStringType& s)
3908
{
3909
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
3910
{
3911
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
3912
}
3913
3914
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
3915
}
3916
3917
template<typename BasicJsonType>
3918
void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
3919
{
3920
get_arithmetic_value(j, val);
3921
}
3922
3923
template<typename BasicJsonType>
3924
void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
3925
{
3926
get_arithmetic_value(j, val);
3927
}
3928
3929
template<typename BasicJsonType>
3930
void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
3931
{
3932
get_arithmetic_value(j, val);
3933
}
3934
3935
template<typename BasicJsonType, typename EnumType,
3936
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
3937
void from_json(const BasicJsonType& j, EnumType& e)
3938
{
3939
typename std::underlying_type<EnumType>::type val;
3940
get_arithmetic_value(j, val);
3941
e = static_cast<EnumType>(val);
3942
}
3943
3944
// forward_list doesn't have an insert method
3945
template<typename BasicJsonType, typename T, typename Allocator,
3946
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
3947
void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
3948
{
3949
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3950
{
3951
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
3952
}
3953
l.clear();
3954
std::transform(j.rbegin(), j.rend(),
3955
std::front_inserter(l), [](const BasicJsonType & i)
3956
{
3957
return i.template get<T>();
3958
});
3959
}
3960
3961
// valarray doesn't have an insert method
3962
template<typename BasicJsonType, typename T,
3963
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
3964
void from_json(const BasicJsonType& j, std::valarray<T>& l)
3965
{
3966
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3967
{
3968
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
3969
}
3970
l.resize(j.size());
3971
std::transform(j.begin(), j.end(), std::begin(l),
3972
[](const BasicJsonType & elem)
3973
{
3974
return elem.template get<T>();
3975
});
3976
}
3977
3978
template<typename BasicJsonType, typename T, std::size_t N>
3979
auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3980
-> decltype(j.template get<T>(), void())
3981
{
3982
for (std::size_t i = 0; i < N; ++i)
3983
{
3984
arr[i] = j.at(i).template get<T>();
3985
}
3986
}
3987
3988
template<typename BasicJsonType>
3989
void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
3990
{
3991
arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
3992
}
3993
3994
template<typename BasicJsonType, typename T, std::size_t N>
3995
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
3996
priority_tag<2> /*unused*/)
3997
-> decltype(j.template get<T>(), void())
3998
{
3999
for (std::size_t i = 0; i < N; ++i)
4000
{
4001
arr[i] = j.at(i).template get<T>();
4002
}
4003
}
4004
4005
template<typename BasicJsonType, typename ConstructibleArrayType,
4006
enable_if_t<
4007
std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4008
int> = 0>
4009
auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4010
-> decltype(
4011
arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4012
j.template get<typename ConstructibleArrayType::value_type>(),
4013
void())
4014
{
4015
using std::end;
4016
4017
ConstructibleArrayType ret;
4018
ret.reserve(j.size());
4019
std::transform(j.begin(), j.end(),
4020
std::inserter(ret, end(ret)), [](const BasicJsonType & i)
4021
{
4022
// get<BasicJsonType>() returns *this, this won't call a from_json
4023
// method when value_type is BasicJsonType
4024
return i.template get<typename ConstructibleArrayType::value_type>();
4025
});
4026
arr = std::move(ret);
4027
}
4028
4029
template<typename BasicJsonType, typename ConstructibleArrayType,
4030
enable_if_t<
4031
std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4032
int> = 0>
4033
void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4034
priority_tag<0> /*unused*/)
4035
{
4036
using std::end;
4037
4038
ConstructibleArrayType ret;
4039
std::transform(
4040
j.begin(), j.end(), std::inserter(ret, end(ret)),
4041
[](const BasicJsonType & i)
4042
{
4043
// get<BasicJsonType>() returns *this, this won't call a from_json
4044
// method when value_type is BasicJsonType
4045
return i.template get<typename ConstructibleArrayType::value_type>();
4046
});
4047
arr = std::move(ret);
4048
}
4049
4050
template < typename BasicJsonType, typename ConstructibleArrayType,
4051
enable_if_t <
4052
is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4053
!is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4054
!is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4055
!std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4056
!is_basic_json<ConstructibleArrayType>::value,
4057
int > = 0 >
4058
auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4059
-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4060
j.template get<typename ConstructibleArrayType::value_type>(),
4061
void())
4062
{
4063
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4064
{
4065
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4066
}
4067
4068
from_json_array_impl(j, arr, priority_tag<3> {});
4069
}
4070
4071
template < typename BasicJsonType, typename T, std::size_t... Idx >
4072
std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4073
identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4074
{
4075
return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4076
}
4077
4078
template < typename BasicJsonType, typename T, std::size_t N >
4079
auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4080
-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4081
{
4082
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4083
{
4084
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4085
}
4086
4087
return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4088
}
4089
4090
template<typename BasicJsonType>
4091
void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4092
{
4093
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4094
{
4095
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j));
4096
}
4097
4098
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4099
}
4100
4101
template<typename BasicJsonType, typename ConstructibleObjectType,
4102
enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
4103
void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
4104
{
4105
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
4106
{
4107
JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j));
4108
}
4109
4110
ConstructibleObjectType ret;
4111
const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4112
using value_type = typename ConstructibleObjectType::value_type;
4113
std::transform(
4114
inner_object->begin(), inner_object->end(),
4115
std::inserter(ret, ret.begin()),
4116
[](typename BasicJsonType::object_t::value_type const & p)
4117
{
4118
return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
4119
});
4120
obj = std::move(ret);
4121
}
4122
4123
// overload for arithmetic types, not chosen for basic_json template arguments
4124
// (BooleanType, etc..); note: Is it really necessary to provide explicit
4125
// overloads for boolean_t etc. in case of a custom BooleanType which is not
4126
// an arithmetic type?
4127
template < typename BasicJsonType, typename ArithmeticType,
4128
enable_if_t <
4129
std::is_arithmetic<ArithmeticType>::value&&
4130
!std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
4131
!std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
4132
!std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
4133
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4134
int > = 0 >
4135
void from_json(const BasicJsonType& j, ArithmeticType& val)
4136
{
4137
switch (static_cast<value_t>(j))
4138
{
4139
case value_t::number_unsigned:
4140
{
4141
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4142
break;
4143
}
4144
case value_t::number_integer:
4145
{
4146
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4147
break;
4148
}
4149
case value_t::number_float:
4150
{
4151
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4152
break;
4153
}
4154
case value_t::boolean:
4155
{
4156
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
4157
break;
4158
}
4159
4160
case value_t::null:
4161
case value_t::object:
4162
case value_t::array:
4163
case value_t::string:
4164
case value_t::binary:
4165
case value_t::discarded:
4166
default:
4167
JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
4168
}
4169
}
4170
4171
template<typename BasicJsonType, typename... Args, std::size_t... Idx>
4172
std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
4173
{
4174
return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
4175
}
4176
4177
template < typename BasicJsonType, class A1, class A2 >
4178
std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
4179
{
4180
return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
4181
std::forward<BasicJsonType>(j).at(1).template get<A2>()};
4182
}
4183
4184
template<typename BasicJsonType, typename A1, typename A2>
4185
void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
4186
{
4187
p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
4188
}
4189
4190
template<typename BasicJsonType, typename... Args>
4191
std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
4192
{
4193
return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4194
}
4195
4196
template<typename BasicJsonType, typename... Args>
4197
void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
4198
{
4199
t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4200
}
4201
4202
template<typename BasicJsonType, typename TupleRelated>
4203
auto from_json(BasicJsonType&& j, TupleRelated&& t)
4204
-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
4205
{
4206
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4207
{
4208
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4209
}
4210
4211
return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
4212
}
4213
4214
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
4215
typename = enable_if_t < !std::is_constructible <
4216
typename BasicJsonType::string_t, Key >::value >>
4217
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
4218
{
4219
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4220
{
4221
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4222
}
4223
m.clear();
4224
for (const auto& p : j)
4225
{
4226
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
4227
{
4228
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
4229
}
4230
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4231
}
4232
}
4233
4234
template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
4235
typename = enable_if_t < !std::is_constructible <
4236
typename BasicJsonType::string_t, Key >::value >>
4237
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
4238
{
4239
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4240
{
4241
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
4242
}
4243
m.clear();
4244
for (const auto& p : j)
4245
{
4246
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
4247
{
4248
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
4249
}
4250
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4251
}
4252
}
4253
4254
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4255
template<typename BasicJsonType>
4256
void from_json(const BasicJsonType& j, std_fs::path& p)
4257
{
4258
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4259
{
4260
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
4261
}
4262
p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4263
}
4264
#endif
4265
4266
struct from_json_fn
4267
{
4268
template<typename BasicJsonType, typename T>
4269
auto operator()(const BasicJsonType& j, T&& val) const
4270
noexcept(noexcept(from_json(j, std::forward<T>(val))))
4271
-> decltype(from_json(j, std::forward<T>(val)))
4272
{
4273
return from_json(j, std::forward<T>(val));
4274
}
4275
};
4276
} // namespace detail
4277
4278
/// namespace to hold default `from_json` function
4279
/// to see why this is required:
4280
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
4281
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
4282
{
4283
constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value; // NOLINT(misc-definitions-in-headers)
4284
} // namespace
4285
} // namespace nlohmann
4286
4287
// #include <nlohmann/detail/conversions/to_json.hpp>
4288
4289
4290
#include <algorithm> // copy
4291
#include <iterator> // begin, end
4292
#include <string> // string
4293
#include <tuple> // tuple, get
4294
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
4295
#include <utility> // move, forward, declval, pair
4296
#include <valarray> // valarray
4297
#include <vector> // vector
4298
4299
// #include <nlohmann/detail/macro_scope.hpp>
4300
4301
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
4302
4303
4304
#include <cstddef> // size_t
4305
#include <iterator> // input_iterator_tag
4306
#include <string> // string, to_string
4307
#include <tuple> // tuple_size, get, tuple_element
4308
#include <utility> // move
4309
4310
// #include <nlohmann/detail/meta/type_traits.hpp>
4311
4312
// #include <nlohmann/detail/value_t.hpp>
4313
4314
4315
namespace nlohmann
4316
{
4317
namespace detail
4318
{
4319
template<typename string_type>
4320
void int_to_string( string_type& target, std::size_t value )
4321
{
4322
// For ADL
4323
using std::to_string;
4324
target = to_string(value);
4325
}
4326
template<typename IteratorType> class iteration_proxy_value
4327
{
4328
public:
4329
using difference_type = std::ptrdiff_t;
4330
using value_type = iteration_proxy_value;
4331
using pointer = value_type * ;
4332
using reference = value_type & ;
4333
using iterator_category = std::input_iterator_tag;
4334
using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
4335
4336
private:
4337
/// the iterator
4338
IteratorType anchor;
4339
/// an index for arrays (used to create key names)
4340
std::size_t array_index = 0;
4341
/// last stringified array index
4342
mutable std::size_t array_index_last = 0;
4343
/// a string representation of the array index
4344
mutable string_type array_index_str = "0";
4345
/// an empty string (to return a reference for primitive values)
4346
const string_type empty_str{};
4347
4348
public:
4349
explicit iteration_proxy_value(IteratorType it) noexcept
4350
: anchor(std::move(it))
4351
{}
4352
4353
/// dereference operator (needed for range-based for)
4354
iteration_proxy_value& operator*()
4355
{
4356
return *this;
4357
}
4358
4359
/// increment operator (needed for range-based for)
4360
iteration_proxy_value& operator++()
4361
{
4362
++anchor;
4363
++array_index;
4364
4365
return *this;
4366
}
4367
4368
/// equality operator (needed for InputIterator)
4369
bool operator==(const iteration_proxy_value& o) const
4370
{
4371
return anchor == o.anchor;
4372
}
4373
4374
/// inequality operator (needed for range-based for)
4375
bool operator!=(const iteration_proxy_value& o) const
4376
{
4377
return anchor != o.anchor;
4378
}
4379
4380
/// return key of the iterator
4381
const string_type& key() const
4382
{
4383
JSON_ASSERT(anchor.m_object != nullptr);
4384
4385
switch (anchor.m_object->type())
4386
{
4387
// use integer array index as key
4388
case value_t::array:
4389
{
4390
if (array_index != array_index_last)
4391
{
4392
int_to_string( array_index_str, array_index );
4393
array_index_last = array_index;
4394
}
4395
return array_index_str;
4396
}
4397
4398
// use key from the object
4399
case value_t::object:
4400
return anchor.key();
4401
4402
// use an empty key for all primitive types
4403
case value_t::null:
4404
case value_t::string:
4405
case value_t::boolean:
4406
case value_t::number_integer:
4407
case value_t::number_unsigned:
4408
case value_t::number_float:
4409
case value_t::binary:
4410
case value_t::discarded:
4411
default:
4412
return empty_str;
4413
}
4414
}
4415
4416
/// return value of the iterator
4417
typename IteratorType::reference value() const
4418
{
4419
return anchor.value();
4420
}
4421
};
4422
4423
/// proxy class for the items() function
4424
template<typename IteratorType> class iteration_proxy
4425
{
4426
private:
4427
/// the container to iterate
4428
typename IteratorType::reference container;
4429
4430
public:
4431
/// construct iteration proxy from a container
4432
explicit iteration_proxy(typename IteratorType::reference cont) noexcept
4433
: container(cont) {}
4434
4435
/// return iterator begin (needed for range-based for)
4436
iteration_proxy_value<IteratorType> begin() noexcept
4437
{
4438
return iteration_proxy_value<IteratorType>(container.begin());
4439
}
4440
4441
/// return iterator end (needed for range-based for)
4442
iteration_proxy_value<IteratorType> end() noexcept
4443
{
4444
return iteration_proxy_value<IteratorType>(container.end());
4445
}
4446
};
4447
// Structured Bindings Support
4448
// For further reference see https://blog.tartanllama.xyz/structured-bindings/
4449
// And see https://github.com/nlohmann/json/pull/1391
4450
template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
4451
auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
4452
{
4453
return i.key();
4454
}
4455
// Structured Bindings Support
4456
// For further reference see https://blog.tartanllama.xyz/structured-bindings/
4457
// And see https://github.com/nlohmann/json/pull/1391
4458
template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
4459
auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
4460
{
4461
return i.value();
4462
}
4463
} // namespace detail
4464
} // namespace nlohmann
4465
4466
// The Addition to the STD Namespace is required to add
4467
// Structured Bindings Support to the iteration_proxy_value class
4468
// For further reference see https://blog.tartanllama.xyz/structured-bindings/
4469
// And see https://github.com/nlohmann/json/pull/1391
4470
namespace std
4471
{
4472
#if defined(__clang__)
4473
// Fix: https://github.com/nlohmann/json/issues/1401
4474
#pragma clang diagnostic push
4475
#pragma clang diagnostic ignored "-Wmismatched-tags"
4476
#endif
4477
template<typename IteratorType>
4478
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
4479
: public std::integral_constant<std::size_t, 2> {};
4480
4481
template<std::size_t N, typename IteratorType>
4482
class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
4483
{
4484
public:
4485
using type = decltype(
4486
get<N>(std::declval <
4487
::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
4488
};
4489
#if defined(__clang__)
4490
#pragma clang diagnostic pop
4491
#endif
4492
} // namespace std
4493
4494
// #include <nlohmann/detail/meta/cpp_future.hpp>
4495
4496
// #include <nlohmann/detail/meta/type_traits.hpp>
4497
4498
// #include <nlohmann/detail/value_t.hpp>
4499
4500
4501
#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4502
#include <experimental/filesystem>
4503
namespace nlohmann::detail
4504
{
4505
namespace std_fs = std::experimental::filesystem;
4506
} // namespace nlohmann::detail
4507
#elif JSON_HAS_FILESYSTEM
4508
#include <filesystem>
4509
namespace nlohmann::detail
4510
{
4511
namespace std_fs = std::filesystem;
4512
} // namespace nlohmann::detail
4513
#endif
4514
4515
namespace nlohmann
4516
{
4517
namespace detail
4518
{
4519
//////////////////
4520
// constructors //
4521
//////////////////
4522
4523
/*
4524
* Note all external_constructor<>::construct functions need to call
4525
* j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an
4526
* allocated value (e.g., a string). See bug issue
4527
* https://github.com/nlohmann/json/issues/2865 for more information.
4528
*/
4529
4530
template<value_t> struct external_constructor;
4531
4532
template<>
4533
struct external_constructor<value_t::boolean>
4534
{
4535
template<typename BasicJsonType>
4536
static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
4537
{
4538
j.m_value.destroy(j.m_type);
4539
j.m_type = value_t::boolean;
4540
j.m_value = b;
4541
j.assert_invariant();
4542
}
4543
};
4544
4545
template<>
4546
struct external_constructor<value_t::string>
4547
{
4548
template<typename BasicJsonType>
4549
static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
4550
{
4551
j.m_value.destroy(j.m_type);
4552
j.m_type = value_t::string;
4553
j.m_value = s;
4554
j.assert_invariant();
4555
}
4556
4557
template<typename BasicJsonType>
4558
static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
4559
{
4560
j.m_value.destroy(j.m_type);
4561
j.m_type = value_t::string;
4562
j.m_value = std::move(s);
4563
j.assert_invariant();
4564
}
4565
4566
template < typename BasicJsonType, typename CompatibleStringType,
4567
enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
4568
int > = 0 >
4569
static void construct(BasicJsonType& j, const CompatibleStringType& str)
4570
{
4571
j.m_value.destroy(j.m_type);
4572
j.m_type = value_t::string;
4573
j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
4574
j.assert_invariant();
4575
}
4576
};
4577
4578
template<>
4579
struct external_constructor<value_t::binary>
4580
{
4581
template<typename BasicJsonType>
4582
static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
4583
{
4584
j.m_value.destroy(j.m_type);
4585
j.m_type = value_t::binary;
4586
j.m_value = typename BasicJsonType::binary_t(b);
4587
j.assert_invariant();
4588
}
4589
4590
template<typename BasicJsonType>
4591
static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
4592
{
4593
j.m_value.destroy(j.m_type);
4594
j.m_type = value_t::binary;
4595
j.m_value = typename BasicJsonType::binary_t(std::move(b));
4596
j.assert_invariant();
4597
}
4598
};
4599
4600
template<>
4601
struct external_constructor<value_t::number_float>
4602
{
4603
template<typename BasicJsonType>
4604
static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
4605
{
4606
j.m_value.destroy(j.m_type);
4607
j.m_type = value_t::number_float;
4608
j.m_value = val;
4609
j.assert_invariant();
4610
}
4611
};
4612
4613
template<>
4614
struct external_constructor<value_t::number_unsigned>
4615
{
4616
template<typename BasicJsonType>
4617
static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
4618
{
4619
j.m_value.destroy(j.m_type);
4620
j.m_type = value_t::number_unsigned;
4621
j.m_value = val;
4622
j.assert_invariant();
4623
}
4624
};
4625
4626
template<>
4627
struct external_constructor<value_t::number_integer>
4628
{
4629
template<typename BasicJsonType>
4630
static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
4631
{
4632
j.m_value.destroy(j.m_type);
4633
j.m_type = value_t::number_integer;
4634
j.m_value = val;
4635
j.assert_invariant();
4636
}
4637
};
4638
4639
template<>
4640
struct external_constructor<value_t::array>
4641
{
4642
template<typename BasicJsonType>
4643
static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
4644
{
4645
j.m_value.destroy(j.m_type);
4646
j.m_type = value_t::array;
4647
j.m_value = arr;
4648
j.set_parents();
4649
j.assert_invariant();
4650
}
4651
4652
template<typename BasicJsonType>
4653
static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
4654
{
4655
j.m_value.destroy(j.m_type);
4656
j.m_type = value_t::array;
4657
j.m_value = std::move(arr);
4658
j.set_parents();
4659
j.assert_invariant();
4660
}
4661
4662
template < typename BasicJsonType, typename CompatibleArrayType,
4663
enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
4664
int > = 0 >
4665
static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
4666
{
4667
using std::begin;
4668
using std::end;
4669
4670
j.m_value.destroy(j.m_type);
4671
j.m_type = value_t::array;
4672
j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
4673
j.set_parents();
4674
j.assert_invariant();
4675
}
4676
4677
template<typename BasicJsonType>
4678
static void construct(BasicJsonType& j, const std::vector<bool>& arr)
4679
{
4680
j.m_value.destroy(j.m_type);
4681
j.m_type = value_t::array;
4682
j.m_value = value_t::array;
4683
j.m_value.array->reserve(arr.size());
4684
for (const bool x : arr)
4685
{
4686
j.m_value.array->push_back(x);
4687
j.set_parent(j.m_value.array->back());
4688
}
4689
j.assert_invariant();
4690
}
4691
4692
template<typename BasicJsonType, typename T,
4693
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
4694
static void construct(BasicJsonType& j, const std::valarray<T>& arr)
4695
{
4696
j.m_value.destroy(j.m_type);
4697
j.m_type = value_t::array;
4698
j.m_value = value_t::array;
4699
j.m_value.array->resize(arr.size());
4700
if (arr.size() > 0)
4701
{
4702
std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
4703
}
4704
j.set_parents();
4705
j.assert_invariant();
4706
}
4707
};
4708
4709
template<>
4710
struct external_constructor<value_t::object>
4711
{
4712
template<typename BasicJsonType>
4713
static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
4714
{
4715
j.m_value.destroy(j.m_type);
4716
j.m_type = value_t::object;
4717
j.m_value = obj;
4718
j.set_parents();
4719
j.assert_invariant();
4720
}
4721
4722
template<typename BasicJsonType>
4723
static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
4724
{
4725
j.m_value.destroy(j.m_type);
4726
j.m_type = value_t::object;
4727
j.m_value = std::move(obj);
4728
j.set_parents();
4729
j.assert_invariant();
4730
}
4731
4732
template < typename BasicJsonType, typename CompatibleObjectType,
4733
enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
4734
static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
4735
{
4736
using std::begin;
4737
using std::end;
4738
4739
j.m_value.destroy(j.m_type);
4740
j.m_type = value_t::object;
4741
j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
4742
j.set_parents();
4743
j.assert_invariant();
4744
}
4745
};
4746
4747
/////////////
4748
// to_json //
4749
/////////////
4750
4751
template<typename BasicJsonType, typename T,
4752
enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
4753
void to_json(BasicJsonType& j, T b) noexcept
4754
{
4755
external_constructor<value_t::boolean>::construct(j, b);
4756
}
4757
4758
template<typename BasicJsonType, typename CompatibleString,
4759
enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
4760
void to_json(BasicJsonType& j, const CompatibleString& s)
4761
{
4762
external_constructor<value_t::string>::construct(j, s);
4763
}
4764
4765
template<typename BasicJsonType>
4766
void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
4767
{
4768
external_constructor<value_t::string>::construct(j, std::move(s));
4769
}
4770
4771
template<typename BasicJsonType, typename FloatType,
4772
enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
4773
void to_json(BasicJsonType& j, FloatType val) noexcept
4774
{
4775
external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
4776
}
4777
4778
template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
4779
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
4780
void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
4781
{
4782
external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
4783
}
4784
4785
template<typename BasicJsonType, typename CompatibleNumberIntegerType,
4786
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
4787
void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
4788
{
4789
external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
4790
}
4791
4792
template<typename BasicJsonType, typename EnumType,
4793
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4794
void to_json(BasicJsonType& j, EnumType e) noexcept
4795
{
4796
using underlying_type = typename std::underlying_type<EnumType>::type;
4797
external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
4798
}
4799
4800
template<typename BasicJsonType>
4801
void to_json(BasicJsonType& j, const std::vector<bool>& e)
4802
{
4803
external_constructor<value_t::array>::construct(j, e);
4804
}
4805
4806
template < typename BasicJsonType, typename CompatibleArrayType,
4807
enable_if_t < is_compatible_array_type<BasicJsonType,
4808
CompatibleArrayType>::value&&
4809
!is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
4810
!is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
4811
!std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
4812
!is_basic_json<CompatibleArrayType>::value,
4813
int > = 0 >
4814
void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
4815
{
4816
external_constructor<value_t::array>::construct(j, arr);
4817
}
4818
4819
template<typename BasicJsonType>
4820
void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
4821
{
4822
external_constructor<value_t::binary>::construct(j, bin);
4823
}
4824
4825
template<typename BasicJsonType, typename T,
4826
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
4827
void to_json(BasicJsonType& j, const std::valarray<T>& arr)
4828
{
4829
external_constructor<value_t::array>::construct(j, std::move(arr));
4830
}
4831
4832
template<typename BasicJsonType>
4833
void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
4834
{
4835
external_constructor<value_t::array>::construct(j, std::move(arr));
4836
}
4837
4838
template < typename BasicJsonType, typename CompatibleObjectType,
4839
enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
4840
void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
4841
{
4842
external_constructor<value_t::object>::construct(j, obj);
4843
}
4844
4845
template<typename BasicJsonType>
4846
void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
4847
{
4848
external_constructor<value_t::object>::construct(j, std::move(obj));
4849
}
4850
4851
template <
4852
typename BasicJsonType, typename T, std::size_t N,
4853
enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
4854
const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4855
int > = 0 >
4856
void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4857
{
4858
external_constructor<value_t::array>::construct(j, arr);
4859
}
4860
4861
template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
4862
void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
4863
{
4864
j = { p.first, p.second };
4865
}
4866
4867
// for https://github.com/nlohmann/json/pull/1134
4868
template<typename BasicJsonType, typename T,
4869
enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
4870
void to_json(BasicJsonType& j, const T& b)
4871
{
4872
j = { {b.key(), b.value()} };
4873
}
4874
4875
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
4876
void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
4877
{
4878
j = { std::get<Idx>(t)... };
4879
}
4880
4881
template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
4882
void to_json(BasicJsonType& j, const T& t)
4883
{
4884
to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
4885
}
4886
4887
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4888
template<typename BasicJsonType>
4889
void to_json(BasicJsonType& j, const std_fs::path& p)
4890
{
4891
j = p.string();
4892
}
4893
#endif
4894
4895
struct to_json_fn
4896
{
4897
template<typename BasicJsonType, typename T>
4898
auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
4899
-> decltype(to_json(j, std::forward<T>(val)), void())
4900
{
4901
return to_json(j, std::forward<T>(val));
4902
}
4903
};
4904
} // namespace detail
4905
4906
/// namespace to hold default `to_json` function
4907
/// to see why this is required:
4908
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
4909
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
4910
{
4911
constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value; // NOLINT(misc-definitions-in-headers)
4912
} // namespace
4913
} // namespace nlohmann
4914
4915
// #include <nlohmann/detail/meta/identity_tag.hpp>
4916
4917
// #include <nlohmann/detail/meta/type_traits.hpp>
4918
4919
4920
namespace nlohmann
4921
{
4922
4923
/// @sa https://json.nlohmann.me/api/adl_serializer/
4924
template<typename ValueType, typename>
4925
struct adl_serializer
4926
{
4927
/// @brief convert a JSON value to any value type
4928
/// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
4929
template<typename BasicJsonType, typename TargetType = ValueType>
4930
static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
4931
noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
4932
-> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
4933
{
4934
::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
4935
}
4936
4937
/// @brief convert a JSON value to any value type
4938
/// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
4939
template<typename BasicJsonType, typename TargetType = ValueType>
4940
static auto from_json(BasicJsonType && j) noexcept(
4941
noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
4942
-> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
4943
{
4944
return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
4945
}
4946
4947
/// @brief convert any value type to a JSON value
4948
/// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
4949
template<typename BasicJsonType, typename TargetType = ValueType>
4950
static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
4951
noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
4952
-> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
4953
{
4954
::nlohmann::to_json(j, std::forward<TargetType>(val));
4955
}
4956
};
4957
} // namespace nlohmann
4958
4959
// #include <nlohmann/byte_container_with_subtype.hpp>
4960
4961
4962
#include <cstdint> // uint8_t, uint64_t
4963
#include <tuple> // tie
4964
#include <utility> // move
4965
4966
namespace nlohmann
4967
{
4968
4969
/// @brief an internal type for a backed binary type
4970
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
4971
template<typename BinaryType>
4972
class byte_container_with_subtype : public BinaryType
4973
{
4974
public:
4975
using container_type = BinaryType;
4976
using subtype_type = std::uint64_t;
4977
4978
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4979
byte_container_with_subtype() noexcept(noexcept(container_type()))
4980
: container_type()
4981
{}
4982
4983
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4984
byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
4985
: container_type(b)
4986
{}
4987
4988
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4989
byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
4990
: container_type(std::move(b))
4991
{}
4992
4993
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
4994
byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
4995
: container_type(b)
4996
, m_subtype(subtype_)
4997
, m_has_subtype(true)
4998
{}
4999
5000
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5001
byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
5002
: container_type(std::move(b))
5003
, m_subtype(subtype_)
5004
, m_has_subtype(true)
5005
{}
5006
5007
bool operator==(const byte_container_with_subtype& rhs) const
5008
{
5009
return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
5010
std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5011
}
5012
5013
bool operator!=(const byte_container_with_subtype& rhs) const
5014
{
5015
return !(rhs == *this);
5016
}
5017
5018
/// @brief sets the binary subtype
5019
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/
5020
void set_subtype(subtype_type subtype_) noexcept
5021
{
5022
m_subtype = subtype_;
5023
m_has_subtype = true;
5024
}
5025
5026
/// @brief return the binary subtype
5027
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/
5028
constexpr subtype_type subtype() const noexcept
5029
{
5030
return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
5031
}
5032
5033
/// @brief return whether the value has a subtype
5034
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/
5035
constexpr bool has_subtype() const noexcept
5036
{
5037
return m_has_subtype;
5038
}
5039
5040
/// @brief clears the binary subtype
5041
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/
5042
void clear_subtype() noexcept
5043
{
5044
m_subtype = 0;
5045
m_has_subtype = false;
5046
}
5047
5048
private:
5049
subtype_type m_subtype = 0;
5050
bool m_has_subtype = false;
5051
};
5052
5053
} // namespace nlohmann
5054
5055
// #include <nlohmann/detail/conversions/from_json.hpp>
5056
5057
// #include <nlohmann/detail/conversions/to_json.hpp>
5058
5059
// #include <nlohmann/detail/exceptions.hpp>
5060
5061
// #include <nlohmann/detail/hash.hpp>
5062
5063
5064
#include <cstdint> // uint8_t
5065
#include <cstddef> // size_t
5066
#include <functional> // hash
5067
5068
// #include <nlohmann/detail/macro_scope.hpp>
5069
5070
// #include <nlohmann/detail/value_t.hpp>
5071
5072
5073
namespace nlohmann
5074
{
5075
namespace detail
5076
{
5077
5078
// boost::hash_combine
5079
inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
5080
{
5081
seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
5082
return seed;
5083
}
5084
5085
/*!
5086
@brief hash a JSON value
5087
5088
The hash function tries to rely on std::hash where possible. Furthermore, the
5089
type of the JSON value is taken into account to have different hash values for
5090
null, 0, 0U, and false, etc.
5091
5092
@tparam BasicJsonType basic_json specialization
5093
@param j JSON value to hash
5094
@return hash value of j
5095
*/
5096
template<typename BasicJsonType>
5097
std::size_t hash(const BasicJsonType& j)
5098
{
5099
using string_t = typename BasicJsonType::string_t;
5100
using number_integer_t = typename BasicJsonType::number_integer_t;
5101
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5102
using number_float_t = typename BasicJsonType::number_float_t;
5103
5104
const auto type = static_cast<std::size_t>(j.type());
5105
switch (j.type())
5106
{
5107
case BasicJsonType::value_t::null:
5108
case BasicJsonType::value_t::discarded:
5109
{
5110
return combine(type, 0);
5111
}
5112
5113
case BasicJsonType::value_t::object:
5114
{
5115
auto seed = combine(type, j.size());
5116
for (const auto& element : j.items())
5117
{
5118
const auto h = std::hash<string_t> {}(element.key());
5119
seed = combine(seed, h);
5120
seed = combine(seed, hash(element.value()));
5121
}
5122
return seed;
5123
}
5124
5125
case BasicJsonType::value_t::array:
5126
{
5127
auto seed = combine(type, j.size());
5128
for (const auto& element : j)
5129
{
5130
seed = combine(seed, hash(element));
5131
}
5132
return seed;
5133
}
5134
5135
case BasicJsonType::value_t::string:
5136
{
5137
const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
5138
return combine(type, h);
5139
}
5140
5141
case BasicJsonType::value_t::boolean:
5142
{
5143
const auto h = std::hash<bool> {}(j.template get<bool>());
5144
return combine(type, h);
5145
}
5146
5147
case BasicJsonType::value_t::number_integer:
5148
{
5149
const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
5150
return combine(type, h);
5151
}
5152
5153
case BasicJsonType::value_t::number_unsigned:
5154
{
5155
const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
5156
return combine(type, h);
5157
}
5158
5159
case BasicJsonType::value_t::number_float:
5160
{
5161
const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
5162
return combine(type, h);
5163
}
5164
5165
case BasicJsonType::value_t::binary:
5166
{
5167
auto seed = combine(type, j.get_binary().size());
5168
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
5169
seed = combine(seed, h);
5170
seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
5171
for (const auto byte : j.get_binary())
5172
{
5173
seed = combine(seed, std::hash<std::uint8_t> {}(byte));
5174
}
5175
return seed;
5176
}
5177
5178
default: // LCOV_EXCL_LINE
5179
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
5180
return 0; // LCOV_EXCL_LINE
5181
}
5182
}
5183
5184
} // namespace detail
5185
} // namespace nlohmann
5186
5187
// #include <nlohmann/detail/input/binary_reader.hpp>
5188
5189
5190
#include <algorithm> // generate_n
5191
#include <array> // array
5192
#include <cmath> // ldexp
5193
#include <cstddef> // size_t
5194
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
5195
#include <cstdio> // snprintf
5196
#include <cstring> // memcpy
5197
#include <iterator> // back_inserter
5198
#include <limits> // numeric_limits
5199
#include <string> // char_traits, string
5200
#include <utility> // make_pair, move
5201
#include <vector> // vector
5202
5203
// #include <nlohmann/detail/exceptions.hpp>
5204
5205
// #include <nlohmann/detail/input/input_adapters.hpp>
5206
5207
5208
#include <array> // array
5209
#include <cstddef> // size_t
5210
#include <cstring> // strlen
5211
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
5212
#include <memory> // shared_ptr, make_shared, addressof
5213
#include <numeric> // accumulate
5214
#include <string> // string, char_traits
5215
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
5216
#include <utility> // pair, declval
5217
5218
#ifndef JSON_NO_IO
5219
#include <cstdio> // FILE *
5220
#include <istream> // istream
5221
#endif // JSON_NO_IO
5222
5223
// #include <nlohmann/detail/iterators/iterator_traits.hpp>
5224
5225
// #include <nlohmann/detail/macro_scope.hpp>
5226
5227
5228
namespace nlohmann
5229
{
5230
namespace detail
5231
{
5232
/// the supported input formats
5233
enum class input_format_t { json, cbor, msgpack, ubjson, bson };
5234
5235
////////////////////
5236
// input adapters //
5237
////////////////////
5238
5239
#ifndef JSON_NO_IO
5240
/*!
5241
Input adapter for stdio file access. This adapter read only 1 byte and do not use any
5242
buffer. This adapter is a very low level adapter.
5243
*/
5244
class file_input_adapter
5245
{
5246
public:
5247
using char_type = char;
5248
5249
JSON_HEDLEY_NON_NULL(2)
5250
explicit file_input_adapter(std::FILE* f) noexcept
5251
: m_file(f)
5252
{}
5253
5254
// make class move-only
5255
file_input_adapter(const file_input_adapter&) = delete;
5256
file_input_adapter(file_input_adapter&&) noexcept = default;
5257
file_input_adapter& operator=(const file_input_adapter&) = delete;
5258
file_input_adapter& operator=(file_input_adapter&&) = delete;
5259
~file_input_adapter() = default;
5260
5261
std::char_traits<char>::int_type get_character() noexcept
5262
{
5263
return std::fgetc(m_file);
5264
}
5265
5266
private:
5267
/// the file pointer to read from
5268
std::FILE* m_file;
5269
};
5270
5271
5272
/*!
5273
Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
5274
beginning of input. Does not support changing the underlying std::streambuf
5275
in mid-input. Maintains underlying std::istream and std::streambuf to support
5276
subsequent use of standard std::istream operations to process any input
5277
characters following those used in parsing the JSON input. Clears the
5278
std::istream flags; any input errors (e.g., EOF) will be detected by the first
5279
subsequent call for input from the std::istream.
5280
*/
5281
class input_stream_adapter
5282
{
5283
public:
5284
using char_type = char;
5285
5286
~input_stream_adapter()
5287
{
5288
// clear stream flags; we use underlying streambuf I/O, do not
5289
// maintain ifstream flags, except eof
5290
if (is != nullptr)
5291
{
5292
is->clear(is->rdstate() & std::ios::eofbit);
5293
}
5294
}
5295
5296
explicit input_stream_adapter(std::istream& i)
5297
: is(&i), sb(i.rdbuf())
5298
{}
5299
5300
// delete because of pointer members
5301
input_stream_adapter(const input_stream_adapter&) = delete;
5302
input_stream_adapter& operator=(input_stream_adapter&) = delete;
5303
input_stream_adapter& operator=(input_stream_adapter&&) = delete;
5304
5305
input_stream_adapter(input_stream_adapter&& rhs) noexcept
5306
: is(rhs.is), sb(rhs.sb)
5307
{
5308
rhs.is = nullptr;
5309
rhs.sb = nullptr;
5310
}
5311
5312
// std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
5313
// ensure that std::char_traits<char>::eof() and the character 0xFF do not
5314
// end up as the same value, e.g. 0xFFFFFFFF.
5315
std::char_traits<char>::int_type get_character()
5316
{
5317
auto res = sb->sbumpc();
5318
// set eof manually, as we don't use the istream interface.
5319
if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
5320
{
5321
is->clear(is->rdstate() | std::ios::eofbit);
5322
}
5323
return res;
5324
}
5325
5326
private:
5327
/// the associated input stream
5328
std::istream* is = nullptr;
5329
std::streambuf* sb = nullptr;
5330
};
5331
#endif // JSON_NO_IO
5332
5333
// General-purpose iterator-based adapter. It might not be as fast as
5334
// theoretically possible for some containers, but it is extremely versatile.
5335
template<typename IteratorType>
5336
class iterator_input_adapter
5337
{
5338
public:
5339
using char_type = typename std::iterator_traits<IteratorType>::value_type;
5340
5341
iterator_input_adapter(IteratorType first, IteratorType last)
5342
: current(std::move(first)), end(std::move(last))
5343
{}
5344
5345
typename std::char_traits<char_type>::int_type get_character()
5346
{
5347
if (JSON_HEDLEY_LIKELY(current != end))
5348
{
5349
auto result = std::char_traits<char_type>::to_int_type(*current);
5350
std::advance(current, 1);
5351
return result;
5352
}
5353
5354
return std::char_traits<char_type>::eof();
5355
}
5356
5357
private:
5358
IteratorType current;
5359
IteratorType end;
5360
5361
template<typename BaseInputAdapter, size_t T>
5362
friend struct wide_string_input_helper;
5363
5364
bool empty() const
5365
{
5366
return current == end;
5367
}
5368
};
5369
5370
5371
template<typename BaseInputAdapter, size_t T>
5372
struct wide_string_input_helper;
5373
5374
template<typename BaseInputAdapter>
5375
struct wide_string_input_helper<BaseInputAdapter, 4>
5376
{
5377
// UTF-32
5378
static void fill_buffer(BaseInputAdapter& input,
5379
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
5380
size_t& utf8_bytes_index,
5381
size_t& utf8_bytes_filled)
5382
{
5383
utf8_bytes_index = 0;
5384
5385
if (JSON_HEDLEY_UNLIKELY(input.empty()))
5386
{
5387
utf8_bytes[0] = std::char_traits<char>::eof();
5388
utf8_bytes_filled = 1;
5389
}
5390
else
5391
{
5392
// get the current character
5393
const auto wc = input.get_character();
5394
5395
// UTF-32 to UTF-8 encoding
5396
if (wc < 0x80)
5397
{
5398
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5399
utf8_bytes_filled = 1;
5400
}
5401
else if (wc <= 0x7FF)
5402
{
5403
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
5404
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5405
utf8_bytes_filled = 2;
5406
}
5407
else if (wc <= 0xFFFF)
5408
{
5409
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
5410
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5411
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5412
utf8_bytes_filled = 3;
5413
}
5414
else if (wc <= 0x10FFFF)
5415
{
5416
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
5417
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
5418
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5419
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5420
utf8_bytes_filled = 4;
5421
}
5422
else
5423
{
5424
// unknown character
5425
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5426
utf8_bytes_filled = 1;
5427
}
5428
}
5429
}
5430
};
5431
5432
template<typename BaseInputAdapter>
5433
struct wide_string_input_helper<BaseInputAdapter, 2>
5434
{
5435
// UTF-16
5436
static void fill_buffer(BaseInputAdapter& input,
5437
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
5438
size_t& utf8_bytes_index,
5439
size_t& utf8_bytes_filled)
5440
{
5441
utf8_bytes_index = 0;
5442
5443
if (JSON_HEDLEY_UNLIKELY(input.empty()))
5444
{
5445
utf8_bytes[0] = std::char_traits<char>::eof();
5446
utf8_bytes_filled = 1;
5447
}
5448
else
5449
{
5450
// get the current character
5451
const auto wc = input.get_character();
5452
5453
// UTF-16 to UTF-8 encoding
5454
if (wc < 0x80)
5455
{
5456
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5457
utf8_bytes_filled = 1;
5458
}
5459
else if (wc <= 0x7FF)
5460
{
5461
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
5462
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5463
utf8_bytes_filled = 2;
5464
}
5465
else if (0xD800 > wc || wc >= 0xE000)
5466
{
5467
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
5468
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5469
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5470
utf8_bytes_filled = 3;
5471
}
5472
else
5473
{
5474
if (JSON_HEDLEY_UNLIKELY(!input.empty()))
5475
{
5476
const auto wc2 = static_cast<unsigned int>(input.get_character());
5477
const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
5478
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
5479
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
5480
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
5481
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
5482
utf8_bytes_filled = 4;
5483
}
5484
else
5485
{
5486
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5487
utf8_bytes_filled = 1;
5488
}
5489
}
5490
}
5491
}
5492
};
5493
5494
// Wraps another input apdater to convert wide character types into individual bytes.
5495
template<typename BaseInputAdapter, typename WideCharType>
5496
class wide_string_input_adapter
5497
{
5498
public:
5499
using char_type = char;
5500
5501
wide_string_input_adapter(BaseInputAdapter base)
5502
: base_adapter(base) {}
5503
5504
typename std::char_traits<char>::int_type get_character() noexcept
5505
{
5506
// check if buffer needs to be filled
5507
if (utf8_bytes_index == utf8_bytes_filled)
5508
{
5509
fill_buffer<sizeof(WideCharType)>();
5510
5511
JSON_ASSERT(utf8_bytes_filled > 0);
5512
JSON_ASSERT(utf8_bytes_index == 0);
5513
}
5514
5515
// use buffer
5516
JSON_ASSERT(utf8_bytes_filled > 0);
5517
JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
5518
return utf8_bytes[utf8_bytes_index++];
5519
}
5520
5521
private:
5522
BaseInputAdapter base_adapter;
5523
5524
template<size_t T>
5525
void fill_buffer()
5526
{
5527
wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
5528
}
5529
5530
/// a buffer for UTF-8 bytes
5531
std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
5532
5533
/// index to the utf8_codes array for the next valid byte
5534
std::size_t utf8_bytes_index = 0;
5535
/// number of valid bytes in the utf8_codes array
5536
std::size_t utf8_bytes_filled = 0;
5537
};
5538
5539
5540
template<typename IteratorType, typename Enable = void>
5541
struct iterator_input_adapter_factory
5542
{
5543
using iterator_type = IteratorType;
5544
using char_type = typename std::iterator_traits<iterator_type>::value_type;
5545
using adapter_type = iterator_input_adapter<iterator_type>;
5546
5547
static adapter_type create(IteratorType first, IteratorType last)
5548
{
5549
return adapter_type(std::move(first), std::move(last));
5550
}
5551
};
5552
5553
template<typename T>
5554
struct is_iterator_of_multibyte
5555
{
5556
using value_type = typename std::iterator_traits<T>::value_type;
5557
enum
5558
{
5559
value = sizeof(value_type) > 1
5560
};
5561
};
5562
5563
template<typename IteratorType>
5564
struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
5565
{
5566
using iterator_type = IteratorType;
5567
using char_type = typename std::iterator_traits<iterator_type>::value_type;
5568
using base_adapter_type = iterator_input_adapter<iterator_type>;
5569
using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
5570
5571
static adapter_type create(IteratorType first, IteratorType last)
5572
{
5573
return adapter_type(base_adapter_type(std::move(first), std::move(last)));
5574
}
5575
};
5576
5577
// General purpose iterator-based input
5578
template<typename IteratorType>
5579
typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
5580
{
5581
using factory_type = iterator_input_adapter_factory<IteratorType>;
5582
return factory_type::create(first, last);
5583
}
5584
5585
// Convenience shorthand from container to iterator
5586
// Enables ADL on begin(container) and end(container)
5587
// Encloses the using declarations in namespace for not to leak them to outside scope
5588
5589
namespace container_input_adapter_factory_impl
5590
{
5591
5592
using std::begin;
5593
using std::end;
5594
5595
template<typename ContainerType, typename Enable = void>
5596
struct container_input_adapter_factory {};
5597
5598
template<typename ContainerType>
5599
struct container_input_adapter_factory< ContainerType,
5600
void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
5601
{
5602
using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
5603
5604
static adapter_type create(const ContainerType& container)
5605
{
5606
return input_adapter(begin(container), end(container));
5607
}
5608
};
5609
5610
} // namespace container_input_adapter_factory_impl
5611
5612
template<typename ContainerType>
5613
typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
5614
{
5615
return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
5616
}
5617
5618
#ifndef JSON_NO_IO
5619
// Special cases with fast paths
5620
inline file_input_adapter input_adapter(std::FILE* file)
5621
{
5622
return file_input_adapter(file);
5623
}
5624
5625
inline input_stream_adapter input_adapter(std::istream& stream)
5626
{
5627
return input_stream_adapter(stream);
5628
}
5629
5630
inline input_stream_adapter input_adapter(std::istream&& stream)
5631
{
5632
return input_stream_adapter(stream);
5633
}
5634
#endif // JSON_NO_IO
5635
5636
using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
5637
5638
// Null-delimited strings, and the like.
5639
template < typename CharT,
5640
typename std::enable_if <
5641
std::is_pointer<CharT>::value&&
5642
!std::is_array<CharT>::value&&
5643
std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
5644
sizeof(typename std::remove_pointer<CharT>::type) == 1,
5645
int >::type = 0 >
5646
contiguous_bytes_input_adapter input_adapter(CharT b)
5647
{
5648
auto length = std::strlen(reinterpret_cast<const char*>(b));
5649
const auto* ptr = reinterpret_cast<const char*>(b);
5650
return input_adapter(ptr, ptr + length);
5651
}
5652
5653
template<typename T, std::size_t N>
5654
auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5655
{
5656
return input_adapter(array, array + N);
5657
}
5658
5659
// This class only handles inputs of input_buffer_adapter type.
5660
// It's required so that expressions like {ptr, len} can be implicitly cast
5661
// to the correct adapter.
5662
class span_input_adapter
5663
{
5664
public:
5665
template < typename CharT,
5666
typename std::enable_if <
5667
std::is_pointer<CharT>::value&&
5668
std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
5669
sizeof(typename std::remove_pointer<CharT>::type) == 1,
5670
int >::type = 0 >
5671
span_input_adapter(CharT b, std::size_t l)
5672
: ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
5673
5674
template<class IteratorType,
5675
typename std::enable_if<
5676
std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
5677
int>::type = 0>
5678
span_input_adapter(IteratorType first, IteratorType last)
5679
: ia(input_adapter(first, last)) {}
5680
5681
contiguous_bytes_input_adapter&& get()
5682
{
5683
return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
5684
}
5685
5686
private:
5687
contiguous_bytes_input_adapter ia;
5688
};
5689
} // namespace detail
5690
} // namespace nlohmann
5691
5692
// #include <nlohmann/detail/input/json_sax.hpp>
5693
5694
5695
#include <cstddef>
5696
#include <string> // string
5697
#include <utility> // move
5698
#include <vector> // vector
5699
5700
// #include <nlohmann/detail/exceptions.hpp>
5701
5702
// #include <nlohmann/detail/macro_scope.hpp>
5703
5704
5705
namespace nlohmann
5706
{
5707
5708
/*!
5709
@brief SAX interface
5710
5711
This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
5712
Each function is called in different situations while the input is parsed. The
5713
boolean return value informs the parser whether to continue processing the
5714
input.
5715
*/
5716
template<typename BasicJsonType>
5717
struct json_sax
5718
{
5719
using number_integer_t = typename BasicJsonType::number_integer_t;
5720
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5721
using number_float_t = typename BasicJsonType::number_float_t;
5722
using string_t = typename BasicJsonType::string_t;
5723
using binary_t = typename BasicJsonType::binary_t;
5724
5725
/*!
5726
@brief a null value was read
5727
@return whether parsing should proceed
5728
*/
5729
virtual bool null() = 0;
5730
5731
/*!
5732
@brief a boolean value was read
5733
@param[in] val boolean value
5734
@return whether parsing should proceed
5735
*/
5736
virtual bool boolean(bool val) = 0;
5737
5738
/*!
5739
@brief an integer number was read
5740
@param[in] val integer value
5741
@return whether parsing should proceed
5742
*/
5743
virtual bool number_integer(number_integer_t val) = 0;
5744
5745
/*!
5746
@brief an unsigned integer number was read
5747
@param[in] val unsigned integer value
5748
@return whether parsing should proceed
5749
*/
5750
virtual bool number_unsigned(number_unsigned_t val) = 0;
5751
5752
/*!
5753
@brief a floating-point number was read
5754
@param[in] val floating-point value
5755
@param[in] s raw token value
5756
@return whether parsing should proceed
5757
*/
5758
virtual bool number_float(number_float_t val, const string_t& s) = 0;
5759
5760
/*!
5761
@brief a string value was read
5762
@param[in] val string value
5763
@return whether parsing should proceed
5764
@note It is safe to move the passed string value.
5765
*/
5766
virtual bool string(string_t& val) = 0;
5767
5768
/*!
5769
@brief a binary value was read
5770
@param[in] val binary value
5771
@return whether parsing should proceed
5772
@note It is safe to move the passed binary value.
5773
*/
5774
virtual bool binary(binary_t& val) = 0;
5775
5776
/*!
5777
@brief the beginning of an object was read
5778
@param[in] elements number of object elements or -1 if unknown
5779
@return whether parsing should proceed
5780
@note binary formats may report the number of elements
5781
*/
5782
virtual bool start_object(std::size_t elements) = 0;
5783
5784
/*!
5785
@brief an object key was read
5786
@param[in] val object key
5787
@return whether parsing should proceed
5788
@note It is safe to move the passed string.
5789
*/
5790
virtual bool key(string_t& val) = 0;
5791
5792
/*!
5793
@brief the end of an object was read
5794
@return whether parsing should proceed
5795
*/
5796
virtual bool end_object() = 0;
5797
5798
/*!
5799
@brief the beginning of an array was read
5800
@param[in] elements number of array elements or -1 if unknown
5801
@return whether parsing should proceed
5802
@note binary formats may report the number of elements
5803
*/
5804
virtual bool start_array(std::size_t elements) = 0;
5805
5806
/*!
5807
@brief the end of an array was read
5808
@return whether parsing should proceed
5809
*/
5810
virtual bool end_array() = 0;
5811
5812
/*!
5813
@brief a parse error occurred
5814
@param[in] position the position in the input where the error occurs
5815
@param[in] last_token the last read token
5816
@param[in] ex an exception object describing the error
5817
@return whether parsing should proceed (must return false)
5818
*/
5819
virtual bool parse_error(std::size_t position,
5820
const std::string& last_token,
5821
const detail::exception& ex) = 0;
5822
5823
json_sax() = default;
5824
json_sax(const json_sax&) = default;
5825
json_sax(json_sax&&) noexcept = default;
5826
json_sax& operator=(const json_sax&) = default;
5827
json_sax& operator=(json_sax&&) noexcept = default;
5828
virtual ~json_sax() = default;
5829
};
5830
5831
5832
namespace detail
5833
{
5834
/*!
5835
@brief SAX implementation to create a JSON value from SAX events
5836
5837
This class implements the @ref json_sax interface and processes the SAX events
5838
to create a JSON value which makes it basically a DOM parser. The structure or
5839
hierarchy of the JSON value is managed by the stack `ref_stack` which contains
5840
a pointer to the respective array or object for each recursion depth.
5841
5842
After successful parsing, the value that is passed by reference to the
5843
constructor contains the parsed value.
5844
5845
@tparam BasicJsonType the JSON type
5846
*/
5847
template<typename BasicJsonType>
5848
class json_sax_dom_parser
5849
{
5850
public:
5851
using number_integer_t = typename BasicJsonType::number_integer_t;
5852
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5853
using number_float_t = typename BasicJsonType::number_float_t;
5854
using string_t = typename BasicJsonType::string_t;
5855
using binary_t = typename BasicJsonType::binary_t;
5856
5857
/*!
5858
@param[in,out] r reference to a JSON value that is manipulated while
5859
parsing
5860
@param[in] allow_exceptions_ whether parse errors yield exceptions
5861
*/
5862
explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
5863
: root(r), allow_exceptions(allow_exceptions_)
5864
{}
5865
5866
// make class move-only
5867
json_sax_dom_parser(const json_sax_dom_parser&) = delete;
5868
json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
5869
json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
5870
json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
5871
~json_sax_dom_parser() = default;
5872
5873
bool null()
5874
{
5875
handle_value(nullptr);
5876
return true;
5877
}
5878
5879
bool boolean(bool val)
5880
{
5881
handle_value(val);
5882
return true;
5883
}
5884
5885
bool number_integer(number_integer_t val)
5886
{
5887
handle_value(val);
5888
return true;
5889
}
5890
5891
bool number_unsigned(number_unsigned_t val)
5892
{
5893
handle_value(val);
5894
return true;
5895
}
5896
5897
bool number_float(number_float_t val, const string_t& /*unused*/)
5898
{
5899
handle_value(val);
5900
return true;
5901
}
5902
5903
bool string(string_t& val)
5904
{
5905
handle_value(val);
5906
return true;
5907
}
5908
5909
bool binary(binary_t& val)
5910
{
5911
handle_value(std::move(val));
5912
return true;
5913
}
5914
5915
bool start_object(std::size_t len)
5916
{
5917
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
5918
5919
if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
5920
{
5921
JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
5922
}
5923
5924
return true;
5925
}
5926
5927
bool key(string_t& val)
5928
{
5929
// add null at given key and store the reference for later
5930
object_element = &(ref_stack.back()->m_value.object->operator[](val));
5931
return true;
5932
}
5933
5934
bool end_object()
5935
{
5936
ref_stack.back()->set_parents();
5937
ref_stack.pop_back();
5938
return true;
5939
}
5940
5941
bool start_array(std::size_t len)
5942
{
5943
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
5944
5945
if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
5946
{
5947
JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
5948
}
5949
5950
return true;
5951
}
5952
5953
bool end_array()
5954
{
5955
ref_stack.back()->set_parents();
5956
ref_stack.pop_back();
5957
return true;
5958
}
5959
5960
template<class Exception>
5961
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
5962
const Exception& ex)
5963
{
5964
errored = true;
5965
static_cast<void>(ex);
5966
if (allow_exceptions)
5967
{
5968
JSON_THROW(ex);
5969
}
5970
return false;
5971
}
5972
5973
constexpr bool is_errored() const
5974
{
5975
return errored;
5976
}
5977
5978
private:
5979
/*!
5980
@invariant If the ref stack is empty, then the passed value will be the new
5981
root.
5982
@invariant If the ref stack contains a value, then it is an array or an
5983
object to which we can add elements
5984
*/
5985
template<typename Value>
5986
JSON_HEDLEY_RETURNS_NON_NULL
5987
BasicJsonType* handle_value(Value&& v)
5988
{
5989
if (ref_stack.empty())
5990
{
5991
root = BasicJsonType(std::forward<Value>(v));
5992
return &root;
5993
}
5994
5995
JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
5996
5997
if (ref_stack.back()->is_array())
5998
{
5999
ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
6000
return &(ref_stack.back()->m_value.array->back());
6001
}
6002
6003
JSON_ASSERT(ref_stack.back()->is_object());
6004
JSON_ASSERT(object_element);
6005
*object_element = BasicJsonType(std::forward<Value>(v));
6006
return object_element;
6007
}
6008
6009
/// the parsed JSON value
6010
BasicJsonType& root;
6011
/// stack to model hierarchy of values
6012
std::vector<BasicJsonType*> ref_stack {};
6013
/// helper to hold the reference for the next object element
6014
BasicJsonType* object_element = nullptr;
6015
/// whether a syntax error occurred
6016
bool errored = false;
6017
/// whether to throw exceptions in case of errors
6018
const bool allow_exceptions = true;
6019
};
6020
6021
template<typename BasicJsonType>
6022
class json_sax_dom_callback_parser
6023
{
6024
public:
6025
using number_integer_t = typename BasicJsonType::number_integer_t;
6026
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6027
using number_float_t = typename BasicJsonType::number_float_t;
6028
using string_t = typename BasicJsonType::string_t;
6029
using binary_t = typename BasicJsonType::binary_t;
6030
using parser_callback_t = typename BasicJsonType::parser_callback_t;
6031
using parse_event_t = typename BasicJsonType::parse_event_t;
6032
6033
json_sax_dom_callback_parser(BasicJsonType& r,
6034
const parser_callback_t cb,
6035
const bool allow_exceptions_ = true)
6036
: root(r), callback(cb), allow_exceptions(allow_exceptions_)
6037
{
6038
keep_stack.push_back(true);
6039
}
6040
6041
// make class move-only
6042
json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
6043
json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6044
json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
6045
json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6046
~json_sax_dom_callback_parser() = default;
6047
6048
bool null()
6049
{
6050
handle_value(nullptr);
6051
return true;
6052
}
6053
6054
bool boolean(bool val)
6055
{
6056
handle_value(val);
6057
return true;
6058
}
6059
6060
bool number_integer(number_integer_t val)
6061
{
6062
handle_value(val);
6063
return true;
6064
}
6065
6066
bool number_unsigned(number_unsigned_t val)
6067
{
6068
handle_value(val);
6069
return true;
6070
}
6071
6072
bool number_float(number_float_t val, const string_t& /*unused*/)
6073
{
6074
handle_value(val);
6075
return true;
6076
}
6077
6078
bool string(string_t& val)
6079
{
6080
handle_value(val);
6081
return true;
6082
}
6083
6084
bool binary(binary_t& val)
6085
{
6086
handle_value(std::move(val));
6087
return true;
6088
}
6089
6090
bool start_object(std::size_t len)
6091
{
6092
// check callback for object start
6093
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
6094
keep_stack.push_back(keep);
6095
6096
auto val = handle_value(BasicJsonType::value_t::object, true);
6097
ref_stack.push_back(val.second);
6098
6099
// check object limit
6100
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6101
{
6102
JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
6103
}
6104
6105
return true;
6106
}
6107
6108
bool key(string_t& val)
6109
{
6110
BasicJsonType k = BasicJsonType(val);
6111
6112
// check callback for key
6113
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
6114
key_keep_stack.push_back(keep);
6115
6116
// add discarded value at given key and store the reference for later
6117
if (keep && ref_stack.back())
6118
{
6119
object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
6120
}
6121
6122
return true;
6123
}
6124
6125
bool end_object()
6126
{
6127
if (ref_stack.back())
6128
{
6129
if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
6130
{
6131
// discard object
6132
*ref_stack.back() = discarded;
6133
}
6134
else
6135
{
6136
ref_stack.back()->set_parents();
6137
}
6138
}
6139
6140
JSON_ASSERT(!ref_stack.empty());
6141
JSON_ASSERT(!keep_stack.empty());
6142
ref_stack.pop_back();
6143
keep_stack.pop_back();
6144
6145
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
6146
{
6147
// remove discarded value
6148
for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
6149
{
6150
if (it->is_discarded())
6151
{
6152
ref_stack.back()->erase(it);
6153
break;
6154
}
6155
}
6156
}
6157
6158
return true;
6159
}
6160
6161
bool start_array(std::size_t len)
6162
{
6163
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
6164
keep_stack.push_back(keep);
6165
6166
auto val = handle_value(BasicJsonType::value_t::array, true);
6167
ref_stack.push_back(val.second);
6168
6169
// check array limit
6170
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6171
{
6172
JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
6173
}
6174
6175
return true;
6176
}
6177
6178
bool end_array()
6179
{
6180
bool keep = true;
6181
6182
if (ref_stack.back())
6183
{
6184
keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
6185
if (keep)
6186
{
6187
ref_stack.back()->set_parents();
6188
}
6189
else
6190
{
6191
// discard array
6192
*ref_stack.back() = discarded;
6193
}
6194
}
6195
6196
JSON_ASSERT(!ref_stack.empty());
6197
JSON_ASSERT(!keep_stack.empty());
6198
ref_stack.pop_back();
6199
keep_stack.pop_back();
6200
6201
// remove discarded value
6202
if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
6203
{
6204
ref_stack.back()->m_value.array->pop_back();
6205
}
6206
6207
return true;
6208
}
6209
6210
template<class Exception>
6211
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
6212
const Exception& ex)
6213
{
6214
errored = true;
6215
static_cast<void>(ex);
6216
if (allow_exceptions)
6217
{
6218
JSON_THROW(ex);
6219
}
6220
return false;
6221
}
6222
6223
constexpr bool is_errored() const
6224
{
6225
return errored;
6226
}
6227
6228
private:
6229
/*!
6230
@param[in] v value to add to the JSON value we build during parsing
6231
@param[in] skip_callback whether we should skip calling the callback
6232
function; this is required after start_array() and
6233
start_object() SAX events, because otherwise we would call the
6234
callback function with an empty array or object, respectively.
6235
6236
@invariant If the ref stack is empty, then the passed value will be the new
6237
root.
6238
@invariant If the ref stack contains a value, then it is an array or an
6239
object to which we can add elements
6240
6241
@return pair of boolean (whether value should be kept) and pointer (to the
6242
passed value in the ref_stack hierarchy; nullptr if not kept)
6243
*/
6244
template<typename Value>
6245
std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
6246
{
6247
JSON_ASSERT(!keep_stack.empty());
6248
6249
// do not handle this value if we know it would be added to a discarded
6250
// container
6251
if (!keep_stack.back())
6252
{
6253
return {false, nullptr};
6254
}
6255
6256
// create value
6257
auto value = BasicJsonType(std::forward<Value>(v));
6258
6259
// check callback
6260
const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
6261
6262
// do not handle this value if we just learnt it shall be discarded
6263
if (!keep)
6264
{
6265
return {false, nullptr};
6266
}
6267
6268
if (ref_stack.empty())
6269
{
6270
root = std::move(value);
6271
return {true, &root};
6272
}
6273
6274
// skip this value if we already decided to skip the parent
6275
// (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
6276
if (!ref_stack.back())
6277
{
6278
return {false, nullptr};
6279
}
6280
6281
// we now only expect arrays and objects
6282
JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6283
6284
// array
6285
if (ref_stack.back()->is_array())
6286
{
6287
ref_stack.back()->m_value.array->emplace_back(std::move(value));
6288
return {true, &(ref_stack.back()->m_value.array->back())};
6289
}
6290
6291
// object
6292
JSON_ASSERT(ref_stack.back()->is_object());
6293
// check if we should store an element for the current key
6294
JSON_ASSERT(!key_keep_stack.empty());
6295
const bool store_element = key_keep_stack.back();
6296
key_keep_stack.pop_back();
6297
6298
if (!store_element)
6299
{
6300
return {false, nullptr};
6301
}
6302
6303
JSON_ASSERT(object_element);
6304
*object_element = std::move(value);
6305
return {true, object_element};
6306
}
6307
6308
/// the parsed JSON value
6309
BasicJsonType& root;
6310
/// stack to model hierarchy of values
6311
std::vector<BasicJsonType*> ref_stack {};
6312
/// stack to manage which values to keep
6313
std::vector<bool> keep_stack {};
6314
/// stack to manage which object keys to keep
6315
std::vector<bool> key_keep_stack {};
6316
/// helper to hold the reference for the next object element
6317
BasicJsonType* object_element = nullptr;
6318
/// whether a syntax error occurred
6319
bool errored = false;
6320
/// callback function
6321
const parser_callback_t callback = nullptr;
6322
/// whether to throw exceptions in case of errors
6323
const bool allow_exceptions = true;
6324
/// a discarded value for the callback
6325
BasicJsonType discarded = BasicJsonType::value_t::discarded;
6326
};
6327
6328
template<typename BasicJsonType>
6329
class json_sax_acceptor
6330
{
6331
public:
6332
using number_integer_t = typename BasicJsonType::number_integer_t;
6333
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6334
using number_float_t = typename BasicJsonType::number_float_t;
6335
using string_t = typename BasicJsonType::string_t;
6336
using binary_t = typename BasicJsonType::binary_t;
6337
6338
bool null()
6339
{
6340
return true;
6341
}
6342
6343
bool boolean(bool /*unused*/)
6344
{
6345
return true;
6346
}
6347
6348
bool number_integer(number_integer_t /*unused*/)
6349
{
6350
return true;
6351
}
6352
6353
bool number_unsigned(number_unsigned_t /*unused*/)
6354
{
6355
return true;
6356
}
6357
6358
bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
6359
{
6360
return true;
6361
}
6362
6363
bool string(string_t& /*unused*/)
6364
{
6365
return true;
6366
}
6367
6368
bool binary(binary_t& /*unused*/)
6369
{
6370
return true;
6371
}
6372
6373
bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
6374
{
6375
return true;
6376
}
6377
6378
bool key(string_t& /*unused*/)
6379
{
6380
return true;
6381
}
6382
6383
bool end_object()
6384
{
6385
return true;
6386
}
6387
6388
bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
6389
{
6390
return true;
6391
}
6392
6393
bool end_array()
6394
{
6395
return true;
6396
}
6397
6398
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
6399
{
6400
return false;
6401
}
6402
};
6403
} // namespace detail
6404
6405
} // namespace nlohmann
6406
6407
// #include <nlohmann/detail/input/lexer.hpp>
6408
6409
6410
#include <array> // array
6411
#include <clocale> // localeconv
6412
#include <cstddef> // size_t
6413
#include <cstdio> // snprintf
6414
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
6415
#include <initializer_list> // initializer_list
6416
#include <string> // char_traits, string
6417
#include <utility> // move
6418
#include <vector> // vector
6419
6420
// #include <nlohmann/detail/input/input_adapters.hpp>
6421
6422
// #include <nlohmann/detail/input/position_t.hpp>
6423
6424
// #include <nlohmann/detail/macro_scope.hpp>
6425
6426
6427
namespace nlohmann
6428
{
6429
namespace detail
6430
{
6431
///////////
6432
// lexer //
6433
///////////
6434
6435
template<typename BasicJsonType>
6436
class lexer_base
6437
{
6438
public:
6439
/// token types for the parser
6440
enum class token_type
6441
{
6442
uninitialized, ///< indicating the scanner is uninitialized
6443
literal_true, ///< the `true` literal
6444
literal_false, ///< the `false` literal
6445
literal_null, ///< the `null` literal
6446
value_string, ///< a string -- use get_string() for actual value
6447
value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
6448
value_integer, ///< a signed integer -- use get_number_integer() for actual value
6449
value_float, ///< an floating point number -- use get_number_float() for actual value
6450
begin_array, ///< the character for array begin `[`
6451
begin_object, ///< the character for object begin `{`
6452
end_array, ///< the character for array end `]`
6453
end_object, ///< the character for object end `}`
6454
name_separator, ///< the name separator `:`
6455
value_separator, ///< the value separator `,`
6456
parse_error, ///< indicating a parse error
6457
end_of_input, ///< indicating the end of the input buffer
6458
literal_or_value ///< a literal or the begin of a value (only for diagnostics)
6459
};
6460
6461
/// return name of values of type token_type (only used for errors)
6462
JSON_HEDLEY_RETURNS_NON_NULL
6463
JSON_HEDLEY_CONST
6464
static const char* token_type_name(const token_type t) noexcept
6465
{
6466
switch (t)
6467
{
6468
case token_type::uninitialized:
6469
return "<uninitialized>";
6470
case token_type::literal_true:
6471
return "true literal";
6472
case token_type::literal_false:
6473
return "false literal";
6474
case token_type::literal_null:
6475
return "null literal";
6476
case token_type::value_string:
6477
return "string literal";
6478
case token_type::value_unsigned:
6479
case token_type::value_integer:
6480
case token_type::value_float:
6481
return "number literal";
6482
case token_type::begin_array:
6483
return "'['";
6484
case token_type::begin_object:
6485
return "'{'";
6486
case token_type::end_array:
6487
return "']'";
6488
case token_type::end_object:
6489
return "'}'";
6490
case token_type::name_separator:
6491
return "':'";
6492
case token_type::value_separator:
6493
return "','";
6494
case token_type::parse_error:
6495
return "<parse error>";
6496
case token_type::end_of_input:
6497
return "end of input";
6498
case token_type::literal_or_value:
6499
return "'[', '{', or a literal";
6500
// LCOV_EXCL_START
6501
default: // catch non-enum values
6502
return "unknown token";
6503
// LCOV_EXCL_STOP
6504
}
6505
}
6506
};
6507
/*!
6508
@brief lexical analysis
6509
6510
This class organizes the lexical analysis during JSON deserialization.
6511
*/
6512
template<typename BasicJsonType, typename InputAdapterType>
6513
class lexer : public lexer_base<BasicJsonType>
6514
{
6515
using number_integer_t = typename BasicJsonType::number_integer_t;
6516
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6517
using number_float_t = typename BasicJsonType::number_float_t;
6518
using string_t = typename BasicJsonType::string_t;
6519
using char_type = typename InputAdapterType::char_type;
6520
using char_int_type = typename std::char_traits<char_type>::int_type;
6521
6522
public:
6523
using token_type = typename lexer_base<BasicJsonType>::token_type;
6524
6525
explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
6526
: ia(std::move(adapter))
6527
, ignore_comments(ignore_comments_)
6528
, decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
6529
{}
6530
6531
// delete because of pointer members
6532
lexer(const lexer&) = delete;
6533
lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6534
lexer& operator=(lexer&) = delete;
6535
lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6536
~lexer() = default;
6537
6538
private:
6539
/////////////////////
6540
// locales
6541
/////////////////////
6542
6543
/// return the locale-dependent decimal point
6544
JSON_HEDLEY_PURE
6545
static char get_decimal_point() noexcept
6546
{
6547
const auto* loc = localeconv();
6548
JSON_ASSERT(loc != nullptr);
6549
return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
6550
}
6551
6552
/////////////////////
6553
// scan functions
6554
/////////////////////
6555
6556
/*!
6557
@brief get codepoint from 4 hex characters following `\u`
6558
6559
For input "\u c1 c2 c3 c4" the codepoint is:
6560
(c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
6561
= (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
6562
6563
Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
6564
must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
6565
conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
6566
between the ASCII value of the character and the desired integer value.
6567
6568
@return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
6569
non-hex character)
6570
*/
6571
int get_codepoint()
6572
{
6573
// this function only makes sense after reading `\u`
6574
JSON_ASSERT(current == 'u');
6575
int codepoint = 0;
6576
6577
const auto factors = { 12u, 8u, 4u, 0u };
6578
for (const auto factor : factors)
6579
{
6580
get();
6581
6582
if (current >= '0' && current <= '9')
6583
{
6584
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
6585
}
6586
else if (current >= 'A' && current <= 'F')
6587
{
6588
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
6589
}
6590
else if (current >= 'a' && current <= 'f')
6591
{
6592
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
6593
}
6594
else
6595
{
6596
return -1;
6597
}
6598
}
6599
6600
JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
6601
return codepoint;
6602
}
6603
6604
/*!
6605
@brief check if the next byte(s) are inside a given range
6606
6607
Adds the current byte and, for each passed range, reads a new byte and
6608
checks if it is inside the range. If a violation was detected, set up an
6609
error message and return false. Otherwise, return true.
6610
6611
@param[in] ranges list of integers; interpreted as list of pairs of
6612
inclusive lower and upper bound, respectively
6613
6614
@pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
6615
1, 2, or 3 pairs. This precondition is enforced by an assertion.
6616
6617
@return true if and only if no range violation was detected
6618
*/
6619
bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
6620
{
6621
JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
6622
add(current);
6623
6624
for (auto range = ranges.begin(); range != ranges.end(); ++range)
6625
{
6626
get();
6627
if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
6628
{
6629
add(current);
6630
}
6631
else
6632
{
6633
error_message = "invalid string: ill-formed UTF-8 byte";
6634
return false;
6635
}
6636
}
6637
6638
return true;
6639
}
6640
6641
/*!
6642
@brief scan a string literal
6643
6644
This function scans a string according to Sect. 7 of RFC 8259. While
6645
scanning, bytes are escaped and copied into buffer token_buffer. Then the
6646
function returns successfully, token_buffer is *not* null-terminated (as it
6647
may contain \0 bytes), and token_buffer.size() is the number of bytes in the
6648
string.
6649
6650
@return token_type::value_string if string could be successfully scanned,
6651
token_type::parse_error otherwise
6652
6653
@note In case of errors, variable error_message contains a textual
6654
description.
6655
*/
6656
token_type scan_string()
6657
{
6658
// reset token_buffer (ignore opening quote)
6659
reset();
6660
6661
// we entered the function by reading an open quote
6662
JSON_ASSERT(current == '\"');
6663
6664
while (true)
6665
{
6666
// get next character
6667
switch (get())
6668
{
6669
// end of file while parsing string
6670
case std::char_traits<char_type>::eof():
6671
{
6672
error_message = "invalid string: missing closing quote";
6673
return token_type::parse_error;
6674
}
6675
6676
// closing quote
6677
case '\"':
6678
{
6679
return token_type::value_string;
6680
}
6681
6682
// escapes
6683
case '\\':
6684
{
6685
switch (get())
6686
{
6687
// quotation mark
6688
case '\"':
6689
add('\"');
6690
break;
6691
// reverse solidus
6692
case '\\':
6693
add('\\');
6694
break;
6695
// solidus
6696
case '/':
6697
add('/');
6698
break;
6699
// backspace
6700
case 'b':
6701
add('\b');
6702
break;
6703
// form feed
6704
case 'f':
6705
add('\f');
6706
break;
6707
// line feed
6708
case 'n':
6709
add('\n');
6710
break;
6711
// carriage return
6712
case 'r':
6713
add('\r');
6714
break;
6715
// tab
6716
case 't':
6717
add('\t');
6718
break;
6719
6720
// unicode escapes
6721
case 'u':
6722
{
6723
const int codepoint1 = get_codepoint();
6724
int codepoint = codepoint1; // start with codepoint1
6725
6726
if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
6727
{
6728
error_message = "invalid string: '\\u' must be followed by 4 hex digits";
6729
return token_type::parse_error;
6730
}
6731
6732
// check if code point is a high surrogate
6733
if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
6734
{
6735
// expect next \uxxxx entry
6736
if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
6737
{
6738
const int codepoint2 = get_codepoint();
6739
6740
if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
6741
{
6742
error_message = "invalid string: '\\u' must be followed by 4 hex digits";
6743
return token_type::parse_error;
6744
}
6745
6746
// check if codepoint2 is a low surrogate
6747
if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
6748
{
6749
// overwrite codepoint
6750
codepoint = static_cast<int>(
6751
// high surrogate occupies the most significant 22 bits
6752
(static_cast<unsigned int>(codepoint1) << 10u)
6753
// low surrogate occupies the least significant 15 bits
6754
+ static_cast<unsigned int>(codepoint2)
6755
// there is still the 0xD800, 0xDC00 and 0x10000 noise
6756
// in the result, so we have to subtract with:
6757
// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6758
- 0x35FDC00u);
6759
}
6760
else
6761
{
6762
error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
6763
return token_type::parse_error;
6764
}
6765
}
6766
else
6767
{
6768
error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
6769
return token_type::parse_error;
6770
}
6771
}
6772
else
6773
{
6774
if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
6775
{
6776
error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
6777
return token_type::parse_error;
6778
}
6779
}
6780
6781
// result of the above calculation yields a proper codepoint
6782
JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
6783
6784
// translate codepoint into bytes
6785
if (codepoint < 0x80)
6786
{
6787
// 1-byte characters: 0xxxxxxx (ASCII)
6788
add(static_cast<char_int_type>(codepoint));
6789
}
6790
else if (codepoint <= 0x7FF)
6791
{
6792
// 2-byte characters: 110xxxxx 10xxxxxx
6793
add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
6794
add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6795
}
6796
else if (codepoint <= 0xFFFF)
6797
{
6798
// 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6799
add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
6800
add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
6801
add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6802
}
6803
else
6804
{
6805
// 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6806
add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
6807
add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
6808
add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
6809
add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6810
}
6811
6812
break;
6813
}
6814
6815
// other characters after escape
6816
default:
6817
error_message = "invalid string: forbidden character after backslash";
6818
return token_type::parse_error;
6819
}
6820
6821
break;
6822
}
6823
6824
// invalid control characters
6825
case 0x00:
6826
{
6827
error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
6828
return token_type::parse_error;
6829
}
6830
6831
case 0x01:
6832
{
6833
error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
6834
return token_type::parse_error;
6835
}
6836
6837
case 0x02:
6838
{
6839
error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
6840
return token_type::parse_error;
6841
}
6842
6843
case 0x03:
6844
{
6845
error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
6846
return token_type::parse_error;
6847
}
6848
6849
case 0x04:
6850
{
6851
error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
6852
return token_type::parse_error;
6853
}
6854
6855
case 0x05:
6856
{
6857
error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
6858
return token_type::parse_error;
6859
}
6860
6861
case 0x06:
6862
{
6863
error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
6864
return token_type::parse_error;
6865
}
6866
6867
case 0x07:
6868
{
6869
error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
6870
return token_type::parse_error;
6871
}
6872
6873
case 0x08:
6874
{
6875
error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
6876
return token_type::parse_error;
6877
}
6878
6879
case 0x09:
6880
{
6881
error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
6882
return token_type::parse_error;
6883
}
6884
6885
case 0x0A:
6886
{
6887
error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
6888
return token_type::parse_error;
6889
}
6890
6891
case 0x0B:
6892
{
6893
error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
6894
return token_type::parse_error;
6895
}
6896
6897
case 0x0C:
6898
{
6899
error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
6900
return token_type::parse_error;
6901
}
6902
6903
case 0x0D:
6904
{
6905
error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
6906
return token_type::parse_error;
6907
}
6908
6909
case 0x0E:
6910
{
6911
error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
6912
return token_type::parse_error;
6913
}
6914
6915
case 0x0F:
6916
{
6917
error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
6918
return token_type::parse_error;
6919
}
6920
6921
case 0x10:
6922
{
6923
error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
6924
return token_type::parse_error;
6925
}
6926
6927
case 0x11:
6928
{
6929
error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
6930
return token_type::parse_error;
6931
}
6932
6933
case 0x12:
6934
{
6935
error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
6936
return token_type::parse_error;
6937
}
6938
6939
case 0x13:
6940
{
6941
error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
6942
return token_type::parse_error;
6943
}
6944
6945
case 0x14:
6946
{
6947
error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
6948
return token_type::parse_error;
6949
}
6950
6951
case 0x15:
6952
{
6953
error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
6954
return token_type::parse_error;
6955
}
6956
6957
case 0x16:
6958
{
6959
error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
6960
return token_type::parse_error;
6961
}
6962
6963
case 0x17:
6964
{
6965
error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
6966
return token_type::parse_error;
6967
}
6968
6969
case 0x18:
6970
{
6971
error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
6972
return token_type::parse_error;
6973
}
6974
6975
case 0x19:
6976
{
6977
error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
6978
return token_type::parse_error;
6979
}
6980
6981
case 0x1A:
6982
{
6983
error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
6984
return token_type::parse_error;
6985
}
6986
6987
case 0x1B:
6988
{
6989
error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
6990
return token_type::parse_error;
6991
}
6992
6993
case 0x1C:
6994
{
6995
error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
6996
return token_type::parse_error;
6997
}
6998
6999
case 0x1D:
7000
{
7001
error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7002
return token_type::parse_error;
7003
}
7004
7005
case 0x1E:
7006
{
7007
error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7008
return token_type::parse_error;
7009
}
7010
7011
case 0x1F:
7012
{
7013
error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7014
return token_type::parse_error;
7015
}
7016
7017
// U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7018
case 0x20:
7019
case 0x21:
7020
case 0x23:
7021
case 0x24:
7022
case 0x25:
7023
case 0x26:
7024
case 0x27:
7025
case 0x28:
7026
case 0x29:
7027
case 0x2A:
7028
case 0x2B:
7029
case 0x2C:
7030
case 0x2D:
7031
case 0x2E:
7032
case 0x2F:
7033
case 0x30:
7034
case 0x31:
7035
case 0x32:
7036
case 0x33:
7037
case 0x34:
7038
case 0x35:
7039
case 0x36:
7040
case 0x37:
7041
case 0x38:
7042
case 0x39:
7043
case 0x3A:
7044
case 0x3B:
7045
case 0x3C:
7046
case 0x3D:
7047
case 0x3E:
7048
case 0x3F:
7049
case 0x40:
7050
case 0x41:
7051
case 0x42:
7052
case 0x43:
7053
case 0x44:
7054
case 0x45:
7055
case 0x46:
7056
case 0x47:
7057
case 0x48:
7058
case 0x49:
7059
case 0x4A:
7060
case 0x4B:
7061
case 0x4C:
7062
case 0x4D:
7063
case 0x4E:
7064
case 0x4F:
7065
case 0x50:
7066
case 0x51:
7067
case 0x52:
7068
case 0x53:
7069
case 0x54:
7070
case 0x55:
7071
case 0x56:
7072
case 0x57:
7073
case 0x58:
7074
case 0x59:
7075
case 0x5A:
7076
case 0x5B:
7077
case 0x5D:
7078
case 0x5E:
7079
case 0x5F:
7080
case 0x60:
7081
case 0x61:
7082
case 0x62:
7083
case 0x63:
7084
case 0x64:
7085
case 0x65:
7086
case 0x66:
7087
case 0x67:
7088
case 0x68:
7089
case 0x69:
7090
case 0x6A:
7091
case 0x6B:
7092
case 0x6C:
7093
case 0x6D:
7094
case 0x6E:
7095
case 0x6F:
7096
case 0x70:
7097
case 0x71:
7098
case 0x72:
7099
case 0x73:
7100
case 0x74:
7101
case 0x75:
7102
case 0x76:
7103
case 0x77:
7104
case 0x78:
7105
case 0x79:
7106
case 0x7A:
7107
case 0x7B:
7108
case 0x7C:
7109
case 0x7D:
7110
case 0x7E:
7111
case 0x7F:
7112
{
7113
add(current);
7114
break;
7115
}
7116
7117
// U+0080..U+07FF: bytes C2..DF 80..BF
7118
case 0xC2:
7119
case 0xC3:
7120
case 0xC4:
7121
case 0xC5:
7122
case 0xC6:
7123
case 0xC7:
7124
case 0xC8:
7125
case 0xC9:
7126
case 0xCA:
7127
case 0xCB:
7128
case 0xCC:
7129
case 0xCD:
7130
case 0xCE:
7131
case 0xCF:
7132
case 0xD0:
7133
case 0xD1:
7134
case 0xD2:
7135
case 0xD3:
7136
case 0xD4:
7137
case 0xD5:
7138
case 0xD6:
7139
case 0xD7:
7140
case 0xD8:
7141
case 0xD9:
7142
case 0xDA:
7143
case 0xDB:
7144
case 0xDC:
7145
case 0xDD:
7146
case 0xDE:
7147
case 0xDF:
7148
{
7149
if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
7150
{
7151
return token_type::parse_error;
7152
}
7153
break;
7154
}
7155
7156
// U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7157
case 0xE0:
7158
{
7159
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7160
{
7161
return token_type::parse_error;
7162
}
7163
break;
7164
}
7165
7166
// U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7167
// U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7168
case 0xE1:
7169
case 0xE2:
7170
case 0xE3:
7171
case 0xE4:
7172
case 0xE5:
7173
case 0xE6:
7174
case 0xE7:
7175
case 0xE8:
7176
case 0xE9:
7177
case 0xEA:
7178
case 0xEB:
7179
case 0xEC:
7180
case 0xEE:
7181
case 0xEF:
7182
{
7183
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7184
{
7185
return token_type::parse_error;
7186
}
7187
break;
7188
}
7189
7190
// U+D000..U+D7FF: bytes ED 80..9F 80..BF
7191
case 0xED:
7192
{
7193
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7194
{
7195
return token_type::parse_error;
7196
}
7197
break;
7198
}
7199
7200
// U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7201
case 0xF0:
7202
{
7203
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7204
{
7205
return token_type::parse_error;
7206
}
7207
break;
7208
}
7209
7210
// U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7211
case 0xF1:
7212
case 0xF2:
7213
case 0xF3:
7214
{
7215
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7216
{
7217
return token_type::parse_error;
7218
}
7219
break;
7220
}
7221
7222
// U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7223
case 0xF4:
7224
{
7225
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
7226
{
7227
return token_type::parse_error;
7228
}
7229
break;
7230
}
7231
7232
// remaining bytes (80..C1 and F5..FF) are ill-formed
7233
default:
7234
{
7235
error_message = "invalid string: ill-formed UTF-8 byte";
7236
return token_type::parse_error;
7237
}
7238
}
7239
}
7240
}
7241
7242
/*!
7243
* @brief scan a comment
7244
* @return whether comment could be scanned successfully
7245
*/
7246
bool scan_comment()
7247
{
7248
switch (get())
7249
{
7250
// single-line comments skip input until a newline or EOF is read
7251
case '/':
7252
{
7253
while (true)
7254
{
7255
switch (get())
7256
{
7257
case '\n':
7258
case '\r':
7259
case std::char_traits<char_type>::eof():
7260
case '\0':
7261
return true;
7262
7263
default:
7264
break;
7265
}
7266
}
7267
}
7268
7269
// multi-line comments skip input until */ is read
7270
case '*':
7271
{
7272
while (true)
7273
{
7274
switch (get())
7275
{
7276
case std::char_traits<char_type>::eof():
7277
case '\0':
7278
{
7279
error_message = "invalid comment; missing closing '*/'";
7280
return false;
7281
}
7282
7283
case '*':
7284
{
7285
switch (get())
7286
{
7287
case '/':
7288
return true;
7289
7290
default:
7291
{
7292
unget();
7293
continue;
7294
}
7295
}
7296
}
7297
7298
default:
7299
continue;
7300
}
7301
}
7302
}
7303
7304
// unexpected character after reading '/'
7305
default:
7306
{
7307
error_message = "invalid comment; expecting '/' or '*' after '/'";
7308
return false;
7309
}
7310
}
7311
}
7312
7313
JSON_HEDLEY_NON_NULL(2)
7314
static void strtof(float& f, const char* str, char** endptr) noexcept
7315
{
7316
f = std::strtof(str, endptr);
7317
}
7318
7319
JSON_HEDLEY_NON_NULL(2)
7320
static void strtof(double& f, const char* str, char** endptr) noexcept
7321
{
7322
f = std::strtod(str, endptr);
7323
}
7324
7325
JSON_HEDLEY_NON_NULL(2)
7326
static void strtof(long double& f, const char* str, char** endptr) noexcept
7327
{
7328
f = std::strtold(str, endptr);
7329
}
7330
7331
/*!
7332
@brief scan a number literal
7333
7334
This function scans a string according to Sect. 6 of RFC 8259.
7335
7336
The function is realized with a deterministic finite state machine derived
7337
from the grammar described in RFC 8259. Starting in state "init", the
7338
input is read and used to determined the next state. Only state "done"
7339
accepts the number. State "error" is a trap state to model errors. In the
7340
table below, "anything" means any character but the ones listed before.
7341
7342
state | 0 | 1-9 | e E | + | - | . | anything
7343
---------|----------|----------|----------|---------|---------|----------|-----------
7344
init | zero | any1 | [error] | [error] | minus | [error] | [error]
7345
minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
7346
zero | done | done | exponent | done | done | decimal1 | done
7347
any1 | any1 | any1 | exponent | done | done | decimal1 | done
7348
decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error]
7349
decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
7350
exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
7351
sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
7352
any2 | any2 | any2 | done | done | done | done | done
7353
7354
The state machine is realized with one label per state (prefixed with
7355
"scan_number_") and `goto` statements between them. The state machine
7356
contains cycles, but any cycle can be left when EOF is read. Therefore,
7357
the function is guaranteed to terminate.
7358
7359
During scanning, the read bytes are stored in token_buffer. This string is
7360
then converted to a signed integer, an unsigned integer, or a
7361
floating-point number.
7362
7363
@return token_type::value_unsigned, token_type::value_integer, or
7364
token_type::value_float if number could be successfully scanned,
7365
token_type::parse_error otherwise
7366
7367
@note The scanner is independent of the current locale. Internally, the
7368
locale's decimal point is used instead of `.` to work with the
7369
locale-dependent converters.
7370
*/
7371
token_type scan_number() // lgtm [cpp/use-of-goto]
7372
{
7373
// reset token_buffer to store the number's bytes
7374
reset();
7375
7376
// the type of the parsed number; initially set to unsigned; will be
7377
// changed if minus sign, decimal point or exponent is read
7378
token_type number_type = token_type::value_unsigned;
7379
7380
// state (init): we just found out we need to scan a number
7381
switch (current)
7382
{
7383
case '-':
7384
{
7385
add(current);
7386
goto scan_number_minus;
7387
}
7388
7389
case '0':
7390
{
7391
add(current);
7392
goto scan_number_zero;
7393
}
7394
7395
case '1':
7396
case '2':
7397
case '3':
7398
case '4':
7399
case '5':
7400
case '6':
7401
case '7':
7402
case '8':
7403
case '9':
7404
{
7405
add(current);
7406
goto scan_number_any1;
7407
}
7408
7409
// all other characters are rejected outside scan_number()
7410
default: // LCOV_EXCL_LINE
7411
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
7412
}
7413
7414
scan_number_minus:
7415
// state: we just parsed a leading minus sign
7416
number_type = token_type::value_integer;
7417
switch (get())
7418
{
7419
case '0':
7420
{
7421
add(current);
7422
goto scan_number_zero;
7423
}
7424
7425
case '1':
7426
case '2':
7427
case '3':
7428
case '4':
7429
case '5':
7430
case '6':
7431
case '7':
7432
case '8':
7433
case '9':
7434
{
7435
add(current);
7436
goto scan_number_any1;
7437
}
7438
7439
default:
7440
{
7441
error_message = "invalid number; expected digit after '-'";
7442
return token_type::parse_error;
7443
}
7444
}
7445
7446
scan_number_zero:
7447
// state: we just parse a zero (maybe with a leading minus sign)
7448
switch (get())
7449
{
7450
case '.':
7451
{
7452
add(decimal_point_char);
7453
goto scan_number_decimal1;
7454
}
7455
7456
case 'e':
7457
case 'E':
7458
{
7459
add(current);
7460
goto scan_number_exponent;
7461
}
7462
7463
default:
7464
goto scan_number_done;
7465
}
7466
7467
scan_number_any1:
7468
// state: we just parsed a number 0-9 (maybe with a leading minus sign)
7469
switch (get())
7470
{
7471
case '0':
7472
case '1':
7473
case '2':
7474
case '3':
7475
case '4':
7476
case '5':
7477
case '6':
7478
case '7':
7479
case '8':
7480
case '9':
7481
{
7482
add(current);
7483
goto scan_number_any1;
7484
}
7485
7486
case '.':
7487
{
7488
add(decimal_point_char);
7489
goto scan_number_decimal1;
7490
}
7491
7492
case 'e':
7493
case 'E':
7494
{
7495
add(current);
7496
goto scan_number_exponent;
7497
}
7498
7499
default:
7500
goto scan_number_done;
7501
}
7502
7503
scan_number_decimal1:
7504
// state: we just parsed a decimal point
7505
number_type = token_type::value_float;
7506
switch (get())
7507
{
7508
case '0':
7509
case '1':
7510
case '2':
7511
case '3':
7512
case '4':
7513
case '5':
7514
case '6':
7515
case '7':
7516
case '8':
7517
case '9':
7518
{
7519
add(current);
7520
goto scan_number_decimal2;
7521
}
7522
7523
default:
7524
{
7525
error_message = "invalid number; expected digit after '.'";
7526
return token_type::parse_error;
7527
}
7528
}
7529
7530
scan_number_decimal2:
7531
// we just parsed at least one number after a decimal point
7532
switch (get())
7533
{
7534
case '0':
7535
case '1':
7536
case '2':
7537
case '3':
7538
case '4':
7539
case '5':
7540
case '6':
7541
case '7':
7542
case '8':
7543
case '9':
7544
{
7545
add(current);
7546
goto scan_number_decimal2;
7547
}
7548
7549
case 'e':
7550
case 'E':
7551
{
7552
add(current);
7553
goto scan_number_exponent;
7554
}
7555
7556
default:
7557
goto scan_number_done;
7558
}
7559
7560
scan_number_exponent:
7561
// we just parsed an exponent
7562
number_type = token_type::value_float;
7563
switch (get())
7564
{
7565
case '+':
7566
case '-':
7567
{
7568
add(current);
7569
goto scan_number_sign;
7570
}
7571
7572
case '0':
7573
case '1':
7574
case '2':
7575
case '3':
7576
case '4':
7577
case '5':
7578
case '6':
7579
case '7':
7580
case '8':
7581
case '9':
7582
{
7583
add(current);
7584
goto scan_number_any2;
7585
}
7586
7587
default:
7588
{
7589
error_message =
7590
"invalid number; expected '+', '-', or digit after exponent";
7591
return token_type::parse_error;
7592
}
7593
}
7594
7595
scan_number_sign:
7596
// we just parsed an exponent sign
7597
switch (get())
7598
{
7599
case '0':
7600
case '1':
7601
case '2':
7602
case '3':
7603
case '4':
7604
case '5':
7605
case '6':
7606
case '7':
7607
case '8':
7608
case '9':
7609
{
7610
add(current);
7611
goto scan_number_any2;
7612
}
7613
7614
default:
7615
{
7616
error_message = "invalid number; expected digit after exponent sign";
7617
return token_type::parse_error;
7618
}
7619
}
7620
7621
scan_number_any2:
7622
// we just parsed a number after the exponent or exponent sign
7623
switch (get())
7624
{
7625
case '0':
7626
case '1':
7627
case '2':
7628
case '3':
7629
case '4':
7630
case '5':
7631
case '6':
7632
case '7':
7633
case '8':
7634
case '9':
7635
{
7636
add(current);
7637
goto scan_number_any2;
7638
}
7639
7640
default:
7641
goto scan_number_done;
7642
}
7643
7644
scan_number_done:
7645
// unget the character after the number (we only read it to know that
7646
// we are done scanning a number)
7647
unget();
7648
7649
char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
7650
errno = 0;
7651
7652
// try to parse integers first and fall back to floats
7653
if (number_type == token_type::value_unsigned)
7654
{
7655
const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
7656
7657
// we checked the number format before
7658
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7659
7660
if (errno == 0)
7661
{
7662
value_unsigned = static_cast<number_unsigned_t>(x);
7663
if (value_unsigned == x)
7664
{
7665
return token_type::value_unsigned;
7666
}
7667
}
7668
}
7669
else if (number_type == token_type::value_integer)
7670
{
7671
const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
7672
7673
// we checked the number format before
7674
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7675
7676
if (errno == 0)
7677
{
7678
value_integer = static_cast<number_integer_t>(x);
7679
if (value_integer == x)
7680
{
7681
return token_type::value_integer;
7682
}
7683
}
7684
}
7685
7686
// this code is reached if we parse a floating-point number or if an
7687
// integer conversion above failed
7688
strtof(value_float, token_buffer.data(), &endptr);
7689
7690
// we checked the number format before
7691
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7692
7693
return token_type::value_float;
7694
}
7695
7696
/*!
7697
@param[in] literal_text the literal text to expect
7698
@param[in] length the length of the passed literal text
7699
@param[in] return_type the token type to return on success
7700
*/
7701
JSON_HEDLEY_NON_NULL(2)
7702
token_type scan_literal(const char_type* literal_text, const std::size_t length,
7703
token_type return_type)
7704
{
7705
JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
7706
for (std::size_t i = 1; i < length; ++i)
7707
{
7708
if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
7709
{
7710
error_message = "invalid literal";
7711
return token_type::parse_error;
7712
}
7713
}
7714
return return_type;
7715
}
7716
7717
/////////////////////
7718
// input management
7719
/////////////////////
7720
7721
/// reset token_buffer; current character is beginning of token
7722
void reset() noexcept
7723
{
7724
token_buffer.clear();
7725
token_string.clear();
7726
token_string.push_back(std::char_traits<char_type>::to_char_type(current));
7727
}
7728
7729
/*
7730
@brief get next character from the input
7731
7732
This function provides the interface to the used input adapter. It does
7733
not throw in case the input reached EOF, but returns a
7734
`std::char_traits<char>::eof()` in that case. Stores the scanned characters
7735
for use in error messages.
7736
7737
@return character read from the input
7738
*/
7739
char_int_type get()
7740
{
7741
++position.chars_read_total;
7742
++position.chars_read_current_line;
7743
7744
if (next_unget)
7745
{
7746
// just reset the next_unget variable and work with current
7747
next_unget = false;
7748
}
7749
else
7750
{
7751
current = ia.get_character();
7752
}
7753
7754
if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
7755
{
7756
token_string.push_back(std::char_traits<char_type>::to_char_type(current));
7757
}
7758
7759
if (current == '\n')
7760
{
7761
++position.lines_read;
7762
position.chars_read_current_line = 0;
7763
}
7764
7765
return current;
7766
}
7767
7768
/*!
7769
@brief unget current character (read it again on next get)
7770
7771
We implement unget by setting variable next_unget to true. The input is not
7772
changed - we just simulate ungetting by modifying chars_read_total,
7773
chars_read_current_line, and token_string. The next call to get() will
7774
behave as if the unget character is read again.
7775
*/
7776
void unget()
7777
{
7778
next_unget = true;
7779
7780
--position.chars_read_total;
7781
7782
// in case we "unget" a newline, we have to also decrement the lines_read
7783
if (position.chars_read_current_line == 0)
7784
{
7785
if (position.lines_read > 0)
7786
{
7787
--position.lines_read;
7788
}
7789
}
7790
else
7791
{
7792
--position.chars_read_current_line;
7793
}
7794
7795
if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
7796
{
7797
JSON_ASSERT(!token_string.empty());
7798
token_string.pop_back();
7799
}
7800
}
7801
7802
/// add a character to token_buffer
7803
void add(char_int_type c)
7804
{
7805
token_buffer.push_back(static_cast<typename string_t::value_type>(c));
7806
}
7807
7808
public:
7809
/////////////////////
7810
// value getters
7811
/////////////////////
7812
7813
/// return integer value
7814
constexpr number_integer_t get_number_integer() const noexcept
7815
{
7816
return value_integer;
7817
}
7818
7819
/// return unsigned integer value
7820
constexpr number_unsigned_t get_number_unsigned() const noexcept
7821
{
7822
return value_unsigned;
7823
}
7824
7825
/// return floating-point value
7826
constexpr number_float_t get_number_float() const noexcept
7827
{
7828
return value_float;
7829
}
7830
7831
/// return current string value (implicitly resets the token; useful only once)
7832
string_t& get_string()
7833
{
7834
return token_buffer;
7835
}
7836
7837
/////////////////////
7838
// diagnostics
7839
/////////////////////
7840
7841
/// return position of last read token
7842
constexpr position_t get_position() const noexcept
7843
{
7844
return position;
7845
}
7846
7847
/// return the last read token (for errors only). Will never contain EOF
7848
/// (an arbitrary value that is not a valid char value, often -1), because
7849
/// 255 may legitimately occur. May contain NUL, which should be escaped.
7850
std::string get_token_string() const
7851
{
7852
// escape control characters
7853
std::string result;
7854
for (const auto c : token_string)
7855
{
7856
if (static_cast<unsigned char>(c) <= '\x1F')
7857
{
7858
// escape control characters
7859
std::array<char, 9> cs{{}};
7860
static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
7861
result += cs.data();
7862
}
7863
else
7864
{
7865
// add character as is
7866
result.push_back(static_cast<std::string::value_type>(c));
7867
}
7868
}
7869
7870
return result;
7871
}
7872
7873
/// return syntax error message
7874
JSON_HEDLEY_RETURNS_NON_NULL
7875
constexpr const char* get_error_message() const noexcept
7876
{
7877
return error_message;
7878
}
7879
7880
/////////////////////
7881
// actual scanner
7882
/////////////////////
7883
7884
/*!
7885
@brief skip the UTF-8 byte order mark
7886
@return true iff there is no BOM or the correct BOM has been skipped
7887
*/
7888
bool skip_bom()
7889
{
7890
if (get() == 0xEF)
7891
{
7892
// check if we completely parse the BOM
7893
return get() == 0xBB && get() == 0xBF;
7894
}
7895
7896
// the first character is not the beginning of the BOM; unget it to
7897
// process is later
7898
unget();
7899
return true;
7900
}
7901
7902
void skip_whitespace()
7903
{
7904
do
7905
{
7906
get();
7907
}
7908
while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
7909
}
7910
7911
token_type scan()
7912
{
7913
// initially, skip the BOM
7914
if (position.chars_read_total == 0 && !skip_bom())
7915
{
7916
error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
7917
return token_type::parse_error;
7918
}
7919
7920
// read next character and ignore whitespace
7921
skip_whitespace();
7922
7923
// ignore comments
7924
while (ignore_comments && current == '/')
7925
{
7926
if (!scan_comment())
7927
{
7928
return token_type::parse_error;
7929
}
7930
7931
// skip following whitespace
7932
skip_whitespace();
7933
}
7934
7935
switch (current)
7936
{
7937
// structural characters
7938
case '[':
7939
return token_type::begin_array;
7940
case ']':
7941
return token_type::end_array;
7942
case '{':
7943
return token_type::begin_object;
7944
case '}':
7945
return token_type::end_object;
7946
case ':':
7947
return token_type::name_separator;
7948
case ',':
7949
return token_type::value_separator;
7950
7951
// literals
7952
case 't':
7953
{
7954
std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}};
7955
return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
7956
}
7957
case 'f':
7958
{
7959
std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}};
7960
return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
7961
}
7962
case 'n':
7963
{
7964
std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}};
7965
return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
7966
}
7967
7968
// string
7969
case '\"':
7970
return scan_string();
7971
7972
// number
7973
case '-':
7974
case '0':
7975
case '1':
7976
case '2':
7977
case '3':
7978
case '4':
7979
case '5':
7980
case '6':
7981
case '7':
7982
case '8':
7983
case '9':
7984
return scan_number();
7985
7986
// end of input (the null byte is needed when parsing from
7987
// string literals)
7988
case '\0':
7989
case std::char_traits<char_type>::eof():
7990
return token_type::end_of_input;
7991
7992
// error
7993
default:
7994
error_message = "invalid literal";
7995
return token_type::parse_error;
7996
}
7997
}
7998
7999
private:
8000
/// input adapter
8001
InputAdapterType ia;
8002
8003
/// whether comments should be ignored (true) or signaled as errors (false)
8004
const bool ignore_comments = false;
8005
8006
/// the current character
8007
char_int_type current = std::char_traits<char_type>::eof();
8008
8009
/// whether the next get() call should just return current
8010
bool next_unget = false;
8011
8012
/// the start position of the current token
8013
position_t position {};
8014
8015
/// raw input token string (for error messages)
8016
std::vector<char_type> token_string {};
8017
8018
/// buffer for variable-length tokens (numbers, strings)
8019
string_t token_buffer {};
8020
8021
/// a description of occurred lexer errors
8022
const char* error_message = "";
8023
8024
// number values
8025
number_integer_t value_integer = 0;
8026
number_unsigned_t value_unsigned = 0;
8027
number_float_t value_float = 0;
8028
8029
/// the decimal point
8030
const char_int_type decimal_point_char = '.';
8031
};
8032
} // namespace detail
8033
} // namespace nlohmann
8034
8035
// #include <nlohmann/detail/macro_scope.hpp>
8036
8037
// #include <nlohmann/detail/meta/is_sax.hpp>
8038
8039
8040
#include <cstdint> // size_t
8041
#include <utility> // declval
8042
#include <string> // string
8043
8044
// #include <nlohmann/detail/meta/detected.hpp>
8045
8046
// #include <nlohmann/detail/meta/type_traits.hpp>
8047
8048
8049
namespace nlohmann
8050
{
8051
namespace detail
8052
{
8053
template<typename T>
8054
using null_function_t = decltype(std::declval<T&>().null());
8055
8056
template<typename T>
8057
using boolean_function_t =
8058
decltype(std::declval<T&>().boolean(std::declval<bool>()));
8059
8060
template<typename T, typename Integer>
8061
using number_integer_function_t =
8062
decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
8063
8064
template<typename T, typename Unsigned>
8065
using number_unsigned_function_t =
8066
decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
8067
8068
template<typename T, typename Float, typename String>
8069
using number_float_function_t = decltype(std::declval<T&>().number_float(
8070
std::declval<Float>(), std::declval<const String&>()));
8071
8072
template<typename T, typename String>
8073
using string_function_t =
8074
decltype(std::declval<T&>().string(std::declval<String&>()));
8075
8076
template<typename T, typename Binary>
8077
using binary_function_t =
8078
decltype(std::declval<T&>().binary(std::declval<Binary&>()));
8079
8080
template<typename T>
8081
using start_object_function_t =
8082
decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
8083
8084
template<typename T, typename String>
8085
using key_function_t =
8086
decltype(std::declval<T&>().key(std::declval<String&>()));
8087
8088
template<typename T>
8089
using end_object_function_t = decltype(std::declval<T&>().end_object());
8090
8091
template<typename T>
8092
using start_array_function_t =
8093
decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
8094
8095
template<typename T>
8096
using end_array_function_t = decltype(std::declval<T&>().end_array());
8097
8098
template<typename T, typename Exception>
8099
using parse_error_function_t = decltype(std::declval<T&>().parse_error(
8100
std::declval<std::size_t>(), std::declval<const std::string&>(),
8101
std::declval<const Exception&>()));
8102
8103
template<typename SAX, typename BasicJsonType>
8104
struct is_sax
8105
{
8106
private:
8107
static_assert(is_basic_json<BasicJsonType>::value,
8108
"BasicJsonType must be of type basic_json<...>");
8109
8110
using number_integer_t = typename BasicJsonType::number_integer_t;
8111
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8112
using number_float_t = typename BasicJsonType::number_float_t;
8113
using string_t = typename BasicJsonType::string_t;
8114
using binary_t = typename BasicJsonType::binary_t;
8115
using exception_t = typename BasicJsonType::exception;
8116
8117
public:
8118
static constexpr bool value =
8119
is_detected_exact<bool, null_function_t, SAX>::value &&
8120
is_detected_exact<bool, boolean_function_t, SAX>::value &&
8121
is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
8122
is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
8123
is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
8124
is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
8125
is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
8126
is_detected_exact<bool, start_object_function_t, SAX>::value &&
8127
is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
8128
is_detected_exact<bool, end_object_function_t, SAX>::value &&
8129
is_detected_exact<bool, start_array_function_t, SAX>::value &&
8130
is_detected_exact<bool, end_array_function_t, SAX>::value &&
8131
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
8132
};
8133
8134
template<typename SAX, typename BasicJsonType>
8135
struct is_sax_static_asserts
8136
{
8137
private:
8138
static_assert(is_basic_json<BasicJsonType>::value,
8139
"BasicJsonType must be of type basic_json<...>");
8140
8141
using number_integer_t = typename BasicJsonType::number_integer_t;
8142
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8143
using number_float_t = typename BasicJsonType::number_float_t;
8144
using string_t = typename BasicJsonType::string_t;
8145
using binary_t = typename BasicJsonType::binary_t;
8146
using exception_t = typename BasicJsonType::exception;
8147
8148
public:
8149
static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
8150
"Missing/invalid function: bool null()");
8151
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
8152
"Missing/invalid function: bool boolean(bool)");
8153
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
8154
"Missing/invalid function: bool boolean(bool)");
8155
static_assert(
8156
is_detected_exact<bool, number_integer_function_t, SAX,
8157
number_integer_t>::value,
8158
"Missing/invalid function: bool number_integer(number_integer_t)");
8159
static_assert(
8160
is_detected_exact<bool, number_unsigned_function_t, SAX,
8161
number_unsigned_t>::value,
8162
"Missing/invalid function: bool number_unsigned(number_unsigned_t)");
8163
static_assert(is_detected_exact<bool, number_float_function_t, SAX,
8164
number_float_t, string_t>::value,
8165
"Missing/invalid function: bool number_float(number_float_t, const string_t&)");
8166
static_assert(
8167
is_detected_exact<bool, string_function_t, SAX, string_t>::value,
8168
"Missing/invalid function: bool string(string_t&)");
8169
static_assert(
8170
is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
8171
"Missing/invalid function: bool binary(binary_t&)");
8172
static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
8173
"Missing/invalid function: bool start_object(std::size_t)");
8174
static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
8175
"Missing/invalid function: bool key(string_t&)");
8176
static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
8177
"Missing/invalid function: bool end_object()");
8178
static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
8179
"Missing/invalid function: bool start_array(std::size_t)");
8180
static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
8181
"Missing/invalid function: bool end_array()");
8182
static_assert(
8183
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
8184
"Missing/invalid function: bool parse_error(std::size_t, const "
8185
"std::string&, const exception&)");
8186
};
8187
} // namespace detail
8188
} // namespace nlohmann
8189
8190
// #include <nlohmann/detail/meta/type_traits.hpp>
8191
8192
// #include <nlohmann/detail/value_t.hpp>
8193
8194
8195
namespace nlohmann
8196
{
8197
namespace detail
8198
{
8199
8200
/// how to treat CBOR tags
8201
enum class cbor_tag_handler_t
8202
{
8203
error, ///< throw a parse_error exception in case of a tag
8204
ignore, ///< ignore tags
8205
store ///< store tags as binary type
8206
};
8207
8208
/*!
8209
@brief determine system byte order
8210
8211
@return true if and only if system's byte order is little endian
8212
8213
@note from https://stackoverflow.com/a/1001328/266378
8214
*/
8215
static inline bool little_endianness(int num = 1) noexcept
8216
{
8217
return *reinterpret_cast<char*>(&num) == 1;
8218
}
8219
8220
8221
///////////////////
8222
// binary reader //
8223
///////////////////
8224
8225
/*!
8226
@brief deserialization of CBOR, MessagePack, and UBJSON values
8227
*/
8228
template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
8229
class binary_reader
8230
{
8231
using number_integer_t = typename BasicJsonType::number_integer_t;
8232
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8233
using number_float_t = typename BasicJsonType::number_float_t;
8234
using string_t = typename BasicJsonType::string_t;
8235
using binary_t = typename BasicJsonType::binary_t;
8236
using json_sax_t = SAX;
8237
using char_type = typename InputAdapterType::char_type;
8238
using char_int_type = typename std::char_traits<char_type>::int_type;
8239
8240
public:
8241
/*!
8242
@brief create a binary reader
8243
8244
@param[in] adapter input adapter to read from
8245
*/
8246
explicit binary_reader(InputAdapterType&& adapter) noexcept : ia(std::move(adapter))
8247
{
8248
(void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
8249
}
8250
8251
// make class move-only
8252
binary_reader(const binary_reader&) = delete;
8253
binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8254
binary_reader& operator=(const binary_reader&) = delete;
8255
binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8256
~binary_reader() = default;
8257
8258
/*!
8259
@param[in] format the binary format to parse
8260
@param[in] sax_ a SAX event processor
8261
@param[in] strict whether to expect the input to be consumed completed
8262
@param[in] tag_handler how to treat CBOR tags
8263
8264
@return whether parsing was successful
8265
*/
8266
JSON_HEDLEY_NON_NULL(3)
8267
bool sax_parse(const input_format_t format,
8268
json_sax_t* sax_,
8269
const bool strict = true,
8270
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
8271
{
8272
sax = sax_;
8273
bool result = false;
8274
8275
switch (format)
8276
{
8277
case input_format_t::bson:
8278
result = parse_bson_internal();
8279
break;
8280
8281
case input_format_t::cbor:
8282
result = parse_cbor_internal(true, tag_handler);
8283
break;
8284
8285
case input_format_t::msgpack:
8286
result = parse_msgpack_internal();
8287
break;
8288
8289
case input_format_t::ubjson:
8290
result = parse_ubjson_internal();
8291
break;
8292
8293
case input_format_t::json: // LCOV_EXCL_LINE
8294
default: // LCOV_EXCL_LINE
8295
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8296
}
8297
8298
// strict mode: next byte must be EOF
8299
if (result && strict)
8300
{
8301
if (format == input_format_t::ubjson)
8302
{
8303
get_ignore_noop();
8304
}
8305
else
8306
{
8307
get();
8308
}
8309
8310
if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
8311
{
8312
return sax->parse_error(chars_read, get_token_string(),
8313
parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"), BasicJsonType()));
8314
}
8315
}
8316
8317
return result;
8318
}
8319
8320
private:
8321
//////////
8322
// BSON //
8323
//////////
8324
8325
/*!
8326
@brief Reads in a BSON-object and passes it to the SAX-parser.
8327
@return whether a valid BSON-value was passed to the SAX parser
8328
*/
8329
bool parse_bson_internal()
8330
{
8331
std::int32_t document_size{};
8332
get_number<std::int32_t, true>(input_format_t::bson, document_size);
8333
8334
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
8335
{
8336
return false;
8337
}
8338
8339
if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
8340
{
8341
return false;
8342
}
8343
8344
return sax->end_object();
8345
}
8346
8347
/*!
8348
@brief Parses a C-style string from the BSON input.
8349
@param[in,out] result A reference to the string variable where the read
8350
string is to be stored.
8351
@return `true` if the \x00-byte indicating the end of the string was
8352
encountered before the EOF; false` indicates an unexpected EOF.
8353
*/
8354
bool get_bson_cstr(string_t& result)
8355
{
8356
auto out = std::back_inserter(result);
8357
while (true)
8358
{
8359
get();
8360
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
8361
{
8362
return false;
8363
}
8364
if (current == 0x00)
8365
{
8366
return true;
8367
}
8368
*out++ = static_cast<typename string_t::value_type>(current);
8369
}
8370
}
8371
8372
/*!
8373
@brief Parses a zero-terminated string of length @a len from the BSON
8374
input.
8375
@param[in] len The length (including the zero-byte at the end) of the
8376
string to be read.
8377
@param[in,out] result A reference to the string variable where the read
8378
string is to be stored.
8379
@tparam NumberType The type of the length @a len
8380
@pre len >= 1
8381
@return `true` if the string was successfully parsed
8382
*/
8383
template<typename NumberType>
8384
bool get_bson_string(const NumberType len, string_t& result)
8385
{
8386
if (JSON_HEDLEY_UNLIKELY(len < 1))
8387
{
8388
auto last_token = get_token_string();
8389
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"), BasicJsonType()));
8390
}
8391
8392
return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
8393
}
8394
8395
/*!
8396
@brief Parses a byte array input of length @a len from the BSON input.
8397
@param[in] len The length of the byte array to be read.
8398
@param[in,out] result A reference to the binary variable where the read
8399
array is to be stored.
8400
@tparam NumberType The type of the length @a len
8401
@pre len >= 0
8402
@return `true` if the byte array was successfully parsed
8403
*/
8404
template<typename NumberType>
8405
bool get_bson_binary(const NumberType len, binary_t& result)
8406
{
8407
if (JSON_HEDLEY_UNLIKELY(len < 0))
8408
{
8409
auto last_token = get_token_string();
8410
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"), BasicJsonType()));
8411
}
8412
8413
// All BSON binary values have a subtype
8414
std::uint8_t subtype{};
8415
get_number<std::uint8_t>(input_format_t::bson, subtype);
8416
result.set_subtype(subtype);
8417
8418
return get_binary(input_format_t::bson, len, result);
8419
}
8420
8421
/*!
8422
@brief Read a BSON document element of the given @a element_type.
8423
@param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
8424
@param[in] element_type_parse_position The position in the input stream,
8425
where the `element_type` was read.
8426
@warning Not all BSON element types are supported yet. An unsupported
8427
@a element_type will give rise to a parse_error.114:
8428
Unsupported BSON record type 0x...
8429
@return whether a valid BSON-object/array was passed to the SAX parser
8430
*/
8431
bool parse_bson_element_internal(const char_int_type element_type,
8432
const std::size_t element_type_parse_position)
8433
{
8434
switch (element_type)
8435
{
8436
case 0x01: // double
8437
{
8438
double number{};
8439
return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
8440
}
8441
8442
case 0x02: // string
8443
{
8444
std::int32_t len{};
8445
string_t value;
8446
return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
8447
}
8448
8449
case 0x03: // object
8450
{
8451
return parse_bson_internal();
8452
}
8453
8454
case 0x04: // array
8455
{
8456
return parse_bson_array();
8457
}
8458
8459
case 0x05: // binary
8460
{
8461
std::int32_t len{};
8462
binary_t value;
8463
return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
8464
}
8465
8466
case 0x08: // boolean
8467
{
8468
return sax->boolean(get() != 0);
8469
}
8470
8471
case 0x0A: // null
8472
{
8473
return sax->null();
8474
}
8475
8476
case 0x10: // int32
8477
{
8478
std::int32_t value{};
8479
return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
8480
}
8481
8482
case 0x12: // int64
8483
{
8484
std::int64_t value{};
8485
return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
8486
}
8487
8488
default: // anything else not supported (yet)
8489
{
8490
std::array<char, 3> cr{{}};
8491
static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8492
return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()), BasicJsonType()));
8493
}
8494
}
8495
}
8496
8497
/*!
8498
@brief Read a BSON element list (as specified in the BSON-spec)
8499
8500
The same binary layout is used for objects and arrays, hence it must be
8501
indicated with the argument @a is_array which one is expected
8502
(true --> array, false --> object).
8503
8504
@param[in] is_array Determines if the element list being read is to be
8505
treated as an object (@a is_array == false), or as an
8506
array (@a is_array == true).
8507
@return whether a valid BSON-object/array was passed to the SAX parser
8508
*/
8509
bool parse_bson_element_list(const bool is_array)
8510
{
8511
string_t key;
8512
8513
while (auto element_type = get())
8514
{
8515
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
8516
{
8517
return false;
8518
}
8519
8520
const std::size_t element_type_parse_position = chars_read;
8521
if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
8522
{
8523
return false;
8524
}
8525
8526
if (!is_array && !sax->key(key))
8527
{
8528
return false;
8529
}
8530
8531
if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
8532
{
8533
return false;
8534
}
8535
8536
// get_bson_cstr only appends
8537
key.clear();
8538
}
8539
8540
return true;
8541
}
8542
8543
/*!
8544
@brief Reads an array from the BSON input and passes it to the SAX-parser.
8545
@return whether a valid BSON-array was passed to the SAX parser
8546
*/
8547
bool parse_bson_array()
8548
{
8549
std::int32_t document_size{};
8550
get_number<std::int32_t, true>(input_format_t::bson, document_size);
8551
8552
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
8553
{
8554
return false;
8555
}
8556
8557
if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
8558
{
8559
return false;
8560
}
8561
8562
return sax->end_array();
8563
}
8564
8565
//////////
8566
// CBOR //
8567
//////////
8568
8569
/*!
8570
@param[in] get_char whether a new character should be retrieved from the
8571
input (true) or whether the last read character should
8572
be considered instead (false)
8573
@param[in] tag_handler how CBOR tags should be treated
8574
8575
@return whether a valid CBOR value was passed to the SAX parser
8576
*/
8577
bool parse_cbor_internal(const bool get_char,
8578
const cbor_tag_handler_t tag_handler)
8579
{
8580
switch (get_char ? get() : current)
8581
{
8582
// EOF
8583
case std::char_traits<char_type>::eof():
8584
return unexpect_eof(input_format_t::cbor, "value");
8585
8586
// Integer 0x00..0x17 (0..23)
8587
case 0x00:
8588
case 0x01:
8589
case 0x02:
8590
case 0x03:
8591
case 0x04:
8592
case 0x05:
8593
case 0x06:
8594
case 0x07:
8595
case 0x08:
8596
case 0x09:
8597
case 0x0A:
8598
case 0x0B:
8599
case 0x0C:
8600
case 0x0D:
8601
case 0x0E:
8602
case 0x0F:
8603
case 0x10:
8604
case 0x11:
8605
case 0x12:
8606
case 0x13:
8607
case 0x14:
8608
case 0x15:
8609
case 0x16:
8610
case 0x17:
8611
return sax->number_unsigned(static_cast<number_unsigned_t>(current));
8612
8613
case 0x18: // Unsigned integer (one-byte uint8_t follows)
8614
{
8615
std::uint8_t number{};
8616
return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8617
}
8618
8619
case 0x19: // Unsigned integer (two-byte uint16_t follows)
8620
{
8621
std::uint16_t number{};
8622
return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8623
}
8624
8625
case 0x1A: // Unsigned integer (four-byte uint32_t follows)
8626
{
8627
std::uint32_t number{};
8628
return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8629
}
8630
8631
case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
8632
{
8633
std::uint64_t number{};
8634
return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8635
}
8636
8637
// Negative integer -1-0x00..-1-0x17 (-1..-24)
8638
case 0x20:
8639
case 0x21:
8640
case 0x22:
8641
case 0x23:
8642
case 0x24:
8643
case 0x25:
8644
case 0x26:
8645
case 0x27:
8646
case 0x28:
8647
case 0x29:
8648
case 0x2A:
8649
case 0x2B:
8650
case 0x2C:
8651
case 0x2D:
8652
case 0x2E:
8653
case 0x2F:
8654
case 0x30:
8655
case 0x31:
8656
case 0x32:
8657
case 0x33:
8658
case 0x34:
8659
case 0x35:
8660
case 0x36:
8661
case 0x37:
8662
return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
8663
8664
case 0x38: // Negative integer (one-byte uint8_t follows)
8665
{
8666
std::uint8_t number{};
8667
return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8668
}
8669
8670
case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
8671
{
8672
std::uint16_t number{};
8673
return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8674
}
8675
8676
case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
8677
{
8678
std::uint32_t number{};
8679
return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8680
}
8681
8682
case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
8683
{
8684
std::uint64_t number{};
8685
return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
8686
- static_cast<number_integer_t>(number));
8687
}
8688
8689
// Binary data (0x00..0x17 bytes follow)
8690
case 0x40:
8691
case 0x41:
8692
case 0x42:
8693
case 0x43:
8694
case 0x44:
8695
case 0x45:
8696
case 0x46:
8697
case 0x47:
8698
case 0x48:
8699
case 0x49:
8700
case 0x4A:
8701
case 0x4B:
8702
case 0x4C:
8703
case 0x4D:
8704
case 0x4E:
8705
case 0x4F:
8706
case 0x50:
8707
case 0x51:
8708
case 0x52:
8709
case 0x53:
8710
case 0x54:
8711
case 0x55:
8712
case 0x56:
8713
case 0x57:
8714
case 0x58: // Binary data (one-byte uint8_t for n follows)
8715
case 0x59: // Binary data (two-byte uint16_t for n follow)
8716
case 0x5A: // Binary data (four-byte uint32_t for n follow)
8717
case 0x5B: // Binary data (eight-byte uint64_t for n follow)
8718
case 0x5F: // Binary data (indefinite length)
8719
{
8720
binary_t b;
8721
return get_cbor_binary(b) && sax->binary(b);
8722
}
8723
8724
// UTF-8 string (0x00..0x17 bytes follow)
8725
case 0x60:
8726
case 0x61:
8727
case 0x62:
8728
case 0x63:
8729
case 0x64:
8730
case 0x65:
8731
case 0x66:
8732
case 0x67:
8733
case 0x68:
8734
case 0x69:
8735
case 0x6A:
8736
case 0x6B:
8737
case 0x6C:
8738
case 0x6D:
8739
case 0x6E:
8740
case 0x6F:
8741
case 0x70:
8742
case 0x71:
8743
case 0x72:
8744
case 0x73:
8745
case 0x74:
8746
case 0x75:
8747
case 0x76:
8748
case 0x77:
8749
case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
8750
case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
8751
case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
8752
case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
8753
case 0x7F: // UTF-8 string (indefinite length)
8754
{
8755
string_t s;
8756
return get_cbor_string(s) && sax->string(s);
8757
}
8758
8759
// array (0x00..0x17 data items follow)
8760
case 0x80:
8761
case 0x81:
8762
case 0x82:
8763
case 0x83:
8764
case 0x84:
8765
case 0x85:
8766
case 0x86:
8767
case 0x87:
8768
case 0x88:
8769
case 0x89:
8770
case 0x8A:
8771
case 0x8B:
8772
case 0x8C:
8773
case 0x8D:
8774
case 0x8E:
8775
case 0x8F:
8776
case 0x90:
8777
case 0x91:
8778
case 0x92:
8779
case 0x93:
8780
case 0x94:
8781
case 0x95:
8782
case 0x96:
8783
case 0x97:
8784
return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
8785
8786
case 0x98: // array (one-byte uint8_t for n follows)
8787
{
8788
std::uint8_t len{};
8789
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8790
}
8791
8792
case 0x99: // array (two-byte uint16_t for n follow)
8793
{
8794
std::uint16_t len{};
8795
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8796
}
8797
8798
case 0x9A: // array (four-byte uint32_t for n follow)
8799
{
8800
std::uint32_t len{};
8801
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8802
}
8803
8804
case 0x9B: // array (eight-byte uint64_t for n follow)
8805
{
8806
std::uint64_t len{};
8807
return get_number(input_format_t::cbor, len) && get_cbor_array(detail::conditional_static_cast<std::size_t>(len), tag_handler);
8808
}
8809
8810
case 0x9F: // array (indefinite length)
8811
return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
8812
8813
// map (0x00..0x17 pairs of data items follow)
8814
case 0xA0:
8815
case 0xA1:
8816
case 0xA2:
8817
case 0xA3:
8818
case 0xA4:
8819
case 0xA5:
8820
case 0xA6:
8821
case 0xA7:
8822
case 0xA8:
8823
case 0xA9:
8824
case 0xAA:
8825
case 0xAB:
8826
case 0xAC:
8827
case 0xAD:
8828
case 0xAE:
8829
case 0xAF:
8830
case 0xB0:
8831
case 0xB1:
8832
case 0xB2:
8833
case 0xB3:
8834
case 0xB4:
8835
case 0xB5:
8836
case 0xB6:
8837
case 0xB7:
8838
return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
8839
8840
case 0xB8: // map (one-byte uint8_t for n follows)
8841
{
8842
std::uint8_t len{};
8843
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8844
}
8845
8846
case 0xB9: // map (two-byte uint16_t for n follow)
8847
{
8848
std::uint16_t len{};
8849
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8850
}
8851
8852
case 0xBA: // map (four-byte uint32_t for n follow)
8853
{
8854
std::uint32_t len{};
8855
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8856
}
8857
8858
case 0xBB: // map (eight-byte uint64_t for n follow)
8859
{
8860
std::uint64_t len{};
8861
return get_number(input_format_t::cbor, len) && get_cbor_object(detail::conditional_static_cast<std::size_t>(len), tag_handler);
8862
}
8863
8864
case 0xBF: // map (indefinite length)
8865
return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
8866
8867
case 0xC6: // tagged item
8868
case 0xC7:
8869
case 0xC8:
8870
case 0xC9:
8871
case 0xCA:
8872
case 0xCB:
8873
case 0xCC:
8874
case 0xCD:
8875
case 0xCE:
8876
case 0xCF:
8877
case 0xD0:
8878
case 0xD1:
8879
case 0xD2:
8880
case 0xD3:
8881
case 0xD4:
8882
case 0xD8: // tagged item (1 bytes follow)
8883
case 0xD9: // tagged item (2 bytes follow)
8884
case 0xDA: // tagged item (4 bytes follow)
8885
case 0xDB: // tagged item (8 bytes follow)
8886
{
8887
switch (tag_handler)
8888
{
8889
case cbor_tag_handler_t::error:
8890
{
8891
auto last_token = get_token_string();
8892
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
8893
}
8894
8895
case cbor_tag_handler_t::ignore:
8896
{
8897
// ignore binary subtype
8898
switch (current)
8899
{
8900
case 0xD8:
8901
{
8902
std::uint8_t subtype_to_ignore{};
8903
get_number(input_format_t::cbor, subtype_to_ignore);
8904
break;
8905
}
8906
case 0xD9:
8907
{
8908
std::uint16_t subtype_to_ignore{};
8909
get_number(input_format_t::cbor, subtype_to_ignore);
8910
break;
8911
}
8912
case 0xDA:
8913
{
8914
std::uint32_t subtype_to_ignore{};
8915
get_number(input_format_t::cbor, subtype_to_ignore);
8916
break;
8917
}
8918
case 0xDB:
8919
{
8920
std::uint64_t subtype_to_ignore{};
8921
get_number(input_format_t::cbor, subtype_to_ignore);
8922
break;
8923
}
8924
default:
8925
break;
8926
}
8927
return parse_cbor_internal(true, tag_handler);
8928
}
8929
8930
case cbor_tag_handler_t::store:
8931
{
8932
binary_t b;
8933
// use binary subtype and store in binary container
8934
switch (current)
8935
{
8936
case 0xD8:
8937
{
8938
std::uint8_t subtype{};
8939
get_number(input_format_t::cbor, subtype);
8940
b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
8941
break;
8942
}
8943
case 0xD9:
8944
{
8945
std::uint16_t subtype{};
8946
get_number(input_format_t::cbor, subtype);
8947
b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
8948
break;
8949
}
8950
case 0xDA:
8951
{
8952
std::uint32_t subtype{};
8953
get_number(input_format_t::cbor, subtype);
8954
b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
8955
break;
8956
}
8957
case 0xDB:
8958
{
8959
std::uint64_t subtype{};
8960
get_number(input_format_t::cbor, subtype);
8961
b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
8962
break;
8963
}
8964
default:
8965
return parse_cbor_internal(true, tag_handler);
8966
}
8967
get();
8968
return get_cbor_binary(b) && sax->binary(b);
8969
}
8970
8971
default: // LCOV_EXCL_LINE
8972
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8973
return false; // LCOV_EXCL_LINE
8974
}
8975
}
8976
8977
case 0xF4: // false
8978
return sax->boolean(false);
8979
8980
case 0xF5: // true
8981
return sax->boolean(true);
8982
8983
case 0xF6: // null
8984
return sax->null();
8985
8986
case 0xF9: // Half-Precision Float (two-byte IEEE 754)
8987
{
8988
const auto byte1_raw = get();
8989
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
8990
{
8991
return false;
8992
}
8993
const auto byte2_raw = get();
8994
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
8995
{
8996
return false;
8997
}
8998
8999
const auto byte1 = static_cast<unsigned char>(byte1_raw);
9000
const auto byte2 = static_cast<unsigned char>(byte2_raw);
9001
9002
// code from RFC 7049, Appendix D, Figure 3:
9003
// As half-precision floating-point numbers were only added
9004
// to IEEE 754 in 2008, today's programming platforms often
9005
// still only have limited support for them. It is very
9006
// easy to include at least decoding support for them even
9007
// without such support. An example of a small decoder for
9008
// half-precision floating-point numbers in the C language
9009
// is shown in Fig. 3.
9010
const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
9011
const double val = [&half]
9012
{
9013
const int exp = (half >> 10u) & 0x1Fu;
9014
const unsigned int mant = half & 0x3FFu;
9015
JSON_ASSERT(0 <= exp&& exp <= 32);
9016
JSON_ASSERT(mant <= 1024);
9017
switch (exp)
9018
{
9019
case 0:
9020
return std::ldexp(mant, -24);
9021
case 31:
9022
return (mant == 0)
9023
? std::numeric_limits<double>::infinity()
9024
: std::numeric_limits<double>::quiet_NaN();
9025
default:
9026
return std::ldexp(mant + 1024, exp - 25);
9027
}
9028
}();
9029
return sax->number_float((half & 0x8000u) != 0
9030
? static_cast<number_float_t>(-val)
9031
: static_cast<number_float_t>(val), "");
9032
}
9033
9034
case 0xFA: // Single-Precision Float (four-byte IEEE 754)
9035
{
9036
float number{};
9037
return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9038
}
9039
9040
case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
9041
{
9042
double number{};
9043
return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9044
}
9045
9046
default: // anything else (0xFF is handled inside the other types)
9047
{
9048
auto last_token = get_token_string();
9049
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
9050
}
9051
}
9052
}
9053
9054
/*!
9055
@brief reads a CBOR string
9056
9057
This function first reads starting bytes to determine the expected
9058
string length and then copies this number of bytes into a string.
9059
Additionally, CBOR's strings with indefinite lengths are supported.
9060
9061
@param[out] result created string
9062
9063
@return whether string creation completed
9064
*/
9065
bool get_cbor_string(string_t& result)
9066
{
9067
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
9068
{
9069
return false;
9070
}
9071
9072
switch (current)
9073
{
9074
// UTF-8 string (0x00..0x17 bytes follow)
9075
case 0x60:
9076
case 0x61:
9077
case 0x62:
9078
case 0x63:
9079
case 0x64:
9080
case 0x65:
9081
case 0x66:
9082
case 0x67:
9083
case 0x68:
9084
case 0x69:
9085
case 0x6A:
9086
case 0x6B:
9087
case 0x6C:
9088
case 0x6D:
9089
case 0x6E:
9090
case 0x6F:
9091
case 0x70:
9092
case 0x71:
9093
case 0x72:
9094
case 0x73:
9095
case 0x74:
9096
case 0x75:
9097
case 0x76:
9098
case 0x77:
9099
{
9100
return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
9101
}
9102
9103
case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9104
{
9105
std::uint8_t len{};
9106
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9107
}
9108
9109
case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9110
{
9111
std::uint16_t len{};
9112
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9113
}
9114
9115
case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9116
{
9117
std::uint32_t len{};
9118
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9119
}
9120
9121
case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9122
{
9123
std::uint64_t len{};
9124
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9125
}
9126
9127
case 0x7F: // UTF-8 string (indefinite length)
9128
{
9129
while (get() != 0xFF)
9130
{
9131
string_t chunk;
9132
if (!get_cbor_string(chunk))
9133
{
9134
return false;
9135
}
9136
result.append(chunk);
9137
}
9138
return true;
9139
}
9140
9141
default:
9142
{
9143
auto last_token = get_token_string();
9144
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"), BasicJsonType()));
9145
}
9146
}
9147
}
9148
9149
/*!
9150
@brief reads a CBOR byte array
9151
9152
This function first reads starting bytes to determine the expected
9153
byte array length and then copies this number of bytes into the byte array.
9154
Additionally, CBOR's byte arrays with indefinite lengths are supported.
9155
9156
@param[out] result created byte array
9157
9158
@return whether byte array creation completed
9159
*/
9160
bool get_cbor_binary(binary_t& result)
9161
{
9162
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
9163
{
9164
return false;
9165
}
9166
9167
switch (current)
9168
{
9169
// Binary data (0x00..0x17 bytes follow)
9170
case 0x40:
9171
case 0x41:
9172
case 0x42:
9173
case 0x43:
9174
case 0x44:
9175
case 0x45:
9176
case 0x46:
9177
case 0x47:
9178
case 0x48:
9179
case 0x49:
9180
case 0x4A:
9181
case 0x4B:
9182
case 0x4C:
9183
case 0x4D:
9184
case 0x4E:
9185
case 0x4F:
9186
case 0x50:
9187
case 0x51:
9188
case 0x52:
9189
case 0x53:
9190
case 0x54:
9191
case 0x55:
9192
case 0x56:
9193
case 0x57:
9194
{
9195
return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
9196
}
9197
9198
case 0x58: // Binary data (one-byte uint8_t for n follows)
9199
{
9200
std::uint8_t len{};
9201
return get_number(input_format_t::cbor, len) &&
9202
get_binary(input_format_t::cbor, len, result);
9203
}
9204
9205
case 0x59: // Binary data (two-byte uint16_t for n follow)
9206
{
9207
std::uint16_t len{};
9208
return get_number(input_format_t::cbor, len) &&
9209
get_binary(input_format_t::cbor, len, result);
9210
}
9211
9212
case 0x5A: // Binary data (four-byte uint32_t for n follow)
9213
{
9214
std::uint32_t len{};
9215
return get_number(input_format_t::cbor, len) &&
9216
get_binary(input_format_t::cbor, len, result);
9217
}
9218
9219
case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9220
{
9221
std::uint64_t len{};
9222
return get_number(input_format_t::cbor, len) &&
9223
get_binary(input_format_t::cbor, len, result);
9224
}
9225
9226
case 0x5F: // Binary data (indefinite length)
9227
{
9228
while (get() != 0xFF)
9229
{
9230
binary_t chunk;
9231
if (!get_cbor_binary(chunk))
9232
{
9233
return false;
9234
}
9235
result.insert(result.end(), chunk.begin(), chunk.end());
9236
}
9237
return true;
9238
}
9239
9240
default:
9241
{
9242
auto last_token = get_token_string();
9243
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"), BasicJsonType()));
9244
}
9245
}
9246
}
9247
9248
/*!
9249
@param[in] len the length of the array or static_cast<std::size_t>(-1) for an
9250
array of indefinite size
9251
@param[in] tag_handler how CBOR tags should be treated
9252
@return whether array creation completed
9253
*/
9254
bool get_cbor_array(const std::size_t len,
9255
const cbor_tag_handler_t tag_handler)
9256
{
9257
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
9258
{
9259
return false;
9260
}
9261
9262
if (len != static_cast<std::size_t>(-1))
9263
{
9264
for (std::size_t i = 0; i < len; ++i)
9265
{
9266
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
9267
{
9268
return false;
9269
}
9270
}
9271
}
9272
else
9273
{
9274
while (get() != 0xFF)
9275
{
9276
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
9277
{
9278
return false;
9279
}
9280
}
9281
}
9282
9283
return sax->end_array();
9284
}
9285
9286
/*!
9287
@param[in] len the length of the object or static_cast<std::size_t>(-1) for an
9288
object of indefinite size
9289
@param[in] tag_handler how CBOR tags should be treated
9290
@return whether object creation completed
9291
*/
9292
bool get_cbor_object(const std::size_t len,
9293
const cbor_tag_handler_t tag_handler)
9294
{
9295
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
9296
{
9297
return false;
9298
}
9299
9300
if (len != 0)
9301
{
9302
string_t key;
9303
if (len != static_cast<std::size_t>(-1))
9304
{
9305
for (std::size_t i = 0; i < len; ++i)
9306
{
9307
get();
9308
if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
9309
{
9310
return false;
9311
}
9312
9313
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
9314
{
9315
return false;
9316
}
9317
key.clear();
9318
}
9319
}
9320
else
9321
{
9322
while (get() != 0xFF)
9323
{
9324
if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
9325
{
9326
return false;
9327
}
9328
9329
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
9330
{
9331
return false;
9332
}
9333
key.clear();
9334
}
9335
}
9336
}
9337
9338
return sax->end_object();
9339
}
9340
9341
/////////////
9342
// MsgPack //
9343
/////////////
9344
9345
/*!
9346
@return whether a valid MessagePack value was passed to the SAX parser
9347
*/
9348
bool parse_msgpack_internal()
9349
{
9350
switch (get())
9351
{
9352
// EOF
9353
case std::char_traits<char_type>::eof():
9354
return unexpect_eof(input_format_t::msgpack, "value");
9355
9356
// positive fixint
9357
case 0x00:
9358
case 0x01:
9359
case 0x02:
9360
case 0x03:
9361
case 0x04:
9362
case 0x05:
9363
case 0x06:
9364
case 0x07:
9365
case 0x08:
9366
case 0x09:
9367
case 0x0A:
9368
case 0x0B:
9369
case 0x0C:
9370
case 0x0D:
9371
case 0x0E:
9372
case 0x0F:
9373
case 0x10:
9374
case 0x11:
9375
case 0x12:
9376
case 0x13:
9377
case 0x14:
9378
case 0x15:
9379
case 0x16:
9380
case 0x17:
9381
case 0x18:
9382
case 0x19:
9383
case 0x1A:
9384
case 0x1B:
9385
case 0x1C:
9386
case 0x1D:
9387
case 0x1E:
9388
case 0x1F:
9389
case 0x20:
9390
case 0x21:
9391
case 0x22:
9392
case 0x23:
9393
case 0x24:
9394
case 0x25:
9395
case 0x26:
9396
case 0x27:
9397
case 0x28:
9398
case 0x29:
9399
case 0x2A:
9400
case 0x2B:
9401
case 0x2C:
9402
case 0x2D:
9403
case 0x2E:
9404
case 0x2F:
9405
case 0x30:
9406
case 0x31:
9407
case 0x32:
9408
case 0x33:
9409
case 0x34:
9410
case 0x35:
9411
case 0x36:
9412
case 0x37:
9413
case 0x38:
9414
case 0x39:
9415
case 0x3A:
9416
case 0x3B:
9417
case 0x3C:
9418
case 0x3D:
9419
case 0x3E:
9420
case 0x3F:
9421
case 0x40:
9422
case 0x41:
9423
case 0x42:
9424
case 0x43:
9425
case 0x44:
9426
case 0x45:
9427
case 0x46:
9428
case 0x47:
9429
case 0x48:
9430
case 0x49:
9431
case 0x4A:
9432
case 0x4B:
9433
case 0x4C:
9434
case 0x4D:
9435
case 0x4E:
9436
case 0x4F:
9437
case 0x50:
9438
case 0x51:
9439
case 0x52:
9440
case 0x53:
9441
case 0x54:
9442
case 0x55:
9443
case 0x56:
9444
case 0x57:
9445
case 0x58:
9446
case 0x59:
9447
case 0x5A:
9448
case 0x5B:
9449
case 0x5C:
9450
case 0x5D:
9451
case 0x5E:
9452
case 0x5F:
9453
case 0x60:
9454
case 0x61:
9455
case 0x62:
9456
case 0x63:
9457
case 0x64:
9458
case 0x65:
9459
case 0x66:
9460
case 0x67:
9461
case 0x68:
9462
case 0x69:
9463
case 0x6A:
9464
case 0x6B:
9465
case 0x6C:
9466
case 0x6D:
9467
case 0x6E:
9468
case 0x6F:
9469
case 0x70:
9470
case 0x71:
9471
case 0x72:
9472
case 0x73:
9473
case 0x74:
9474
case 0x75:
9475
case 0x76:
9476
case 0x77:
9477
case 0x78:
9478
case 0x79:
9479
case 0x7A:
9480
case 0x7B:
9481
case 0x7C:
9482
case 0x7D:
9483
case 0x7E:
9484
case 0x7F:
9485
return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9486
9487
// fixmap
9488
case 0x80:
9489
case 0x81:
9490
case 0x82:
9491
case 0x83:
9492
case 0x84:
9493
case 0x85:
9494
case 0x86:
9495
case 0x87:
9496
case 0x88:
9497
case 0x89:
9498
case 0x8A:
9499
case 0x8B:
9500
case 0x8C:
9501
case 0x8D:
9502
case 0x8E:
9503
case 0x8F:
9504
return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
9505
9506
// fixarray
9507
case 0x90:
9508
case 0x91:
9509
case 0x92:
9510
case 0x93:
9511
case 0x94:
9512
case 0x95:
9513
case 0x96:
9514
case 0x97:
9515
case 0x98:
9516
case 0x99:
9517
case 0x9A:
9518
case 0x9B:
9519
case 0x9C:
9520
case 0x9D:
9521
case 0x9E:
9522
case 0x9F:
9523
return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
9524
9525
// fixstr
9526
case 0xA0:
9527
case 0xA1:
9528
case 0xA2:
9529
case 0xA3:
9530
case 0xA4:
9531
case 0xA5:
9532
case 0xA6:
9533
case 0xA7:
9534
case 0xA8:
9535
case 0xA9:
9536
case 0xAA:
9537
case 0xAB:
9538
case 0xAC:
9539
case 0xAD:
9540
case 0xAE:
9541
case 0xAF:
9542
case 0xB0:
9543
case 0xB1:
9544
case 0xB2:
9545
case 0xB3:
9546
case 0xB4:
9547
case 0xB5:
9548
case 0xB6:
9549
case 0xB7:
9550
case 0xB8:
9551
case 0xB9:
9552
case 0xBA:
9553
case 0xBB:
9554
case 0xBC:
9555
case 0xBD:
9556
case 0xBE:
9557
case 0xBF:
9558
case 0xD9: // str 8
9559
case 0xDA: // str 16
9560
case 0xDB: // str 32
9561
{
9562
string_t s;
9563
return get_msgpack_string(s) && sax->string(s);
9564
}
9565
9566
case 0xC0: // nil
9567
return sax->null();
9568
9569
case 0xC2: // false
9570
return sax->boolean(false);
9571
9572
case 0xC3: // true
9573
return sax->boolean(true);
9574
9575
case 0xC4: // bin 8
9576
case 0xC5: // bin 16
9577
case 0xC6: // bin 32
9578
case 0xC7: // ext 8
9579
case 0xC8: // ext 16
9580
case 0xC9: // ext 32
9581
case 0xD4: // fixext 1
9582
case 0xD5: // fixext 2
9583
case 0xD6: // fixext 4
9584
case 0xD7: // fixext 8
9585
case 0xD8: // fixext 16
9586
{
9587
binary_t b;
9588
return get_msgpack_binary(b) && sax->binary(b);
9589
}
9590
9591
case 0xCA: // float 32
9592
{
9593
float number{};
9594
return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
9595
}
9596
9597
case 0xCB: // float 64
9598
{
9599
double number{};
9600
return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
9601
}
9602
9603
case 0xCC: // uint 8
9604
{
9605
std::uint8_t number{};
9606
return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9607
}
9608
9609
case 0xCD: // uint 16
9610
{
9611
std::uint16_t number{};
9612
return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9613
}
9614
9615
case 0xCE: // uint 32
9616
{
9617
std::uint32_t number{};
9618
return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9619
}
9620
9621
case 0xCF: // uint 64
9622
{
9623
std::uint64_t number{};
9624
return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9625
}
9626
9627
case 0xD0: // int 8
9628
{
9629
std::int8_t number{};
9630
return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9631
}
9632
9633
case 0xD1: // int 16
9634
{
9635
std::int16_t number{};
9636
return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9637
}
9638
9639
case 0xD2: // int 32
9640
{
9641
std::int32_t number{};
9642
return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9643
}
9644
9645
case 0xD3: // int 64
9646
{
9647
std::int64_t number{};
9648
return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9649
}
9650
9651
case 0xDC: // array 16
9652
{
9653
std::uint16_t len{};
9654
return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
9655
}
9656
9657
case 0xDD: // array 32
9658
{
9659
std::uint32_t len{};
9660
return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
9661
}
9662
9663
case 0xDE: // map 16
9664
{
9665
std::uint16_t len{};
9666
return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
9667
}
9668
9669
case 0xDF: // map 32
9670
{
9671
std::uint32_t len{};
9672
return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
9673
}
9674
9675
// negative fixint
9676
case 0xE0:
9677
case 0xE1:
9678
case 0xE2:
9679
case 0xE3:
9680
case 0xE4:
9681
case 0xE5:
9682
case 0xE6:
9683
case 0xE7:
9684
case 0xE8:
9685
case 0xE9:
9686
case 0xEA:
9687
case 0xEB:
9688
case 0xEC:
9689
case 0xED:
9690
case 0xEE:
9691
case 0xEF:
9692
case 0xF0:
9693
case 0xF1:
9694
case 0xF2:
9695
case 0xF3:
9696
case 0xF4:
9697
case 0xF5:
9698
case 0xF6:
9699
case 0xF7:
9700
case 0xF8:
9701
case 0xF9:
9702
case 0xFA:
9703
case 0xFB:
9704
case 0xFC:
9705
case 0xFD:
9706
case 0xFE:
9707
case 0xFF:
9708
return sax->number_integer(static_cast<std::int8_t>(current));
9709
9710
default: // anything else
9711
{
9712
auto last_token = get_token_string();
9713
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
9714
}
9715
}
9716
}
9717
9718
/*!
9719
@brief reads a MessagePack string
9720
9721
This function first reads starting bytes to determine the expected
9722
string length and then copies this number of bytes into a string.
9723
9724
@param[out] result created string
9725
9726
@return whether string creation completed
9727
*/
9728
bool get_msgpack_string(string_t& result)
9729
{
9730
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
9731
{
9732
return false;
9733
}
9734
9735
switch (current)
9736
{
9737
// fixstr
9738
case 0xA0:
9739
case 0xA1:
9740
case 0xA2:
9741
case 0xA3:
9742
case 0xA4:
9743
case 0xA5:
9744
case 0xA6:
9745
case 0xA7:
9746
case 0xA8:
9747
case 0xA9:
9748
case 0xAA:
9749
case 0xAB:
9750
case 0xAC:
9751
case 0xAD:
9752
case 0xAE:
9753
case 0xAF:
9754
case 0xB0:
9755
case 0xB1:
9756
case 0xB2:
9757
case 0xB3:
9758
case 0xB4:
9759
case 0xB5:
9760
case 0xB6:
9761
case 0xB7:
9762
case 0xB8:
9763
case 0xB9:
9764
case 0xBA:
9765
case 0xBB:
9766
case 0xBC:
9767
case 0xBD:
9768
case 0xBE:
9769
case 0xBF:
9770
{
9771
return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
9772
}
9773
9774
case 0xD9: // str 8
9775
{
9776
std::uint8_t len{};
9777
return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9778
}
9779
9780
case 0xDA: // str 16
9781
{
9782
std::uint16_t len{};
9783
return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9784
}
9785
9786
case 0xDB: // str 32
9787
{
9788
std::uint32_t len{};
9789
return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9790
}
9791
9792
default:
9793
{
9794
auto last_token = get_token_string();
9795
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"), BasicJsonType()));
9796
}
9797
}
9798
}
9799
9800
/*!
9801
@brief reads a MessagePack byte array
9802
9803
This function first reads starting bytes to determine the expected
9804
byte array length and then copies this number of bytes into a byte array.
9805
9806
@param[out] result created byte array
9807
9808
@return whether byte array creation completed
9809
*/
9810
bool get_msgpack_binary(binary_t& result)
9811
{
9812
// helper function to set the subtype
9813
auto assign_and_return_true = [&result](std::int8_t subtype)
9814
{
9815
result.set_subtype(static_cast<std::uint8_t>(subtype));
9816
return true;
9817
};
9818
9819
switch (current)
9820
{
9821
case 0xC4: // bin 8
9822
{
9823
std::uint8_t len{};
9824
return get_number(input_format_t::msgpack, len) &&
9825
get_binary(input_format_t::msgpack, len, result);
9826
}
9827
9828
case 0xC5: // bin 16
9829
{
9830
std::uint16_t len{};
9831
return get_number(input_format_t::msgpack, len) &&
9832
get_binary(input_format_t::msgpack, len, result);
9833
}
9834
9835
case 0xC6: // bin 32
9836
{
9837
std::uint32_t len{};
9838
return get_number(input_format_t::msgpack, len) &&
9839
get_binary(input_format_t::msgpack, len, result);
9840
}
9841
9842
case 0xC7: // ext 8
9843
{
9844
std::uint8_t len{};
9845
std::int8_t subtype{};
9846
return get_number(input_format_t::msgpack, len) &&
9847
get_number(input_format_t::msgpack, subtype) &&
9848
get_binary(input_format_t::msgpack, len, result) &&
9849
assign_and_return_true(subtype);
9850
}
9851
9852
case 0xC8: // ext 16
9853
{
9854
std::uint16_t len{};
9855
std::int8_t subtype{};
9856
return get_number(input_format_t::msgpack, len) &&
9857
get_number(input_format_t::msgpack, subtype) &&
9858
get_binary(input_format_t::msgpack, len, result) &&
9859
assign_and_return_true(subtype);
9860
}
9861
9862
case 0xC9: // ext 32
9863
{
9864
std::uint32_t len{};
9865
std::int8_t subtype{};
9866
return get_number(input_format_t::msgpack, len) &&
9867
get_number(input_format_t::msgpack, subtype) &&
9868
get_binary(input_format_t::msgpack, len, result) &&
9869
assign_and_return_true(subtype);
9870
}
9871
9872
case 0xD4: // fixext 1
9873
{
9874
std::int8_t subtype{};
9875
return get_number(input_format_t::msgpack, subtype) &&
9876
get_binary(input_format_t::msgpack, 1, result) &&
9877
assign_and_return_true(subtype);
9878
}
9879
9880
case 0xD5: // fixext 2
9881
{
9882
std::int8_t subtype{};
9883
return get_number(input_format_t::msgpack, subtype) &&
9884
get_binary(input_format_t::msgpack, 2, result) &&
9885
assign_and_return_true(subtype);
9886
}
9887
9888
case 0xD6: // fixext 4
9889
{
9890
std::int8_t subtype{};
9891
return get_number(input_format_t::msgpack, subtype) &&
9892
get_binary(input_format_t::msgpack, 4, result) &&
9893
assign_and_return_true(subtype);
9894
}
9895
9896
case 0xD7: // fixext 8
9897
{
9898
std::int8_t subtype{};
9899
return get_number(input_format_t::msgpack, subtype) &&
9900
get_binary(input_format_t::msgpack, 8, result) &&
9901
assign_and_return_true(subtype);
9902
}
9903
9904
case 0xD8: // fixext 16
9905
{
9906
std::int8_t subtype{};
9907
return get_number(input_format_t::msgpack, subtype) &&
9908
get_binary(input_format_t::msgpack, 16, result) &&
9909
assign_and_return_true(subtype);
9910
}
9911
9912
default: // LCOV_EXCL_LINE
9913
return false; // LCOV_EXCL_LINE
9914
}
9915
}
9916
9917
/*!
9918
@param[in] len the length of the array
9919
@return whether array creation completed
9920
*/
9921
bool get_msgpack_array(const std::size_t len)
9922
{
9923
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
9924
{
9925
return false;
9926
}
9927
9928
for (std::size_t i = 0; i < len; ++i)
9929
{
9930
if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
9931
{
9932
return false;
9933
}
9934
}
9935
9936
return sax->end_array();
9937
}
9938
9939
/*!
9940
@param[in] len the length of the object
9941
@return whether object creation completed
9942
*/
9943
bool get_msgpack_object(const std::size_t len)
9944
{
9945
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
9946
{
9947
return false;
9948
}
9949
9950
string_t key;
9951
for (std::size_t i = 0; i < len; ++i)
9952
{
9953
get();
9954
if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
9955
{
9956
return false;
9957
}
9958
9959
if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
9960
{
9961
return false;
9962
}
9963
key.clear();
9964
}
9965
9966
return sax->end_object();
9967
}
9968
9969
////////////
9970
// UBJSON //
9971
////////////
9972
9973
/*!
9974
@param[in] get_char whether a new character should be retrieved from the
9975
input (true, default) or whether the last read
9976
character should be considered instead
9977
9978
@return whether a valid UBJSON value was passed to the SAX parser
9979
*/
9980
bool parse_ubjson_internal(const bool get_char = true)
9981
{
9982
return get_ubjson_value(get_char ? get_ignore_noop() : current);
9983
}
9984
9985
/*!
9986
@brief reads a UBJSON string
9987
9988
This function is either called after reading the 'S' byte explicitly
9989
indicating a string, or in case of an object key where the 'S' byte can be
9990
left out.
9991
9992
@param[out] result created string
9993
@param[in] get_char whether a new character should be retrieved from the
9994
input (true, default) or whether the last read
9995
character should be considered instead
9996
9997
@return whether string creation completed
9998
*/
9999
bool get_ubjson_string(string_t& result, const bool get_char = true)
10000
{
10001
if (get_char)
10002
{
10003
get(); // TODO(niels): may we ignore N here?
10004
}
10005
10006
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
10007
{
10008
return false;
10009
}
10010
10011
switch (current)
10012
{
10013
case 'U':
10014
{
10015
std::uint8_t len{};
10016
return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10017
}
10018
10019
case 'i':
10020
{
10021
std::int8_t len{};
10022
return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10023
}
10024
10025
case 'I':
10026
{
10027
std::int16_t len{};
10028
return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10029
}
10030
10031
case 'l':
10032
{
10033
std::int32_t len{};
10034
return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10035
}
10036
10037
case 'L':
10038
{
10039
std::int64_t len{};
10040
return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
10041
}
10042
10043
default:
10044
auto last_token = get_token_string();
10045
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"), BasicJsonType()));
10046
}
10047
}
10048
10049
/*!
10050
@param[out] result determined size
10051
@return whether size determination completed
10052
*/
10053
bool get_ubjson_size_value(std::size_t& result)
10054
{
10055
switch (get_ignore_noop())
10056
{
10057
case 'U':
10058
{
10059
std::uint8_t number{};
10060
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10061
{
10062
return false;
10063
}
10064
result = static_cast<std::size_t>(number);
10065
return true;
10066
}
10067
10068
case 'i':
10069
{
10070
std::int8_t number{};
10071
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10072
{
10073
return false;
10074
}
10075
result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
10076
return true;
10077
}
10078
10079
case 'I':
10080
{
10081
std::int16_t number{};
10082
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10083
{
10084
return false;
10085
}
10086
result = static_cast<std::size_t>(number);
10087
return true;
10088
}
10089
10090
case 'l':
10091
{
10092
std::int32_t number{};
10093
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10094
{
10095
return false;
10096
}
10097
result = static_cast<std::size_t>(number);
10098
return true;
10099
}
10100
10101
case 'L':
10102
{
10103
std::int64_t number{};
10104
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
10105
{
10106
return false;
10107
}
10108
result = static_cast<std::size_t>(number);
10109
return true;
10110
}
10111
10112
default:
10113
{
10114
auto last_token = get_token_string();
10115
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"), BasicJsonType()));
10116
}
10117
}
10118
}
10119
10120
/*!
10121
@brief determine the type and size for a container
10122
10123
In the optimized UBJSON format, a type and a size can be provided to allow
10124
for a more compact representation.
10125
10126
@param[out] result pair of the size and the type
10127
10128
@return whether pair creation completed
10129
*/
10130
bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result)
10131
{
10132
result.first = string_t::npos; // size
10133
result.second = 0; // type
10134
10135
get_ignore_noop();
10136
10137
if (current == '$')
10138
{
10139
result.second = get(); // must not ignore 'N', because 'N' maybe the type
10140
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type")))
10141
{
10142
return false;
10143
}
10144
10145
get_ignore_noop();
10146
if (JSON_HEDLEY_UNLIKELY(current != '#'))
10147
{
10148
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
10149
{
10150
return false;
10151
}
10152
auto last_token = get_token_string();
10153
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"), BasicJsonType()));
10154
}
10155
10156
return get_ubjson_size_value(result.first);
10157
}
10158
10159
if (current == '#')
10160
{
10161
return get_ubjson_size_value(result.first);
10162
}
10163
10164
return true;
10165
}
10166
10167
/*!
10168
@param prefix the previously read or set type prefix
10169
@return whether value creation completed
10170
*/
10171
bool get_ubjson_value(const char_int_type prefix)
10172
{
10173
switch (prefix)
10174
{
10175
case std::char_traits<char_type>::eof(): // EOF
10176
return unexpect_eof(input_format_t::ubjson, "value");
10177
10178
case 'T': // true
10179
return sax->boolean(true);
10180
case 'F': // false
10181
return sax->boolean(false);
10182
10183
case 'Z': // null
10184
return sax->null();
10185
10186
case 'U':
10187
{
10188
std::uint8_t number{};
10189
return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number);
10190
}
10191
10192
case 'i':
10193
{
10194
std::int8_t number{};
10195
return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
10196
}
10197
10198
case 'I':
10199
{
10200
std::int16_t number{};
10201
return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
10202
}
10203
10204
case 'l':
10205
{
10206
std::int32_t number{};
10207
return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
10208
}
10209
10210
case 'L':
10211
{
10212
std::int64_t number{};
10213
return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
10214
}
10215
10216
case 'd':
10217
{
10218
float number{};
10219
return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10220
}
10221
10222
case 'D':
10223
{
10224
double number{};
10225
return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10226
}
10227
10228
case 'H':
10229
{
10230
return get_ubjson_high_precision_number();
10231
}
10232
10233
case 'C': // char
10234
{
10235
get();
10236
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char")))
10237
{
10238
return false;
10239
}
10240
if (JSON_HEDLEY_UNLIKELY(current > 127))
10241
{
10242
auto last_token = get_token_string();
10243
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"), BasicJsonType()));
10244
}
10245
string_t s(1, static_cast<typename string_t::value_type>(current));
10246
return sax->string(s);
10247
}
10248
10249
case 'S': // string
10250
{
10251
string_t s;
10252
return get_ubjson_string(s) && sax->string(s);
10253
}
10254
10255
case '[': // array
10256
return get_ubjson_array();
10257
10258
case '{': // object
10259
return get_ubjson_object();
10260
10261
default: // anything else
10262
{
10263
auto last_token = get_token_string();
10264
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
10265
}
10266
}
10267
}
10268
10269
/*!
10270
@return whether array creation completed
10271
*/
10272
bool get_ubjson_array()
10273
{
10274
std::pair<std::size_t, char_int_type> size_and_type;
10275
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
10276
{
10277
return false;
10278
}
10279
10280
if (size_and_type.first != string_t::npos)
10281
{
10282
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
10283
{
10284
return false;
10285
}
10286
10287
if (size_and_type.second != 0)
10288
{
10289
if (size_and_type.second != 'N')
10290
{
10291
for (std::size_t i = 0; i < size_and_type.first; ++i)
10292
{
10293
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
10294
{
10295
return false;
10296
}
10297
}
10298
}
10299
}
10300
else
10301
{
10302
for (std::size_t i = 0; i < size_and_type.first; ++i)
10303
{
10304
if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
10305
{
10306
return false;
10307
}
10308
}
10309
}
10310
}
10311
else
10312
{
10313
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
10314
{
10315
return false;
10316
}
10317
10318
while (current != ']')
10319
{
10320
if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
10321
{
10322
return false;
10323
}
10324
get_ignore_noop();
10325
}
10326
}
10327
10328
return sax->end_array();
10329
}
10330
10331
/*!
10332
@return whether object creation completed
10333
*/
10334
bool get_ubjson_object()
10335
{
10336
std::pair<std::size_t, char_int_type> size_and_type;
10337
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
10338
{
10339
return false;
10340
}
10341
10342
string_t key;
10343
if (size_and_type.first != string_t::npos)
10344
{
10345
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
10346
{
10347
return false;
10348
}
10349
10350
if (size_and_type.second != 0)
10351
{
10352
for (std::size_t i = 0; i < size_and_type.first; ++i)
10353
{
10354
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
10355
{
10356
return false;
10357
}
10358
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
10359
{
10360
return false;
10361
}
10362
key.clear();
10363
}
10364
}
10365
else
10366
{
10367
for (std::size_t i = 0; i < size_and_type.first; ++i)
10368
{
10369
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
10370
{
10371
return false;
10372
}
10373
if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
10374
{
10375
return false;
10376
}
10377
key.clear();
10378
}
10379
}
10380
}
10381
else
10382
{
10383
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
10384
{
10385
return false;
10386
}
10387
10388
while (current != '}')
10389
{
10390
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
10391
{
10392
return false;
10393
}
10394
if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
10395
{
10396
return false;
10397
}
10398
get_ignore_noop();
10399
key.clear();
10400
}
10401
}
10402
10403
return sax->end_object();
10404
}
10405
10406
// Note, no reader for UBJSON binary types is implemented because they do
10407
// not exist
10408
10409
bool get_ubjson_high_precision_number()
10410
{
10411
// get size of following number string
10412
std::size_t size{};
10413
auto res = get_ubjson_size_value(size);
10414
if (JSON_HEDLEY_UNLIKELY(!res))
10415
{
10416
return res;
10417
}
10418
10419
// get number string
10420
std::vector<char> number_vector;
10421
for (std::size_t i = 0; i < size; ++i)
10422
{
10423
get();
10424
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number")))
10425
{
10426
return false;
10427
}
10428
number_vector.push_back(static_cast<char>(current));
10429
}
10430
10431
// parse number string
10432
using ia_type = decltype(detail::input_adapter(number_vector));
10433
auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
10434
const auto result_number = number_lexer.scan();
10435
const auto number_string = number_lexer.get_token_string();
10436
const auto result_remainder = number_lexer.scan();
10437
10438
using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
10439
10440
if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
10441
{
10442
return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType()));
10443
}
10444
10445
switch (result_number)
10446
{
10447
case token_type::value_integer:
10448
return sax->number_integer(number_lexer.get_number_integer());
10449
case token_type::value_unsigned:
10450
return sax->number_unsigned(number_lexer.get_number_unsigned());
10451
case token_type::value_float:
10452
return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
10453
case token_type::uninitialized:
10454
case token_type::literal_true:
10455
case token_type::literal_false:
10456
case token_type::literal_null:
10457
case token_type::value_string:
10458
case token_type::begin_array:
10459
case token_type::begin_object:
10460
case token_type::end_array:
10461
case token_type::end_object:
10462
case token_type::name_separator:
10463
case token_type::value_separator:
10464
case token_type::parse_error:
10465
case token_type::end_of_input:
10466
case token_type::literal_or_value:
10467
default:
10468
return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType()));
10469
}
10470
}
10471
10472
///////////////////////
10473
// Utility functions //
10474
///////////////////////
10475
10476
/*!
10477
@brief get next character from the input
10478
10479
This function provides the interface to the used input adapter. It does
10480
not throw in case the input reached EOF, but returns a -'ve valued
10481
`std::char_traits<char_type>::eof()` in that case.
10482
10483
@return character read from the input
10484
*/
10485
char_int_type get()
10486
{
10487
++chars_read;
10488
return current = ia.get_character();
10489
}
10490
10491
/*!
10492
@return character read from the input after ignoring all 'N' entries
10493
*/
10494
char_int_type get_ignore_noop()
10495
{
10496
do
10497
{
10498
get();
10499
}
10500
while (current == 'N');
10501
10502
return current;
10503
}
10504
10505
/*
10506
@brief read a number from the input
10507
10508
@tparam NumberType the type of the number
10509
@param[in] format the current format (for diagnostics)
10510
@param[out] result number of type @a NumberType
10511
10512
@return whether conversion completed
10513
10514
@note This function needs to respect the system's endianness, because
10515
bytes in CBOR, MessagePack, and UBJSON are stored in network order
10516
(big endian) and therefore need reordering on little endian systems.
10517
*/
10518
template<typename NumberType, bool InputIsLittleEndian = false>
10519
bool get_number(const input_format_t format, NumberType& result)
10520
{
10521
// step 1: read input into array with system's byte order
10522
std::array<std::uint8_t, sizeof(NumberType)> vec{};
10523
for (std::size_t i = 0; i < sizeof(NumberType); ++i)
10524
{
10525
get();
10526
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
10527
{
10528
return false;
10529
}
10530
10531
// reverse byte order prior to conversion if necessary
10532
if (is_little_endian != InputIsLittleEndian)
10533
{
10534
vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
10535
}
10536
else
10537
{
10538
vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
10539
}
10540
}
10541
10542
// step 2: convert array into number of type T and return
10543
std::memcpy(&result, vec.data(), sizeof(NumberType));
10544
return true;
10545
}
10546
10547
/*!
10548
@brief create a string by reading characters from the input
10549
10550
@tparam NumberType the type of the number
10551
@param[in] format the current format (for diagnostics)
10552
@param[in] len number of characters to read
10553
@param[out] result string created by reading @a len bytes
10554
10555
@return whether string creation completed
10556
10557
@note We can not reserve @a len bytes for the result, because @a len
10558
may be too large. Usually, @ref unexpect_eof() detects the end of
10559
the input before we run out of string memory.
10560
*/
10561
template<typename NumberType>
10562
bool get_string(const input_format_t format,
10563
const NumberType len,
10564
string_t& result)
10565
{
10566
bool success = true;
10567
for (NumberType i = 0; i < len; i++)
10568
{
10569
get();
10570
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
10571
{
10572
success = false;
10573
break;
10574
}
10575
result.push_back(static_cast<typename string_t::value_type>(current));
10576
}
10577
return success;
10578
}
10579
10580
/*!
10581
@brief create a byte array by reading bytes from the input
10582
10583
@tparam NumberType the type of the number
10584
@param[in] format the current format (for diagnostics)
10585
@param[in] len number of bytes to read
10586
@param[out] result byte array created by reading @a len bytes
10587
10588
@return whether byte array creation completed
10589
10590
@note We can not reserve @a len bytes for the result, because @a len
10591
may be too large. Usually, @ref unexpect_eof() detects the end of
10592
the input before we run out of memory.
10593
*/
10594
template<typename NumberType>
10595
bool get_binary(const input_format_t format,
10596
const NumberType len,
10597
binary_t& result)
10598
{
10599
bool success = true;
10600
for (NumberType i = 0; i < len; i++)
10601
{
10602
get();
10603
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
10604
{
10605
success = false;
10606
break;
10607
}
10608
result.push_back(static_cast<std::uint8_t>(current));
10609
}
10610
return success;
10611
}
10612
10613
/*!
10614
@param[in] format the current format (for diagnostics)
10615
@param[in] context further context information (for diagnostics)
10616
@return whether the last read character is not EOF
10617
*/
10618
JSON_HEDLEY_NON_NULL(3)
10619
bool unexpect_eof(const input_format_t format, const char* context) const
10620
{
10621
if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
10622
{
10623
return sax->parse_error(chars_read, "<end of file>",
10624
parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), BasicJsonType()));
10625
}
10626
return true;
10627
}
10628
10629
/*!
10630
@return a string representation of the last read byte
10631
*/
10632
std::string get_token_string() const
10633
{
10634
std::array<char, 3> cr{{}};
10635
static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
10636
return std::string{cr.data()};
10637
}
10638
10639
/*!
10640
@param[in] format the current format
10641
@param[in] detail a detailed error message
10642
@param[in] context further context information
10643
@return a message string to use in the parse_error exceptions
10644
*/
10645
std::string exception_message(const input_format_t format,
10646
const std::string& detail,
10647
const std::string& context) const
10648
{
10649
std::string error_msg = "syntax error while parsing ";
10650
10651
switch (format)
10652
{
10653
case input_format_t::cbor:
10654
error_msg += "CBOR";
10655
break;
10656
10657
case input_format_t::msgpack:
10658
error_msg += "MessagePack";
10659
break;
10660
10661
case input_format_t::ubjson:
10662
error_msg += "UBJSON";
10663
break;
10664
10665
case input_format_t::bson:
10666
error_msg += "BSON";
10667
break;
10668
10669
case input_format_t::json: // LCOV_EXCL_LINE
10670
default: // LCOV_EXCL_LINE
10671
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10672
}
10673
10674
return error_msg + " " + context + ": " + detail;
10675
}
10676
10677
private:
10678
/// input adapter
10679
InputAdapterType ia;
10680
10681
/// the current character
10682
char_int_type current = std::char_traits<char_type>::eof();
10683
10684
/// the number of characters read
10685
std::size_t chars_read = 0;
10686
10687
/// whether we can assume little endianness
10688
const bool is_little_endian = little_endianness();
10689
10690
/// the SAX parser
10691
json_sax_t* sax = nullptr;
10692
};
10693
} // namespace detail
10694
} // namespace nlohmann
10695
10696
// #include <nlohmann/detail/input/input_adapters.hpp>
10697
10698
// #include <nlohmann/detail/input/lexer.hpp>
10699
10700
// #include <nlohmann/detail/input/parser.hpp>
10701
10702
10703
#include <cmath> // isfinite
10704
#include <cstdint> // uint8_t
10705
#include <functional> // function
10706
#include <string> // string
10707
#include <utility> // move
10708
#include <vector> // vector
10709
10710
// #include <nlohmann/detail/exceptions.hpp>
10711
10712
// #include <nlohmann/detail/input/input_adapters.hpp>
10713
10714
// #include <nlohmann/detail/input/json_sax.hpp>
10715
10716
// #include <nlohmann/detail/input/lexer.hpp>
10717
10718
// #include <nlohmann/detail/macro_scope.hpp>
10719
10720
// #include <nlohmann/detail/meta/is_sax.hpp>
10721
10722
// #include <nlohmann/detail/value_t.hpp>
10723
10724
10725
namespace nlohmann
10726
{
10727
namespace detail
10728
{
10729
////////////
10730
// parser //
10731
////////////
10732
10733
enum class parse_event_t : std::uint8_t
10734
{
10735
/// the parser read `{` and started to process a JSON object
10736
object_start,
10737
/// the parser read `}` and finished processing a JSON object
10738
object_end,
10739
/// the parser read `[` and started to process a JSON array
10740
array_start,
10741
/// the parser read `]` and finished processing a JSON array
10742
array_end,
10743
/// the parser read a key of a value in an object
10744
key,
10745
/// the parser finished reading a JSON value
10746
value
10747
};
10748
10749
template<typename BasicJsonType>
10750
using parser_callback_t =
10751
std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
10752
10753
/*!
10754
@brief syntax analysis
10755
10756
This class implements a recursive descent parser.
10757
*/
10758
template<typename BasicJsonType, typename InputAdapterType>
10759
class parser
10760
{
10761
using number_integer_t = typename BasicJsonType::number_integer_t;
10762
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
10763
using number_float_t = typename BasicJsonType::number_float_t;
10764
using string_t = typename BasicJsonType::string_t;
10765
using lexer_t = lexer<BasicJsonType, InputAdapterType>;
10766
using token_type = typename lexer_t::token_type;
10767
10768
public:
10769
/// a parser reading from an input adapter
10770
explicit parser(InputAdapterType&& adapter,
10771
const parser_callback_t<BasicJsonType> cb = nullptr,
10772
const bool allow_exceptions_ = true,
10773
const bool skip_comments = false)
10774
: callback(cb)
10775
, m_lexer(std::move(adapter), skip_comments)
10776
, allow_exceptions(allow_exceptions_)
10777
{
10778
// read first token
10779
get_token();
10780
}
10781
10782
/*!
10783
@brief public parser interface
10784
10785
@param[in] strict whether to expect the last token to be EOF
10786
@param[in,out] result parsed JSON value
10787
10788
@throw parse_error.101 in case of an unexpected token
10789
@throw parse_error.102 if to_unicode fails or surrogate error
10790
@throw parse_error.103 if to_unicode fails
10791
*/
10792
void parse(const bool strict, BasicJsonType& result)
10793
{
10794
if (callback)
10795
{
10796
json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
10797
sax_parse_internal(&sdp);
10798
10799
// in strict mode, input must be completely read
10800
if (strict && (get_token() != token_type::end_of_input))
10801
{
10802
sdp.parse_error(m_lexer.get_position(),
10803
m_lexer.get_token_string(),
10804
parse_error::create(101, m_lexer.get_position(),
10805
exception_message(token_type::end_of_input, "value"), BasicJsonType()));
10806
}
10807
10808
// in case of an error, return discarded value
10809
if (sdp.is_errored())
10810
{
10811
result = value_t::discarded;
10812
return;
10813
}
10814
10815
// set top-level value to null if it was discarded by the callback
10816
// function
10817
if (result.is_discarded())
10818
{
10819
result = nullptr;
10820
}
10821
}
10822
else
10823
{
10824
json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
10825
sax_parse_internal(&sdp);
10826
10827
// in strict mode, input must be completely read
10828
if (strict && (get_token() != token_type::end_of_input))
10829
{
10830
sdp.parse_error(m_lexer.get_position(),
10831
m_lexer.get_token_string(),
10832
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
10833
}
10834
10835
// in case of an error, return discarded value
10836
if (sdp.is_errored())
10837
{
10838
result = value_t::discarded;
10839
return;
10840
}
10841
}
10842
10843
result.assert_invariant();
10844
}
10845
10846
/*!
10847
@brief public accept interface
10848
10849
@param[in] strict whether to expect the last token to be EOF
10850
@return whether the input is a proper JSON text
10851
*/
10852
bool accept(const bool strict = true)
10853
{
10854
json_sax_acceptor<BasicJsonType> sax_acceptor;
10855
return sax_parse(&sax_acceptor, strict);
10856
}
10857
10858
template<typename SAX>
10859
JSON_HEDLEY_NON_NULL(2)
10860
bool sax_parse(SAX* sax, const bool strict = true)
10861
{
10862
(void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
10863
const bool result = sax_parse_internal(sax);
10864
10865
// strict mode: next byte must be EOF
10866
if (result && strict && (get_token() != token_type::end_of_input))
10867
{
10868
return sax->parse_error(m_lexer.get_position(),
10869
m_lexer.get_token_string(),
10870
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
10871
}
10872
10873
return result;
10874
}
10875
10876
private:
10877
template<typename SAX>
10878
JSON_HEDLEY_NON_NULL(2)
10879
bool sax_parse_internal(SAX* sax)
10880
{
10881
// stack to remember the hierarchy of structured values we are parsing
10882
// true = array; false = object
10883
std::vector<bool> states;
10884
// value to avoid a goto (see comment where set to true)
10885
bool skip_to_state_evaluation = false;
10886
10887
while (true)
10888
{
10889
if (!skip_to_state_evaluation)
10890
{
10891
// invariant: get_token() was called before each iteration
10892
switch (last_token)
10893
{
10894
case token_type::begin_object:
10895
{
10896
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
10897
{
10898
return false;
10899
}
10900
10901
// closing } -> we are done
10902
if (get_token() == token_type::end_object)
10903
{
10904
if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
10905
{
10906
return false;
10907
}
10908
break;
10909
}
10910
10911
// parse key
10912
if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
10913
{
10914
return sax->parse_error(m_lexer.get_position(),
10915
m_lexer.get_token_string(),
10916
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType()));
10917
}
10918
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
10919
{
10920
return false;
10921
}
10922
10923
// parse separator (:)
10924
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
10925
{
10926
return sax->parse_error(m_lexer.get_position(),
10927
m_lexer.get_token_string(),
10928
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType()));
10929
}
10930
10931
// remember we are now inside an object
10932
states.push_back(false);
10933
10934
// parse values
10935
get_token();
10936
continue;
10937
}
10938
10939
case token_type::begin_array:
10940
{
10941
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
10942
{
10943
return false;
10944
}
10945
10946
// closing ] -> we are done
10947
if (get_token() == token_type::end_array)
10948
{
10949
if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
10950
{
10951
return false;
10952
}
10953
break;
10954
}
10955
10956
// remember we are now inside an array
10957
states.push_back(true);
10958
10959
// parse values (no need to call get_token)
10960
continue;
10961
}
10962
10963
case token_type::value_float:
10964
{
10965
const auto res = m_lexer.get_number_float();
10966
10967
if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
10968
{
10969
return sax->parse_error(m_lexer.get_position(),
10970
m_lexer.get_token_string(),
10971
out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'", BasicJsonType()));
10972
}
10973
10974
if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
10975
{
10976
return false;
10977
}
10978
10979
break;
10980
}
10981
10982
case token_type::literal_false:
10983
{
10984
if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
10985
{
10986
return false;
10987
}
10988
break;
10989
}
10990
10991
case token_type::literal_null:
10992
{
10993
if (JSON_HEDLEY_UNLIKELY(!sax->null()))
10994
{
10995
return false;
10996
}
10997
break;
10998
}
10999
11000
case token_type::literal_true:
11001
{
11002
if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
11003
{
11004
return false;
11005
}
11006
break;
11007
}
11008
11009
case token_type::value_integer:
11010
{
11011
if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
11012
{
11013
return false;
11014
}
11015
break;
11016
}
11017
11018
case token_type::value_string:
11019
{
11020
if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
11021
{
11022
return false;
11023
}
11024
break;
11025
}
11026
11027
case token_type::value_unsigned:
11028
{
11029
if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
11030
{
11031
return false;
11032
}
11033
break;
11034
}
11035
11036
case token_type::parse_error:
11037
{
11038
// using "uninitialized" to avoid "expected" message
11039
return sax->parse_error(m_lexer.get_position(),
11040
m_lexer.get_token_string(),
11041
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), BasicJsonType()));
11042
}
11043
11044
case token_type::uninitialized:
11045
case token_type::end_array:
11046
case token_type::end_object:
11047
case token_type::name_separator:
11048
case token_type::value_separator:
11049
case token_type::end_of_input:
11050
case token_type::literal_or_value:
11051
default: // the last token was unexpected
11052
{
11053
return sax->parse_error(m_lexer.get_position(),
11054
m_lexer.get_token_string(),
11055
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), BasicJsonType()));
11056
}
11057
}
11058
}
11059
else
11060
{
11061
skip_to_state_evaluation = false;
11062
}
11063
11064
// we reached this line after we successfully parsed a value
11065
if (states.empty())
11066
{
11067
// empty stack: we reached the end of the hierarchy: done
11068
return true;
11069
}
11070
11071
if (states.back()) // array
11072
{
11073
// comma -> next value
11074
if (get_token() == token_type::value_separator)
11075
{
11076
// parse a new value
11077
get_token();
11078
continue;
11079
}
11080
11081
// closing ]
11082
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
11083
{
11084
if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
11085
{
11086
return false;
11087
}
11088
11089
// We are done with this array. Before we can parse a
11090
// new value, we need to evaluate the new state first.
11091
// By setting skip_to_state_evaluation to false, we
11092
// are effectively jumping to the beginning of this if.
11093
JSON_ASSERT(!states.empty());
11094
states.pop_back();
11095
skip_to_state_evaluation = true;
11096
continue;
11097
}
11098
11099
return sax->parse_error(m_lexer.get_position(),
11100
m_lexer.get_token_string(),
11101
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), BasicJsonType()));
11102
}
11103
11104
// states.back() is false -> object
11105
11106
// comma -> next value
11107
if (get_token() == token_type::value_separator)
11108
{
11109
// parse key
11110
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
11111
{
11112
return sax->parse_error(m_lexer.get_position(),
11113
m_lexer.get_token_string(),
11114
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType()));
11115
}
11116
11117
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
11118
{
11119
return false;
11120
}
11121
11122
// parse separator (:)
11123
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
11124
{
11125
return sax->parse_error(m_lexer.get_position(),
11126
m_lexer.get_token_string(),
11127
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType()));
11128
}
11129
11130
// parse values
11131
get_token();
11132
continue;
11133
}
11134
11135
// closing }
11136
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
11137
{
11138
if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
11139
{
11140
return false;
11141
}
11142
11143
// We are done with this object. Before we can parse a
11144
// new value, we need to evaluate the new state first.
11145
// By setting skip_to_state_evaluation to false, we
11146
// are effectively jumping to the beginning of this if.
11147
JSON_ASSERT(!states.empty());
11148
states.pop_back();
11149
skip_to_state_evaluation = true;
11150
continue;
11151
}
11152
11153
return sax->parse_error(m_lexer.get_position(),
11154
m_lexer.get_token_string(),
11155
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), BasicJsonType()));
11156
}
11157
}
11158
11159
/// get next token from lexer
11160
token_type get_token()
11161
{
11162
return last_token = m_lexer.scan();
11163
}
11164
11165
std::string exception_message(const token_type expected, const std::string& context)
11166
{
11167
std::string error_msg = "syntax error ";
11168
11169
if (!context.empty())
11170
{
11171
error_msg += "while parsing " + context + " ";
11172
}
11173
11174
error_msg += "- ";
11175
11176
if (last_token == token_type::parse_error)
11177
{
11178
error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
11179
m_lexer.get_token_string() + "'";
11180
}
11181
else
11182
{
11183
error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
11184
}
11185
11186
if (expected != token_type::uninitialized)
11187
{
11188
error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
11189
}
11190
11191
return error_msg;
11192
}
11193
11194
private:
11195
/// callback function
11196
const parser_callback_t<BasicJsonType> callback = nullptr;
11197
/// the type of the last read token
11198
token_type last_token = token_type::uninitialized;
11199
/// the lexer
11200
lexer_t m_lexer;
11201
/// whether to throw exceptions in case of errors
11202
const bool allow_exceptions = true;
11203
};
11204
11205
} // namespace detail
11206
} // namespace nlohmann
11207
11208
// #include <nlohmann/detail/iterators/internal_iterator.hpp>
11209
11210
11211
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
11212
11213
11214
#include <cstddef> // ptrdiff_t
11215
#include <limits> // numeric_limits
11216
11217
// #include <nlohmann/detail/macro_scope.hpp>
11218
11219
11220
namespace nlohmann
11221
{
11222
namespace detail
11223
{
11224
/*
11225
@brief an iterator for primitive JSON types
11226
11227
This class models an iterator for primitive JSON types (boolean, number,
11228
string). It's only purpose is to allow the iterator/const_iterator classes
11229
to "iterate" over primitive values. Internally, the iterator is modeled by
11230
a `difference_type` variable. Value begin_value (`0`) models the begin,
11231
end_value (`1`) models past the end.
11232
*/
11233
class primitive_iterator_t
11234
{
11235
private:
11236
using difference_type = std::ptrdiff_t;
11237
static constexpr difference_type begin_value = 0;
11238
static constexpr difference_type end_value = begin_value + 1;
11239
11240
JSON_PRIVATE_UNLESS_TESTED:
11241
/// iterator as signed integer type
11242
difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
11243
11244
public:
11245
constexpr difference_type get_value() const noexcept
11246
{
11247
return m_it;
11248
}
11249
11250
/// set iterator to a defined beginning
11251
void set_begin() noexcept
11252
{
11253
m_it = begin_value;
11254
}
11255
11256
/// set iterator to a defined past the end
11257
void set_end() noexcept
11258
{
11259
m_it = end_value;
11260
}
11261
11262
/// return whether the iterator can be dereferenced
11263
constexpr bool is_begin() const noexcept
11264
{
11265
return m_it == begin_value;
11266
}
11267
11268
/// return whether the iterator is at end
11269
constexpr bool is_end() const noexcept
11270
{
11271
return m_it == end_value;
11272
}
11273
11274
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
11275
{
11276
return lhs.m_it == rhs.m_it;
11277
}
11278
11279
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
11280
{
11281
return lhs.m_it < rhs.m_it;
11282
}
11283
11284
primitive_iterator_t operator+(difference_type n) noexcept
11285
{
11286
auto result = *this;
11287
result += n;
11288
return result;
11289
}
11290
11291
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
11292
{
11293
return lhs.m_it - rhs.m_it;
11294
}
11295
11296
primitive_iterator_t& operator++() noexcept
11297
{
11298
++m_it;
11299
return *this;
11300
}
11301
11302
primitive_iterator_t const operator++(int) noexcept // NOLINT(readability-const-return-type)
11303
{
11304
auto result = *this;
11305
++m_it;
11306
return result;
11307
}
11308
11309
primitive_iterator_t& operator--() noexcept
11310
{
11311
--m_it;
11312
return *this;
11313
}
11314
11315
primitive_iterator_t const operator--(int) noexcept // NOLINT(readability-const-return-type)
11316
{
11317
auto result = *this;
11318
--m_it;
11319
return result;
11320
}
11321
11322
primitive_iterator_t& operator+=(difference_type n) noexcept
11323
{
11324
m_it += n;
11325
return *this;
11326
}
11327
11328
primitive_iterator_t& operator-=(difference_type n) noexcept
11329
{
11330
m_it -= n;
11331
return *this;
11332
}
11333
};
11334
} // namespace detail
11335
} // namespace nlohmann
11336
11337
11338
namespace nlohmann
11339
{
11340
namespace detail
11341
{
11342
/*!
11343
@brief an iterator value
11344
11345
@note This structure could easily be a union, but MSVC currently does not allow
11346
unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
11347
*/
11348
template<typename BasicJsonType> struct internal_iterator
11349
{
11350
/// iterator for JSON objects
11351
typename BasicJsonType::object_t::iterator object_iterator {};
11352
/// iterator for JSON arrays
11353
typename BasicJsonType::array_t::iterator array_iterator {};
11354
/// generic iterator for all other types
11355
primitive_iterator_t primitive_iterator {};
11356
};
11357
} // namespace detail
11358
} // namespace nlohmann
11359
11360
// #include <nlohmann/detail/iterators/iter_impl.hpp>
11361
11362
11363
#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
11364
#include <type_traits> // conditional, is_const, remove_const
11365
11366
// #include <nlohmann/detail/exceptions.hpp>
11367
11368
// #include <nlohmann/detail/iterators/internal_iterator.hpp>
11369
11370
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
11371
11372
// #include <nlohmann/detail/macro_scope.hpp>
11373
11374
// #include <nlohmann/detail/meta/cpp_future.hpp>
11375
11376
// #include <nlohmann/detail/meta/type_traits.hpp>
11377
11378
// #include <nlohmann/detail/value_t.hpp>
11379
11380
11381
namespace nlohmann
11382
{
11383
namespace detail
11384
{
11385
// forward declare, to be able to friend it later on
11386
template<typename IteratorType> class iteration_proxy;
11387
template<typename IteratorType> class iteration_proxy_value;
11388
11389
/*!
11390
@brief a template for a bidirectional iterator for the @ref basic_json class
11391
This class implements a both iterators (iterator and const_iterator) for the
11392
@ref basic_json class.
11393
@note An iterator is called *initialized* when a pointer to a JSON value has
11394
been set (e.g., by a constructor or a copy assignment). If the iterator is
11395
default-constructed, it is *uninitialized* and most methods are undefined.
11396
**The library uses assertions to detect calls on uninitialized iterators.**
11397
@requirement The class satisfies the following concept requirements:
11398
-
11399
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
11400
The iterator that can be moved can be moved in both directions (i.e.
11401
incremented and decremented).
11402
@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
11403
iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
11404
*/
11405
template<typename BasicJsonType>
11406
class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
11407
{
11408
/// the iterator with BasicJsonType of different const-ness
11409
using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
11410
/// allow basic_json to access private members
11411
friend other_iter_impl;
11412
friend BasicJsonType;
11413
friend iteration_proxy<iter_impl>;
11414
friend iteration_proxy_value<iter_impl>;
11415
11416
using object_t = typename BasicJsonType::object_t;
11417
using array_t = typename BasicJsonType::array_t;
11418
// make sure BasicJsonType is basic_json or const basic_json
11419
static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
11420
"iter_impl only accepts (const) basic_json");
11421
11422
public:
11423
11424
/// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
11425
/// The C++ Standard has never required user-defined iterators to derive from std::iterator.
11426
/// A user-defined iterator should provide publicly accessible typedefs named
11427
/// iterator_category, value_type, difference_type, pointer, and reference.
11428
/// Note that value_type is required to be non-const, even for constant iterators.
11429
using iterator_category = std::bidirectional_iterator_tag;
11430
11431
/// the type of the values when the iterator is dereferenced
11432
using value_type = typename BasicJsonType::value_type;
11433
/// a type to represent differences between iterators
11434
using difference_type = typename BasicJsonType::difference_type;
11435
/// defines a pointer to the type iterated over (value_type)
11436
using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
11437
typename BasicJsonType::const_pointer,
11438
typename BasicJsonType::pointer>::type;
11439
/// defines a reference to the type iterated over (value_type)
11440
using reference =
11441
typename std::conditional<std::is_const<BasicJsonType>::value,
11442
typename BasicJsonType::const_reference,
11443
typename BasicJsonType::reference>::type;
11444
11445
iter_impl() = default;
11446
~iter_impl() = default;
11447
iter_impl(iter_impl&&) noexcept = default;
11448
iter_impl& operator=(iter_impl&&) noexcept = default;
11449
11450
/*!
11451
@brief constructor for a given JSON instance
11452
@param[in] object pointer to a JSON object for this iterator
11453
@pre object != nullptr
11454
@post The iterator is initialized; i.e. `m_object != nullptr`.
11455
*/
11456
explicit iter_impl(pointer object) noexcept : m_object(object)
11457
{
11458
JSON_ASSERT(m_object != nullptr);
11459
11460
switch (m_object->m_type)
11461
{
11462
case value_t::object:
11463
{
11464
m_it.object_iterator = typename object_t::iterator();
11465
break;
11466
}
11467
11468
case value_t::array:
11469
{
11470
m_it.array_iterator = typename array_t::iterator();
11471
break;
11472
}
11473
11474
case value_t::null:
11475
case value_t::string:
11476
case value_t::boolean:
11477
case value_t::number_integer:
11478
case value_t::number_unsigned:
11479
case value_t::number_float:
11480
case value_t::binary:
11481
case value_t::discarded:
11482
default:
11483
{
11484
m_it.primitive_iterator = primitive_iterator_t();
11485
break;
11486
}
11487
}
11488
}
11489
11490
/*!
11491
@note The conventional copy constructor and copy assignment are implicitly
11492
defined. Combined with the following converting constructor and
11493
assignment, they support: (1) copy from iterator to iterator, (2)
11494
copy from const iterator to const iterator, and (3) conversion from
11495
iterator to const iterator. However conversion from const iterator
11496
to iterator is not defined.
11497
*/
11498
11499
/*!
11500
@brief const copy constructor
11501
@param[in] other const iterator to copy from
11502
@note This copy constructor had to be defined explicitly to circumvent a bug
11503
occurring on msvc v19.0 compiler (VS 2015) debug build. For more
11504
information refer to: https://github.com/nlohmann/json/issues/1608
11505
*/
11506
iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
11507
: m_object(other.m_object), m_it(other.m_it)
11508
{}
11509
11510
/*!
11511
@brief converting assignment
11512
@param[in] other const iterator to copy from
11513
@return const/non-const iterator
11514
@note It is not checked whether @a other is initialized.
11515
*/
11516
iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
11517
{
11518
if (&other != this)
11519
{
11520
m_object = other.m_object;
11521
m_it = other.m_it;
11522
}
11523
return *this;
11524
}
11525
11526
/*!
11527
@brief converting constructor
11528
@param[in] other non-const iterator to copy from
11529
@note It is not checked whether @a other is initialized.
11530
*/
11531
iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
11532
: m_object(other.m_object), m_it(other.m_it)
11533
{}
11534
11535
/*!
11536
@brief converting assignment
11537
@param[in] other non-const iterator to copy from
11538
@return const/non-const iterator
11539
@note It is not checked whether @a other is initialized.
11540
*/
11541
iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
11542
{
11543
m_object = other.m_object;
11544
m_it = other.m_it;
11545
return *this;
11546
}
11547
11548
JSON_PRIVATE_UNLESS_TESTED:
11549
/*!
11550
@brief set the iterator to the first value
11551
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11552
*/
11553
void set_begin() noexcept
11554
{
11555
JSON_ASSERT(m_object != nullptr);
11556
11557
switch (m_object->m_type)
11558
{
11559
case value_t::object:
11560
{
11561
m_it.object_iterator = m_object->m_value.object->begin();
11562
break;
11563
}
11564
11565
case value_t::array:
11566
{
11567
m_it.array_iterator = m_object->m_value.array->begin();
11568
break;
11569
}
11570
11571
case value_t::null:
11572
{
11573
// set to end so begin()==end() is true: null is empty
11574
m_it.primitive_iterator.set_end();
11575
break;
11576
}
11577
11578
case value_t::string:
11579
case value_t::boolean:
11580
case value_t::number_integer:
11581
case value_t::number_unsigned:
11582
case value_t::number_float:
11583
case value_t::binary:
11584
case value_t::discarded:
11585
default:
11586
{
11587
m_it.primitive_iterator.set_begin();
11588
break;
11589
}
11590
}
11591
}
11592
11593
/*!
11594
@brief set the iterator past the last value
11595
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11596
*/
11597
void set_end() noexcept
11598
{
11599
JSON_ASSERT(m_object != nullptr);
11600
11601
switch (m_object->m_type)
11602
{
11603
case value_t::object:
11604
{
11605
m_it.object_iterator = m_object->m_value.object->end();
11606
break;
11607
}
11608
11609
case value_t::array:
11610
{
11611
m_it.array_iterator = m_object->m_value.array->end();
11612
break;
11613
}
11614
11615
case value_t::null:
11616
case value_t::string:
11617
case value_t::boolean:
11618
case value_t::number_integer:
11619
case value_t::number_unsigned:
11620
case value_t::number_float:
11621
case value_t::binary:
11622
case value_t::discarded:
11623
default:
11624
{
11625
m_it.primitive_iterator.set_end();
11626
break;
11627
}
11628
}
11629
}
11630
11631
public:
11632
/*!
11633
@brief return a reference to the value pointed to by the iterator
11634
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11635
*/
11636
reference operator*() const
11637
{
11638
JSON_ASSERT(m_object != nullptr);
11639
11640
switch (m_object->m_type)
11641
{
11642
case value_t::object:
11643
{
11644
JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
11645
return m_it.object_iterator->second;
11646
}
11647
11648
case value_t::array:
11649
{
11650
JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
11651
return *m_it.array_iterator;
11652
}
11653
11654
case value_t::null:
11655
JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11656
11657
case value_t::string:
11658
case value_t::boolean:
11659
case value_t::number_integer:
11660
case value_t::number_unsigned:
11661
case value_t::number_float:
11662
case value_t::binary:
11663
case value_t::discarded:
11664
default:
11665
{
11666
if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
11667
{
11668
return *m_object;
11669
}
11670
11671
JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11672
}
11673
}
11674
}
11675
11676
/*!
11677
@brief dereference the iterator
11678
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11679
*/
11680
pointer operator->() const
11681
{
11682
JSON_ASSERT(m_object != nullptr);
11683
11684
switch (m_object->m_type)
11685
{
11686
case value_t::object:
11687
{
11688
JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
11689
return &(m_it.object_iterator->second);
11690
}
11691
11692
case value_t::array:
11693
{
11694
JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
11695
return &*m_it.array_iterator;
11696
}
11697
11698
case value_t::null:
11699
case value_t::string:
11700
case value_t::boolean:
11701
case value_t::number_integer:
11702
case value_t::number_unsigned:
11703
case value_t::number_float:
11704
case value_t::binary:
11705
case value_t::discarded:
11706
default:
11707
{
11708
if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
11709
{
11710
return m_object;
11711
}
11712
11713
JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
11714
}
11715
}
11716
}
11717
11718
/*!
11719
@brief post-increment (it++)
11720
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11721
*/
11722
iter_impl const operator++(int) // NOLINT(readability-const-return-type)
11723
{
11724
auto result = *this;
11725
++(*this);
11726
return result;
11727
}
11728
11729
/*!
11730
@brief pre-increment (++it)
11731
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11732
*/
11733
iter_impl& operator++()
11734
{
11735
JSON_ASSERT(m_object != nullptr);
11736
11737
switch (m_object->m_type)
11738
{
11739
case value_t::object:
11740
{
11741
std::advance(m_it.object_iterator, 1);
11742
break;
11743
}
11744
11745
case value_t::array:
11746
{
11747
std::advance(m_it.array_iterator, 1);
11748
break;
11749
}
11750
11751
case value_t::null:
11752
case value_t::string:
11753
case value_t::boolean:
11754
case value_t::number_integer:
11755
case value_t::number_unsigned:
11756
case value_t::number_float:
11757
case value_t::binary:
11758
case value_t::discarded:
11759
default:
11760
{
11761
++m_it.primitive_iterator;
11762
break;
11763
}
11764
}
11765
11766
return *this;
11767
}
11768
11769
/*!
11770
@brief post-decrement (it--)
11771
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11772
*/
11773
iter_impl const operator--(int) // NOLINT(readability-const-return-type)
11774
{
11775
auto result = *this;
11776
--(*this);
11777
return result;
11778
}
11779
11780
/*!
11781
@brief pre-decrement (--it)
11782
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11783
*/
11784
iter_impl& operator--()
11785
{
11786
JSON_ASSERT(m_object != nullptr);
11787
11788
switch (m_object->m_type)
11789
{
11790
case value_t::object:
11791
{
11792
std::advance(m_it.object_iterator, -1);
11793
break;
11794
}
11795
11796
case value_t::array:
11797
{
11798
std::advance(m_it.array_iterator, -1);
11799
break;
11800
}
11801
11802
case value_t::null:
11803
case value_t::string:
11804
case value_t::boolean:
11805
case value_t::number_integer:
11806
case value_t::number_unsigned:
11807
case value_t::number_float:
11808
case value_t::binary:
11809
case value_t::discarded:
11810
default:
11811
{
11812
--m_it.primitive_iterator;
11813
break;
11814
}
11815
}
11816
11817
return *this;
11818
}
11819
11820
/*!
11821
@brief comparison: equal
11822
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11823
*/
11824
template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
11825
bool operator==(const IterImpl& other) const
11826
{
11827
// if objects are not the same, the comparison is undefined
11828
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
11829
{
11830
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
11831
}
11832
11833
JSON_ASSERT(m_object != nullptr);
11834
11835
switch (m_object->m_type)
11836
{
11837
case value_t::object:
11838
return (m_it.object_iterator == other.m_it.object_iterator);
11839
11840
case value_t::array:
11841
return (m_it.array_iterator == other.m_it.array_iterator);
11842
11843
case value_t::null:
11844
case value_t::string:
11845
case value_t::boolean:
11846
case value_t::number_integer:
11847
case value_t::number_unsigned:
11848
case value_t::number_float:
11849
case value_t::binary:
11850
case value_t::discarded:
11851
default:
11852
return (m_it.primitive_iterator == other.m_it.primitive_iterator);
11853
}
11854
}
11855
11856
/*!
11857
@brief comparison: not equal
11858
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11859
*/
11860
template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
11861
bool operator!=(const IterImpl& other) const
11862
{
11863
return !operator==(other);
11864
}
11865
11866
/*!
11867
@brief comparison: smaller
11868
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11869
*/
11870
bool operator<(const iter_impl& other) const
11871
{
11872
// if objects are not the same, the comparison is undefined
11873
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
11874
{
11875
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
11876
}
11877
11878
JSON_ASSERT(m_object != nullptr);
11879
11880
switch (m_object->m_type)
11881
{
11882
case value_t::object:
11883
JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object));
11884
11885
case value_t::array:
11886
return (m_it.array_iterator < other.m_it.array_iterator);
11887
11888
case value_t::null:
11889
case value_t::string:
11890
case value_t::boolean:
11891
case value_t::number_integer:
11892
case value_t::number_unsigned:
11893
case value_t::number_float:
11894
case value_t::binary:
11895
case value_t::discarded:
11896
default:
11897
return (m_it.primitive_iterator < other.m_it.primitive_iterator);
11898
}
11899
}
11900
11901
/*!
11902
@brief comparison: less than or equal
11903
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11904
*/
11905
bool operator<=(const iter_impl& other) const
11906
{
11907
return !other.operator < (*this);
11908
}
11909
11910
/*!
11911
@brief comparison: greater than
11912
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11913
*/
11914
bool operator>(const iter_impl& other) const
11915
{
11916
return !operator<=(other);
11917
}
11918
11919
/*!
11920
@brief comparison: greater than or equal
11921
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11922
*/
11923
bool operator>=(const iter_impl& other) const
11924
{
11925
return !operator<(other);
11926
}
11927
11928
/*!
11929
@brief add to iterator
11930
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11931
*/
11932
iter_impl& operator+=(difference_type i)
11933
{
11934
JSON_ASSERT(m_object != nullptr);
11935
11936
switch (m_object->m_type)
11937
{
11938
case value_t::object:
11939
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
11940
11941
case value_t::array:
11942
{
11943
std::advance(m_it.array_iterator, i);
11944
break;
11945
}
11946
11947
case value_t::null:
11948
case value_t::string:
11949
case value_t::boolean:
11950
case value_t::number_integer:
11951
case value_t::number_unsigned:
11952
case value_t::number_float:
11953
case value_t::binary:
11954
case value_t::discarded:
11955
default:
11956
{
11957
m_it.primitive_iterator += i;
11958
break;
11959
}
11960
}
11961
11962
return *this;
11963
}
11964
11965
/*!
11966
@brief subtract from iterator
11967
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11968
*/
11969
iter_impl& operator-=(difference_type i)
11970
{
11971
return operator+=(-i);
11972
}
11973
11974
/*!
11975
@brief add to iterator
11976
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11977
*/
11978
iter_impl operator+(difference_type i) const
11979
{
11980
auto result = *this;
11981
result += i;
11982
return result;
11983
}
11984
11985
/*!
11986
@brief addition of distance and iterator
11987
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11988
*/
11989
friend iter_impl operator+(difference_type i, const iter_impl& it)
11990
{
11991
auto result = it;
11992
result += i;
11993
return result;
11994
}
11995
11996
/*!
11997
@brief subtract from iterator
11998
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11999
*/
12000
iter_impl operator-(difference_type i) const
12001
{
12002
auto result = *this;
12003
result -= i;
12004
return result;
12005
}
12006
12007
/*!
12008
@brief return difference
12009
@pre The iterator is initialized; i.e. `m_object != nullptr`.
12010
*/
12011
difference_type operator-(const iter_impl& other) const
12012
{
12013
JSON_ASSERT(m_object != nullptr);
12014
12015
switch (m_object->m_type)
12016
{
12017
case value_t::object:
12018
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
12019
12020
case value_t::array:
12021
return m_it.array_iterator - other.m_it.array_iterator;
12022
12023
case value_t::null:
12024
case value_t::string:
12025
case value_t::boolean:
12026
case value_t::number_integer:
12027
case value_t::number_unsigned:
12028
case value_t::number_float:
12029
case value_t::binary:
12030
case value_t::discarded:
12031
default:
12032
return m_it.primitive_iterator - other.m_it.primitive_iterator;
12033
}
12034
}
12035
12036
/*!
12037
@brief access to successor
12038
@pre The iterator is initialized; i.e. `m_object != nullptr`.
12039
*/
12040
reference operator[](difference_type n) const
12041
{
12042
JSON_ASSERT(m_object != nullptr);
12043
12044
switch (m_object->m_type)
12045
{
12046
case value_t::object:
12047
JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object));
12048
12049
case value_t::array:
12050
return *std::next(m_it.array_iterator, n);
12051
12052
case value_t::null:
12053
JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
12054
12055
case value_t::string:
12056
case value_t::boolean:
12057
case value_t::number_integer:
12058
case value_t::number_unsigned:
12059
case value_t::number_float:
12060
case value_t::binary:
12061
case value_t::discarded:
12062
default:
12063
{
12064
if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
12065
{
12066
return *m_object;
12067
}
12068
12069
JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
12070
}
12071
}
12072
}
12073
12074
/*!
12075
@brief return the key of an object iterator
12076
@pre The iterator is initialized; i.e. `m_object != nullptr`.
12077
*/
12078
const typename object_t::key_type& key() const
12079
{
12080
JSON_ASSERT(m_object != nullptr);
12081
12082
if (JSON_HEDLEY_LIKELY(m_object->is_object()))
12083
{
12084
return m_it.object_iterator->first;
12085
}
12086
12087
JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object));
12088
}
12089
12090
/*!
12091
@brief return the value of an iterator
12092
@pre The iterator is initialized; i.e. `m_object != nullptr`.
12093
*/
12094
reference value() const
12095
{
12096
return operator*();
12097
}
12098
12099
JSON_PRIVATE_UNLESS_TESTED:
12100
/// associated JSON instance
12101
pointer m_object = nullptr;
12102
/// the actual iterator of the associated instance
12103
internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
12104
};
12105
} // namespace detail
12106
} // namespace nlohmann
12107
12108
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
12109
12110
// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
12111
12112
12113
#include <cstddef> // ptrdiff_t
12114
#include <iterator> // reverse_iterator
12115
#include <utility> // declval
12116
12117
namespace nlohmann
12118
{
12119
namespace detail
12120
{
12121
//////////////////////
12122
// reverse_iterator //
12123
//////////////////////
12124
12125
/*!
12126
@brief a template for a reverse iterator class
12127
12128
@tparam Base the base iterator type to reverse. Valid types are @ref
12129
iterator (to create @ref reverse_iterator) and @ref const_iterator (to
12130
create @ref const_reverse_iterator).
12131
12132
@requirement The class satisfies the following concept requirements:
12133
-
12134
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
12135
The iterator that can be moved can be moved in both directions (i.e.
12136
incremented and decremented).
12137
- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
12138
It is possible to write to the pointed-to element (only if @a Base is
12139
@ref iterator).
12140
12141
@since version 1.0.0
12142
*/
12143
template<typename Base>
12144
class json_reverse_iterator : public std::reverse_iterator<Base>
12145
{
12146
public:
12147
using difference_type = std::ptrdiff_t;
12148
/// shortcut to the reverse iterator adapter
12149
using base_iterator = std::reverse_iterator<Base>;
12150
/// the reference type for the pointed-to element
12151
using reference = typename Base::reference;
12152
12153
/// create reverse iterator from iterator
12154
explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
12155
: base_iterator(it) {}
12156
12157
/// create reverse iterator from base class
12158
explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
12159
12160
/// post-increment (it++)
12161
json_reverse_iterator const operator++(int) // NOLINT(readability-const-return-type)
12162
{
12163
return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
12164
}
12165
12166
/// pre-increment (++it)
12167
json_reverse_iterator& operator++()
12168
{
12169
return static_cast<json_reverse_iterator&>(base_iterator::operator++());
12170
}
12171
12172
/// post-decrement (it--)
12173
json_reverse_iterator const operator--(int) // NOLINT(readability-const-return-type)
12174
{
12175
return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
12176
}
12177
12178
/// pre-decrement (--it)
12179
json_reverse_iterator& operator--()
12180
{
12181
return static_cast<json_reverse_iterator&>(base_iterator::operator--());
12182
}
12183
12184
/// add to iterator
12185
json_reverse_iterator& operator+=(difference_type i)
12186
{
12187
return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
12188
}
12189
12190
/// add to iterator
12191
json_reverse_iterator operator+(difference_type i) const
12192
{
12193
return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
12194
}
12195
12196
/// subtract from iterator
12197
json_reverse_iterator operator-(difference_type i) const
12198
{
12199
return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
12200
}
12201
12202
/// return difference
12203
difference_type operator-(const json_reverse_iterator& other) const
12204
{
12205
return base_iterator(*this) - base_iterator(other);
12206
}
12207
12208
/// access to successor
12209
reference operator[](difference_type n) const
12210
{
12211
return *(this->operator+(n));
12212
}
12213
12214
/// return the key of an object iterator
12215
auto key() const -> decltype(std::declval<Base>().key())
12216
{
12217
auto it = --this->base();
12218
return it.key();
12219
}
12220
12221
/// return the value of an iterator
12222
reference value() const
12223
{
12224
auto it = --this->base();
12225
return it.operator * ();
12226
}
12227
};
12228
} // namespace detail
12229
} // namespace nlohmann
12230
12231
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12232
12233
// #include <nlohmann/detail/json_pointer.hpp>
12234
12235
12236
#include <algorithm> // all_of
12237
#include <cctype> // isdigit
12238
#include <limits> // max
12239
#include <numeric> // accumulate
12240
#include <string> // string
12241
#include <utility> // move
12242
#include <vector> // vector
12243
12244
// #include <nlohmann/detail/exceptions.hpp>
12245
12246
// #include <nlohmann/detail/macro_scope.hpp>
12247
12248
// #include <nlohmann/detail/string_escape.hpp>
12249
12250
// #include <nlohmann/detail/value_t.hpp>
12251
12252
12253
namespace nlohmann
12254
{
12255
12256
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
12257
/// @sa https://json.nlohmann.me/api/json_pointer/
12258
template<typename BasicJsonType>
12259
class json_pointer
12260
{
12261
// allow basic_json to access private members
12262
NLOHMANN_BASIC_JSON_TPL_DECLARATION
12263
friend class basic_json;
12264
12265
public:
12266
/// @brief create JSON pointer
12267
/// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
12268
explicit json_pointer(const std::string& s = "")
12269
: reference_tokens(split(s))
12270
{}
12271
12272
/// @brief return a string representation of the JSON pointer
12273
/// @sa https://json.nlohmann.me/api/json_pointer/to_string/
12274
std::string to_string() const
12275
{
12276
return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
12277
std::string{},
12278
[](const std::string & a, const std::string & b)
12279
{
12280
return a + "/" + detail::escape(b);
12281
});
12282
}
12283
12284
/// @brief return a string representation of the JSON pointer
12285
/// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
12286
operator std::string() const
12287
{
12288
return to_string();
12289
}
12290
12291
/// @brief append another JSON pointer at the end of this JSON pointer
12292
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
12293
json_pointer& operator/=(const json_pointer& ptr)
12294
{
12295
reference_tokens.insert(reference_tokens.end(),
12296
ptr.reference_tokens.begin(),
12297
ptr.reference_tokens.end());
12298
return *this;
12299
}
12300
12301
/// @brief append an unescaped reference token at the end of this JSON pointer
12302
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
12303
json_pointer& operator/=(std::string token)
12304
{
12305
push_back(std::move(token));
12306
return *this;
12307
}
12308
12309
/// @brief append an array index at the end of this JSON pointer
12310
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
12311
json_pointer& operator/=(std::size_t array_idx)
12312
{
12313
return *this /= std::to_string(array_idx);
12314
}
12315
12316
/// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
12317
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
12318
friend json_pointer operator/(const json_pointer& lhs,
12319
const json_pointer& rhs)
12320
{
12321
return json_pointer(lhs) /= rhs;
12322
}
12323
12324
/// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
12325
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
12326
friend json_pointer operator/(const json_pointer& lhs, std::string token) // NOLINT(performance-unnecessary-value-param)
12327
{
12328
return json_pointer(lhs) /= std::move(token);
12329
}
12330
12331
/// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
12332
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
12333
friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
12334
{
12335
return json_pointer(lhs) /= array_idx;
12336
}
12337
12338
/// @brief returns the parent of this JSON pointer
12339
/// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
12340
json_pointer parent_pointer() const
12341
{
12342
if (empty())
12343
{
12344
return *this;
12345
}
12346
12347
json_pointer res = *this;
12348
res.pop_back();
12349
return res;
12350
}
12351
12352
/// @brief remove last reference token
12353
/// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
12354
void pop_back()
12355
{
12356
if (JSON_HEDLEY_UNLIKELY(empty()))
12357
{
12358
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
12359
}
12360
12361
reference_tokens.pop_back();
12362
}
12363
12364
/// @brief return last reference token
12365
/// @sa https://json.nlohmann.me/api/json_pointer/back/
12366
const std::string& back() const
12367
{
12368
if (JSON_HEDLEY_UNLIKELY(empty()))
12369
{
12370
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
12371
}
12372
12373
return reference_tokens.back();
12374
}
12375
12376
/// @brief append an unescaped token at the end of the reference pointer
12377
/// @sa https://json.nlohmann.me/api/json_pointer/push_back/
12378
void push_back(const std::string& token)
12379
{
12380
reference_tokens.push_back(token);
12381
}
12382
12383
/// @brief append an unescaped token at the end of the reference pointer
12384
/// @sa https://json.nlohmann.me/api/json_pointer/push_back/
12385
void push_back(std::string&& token)
12386
{
12387
reference_tokens.push_back(std::move(token));
12388
}
12389
12390
/// @brief return whether pointer points to the root document
12391
/// @sa https://json.nlohmann.me/api/json_pointer/empty/
12392
bool empty() const noexcept
12393
{
12394
return reference_tokens.empty();
12395
}
12396
12397
private:
12398
/*!
12399
@param[in] s reference token to be converted into an array index
12400
12401
@return integer representation of @a s
12402
12403
@throw parse_error.106 if an array index begins with '0'
12404
@throw parse_error.109 if an array index begins not with a digit
12405
@throw out_of_range.404 if string @a s could not be converted to an integer
12406
@throw out_of_range.410 if an array index exceeds size_type
12407
*/
12408
static typename BasicJsonType::size_type array_index(const std::string& s)
12409
{
12410
using size_type = typename BasicJsonType::size_type;
12411
12412
// error condition (cf. RFC 6901, Sect. 4)
12413
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
12414
{
12415
JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", BasicJsonType()));
12416
}
12417
12418
// error condition (cf. RFC 6901, Sect. 4)
12419
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
12420
{
12421
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType()));
12422
}
12423
12424
std::size_t processed_chars = 0;
12425
unsigned long long res = 0; // NOLINT(runtime/int)
12426
JSON_TRY
12427
{
12428
res = std::stoull(s, &processed_chars);
12429
}
12430
JSON_CATCH(std::out_of_range&)
12431
{
12432
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
12433
}
12434
12435
// check if the string was completely read
12436
if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
12437
{
12438
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
12439
}
12440
12441
// only triggered on special platforms (like 32bit), see also
12442
// https://github.com/nlohmann/json/pull/2203
12443
if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
12444
{
12445
JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", BasicJsonType())); // LCOV_EXCL_LINE
12446
}
12447
12448
return static_cast<size_type>(res);
12449
}
12450
12451
JSON_PRIVATE_UNLESS_TESTED:
12452
json_pointer top() const
12453
{
12454
if (JSON_HEDLEY_UNLIKELY(empty()))
12455
{
12456
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
12457
}
12458
12459
json_pointer result = *this;
12460
result.reference_tokens = {reference_tokens[0]};
12461
return result;
12462
}
12463
12464
private:
12465
/*!
12466
@brief create and return a reference to the pointed to value
12467
12468
@complexity Linear in the number of reference tokens.
12469
12470
@throw parse_error.109 if array index is not a number
12471
@throw type_error.313 if value cannot be unflattened
12472
*/
12473
BasicJsonType& get_and_create(BasicJsonType& j) const
12474
{
12475
auto* result = &j;
12476
12477
// in case no reference tokens exist, return a reference to the JSON value
12478
// j which will be overwritten by a primitive value
12479
for (const auto& reference_token : reference_tokens)
12480
{
12481
switch (result->type())
12482
{
12483
case detail::value_t::null:
12484
{
12485
if (reference_token == "0")
12486
{
12487
// start a new array if reference token is 0
12488
result = &result->operator[](0);
12489
}
12490
else
12491
{
12492
// start a new object otherwise
12493
result = &result->operator[](reference_token);
12494
}
12495
break;
12496
}
12497
12498
case detail::value_t::object:
12499
{
12500
// create an entry in the object
12501
result = &result->operator[](reference_token);
12502
break;
12503
}
12504
12505
case detail::value_t::array:
12506
{
12507
// create an entry in the array
12508
result = &result->operator[](array_index(reference_token));
12509
break;
12510
}
12511
12512
/*
12513
The following code is only reached if there exists a reference
12514
token _and_ the current value is primitive. In this case, we have
12515
an error situation, because primitive values may only occur as
12516
single value; that is, with an empty list of reference tokens.
12517
*/
12518
case detail::value_t::string:
12519
case detail::value_t::boolean:
12520
case detail::value_t::number_integer:
12521
case detail::value_t::number_unsigned:
12522
case detail::value_t::number_float:
12523
case detail::value_t::binary:
12524
case detail::value_t::discarded:
12525
default:
12526
JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j));
12527
}
12528
}
12529
12530
return *result;
12531
}
12532
12533
/*!
12534
@brief return a reference to the pointed to value
12535
12536
@note This version does not throw if a value is not present, but tries to
12537
create nested values instead. For instance, calling this function
12538
with pointer `"/this/that"` on a null value is equivalent to calling
12539
`operator[]("this").operator[]("that")` on that value, effectively
12540
changing the null value to an object.
12541
12542
@param[in] ptr a JSON value
12543
12544
@return reference to the JSON value pointed to by the JSON pointer
12545
12546
@complexity Linear in the length of the JSON pointer.
12547
12548
@throw parse_error.106 if an array index begins with '0'
12549
@throw parse_error.109 if an array index was not a number
12550
@throw out_of_range.404 if the JSON pointer can not be resolved
12551
*/
12552
BasicJsonType& get_unchecked(BasicJsonType* ptr) const
12553
{
12554
for (const auto& reference_token : reference_tokens)
12555
{
12556
// convert null values to arrays or objects before continuing
12557
if (ptr->is_null())
12558
{
12559
// check if reference token is a number
12560
const bool nums =
12561
std::all_of(reference_token.begin(), reference_token.end(),
12562
[](const unsigned char x)
12563
{
12564
return std::isdigit(x);
12565
});
12566
12567
// change value to array for numbers or "-" or to object otherwise
12568
*ptr = (nums || reference_token == "-")
12569
? detail::value_t::array
12570
: detail::value_t::object;
12571
}
12572
12573
switch (ptr->type())
12574
{
12575
case detail::value_t::object:
12576
{
12577
// use unchecked object access
12578
ptr = &ptr->operator[](reference_token);
12579
break;
12580
}
12581
12582
case detail::value_t::array:
12583
{
12584
if (reference_token == "-")
12585
{
12586
// explicitly treat "-" as index beyond the end
12587
ptr = &ptr->operator[](ptr->m_value.array->size());
12588
}
12589
else
12590
{
12591
// convert array index to number; unchecked access
12592
ptr = &ptr->operator[](array_index(reference_token));
12593
}
12594
break;
12595
}
12596
12597
case detail::value_t::null:
12598
case detail::value_t::string:
12599
case detail::value_t::boolean:
12600
case detail::value_t::number_integer:
12601
case detail::value_t::number_unsigned:
12602
case detail::value_t::number_float:
12603
case detail::value_t::binary:
12604
case detail::value_t::discarded:
12605
default:
12606
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
12607
}
12608
}
12609
12610
return *ptr;
12611
}
12612
12613
/*!
12614
@throw parse_error.106 if an array index begins with '0'
12615
@throw parse_error.109 if an array index was not a number
12616
@throw out_of_range.402 if the array index '-' is used
12617
@throw out_of_range.404 if the JSON pointer can not be resolved
12618
*/
12619
BasicJsonType& get_checked(BasicJsonType* ptr) const
12620
{
12621
for (const auto& reference_token : reference_tokens)
12622
{
12623
switch (ptr->type())
12624
{
12625
case detail::value_t::object:
12626
{
12627
// note: at performs range check
12628
ptr = &ptr->at(reference_token);
12629
break;
12630
}
12631
12632
case detail::value_t::array:
12633
{
12634
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12635
{
12636
// "-" always fails the range check
12637
JSON_THROW(detail::out_of_range::create(402,
12638
"array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12639
") is out of range", *ptr));
12640
}
12641
12642
// note: at performs range check
12643
ptr = &ptr->at(array_index(reference_token));
12644
break;
12645
}
12646
12647
case detail::value_t::null:
12648
case detail::value_t::string:
12649
case detail::value_t::boolean:
12650
case detail::value_t::number_integer:
12651
case detail::value_t::number_unsigned:
12652
case detail::value_t::number_float:
12653
case detail::value_t::binary:
12654
case detail::value_t::discarded:
12655
default:
12656
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
12657
}
12658
}
12659
12660
return *ptr;
12661
}
12662
12663
/*!
12664
@brief return a const reference to the pointed to value
12665
12666
@param[in] ptr a JSON value
12667
12668
@return const reference to the JSON value pointed to by the JSON
12669
pointer
12670
12671
@throw parse_error.106 if an array index begins with '0'
12672
@throw parse_error.109 if an array index was not a number
12673
@throw out_of_range.402 if the array index '-' is used
12674
@throw out_of_range.404 if the JSON pointer can not be resolved
12675
*/
12676
const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
12677
{
12678
for (const auto& reference_token : reference_tokens)
12679
{
12680
switch (ptr->type())
12681
{
12682
case detail::value_t::object:
12683
{
12684
// use unchecked object access
12685
ptr = &ptr->operator[](reference_token);
12686
break;
12687
}
12688
12689
case detail::value_t::array:
12690
{
12691
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12692
{
12693
// "-" cannot be used for const access
12694
JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range", *ptr));
12695
}
12696
12697
// use unchecked array access
12698
ptr = &ptr->operator[](array_index(reference_token));
12699
break;
12700
}
12701
12702
case detail::value_t::null:
12703
case detail::value_t::string:
12704
case detail::value_t::boolean:
12705
case detail::value_t::number_integer:
12706
case detail::value_t::number_unsigned:
12707
case detail::value_t::number_float:
12708
case detail::value_t::binary:
12709
case detail::value_t::discarded:
12710
default:
12711
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
12712
}
12713
}
12714
12715
return *ptr;
12716
}
12717
12718
/*!
12719
@throw parse_error.106 if an array index begins with '0'
12720
@throw parse_error.109 if an array index was not a number
12721
@throw out_of_range.402 if the array index '-' is used
12722
@throw out_of_range.404 if the JSON pointer can not be resolved
12723
*/
12724
const BasicJsonType& get_checked(const BasicJsonType* ptr) const
12725
{
12726
for (const auto& reference_token : reference_tokens)
12727
{
12728
switch (ptr->type())
12729
{
12730
case detail::value_t::object:
12731
{
12732
// note: at performs range check
12733
ptr = &ptr->at(reference_token);
12734
break;
12735
}
12736
12737
case detail::value_t::array:
12738
{
12739
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12740
{
12741
// "-" always fails the range check
12742
JSON_THROW(detail::out_of_range::create(402,
12743
"array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12744
") is out of range", *ptr));
12745
}
12746
12747
// note: at performs range check
12748
ptr = &ptr->at(array_index(reference_token));
12749
break;
12750
}
12751
12752
case detail::value_t::null:
12753
case detail::value_t::string:
12754
case detail::value_t::boolean:
12755
case detail::value_t::number_integer:
12756
case detail::value_t::number_unsigned:
12757
case detail::value_t::number_float:
12758
case detail::value_t::binary:
12759
case detail::value_t::discarded:
12760
default:
12761
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
12762
}
12763
}
12764
12765
return *ptr;
12766
}
12767
12768
/*!
12769
@throw parse_error.106 if an array index begins with '0'
12770
@throw parse_error.109 if an array index was not a number
12771
*/
12772
bool contains(const BasicJsonType* ptr) const
12773
{
12774
for (const auto& reference_token : reference_tokens)
12775
{
12776
switch (ptr->type())
12777
{
12778
case detail::value_t::object:
12779
{
12780
if (!ptr->contains(reference_token))
12781
{
12782
// we did not find the key in the object
12783
return false;
12784
}
12785
12786
ptr = &ptr->operator[](reference_token);
12787
break;
12788
}
12789
12790
case detail::value_t::array:
12791
{
12792
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12793
{
12794
// "-" always fails the range check
12795
return false;
12796
}
12797
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
12798
{
12799
// invalid char
12800
return false;
12801
}
12802
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
12803
{
12804
if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
12805
{
12806
// first char should be between '1' and '9'
12807
return false;
12808
}
12809
for (std::size_t i = 1; i < reference_token.size(); i++)
12810
{
12811
if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
12812
{
12813
// other char should be between '0' and '9'
12814
return false;
12815
}
12816
}
12817
}
12818
12819
const auto idx = array_index(reference_token);
12820
if (idx >= ptr->size())
12821
{
12822
// index out of range
12823
return false;
12824
}
12825
12826
ptr = &ptr->operator[](idx);
12827
break;
12828
}
12829
12830
case detail::value_t::null:
12831
case detail::value_t::string:
12832
case detail::value_t::boolean:
12833
case detail::value_t::number_integer:
12834
case detail::value_t::number_unsigned:
12835
case detail::value_t::number_float:
12836
case detail::value_t::binary:
12837
case detail::value_t::discarded:
12838
default:
12839
{
12840
// we do not expect primitive values if there is still a
12841
// reference token to process
12842
return false;
12843
}
12844
}
12845
}
12846
12847
// no reference token left means we found a primitive value
12848
return true;
12849
}
12850
12851
/*!
12852
@brief split the string input to reference tokens
12853
12854
@note This function is only called by the json_pointer constructor.
12855
All exceptions below are documented there.
12856
12857
@throw parse_error.107 if the pointer is not empty or begins with '/'
12858
@throw parse_error.108 if character '~' is not followed by '0' or '1'
12859
*/
12860
static std::vector<std::string> split(const std::string& reference_string)
12861
{
12862
std::vector<std::string> result;
12863
12864
// special case: empty reference string -> no reference tokens
12865
if (reference_string.empty())
12866
{
12867
return result;
12868
}
12869
12870
// check if nonempty reference string begins with slash
12871
if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
12872
{
12873
JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", BasicJsonType()));
12874
}
12875
12876
// extract the reference tokens:
12877
// - slash: position of the last read slash (or end of string)
12878
// - start: position after the previous slash
12879
for (
12880
// search for the first slash after the first character
12881
std::size_t slash = reference_string.find_first_of('/', 1),
12882
// set the beginning of the first reference token
12883
start = 1;
12884
// we can stop if start == 0 (if slash == std::string::npos)
12885
start != 0;
12886
// set the beginning of the next reference token
12887
// (will eventually be 0 if slash == std::string::npos)
12888
start = (slash == std::string::npos) ? 0 : slash + 1,
12889
// find next slash
12890
slash = reference_string.find_first_of('/', start))
12891
{
12892
// use the text between the beginning of the reference token
12893
// (start) and the last slash (slash).
12894
auto reference_token = reference_string.substr(start, slash - start);
12895
12896
// check reference tokens are properly escaped
12897
for (std::size_t pos = reference_token.find_first_of('~');
12898
pos != std::string::npos;
12899
pos = reference_token.find_first_of('~', pos + 1))
12900
{
12901
JSON_ASSERT(reference_token[pos] == '~');
12902
12903
// ~ must be followed by 0 or 1
12904
if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
12905
(reference_token[pos + 1] != '0' &&
12906
reference_token[pos + 1] != '1')))
12907
{
12908
JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType()));
12909
}
12910
}
12911
12912
// finally, store the reference token
12913
detail::unescape(reference_token);
12914
result.push_back(reference_token);
12915
}
12916
12917
return result;
12918
}
12919
12920
private:
12921
/*!
12922
@param[in] reference_string the reference string to the current value
12923
@param[in] value the value to consider
12924
@param[in,out] result the result object to insert values to
12925
12926
@note Empty objects or arrays are flattened to `null`.
12927
*/
12928
static void flatten(const std::string& reference_string,
12929
const BasicJsonType& value,
12930
BasicJsonType& result)
12931
{
12932
switch (value.type())
12933
{
12934
case detail::value_t::array:
12935
{
12936
if (value.m_value.array->empty())
12937
{
12938
// flatten empty array as null
12939
result[reference_string] = nullptr;
12940
}
12941
else
12942
{
12943
// iterate array and use index as reference string
12944
for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
12945
{
12946
flatten(reference_string + "/" + std::to_string(i),
12947
value.m_value.array->operator[](i), result);
12948
}
12949
}
12950
break;
12951
}
12952
12953
case detail::value_t::object:
12954
{
12955
if (value.m_value.object->empty())
12956
{
12957
// flatten empty object as null
12958
result[reference_string] = nullptr;
12959
}
12960
else
12961
{
12962
// iterate object and use keys as reference string
12963
for (const auto& element : *value.m_value.object)
12964
{
12965
flatten(reference_string + "/" + detail::escape(element.first), element.second, result);
12966
}
12967
}
12968
break;
12969
}
12970
12971
case detail::value_t::null:
12972
case detail::value_t::string:
12973
case detail::value_t::boolean:
12974
case detail::value_t::number_integer:
12975
case detail::value_t::number_unsigned:
12976
case detail::value_t::number_float:
12977
case detail::value_t::binary:
12978
case detail::value_t::discarded:
12979
default:
12980
{
12981
// add primitive value with its reference string
12982
result[reference_string] = value;
12983
break;
12984
}
12985
}
12986
}
12987
12988
/*!
12989
@param[in] value flattened JSON
12990
12991
@return unflattened JSON
12992
12993
@throw parse_error.109 if array index is not a number
12994
@throw type_error.314 if value is not an object
12995
@throw type_error.315 if object values are not primitive
12996
@throw type_error.313 if value cannot be unflattened
12997
*/
12998
static BasicJsonType
12999
unflatten(const BasicJsonType& value)
13000
{
13001
if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
13002
{
13003
JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value));
13004
}
13005
13006
BasicJsonType result;
13007
13008
// iterate the JSON object values
13009
for (const auto& element : *value.m_value.object)
13010
{
13011
if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
13012
{
13013
JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second));
13014
}
13015
13016
// assign value to reference pointed to by JSON pointer; Note that if
13017
// the JSON pointer is "" (i.e., points to the whole value), function
13018
// get_and_create returns a reference to result itself. An assignment
13019
// will then create a primitive value.
13020
json_pointer(element.first).get_and_create(result) = element.second;
13021
}
13022
13023
return result;
13024
}
13025
13026
/*!
13027
@brief compares two JSON pointers for equality
13028
13029
@param[in] lhs JSON pointer to compare
13030
@param[in] rhs JSON pointer to compare
13031
@return whether @a lhs is equal to @a rhs
13032
13033
@complexity Linear in the length of the JSON pointer
13034
13035
@exceptionsafety No-throw guarantee: this function never throws exceptions.
13036
*/
13037
friend bool operator==(json_pointer const& lhs,
13038
json_pointer const& rhs) noexcept
13039
{
13040
return lhs.reference_tokens == rhs.reference_tokens;
13041
}
13042
13043
/*!
13044
@brief compares two JSON pointers for inequality
13045
13046
@param[in] lhs JSON pointer to compare
13047
@param[in] rhs JSON pointer to compare
13048
@return whether @a lhs is not equal @a rhs
13049
13050
@complexity Linear in the length of the JSON pointer
13051
13052
@exceptionsafety No-throw guarantee: this function never throws exceptions.
13053
*/
13054
friend bool operator!=(json_pointer const& lhs,
13055
json_pointer const& rhs) noexcept
13056
{
13057
return !(lhs == rhs);
13058
}
13059
13060
/// the reference tokens
13061
std::vector<std::string> reference_tokens;
13062
};
13063
} // namespace nlohmann
13064
13065
// #include <nlohmann/detail/json_ref.hpp>
13066
13067
13068
#include <initializer_list>
13069
#include <utility>
13070
13071
// #include <nlohmann/detail/meta/type_traits.hpp>
13072
13073
13074
namespace nlohmann
13075
{
13076
namespace detail
13077
{
13078
template<typename BasicJsonType>
13079
class json_ref
13080
{
13081
public:
13082
using value_type = BasicJsonType;
13083
13084
json_ref(value_type&& value)
13085
: owned_value(std::move(value))
13086
{}
13087
13088
json_ref(const value_type& value)
13089
: value_ref(&value)
13090
{}
13091
13092
json_ref(std::initializer_list<json_ref> init)
13093
: owned_value(init)
13094
{}
13095
13096
template <
13097
class... Args,
13098
enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
13099
json_ref(Args && ... args)
13100
: owned_value(std::forward<Args>(args)...)
13101
{}
13102
13103
// class should be movable only
13104
json_ref(json_ref&&) noexcept = default;
13105
json_ref(const json_ref&) = delete;
13106
json_ref& operator=(const json_ref&) = delete;
13107
json_ref& operator=(json_ref&&) = delete;
13108
~json_ref() = default;
13109
13110
value_type moved_or_copied() const
13111
{
13112
if (value_ref == nullptr)
13113
{
13114
return std::move(owned_value);
13115
}
13116
return *value_ref;
13117
}
13118
13119
value_type const& operator*() const
13120
{
13121
return value_ref ? *value_ref : owned_value;
13122
}
13123
13124
value_type const* operator->() const
13125
{
13126
return &** this;
13127
}
13128
13129
private:
13130
mutable value_type owned_value = nullptr;
13131
value_type const* value_ref = nullptr;
13132
};
13133
} // namespace detail
13134
} // namespace nlohmann
13135
13136
// #include <nlohmann/detail/macro_scope.hpp>
13137
13138
// #include <nlohmann/detail/string_escape.hpp>
13139
13140
// #include <nlohmann/detail/meta/cpp_future.hpp>
13141
13142
// #include <nlohmann/detail/meta/type_traits.hpp>
13143
13144
// #include <nlohmann/detail/output/binary_writer.hpp>
13145
13146
13147
#include <algorithm> // reverse
13148
#include <array> // array
13149
#include <cmath> // isnan, isinf
13150
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
13151
#include <cstring> // memcpy
13152
#include <limits> // numeric_limits
13153
#include <string> // string
13154
#include <utility> // move
13155
13156
// #include <nlohmann/detail/input/binary_reader.hpp>
13157
13158
// #include <nlohmann/detail/macro_scope.hpp>
13159
13160
// #include <nlohmann/detail/output/output_adapters.hpp>
13161
13162
13163
#include <algorithm> // copy
13164
#include <cstddef> // size_t
13165
#include <iterator> // back_inserter
13166
#include <memory> // shared_ptr, make_shared
13167
#include <string> // basic_string
13168
#include <vector> // vector
13169
13170
#ifndef JSON_NO_IO
13171
#include <ios> // streamsize
13172
#include <ostream> // basic_ostream
13173
#endif // JSON_NO_IO
13174
13175
// #include <nlohmann/detail/macro_scope.hpp>
13176
13177
13178
namespace nlohmann
13179
{
13180
namespace detail
13181
{
13182
/// abstract output adapter interface
13183
template<typename CharType> struct output_adapter_protocol
13184
{
13185
virtual void write_character(CharType c) = 0;
13186
virtual void write_characters(const CharType* s, std::size_t length) = 0;
13187
virtual ~output_adapter_protocol() = default;
13188
13189
output_adapter_protocol() = default;
13190
output_adapter_protocol(const output_adapter_protocol&) = default;
13191
output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
13192
output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
13193
output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
13194
};
13195
13196
/// a type to simplify interfaces
13197
template<typename CharType>
13198
using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
13199
13200
/// output adapter for byte vectors
13201
template<typename CharType, typename AllocatorType = std::allocator<CharType>>
13202
class output_vector_adapter : public output_adapter_protocol<CharType>
13203
{
13204
public:
13205
explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
13206
: v(vec)
13207
{}
13208
13209
void write_character(CharType c) override
13210
{
13211
v.push_back(c);
13212
}
13213
13214
JSON_HEDLEY_NON_NULL(2)
13215
void write_characters(const CharType* s, std::size_t length) override
13216
{
13217
std::copy(s, s + length, std::back_inserter(v));
13218
}
13219
13220
private:
13221
std::vector<CharType, AllocatorType>& v;
13222
};
13223
13224
#ifndef JSON_NO_IO
13225
/// output adapter for output streams
13226
template<typename CharType>
13227
class output_stream_adapter : public output_adapter_protocol<CharType>
13228
{
13229
public:
13230
explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
13231
: stream(s)
13232
{}
13233
13234
void write_character(CharType c) override
13235
{
13236
stream.put(c);
13237
}
13238
13239
JSON_HEDLEY_NON_NULL(2)
13240
void write_characters(const CharType* s, std::size_t length) override
13241
{
13242
stream.write(s, static_cast<std::streamsize>(length));
13243
}
13244
13245
private:
13246
std::basic_ostream<CharType>& stream;
13247
};
13248
#endif // JSON_NO_IO
13249
13250
/// output adapter for basic_string
13251
template<typename CharType, typename StringType = std::basic_string<CharType>>
13252
class output_string_adapter : public output_adapter_protocol<CharType>
13253
{
13254
public:
13255
explicit output_string_adapter(StringType& s) noexcept
13256
: str(s)
13257
{}
13258
13259
void write_character(CharType c) override
13260
{
13261
str.push_back(c);
13262
}
13263
13264
JSON_HEDLEY_NON_NULL(2)
13265
void write_characters(const CharType* s, std::size_t length) override
13266
{
13267
str.append(s, length);
13268
}
13269
13270
private:
13271
StringType& str;
13272
};
13273
13274
template<typename CharType, typename StringType = std::basic_string<CharType>>
13275
class output_adapter
13276
{
13277
public:
13278
template<typename AllocatorType = std::allocator<CharType>>
13279
output_adapter(std::vector<CharType, AllocatorType>& vec)
13280
: oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
13281
13282
#ifndef JSON_NO_IO
13283
output_adapter(std::basic_ostream<CharType>& s)
13284
: oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
13285
#endif // JSON_NO_IO
13286
13287
output_adapter(StringType& s)
13288
: oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
13289
13290
operator output_adapter_t<CharType>()
13291
{
13292
return oa;
13293
}
13294
13295
private:
13296
output_adapter_t<CharType> oa = nullptr;
13297
};
13298
} // namespace detail
13299
} // namespace nlohmann
13300
13301
13302
namespace nlohmann
13303
{
13304
namespace detail
13305
{
13306
///////////////////
13307
// binary writer //
13308
///////////////////
13309
13310
/*!
13311
@brief serialization to CBOR and MessagePack values
13312
*/
13313
template<typename BasicJsonType, typename CharType>
13314
class binary_writer
13315
{
13316
using string_t = typename BasicJsonType::string_t;
13317
using binary_t = typename BasicJsonType::binary_t;
13318
using number_float_t = typename BasicJsonType::number_float_t;
13319
13320
public:
13321
/*!
13322
@brief create a binary writer
13323
13324
@param[in] adapter output adapter to write to
13325
*/
13326
explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
13327
{
13328
JSON_ASSERT(oa);
13329
}
13330
13331
/*!
13332
@param[in] j JSON value to serialize
13333
@pre j.type() == value_t::object
13334
*/
13335
void write_bson(const BasicJsonType& j)
13336
{
13337
switch (j.type())
13338
{
13339
case value_t::object:
13340
{
13341
write_bson_object(*j.m_value.object);
13342
break;
13343
}
13344
13345
case value_t::null:
13346
case value_t::array:
13347
case value_t::string:
13348
case value_t::boolean:
13349
case value_t::number_integer:
13350
case value_t::number_unsigned:
13351
case value_t::number_float:
13352
case value_t::binary:
13353
case value_t::discarded:
13354
default:
13355
{
13356
JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j));
13357
}
13358
}
13359
}
13360
13361
/*!
13362
@param[in] j JSON value to serialize
13363
*/
13364
void write_cbor(const BasicJsonType& j)
13365
{
13366
switch (j.type())
13367
{
13368
case value_t::null:
13369
{
13370
oa->write_character(to_char_type(0xF6));
13371
break;
13372
}
13373
13374
case value_t::boolean:
13375
{
13376
oa->write_character(j.m_value.boolean
13377
? to_char_type(0xF5)
13378
: to_char_type(0xF4));
13379
break;
13380
}
13381
13382
case value_t::number_integer:
13383
{
13384
if (j.m_value.number_integer >= 0)
13385
{
13386
// CBOR does not differentiate between positive signed
13387
// integers and unsigned integers. Therefore, we used the
13388
// code from the value_t::number_unsigned case here.
13389
if (j.m_value.number_integer <= 0x17)
13390
{
13391
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13392
}
13393
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
13394
{
13395
oa->write_character(to_char_type(0x18));
13396
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13397
}
13398
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
13399
{
13400
oa->write_character(to_char_type(0x19));
13401
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13402
}
13403
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
13404
{
13405
oa->write_character(to_char_type(0x1A));
13406
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13407
}
13408
else
13409
{
13410
oa->write_character(to_char_type(0x1B));
13411
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13412
}
13413
}
13414
else
13415
{
13416
// The conversions below encode the sign in the first
13417
// byte, and the value is converted to a positive number.
13418
const auto positive_number = -1 - j.m_value.number_integer;
13419
if (j.m_value.number_integer >= -24)
13420
{
13421
write_number(static_cast<std::uint8_t>(0x20 + positive_number));
13422
}
13423
else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
13424
{
13425
oa->write_character(to_char_type(0x38));
13426
write_number(static_cast<std::uint8_t>(positive_number));
13427
}
13428
else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
13429
{
13430
oa->write_character(to_char_type(0x39));
13431
write_number(static_cast<std::uint16_t>(positive_number));
13432
}
13433
else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
13434
{
13435
oa->write_character(to_char_type(0x3A));
13436
write_number(static_cast<std::uint32_t>(positive_number));
13437
}
13438
else
13439
{
13440
oa->write_character(to_char_type(0x3B));
13441
write_number(static_cast<std::uint64_t>(positive_number));
13442
}
13443
}
13444
break;
13445
}
13446
13447
case value_t::number_unsigned:
13448
{
13449
if (j.m_value.number_unsigned <= 0x17)
13450
{
13451
write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
13452
}
13453
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
13454
{
13455
oa->write_character(to_char_type(0x18));
13456
write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
13457
}
13458
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
13459
{
13460
oa->write_character(to_char_type(0x19));
13461
write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
13462
}
13463
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
13464
{
13465
oa->write_character(to_char_type(0x1A));
13466
write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
13467
}
13468
else
13469
{
13470
oa->write_character(to_char_type(0x1B));
13471
write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
13472
}
13473
break;
13474
}
13475
13476
case value_t::number_float:
13477
{
13478
if (std::isnan(j.m_value.number_float))
13479
{
13480
// NaN is 0xf97e00 in CBOR
13481
oa->write_character(to_char_type(0xF9));
13482
oa->write_character(to_char_type(0x7E));
13483
oa->write_character(to_char_type(0x00));
13484
}
13485
else if (std::isinf(j.m_value.number_float))
13486
{
13487
// Infinity is 0xf97c00, -Infinity is 0xf9fc00
13488
oa->write_character(to_char_type(0xf9));
13489
oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
13490
oa->write_character(to_char_type(0x00));
13491
}
13492
else
13493
{
13494
write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
13495
}
13496
break;
13497
}
13498
13499
case value_t::string:
13500
{
13501
// step 1: write control byte and the string length
13502
const auto N = j.m_value.string->size();
13503
if (N <= 0x17)
13504
{
13505
write_number(static_cast<std::uint8_t>(0x60 + N));
13506
}
13507
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13508
{
13509
oa->write_character(to_char_type(0x78));
13510
write_number(static_cast<std::uint8_t>(N));
13511
}
13512
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13513
{
13514
oa->write_character(to_char_type(0x79));
13515
write_number(static_cast<std::uint16_t>(N));
13516
}
13517
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13518
{
13519
oa->write_character(to_char_type(0x7A));
13520
write_number(static_cast<std::uint32_t>(N));
13521
}
13522
// LCOV_EXCL_START
13523
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13524
{
13525
oa->write_character(to_char_type(0x7B));
13526
write_number(static_cast<std::uint64_t>(N));
13527
}
13528
// LCOV_EXCL_STOP
13529
13530
// step 2: write the string
13531
oa->write_characters(
13532
reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
13533
j.m_value.string->size());
13534
break;
13535
}
13536
13537
case value_t::array:
13538
{
13539
// step 1: write control byte and the array size
13540
const auto N = j.m_value.array->size();
13541
if (N <= 0x17)
13542
{
13543
write_number(static_cast<std::uint8_t>(0x80 + N));
13544
}
13545
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13546
{
13547
oa->write_character(to_char_type(0x98));
13548
write_number(static_cast<std::uint8_t>(N));
13549
}
13550
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13551
{
13552
oa->write_character(to_char_type(0x99));
13553
write_number(static_cast<std::uint16_t>(N));
13554
}
13555
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13556
{
13557
oa->write_character(to_char_type(0x9A));
13558
write_number(static_cast<std::uint32_t>(N));
13559
}
13560
// LCOV_EXCL_START
13561
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13562
{
13563
oa->write_character(to_char_type(0x9B));
13564
write_number(static_cast<std::uint64_t>(N));
13565
}
13566
// LCOV_EXCL_STOP
13567
13568
// step 2: write each element
13569
for (const auto& el : *j.m_value.array)
13570
{
13571
write_cbor(el);
13572
}
13573
break;
13574
}
13575
13576
case value_t::binary:
13577
{
13578
if (j.m_value.binary->has_subtype())
13579
{
13580
if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
13581
{
13582
write_number(static_cast<std::uint8_t>(0xd8));
13583
write_number(static_cast<std::uint8_t>(j.m_value.binary->subtype()));
13584
}
13585
else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
13586
{
13587
write_number(static_cast<std::uint8_t>(0xd9));
13588
write_number(static_cast<std::uint16_t>(j.m_value.binary->subtype()));
13589
}
13590
else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
13591
{
13592
write_number(static_cast<std::uint8_t>(0xda));
13593
write_number(static_cast<std::uint32_t>(j.m_value.binary->subtype()));
13594
}
13595
else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
13596
{
13597
write_number(static_cast<std::uint8_t>(0xdb));
13598
write_number(static_cast<std::uint64_t>(j.m_value.binary->subtype()));
13599
}
13600
}
13601
13602
// step 1: write control byte and the binary array size
13603
const auto N = j.m_value.binary->size();
13604
if (N <= 0x17)
13605
{
13606
write_number(static_cast<std::uint8_t>(0x40 + N));
13607
}
13608
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13609
{
13610
oa->write_character(to_char_type(0x58));
13611
write_number(static_cast<std::uint8_t>(N));
13612
}
13613
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13614
{
13615
oa->write_character(to_char_type(0x59));
13616
write_number(static_cast<std::uint16_t>(N));
13617
}
13618
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13619
{
13620
oa->write_character(to_char_type(0x5A));
13621
write_number(static_cast<std::uint32_t>(N));
13622
}
13623
// LCOV_EXCL_START
13624
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13625
{
13626
oa->write_character(to_char_type(0x5B));
13627
write_number(static_cast<std::uint64_t>(N));
13628
}
13629
// LCOV_EXCL_STOP
13630
13631
// step 2: write each element
13632
oa->write_characters(
13633
reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13634
N);
13635
13636
break;
13637
}
13638
13639
case value_t::object:
13640
{
13641
// step 1: write control byte and the object size
13642
const auto N = j.m_value.object->size();
13643
if (N <= 0x17)
13644
{
13645
write_number(static_cast<std::uint8_t>(0xA0 + N));
13646
}
13647
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13648
{
13649
oa->write_character(to_char_type(0xB8));
13650
write_number(static_cast<std::uint8_t>(N));
13651
}
13652
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13653
{
13654
oa->write_character(to_char_type(0xB9));
13655
write_number(static_cast<std::uint16_t>(N));
13656
}
13657
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13658
{
13659
oa->write_character(to_char_type(0xBA));
13660
write_number(static_cast<std::uint32_t>(N));
13661
}
13662
// LCOV_EXCL_START
13663
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13664
{
13665
oa->write_character(to_char_type(0xBB));
13666
write_number(static_cast<std::uint64_t>(N));
13667
}
13668
// LCOV_EXCL_STOP
13669
13670
// step 2: write each element
13671
for (const auto& el : *j.m_value.object)
13672
{
13673
write_cbor(el.first);
13674
write_cbor(el.second);
13675
}
13676
break;
13677
}
13678
13679
case value_t::discarded:
13680
default:
13681
break;
13682
}
13683
}
13684
13685
/*!
13686
@param[in] j JSON value to serialize
13687
*/
13688
void write_msgpack(const BasicJsonType& j)
13689
{
13690
switch (j.type())
13691
{
13692
case value_t::null: // nil
13693
{
13694
oa->write_character(to_char_type(0xC0));
13695
break;
13696
}
13697
13698
case value_t::boolean: // true and false
13699
{
13700
oa->write_character(j.m_value.boolean
13701
? to_char_type(0xC3)
13702
: to_char_type(0xC2));
13703
break;
13704
}
13705
13706
case value_t::number_integer:
13707
{
13708
if (j.m_value.number_integer >= 0)
13709
{
13710
// MessagePack does not differentiate between positive
13711
// signed integers and unsigned integers. Therefore, we used
13712
// the code from the value_t::number_unsigned case here.
13713
if (j.m_value.number_unsigned < 128)
13714
{
13715
// positive fixnum
13716
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13717
}
13718
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
13719
{
13720
// uint 8
13721
oa->write_character(to_char_type(0xCC));
13722
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13723
}
13724
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
13725
{
13726
// uint 16
13727
oa->write_character(to_char_type(0xCD));
13728
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13729
}
13730
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
13731
{
13732
// uint 32
13733
oa->write_character(to_char_type(0xCE));
13734
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13735
}
13736
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
13737
{
13738
// uint 64
13739
oa->write_character(to_char_type(0xCF));
13740
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13741
}
13742
}
13743
else
13744
{
13745
if (j.m_value.number_integer >= -32)
13746
{
13747
// negative fixnum
13748
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
13749
}
13750
else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
13751
j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
13752
{
13753
// int 8
13754
oa->write_character(to_char_type(0xD0));
13755
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
13756
}
13757
else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
13758
j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
13759
{
13760
// int 16
13761
oa->write_character(to_char_type(0xD1));
13762
write_number(static_cast<std::int16_t>(j.m_value.number_integer));
13763
}
13764
else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
13765
j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
13766
{
13767
// int 32
13768
oa->write_character(to_char_type(0xD2));
13769
write_number(static_cast<std::int32_t>(j.m_value.number_integer));
13770
}
13771
else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
13772
j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
13773
{
13774
// int 64
13775
oa->write_character(to_char_type(0xD3));
13776
write_number(static_cast<std::int64_t>(j.m_value.number_integer));
13777
}
13778
}
13779
break;
13780
}
13781
13782
case value_t::number_unsigned:
13783
{
13784
if (j.m_value.number_unsigned < 128)
13785
{
13786
// positive fixnum
13787
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13788
}
13789
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
13790
{
13791
// uint 8
13792
oa->write_character(to_char_type(0xCC));
13793
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13794
}
13795
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
13796
{
13797
// uint 16
13798
oa->write_character(to_char_type(0xCD));
13799
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13800
}
13801
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
13802
{
13803
// uint 32
13804
oa->write_character(to_char_type(0xCE));
13805
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13806
}
13807
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
13808
{
13809
// uint 64
13810
oa->write_character(to_char_type(0xCF));
13811
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13812
}
13813
break;
13814
}
13815
13816
case value_t::number_float:
13817
{
13818
write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
13819
break;
13820
}
13821
13822
case value_t::string:
13823
{
13824
// step 1: write control byte and the string length
13825
const auto N = j.m_value.string->size();
13826
if (N <= 31)
13827
{
13828
// fixstr
13829
write_number(static_cast<std::uint8_t>(0xA0 | N));
13830
}
13831
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13832
{
13833
// str 8
13834
oa->write_character(to_char_type(0xD9));
13835
write_number(static_cast<std::uint8_t>(N));
13836
}
13837
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13838
{
13839
// str 16
13840
oa->write_character(to_char_type(0xDA));
13841
write_number(static_cast<std::uint16_t>(N));
13842
}
13843
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13844
{
13845
// str 32
13846
oa->write_character(to_char_type(0xDB));
13847
write_number(static_cast<std::uint32_t>(N));
13848
}
13849
13850
// step 2: write the string
13851
oa->write_characters(
13852
reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
13853
j.m_value.string->size());
13854
break;
13855
}
13856
13857
case value_t::array:
13858
{
13859
// step 1: write control byte and the array size
13860
const auto N = j.m_value.array->size();
13861
if (N <= 15)
13862
{
13863
// fixarray
13864
write_number(static_cast<std::uint8_t>(0x90 | N));
13865
}
13866
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13867
{
13868
// array 16
13869
oa->write_character(to_char_type(0xDC));
13870
write_number(static_cast<std::uint16_t>(N));
13871
}
13872
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13873
{
13874
// array 32
13875
oa->write_character(to_char_type(0xDD));
13876
write_number(static_cast<std::uint32_t>(N));
13877
}
13878
13879
// step 2: write each element
13880
for (const auto& el : *j.m_value.array)
13881
{
13882
write_msgpack(el);
13883
}
13884
break;
13885
}
13886
13887
case value_t::binary:
13888
{
13889
// step 0: determine if the binary type has a set subtype to
13890
// determine whether or not to use the ext or fixext types
13891
const bool use_ext = j.m_value.binary->has_subtype();
13892
13893
// step 1: write control byte and the byte string length
13894
const auto N = j.m_value.binary->size();
13895
if (N <= (std::numeric_limits<std::uint8_t>::max)())
13896
{
13897
std::uint8_t output_type{};
13898
bool fixed = true;
13899
if (use_ext)
13900
{
13901
switch (N)
13902
{
13903
case 1:
13904
output_type = 0xD4; // fixext 1
13905
break;
13906
case 2:
13907
output_type = 0xD5; // fixext 2
13908
break;
13909
case 4:
13910
output_type = 0xD6; // fixext 4
13911
break;
13912
case 8:
13913
output_type = 0xD7; // fixext 8
13914
break;
13915
case 16:
13916
output_type = 0xD8; // fixext 16
13917
break;
13918
default:
13919
output_type = 0xC7; // ext 8
13920
fixed = false;
13921
break;
13922
}
13923
13924
}
13925
else
13926
{
13927
output_type = 0xC4; // bin 8
13928
fixed = false;
13929
}
13930
13931
oa->write_character(to_char_type(output_type));
13932
if (!fixed)
13933
{
13934
write_number(static_cast<std::uint8_t>(N));
13935
}
13936
}
13937
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13938
{
13939
std::uint8_t output_type = use_ext
13940
? 0xC8 // ext 16
13941
: 0xC5; // bin 16
13942
13943
oa->write_character(to_char_type(output_type));
13944
write_number(static_cast<std::uint16_t>(N));
13945
}
13946
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13947
{
13948
std::uint8_t output_type = use_ext
13949
? 0xC9 // ext 32
13950
: 0xC6; // bin 32
13951
13952
oa->write_character(to_char_type(output_type));
13953
write_number(static_cast<std::uint32_t>(N));
13954
}
13955
13956
// step 1.5: if this is an ext type, write the subtype
13957
if (use_ext)
13958
{
13959
write_number(static_cast<std::int8_t>(j.m_value.binary->subtype()));
13960
}
13961
13962
// step 2: write the byte string
13963
oa->write_characters(
13964
reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13965
N);
13966
13967
break;
13968
}
13969
13970
case value_t::object:
13971
{
13972
// step 1: write control byte and the object size
13973
const auto N = j.m_value.object->size();
13974
if (N <= 15)
13975
{
13976
// fixmap
13977
write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
13978
}
13979
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13980
{
13981
// map 16
13982
oa->write_character(to_char_type(0xDE));
13983
write_number(static_cast<std::uint16_t>(N));
13984
}
13985
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13986
{
13987
// map 32
13988
oa->write_character(to_char_type(0xDF));
13989
write_number(static_cast<std::uint32_t>(N));
13990
}
13991
13992
// step 2: write each element
13993
for (const auto& el : *j.m_value.object)
13994
{
13995
write_msgpack(el.first);
13996
write_msgpack(el.second);
13997
}
13998
break;
13999
}
14000
14001
case value_t::discarded:
14002
default:
14003
break;
14004
}
14005
}
14006
14007
/*!
14008
@param[in] j JSON value to serialize
14009
@param[in] use_count whether to use '#' prefixes (optimized format)
14010
@param[in] use_type whether to use '$' prefixes (optimized format)
14011
@param[in] add_prefix whether prefixes need to be used for this value
14012
*/
14013
void write_ubjson(const BasicJsonType& j, const bool use_count,
14014
const bool use_type, const bool add_prefix = true)
14015
{
14016
switch (j.type())
14017
{
14018
case value_t::null:
14019
{
14020
if (add_prefix)
14021
{
14022
oa->write_character(to_char_type('Z'));
14023
}
14024
break;
14025
}
14026
14027
case value_t::boolean:
14028
{
14029
if (add_prefix)
14030
{
14031
oa->write_character(j.m_value.boolean
14032
? to_char_type('T')
14033
: to_char_type('F'));
14034
}
14035
break;
14036
}
14037
14038
case value_t::number_integer:
14039
{
14040
write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
14041
break;
14042
}
14043
14044
case value_t::number_unsigned:
14045
{
14046
write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
14047
break;
14048
}
14049
14050
case value_t::number_float:
14051
{
14052
write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
14053
break;
14054
}
14055
14056
case value_t::string:
14057
{
14058
if (add_prefix)
14059
{
14060
oa->write_character(to_char_type('S'));
14061
}
14062
write_number_with_ubjson_prefix(j.m_value.string->size(), true);
14063
oa->write_characters(
14064
reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
14065
j.m_value.string->size());
14066
break;
14067
}
14068
14069
case value_t::array:
14070
{
14071
if (add_prefix)
14072
{
14073
oa->write_character(to_char_type('['));
14074
}
14075
14076
bool prefix_required = true;
14077
if (use_type && !j.m_value.array->empty())
14078
{
14079
JSON_ASSERT(use_count);
14080
const CharType first_prefix = ubjson_prefix(j.front());
14081
const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
14082
[this, first_prefix](const BasicJsonType & v)
14083
{
14084
return ubjson_prefix(v) == first_prefix;
14085
});
14086
14087
if (same_prefix)
14088
{
14089
prefix_required = false;
14090
oa->write_character(to_char_type('$'));
14091
oa->write_character(first_prefix);
14092
}
14093
}
14094
14095
if (use_count)
14096
{
14097
oa->write_character(to_char_type('#'));
14098
write_number_with_ubjson_prefix(j.m_value.array->size(), true);
14099
}
14100
14101
for (const auto& el : *j.m_value.array)
14102
{
14103
write_ubjson(el, use_count, use_type, prefix_required);
14104
}
14105
14106
if (!use_count)
14107
{
14108
oa->write_character(to_char_type(']'));
14109
}
14110
14111
break;
14112
}
14113
14114
case value_t::binary:
14115
{
14116
if (add_prefix)
14117
{
14118
oa->write_character(to_char_type('['));
14119
}
14120
14121
if (use_type && !j.m_value.binary->empty())
14122
{
14123
JSON_ASSERT(use_count);
14124
oa->write_character(to_char_type('$'));
14125
oa->write_character('U');
14126
}
14127
14128
if (use_count)
14129
{
14130
oa->write_character(to_char_type('#'));
14131
write_number_with_ubjson_prefix(j.m_value.binary->size(), true);
14132
}
14133
14134
if (use_type)
14135
{
14136
oa->write_characters(
14137
reinterpret_cast<const CharType*>(j.m_value.binary->data()),
14138
j.m_value.binary->size());
14139
}
14140
else
14141
{
14142
for (size_t i = 0; i < j.m_value.binary->size(); ++i)
14143
{
14144
oa->write_character(to_char_type('U'));
14145
oa->write_character(j.m_value.binary->data()[i]);
14146
}
14147
}
14148
14149
if (!use_count)
14150
{
14151
oa->write_character(to_char_type(']'));
14152
}
14153
14154
break;
14155
}
14156
14157
case value_t::object:
14158
{
14159
if (add_prefix)
14160
{
14161
oa->write_character(to_char_type('{'));
14162
}
14163
14164
bool prefix_required = true;
14165
if (use_type && !j.m_value.object->empty())
14166
{
14167
JSON_ASSERT(use_count);
14168
const CharType first_prefix = ubjson_prefix(j.front());
14169
const bool same_prefix = std::all_of(j.begin(), j.end(),
14170
[this, first_prefix](const BasicJsonType & v)
14171
{
14172
return ubjson_prefix(v) == first_prefix;
14173
});
14174
14175
if (same_prefix)
14176
{
14177
prefix_required = false;
14178
oa->write_character(to_char_type('$'));
14179
oa->write_character(first_prefix);
14180
}
14181
}
14182
14183
if (use_count)
14184
{
14185
oa->write_character(to_char_type('#'));
14186
write_number_with_ubjson_prefix(j.m_value.object->size(), true);
14187
}
14188
14189
for (const auto& el : *j.m_value.object)
14190
{
14191
write_number_with_ubjson_prefix(el.first.size(), true);
14192
oa->write_characters(
14193
reinterpret_cast<const CharType*>(el.first.c_str()),
14194
el.first.size());
14195
write_ubjson(el.second, use_count, use_type, prefix_required);
14196
}
14197
14198
if (!use_count)
14199
{
14200
oa->write_character(to_char_type('}'));
14201
}
14202
14203
break;
14204
}
14205
14206
case value_t::discarded:
14207
default:
14208
break;
14209
}
14210
}
14211
14212
private:
14213
//////////
14214
// BSON //
14215
//////////
14216
14217
/*!
14218
@return The size of a BSON document entry header, including the id marker
14219
and the entry name size (and its null-terminator).
14220
*/
14221
static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
14222
{
14223
const auto it = name.find(static_cast<typename string_t::value_type>(0));
14224
if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
14225
{
14226
JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j));
14227
static_cast<void>(j);
14228
}
14229
14230
return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
14231
}
14232
14233
/*!
14234
@brief Writes the given @a element_type and @a name to the output adapter
14235
*/
14236
void write_bson_entry_header(const string_t& name,
14237
const std::uint8_t element_type)
14238
{
14239
oa->write_character(to_char_type(element_type)); // boolean
14240
oa->write_characters(
14241
reinterpret_cast<const CharType*>(name.c_str()),
14242
name.size() + 1u);
14243
}
14244
14245
/*!
14246
@brief Writes a BSON element with key @a name and boolean value @a value
14247
*/
14248
void write_bson_boolean(const string_t& name,
14249
const bool value)
14250
{
14251
write_bson_entry_header(name, 0x08);
14252
oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
14253
}
14254
14255
/*!
14256
@brief Writes a BSON element with key @a name and double value @a value
14257
*/
14258
void write_bson_double(const string_t& name,
14259
const double value)
14260
{
14261
write_bson_entry_header(name, 0x01);
14262
write_number<double, true>(value);
14263
}
14264
14265
/*!
14266
@return The size of the BSON-encoded string in @a value
14267
*/
14268
static std::size_t calc_bson_string_size(const string_t& value)
14269
{
14270
return sizeof(std::int32_t) + value.size() + 1ul;
14271
}
14272
14273
/*!
14274
@brief Writes a BSON element with key @a name and string value @a value
14275
*/
14276
void write_bson_string(const string_t& name,
14277
const string_t& value)
14278
{
14279
write_bson_entry_header(name, 0x02);
14280
14281
write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
14282
oa->write_characters(
14283
reinterpret_cast<const CharType*>(value.c_str()),
14284
value.size() + 1);
14285
}
14286
14287
/*!
14288
@brief Writes a BSON element with key @a name and null value
14289
*/
14290
void write_bson_null(const string_t& name)
14291
{
14292
write_bson_entry_header(name, 0x0A);
14293
}
14294
14295
/*!
14296
@return The size of the BSON-encoded integer @a value
14297
*/
14298
static std::size_t calc_bson_integer_size(const std::int64_t value)
14299
{
14300
return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
14301
? sizeof(std::int32_t)
14302
: sizeof(std::int64_t);
14303
}
14304
14305
/*!
14306
@brief Writes a BSON element with key @a name and integer @a value
14307
*/
14308
void write_bson_integer(const string_t& name,
14309
const std::int64_t value)
14310
{
14311
if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
14312
{
14313
write_bson_entry_header(name, 0x10); // int32
14314
write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
14315
}
14316
else
14317
{
14318
write_bson_entry_header(name, 0x12); // int64
14319
write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
14320
}
14321
}
14322
14323
/*!
14324
@return The size of the BSON-encoded unsigned integer in @a j
14325
*/
14326
static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
14327
{
14328
return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14329
? sizeof(std::int32_t)
14330
: sizeof(std::int64_t);
14331
}
14332
14333
/*!
14334
@brief Writes a BSON element with key @a name and unsigned @a value
14335
*/
14336
void write_bson_unsigned(const string_t& name,
14337
const BasicJsonType& j)
14338
{
14339
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14340
{
14341
write_bson_entry_header(name, 0x10 /* int32 */);
14342
write_number<std::int32_t, true>(static_cast<std::int32_t>(j.m_value.number_unsigned));
14343
}
14344
else if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14345
{
14346
write_bson_entry_header(name, 0x12 /* int64 */);
14347
write_number<std::int64_t, true>(static_cast<std::int64_t>(j.m_value.number_unsigned));
14348
}
14349
else
14350
{
14351
JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", j));
14352
}
14353
}
14354
14355
/*!
14356
@brief Writes a BSON element with key @a name and object @a value
14357
*/
14358
void write_bson_object_entry(const string_t& name,
14359
const typename BasicJsonType::object_t& value)
14360
{
14361
write_bson_entry_header(name, 0x03); // object
14362
write_bson_object(value);
14363
}
14364
14365
/*!
14366
@return The size of the BSON-encoded array @a value
14367
*/
14368
static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
14369
{
14370
std::size_t array_index = 0ul;
14371
14372
const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
14373
{
14374
return result + calc_bson_element_size(std::to_string(array_index++), el);
14375
});
14376
14377
return sizeof(std::int32_t) + embedded_document_size + 1ul;
14378
}
14379
14380
/*!
14381
@return The size of the BSON-encoded binary array @a value
14382
*/
14383
static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
14384
{
14385
return sizeof(std::int32_t) + value.size() + 1ul;
14386
}
14387
14388
/*!
14389
@brief Writes a BSON element with key @a name and array @a value
14390
*/
14391
void write_bson_array(const string_t& name,
14392
const typename BasicJsonType::array_t& value)
14393
{
14394
write_bson_entry_header(name, 0x04); // array
14395
write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
14396
14397
std::size_t array_index = 0ul;
14398
14399
for (const auto& el : value)
14400
{
14401
write_bson_element(std::to_string(array_index++), el);
14402
}
14403
14404
oa->write_character(to_char_type(0x00));
14405
}
14406
14407
/*!
14408
@brief Writes a BSON element with key @a name and binary value @a value
14409
*/
14410
void write_bson_binary(const string_t& name,
14411
const binary_t& value)
14412
{
14413
write_bson_entry_header(name, 0x05);
14414
14415
write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
14416
write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
14417
14418
oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
14419
}
14420
14421
/*!
14422
@brief Calculates the size necessary to serialize the JSON value @a j with its @a name
14423
@return The calculated size for the BSON document entry for @a j with the given @a name.
14424
*/
14425
static std::size_t calc_bson_element_size(const string_t& name,
14426
const BasicJsonType& j)
14427
{
14428
const auto header_size = calc_bson_entry_header_size(name, j);
14429
switch (j.type())
14430
{
14431
case value_t::object:
14432
return header_size + calc_bson_object_size(*j.m_value.object);
14433
14434
case value_t::array:
14435
return header_size + calc_bson_array_size(*j.m_value.array);
14436
14437
case value_t::binary:
14438
return header_size + calc_bson_binary_size(*j.m_value.binary);
14439
14440
case value_t::boolean:
14441
return header_size + 1ul;
14442
14443
case value_t::number_float:
14444
return header_size + 8ul;
14445
14446
case value_t::number_integer:
14447
return header_size + calc_bson_integer_size(j.m_value.number_integer);
14448
14449
case value_t::number_unsigned:
14450
return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
14451
14452
case value_t::string:
14453
return header_size + calc_bson_string_size(*j.m_value.string);
14454
14455
case value_t::null:
14456
return header_size + 0ul;
14457
14458
// LCOV_EXCL_START
14459
case value_t::discarded:
14460
default:
14461
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
14462
return 0ul;
14463
// LCOV_EXCL_STOP
14464
}
14465
}
14466
14467
/*!
14468
@brief Serializes the JSON value @a j to BSON and associates it with the
14469
key @a name.
14470
@param name The name to associate with the JSON entity @a j within the
14471
current BSON document
14472
*/
14473
void write_bson_element(const string_t& name,
14474
const BasicJsonType& j)
14475
{
14476
switch (j.type())
14477
{
14478
case value_t::object:
14479
return write_bson_object_entry(name, *j.m_value.object);
14480
14481
case value_t::array:
14482
return write_bson_array(name, *j.m_value.array);
14483
14484
case value_t::binary:
14485
return write_bson_binary(name, *j.m_value.binary);
14486
14487
case value_t::boolean:
14488
return write_bson_boolean(name, j.m_value.boolean);
14489
14490
case value_t::number_float:
14491
return write_bson_double(name, j.m_value.number_float);
14492
14493
case value_t::number_integer:
14494
return write_bson_integer(name, j.m_value.number_integer);
14495
14496
case value_t::number_unsigned:
14497
return write_bson_unsigned(name, j);
14498
14499
case value_t::string:
14500
return write_bson_string(name, *j.m_value.string);
14501
14502
case value_t::null:
14503
return write_bson_null(name);
14504
14505
// LCOV_EXCL_START
14506
case value_t::discarded:
14507
default:
14508
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
14509
return;
14510
// LCOV_EXCL_STOP
14511
}
14512
}
14513
14514
/*!
14515
@brief Calculates the size of the BSON serialization of the given
14516
JSON-object @a j.
14517
@param[in] value JSON value to serialize
14518
@pre value.type() == value_t::object
14519
*/
14520
static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
14521
{
14522
std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
14523
[](size_t result, const typename BasicJsonType::object_t::value_type & el)
14524
{
14525
return result += calc_bson_element_size(el.first, el.second);
14526
});
14527
14528
return sizeof(std::int32_t) + document_size + 1ul;
14529
}
14530
14531
/*!
14532
@param[in] value JSON value to serialize
14533
@pre value.type() == value_t::object
14534
*/
14535
void write_bson_object(const typename BasicJsonType::object_t& value)
14536
{
14537
write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
14538
14539
for (const auto& el : value)
14540
{
14541
write_bson_element(el.first, el.second);
14542
}
14543
14544
oa->write_character(to_char_type(0x00));
14545
}
14546
14547
//////////
14548
// CBOR //
14549
//////////
14550
14551
static constexpr CharType get_cbor_float_prefix(float /*unused*/)
14552
{
14553
return to_char_type(0xFA); // Single-Precision Float
14554
}
14555
14556
static constexpr CharType get_cbor_float_prefix(double /*unused*/)
14557
{
14558
return to_char_type(0xFB); // Double-Precision Float
14559
}
14560
14561
/////////////
14562
// MsgPack //
14563
/////////////
14564
14565
static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
14566
{
14567
return to_char_type(0xCA); // float 32
14568
}
14569
14570
static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
14571
{
14572
return to_char_type(0xCB); // float 64
14573
}
14574
14575
////////////
14576
// UBJSON //
14577
////////////
14578
14579
// UBJSON: write number (floating point)
14580
template<typename NumberType, typename std::enable_if<
14581
std::is_floating_point<NumberType>::value, int>::type = 0>
14582
void write_number_with_ubjson_prefix(const NumberType n,
14583
const bool add_prefix)
14584
{
14585
if (add_prefix)
14586
{
14587
oa->write_character(get_ubjson_float_prefix(n));
14588
}
14589
write_number(n);
14590
}
14591
14592
// UBJSON: write number (unsigned integer)
14593
template<typename NumberType, typename std::enable_if<
14594
std::is_unsigned<NumberType>::value, int>::type = 0>
14595
void write_number_with_ubjson_prefix(const NumberType n,
14596
const bool add_prefix)
14597
{
14598
if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
14599
{
14600
if (add_prefix)
14601
{
14602
oa->write_character(to_char_type('i')); // int8
14603
}
14604
write_number(static_cast<std::uint8_t>(n));
14605
}
14606
else if (n <= (std::numeric_limits<std::uint8_t>::max)())
14607
{
14608
if (add_prefix)
14609
{
14610
oa->write_character(to_char_type('U')); // uint8
14611
}
14612
write_number(static_cast<std::uint8_t>(n));
14613
}
14614
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
14615
{
14616
if (add_prefix)
14617
{
14618
oa->write_character(to_char_type('I')); // int16
14619
}
14620
write_number(static_cast<std::int16_t>(n));
14621
}
14622
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14623
{
14624
if (add_prefix)
14625
{
14626
oa->write_character(to_char_type('l')); // int32
14627
}
14628
write_number(static_cast<std::int32_t>(n));
14629
}
14630
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14631
{
14632
if (add_prefix)
14633
{
14634
oa->write_character(to_char_type('L')); // int64
14635
}
14636
write_number(static_cast<std::int64_t>(n));
14637
}
14638
else
14639
{
14640
if (add_prefix)
14641
{
14642
oa->write_character(to_char_type('H')); // high-precision number
14643
}
14644
14645
const auto number = BasicJsonType(n).dump();
14646
write_number_with_ubjson_prefix(number.size(), true);
14647
for (std::size_t i = 0; i < number.size(); ++i)
14648
{
14649
oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
14650
}
14651
}
14652
}
14653
14654
// UBJSON: write number (signed integer)
14655
template < typename NumberType, typename std::enable_if <
14656
std::is_signed<NumberType>::value&&
14657
!std::is_floating_point<NumberType>::value, int >::type = 0 >
14658
void write_number_with_ubjson_prefix(const NumberType n,
14659
const bool add_prefix)
14660
{
14661
if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
14662
{
14663
if (add_prefix)
14664
{
14665
oa->write_character(to_char_type('i')); // int8
14666
}
14667
write_number(static_cast<std::int8_t>(n));
14668
}
14669
else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
14670
{
14671
if (add_prefix)
14672
{
14673
oa->write_character(to_char_type('U')); // uint8
14674
}
14675
write_number(static_cast<std::uint8_t>(n));
14676
}
14677
else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
14678
{
14679
if (add_prefix)
14680
{
14681
oa->write_character(to_char_type('I')); // int16
14682
}
14683
write_number(static_cast<std::int16_t>(n));
14684
}
14685
else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
14686
{
14687
if (add_prefix)
14688
{
14689
oa->write_character(to_char_type('l')); // int32
14690
}
14691
write_number(static_cast<std::int32_t>(n));
14692
}
14693
else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
14694
{
14695
if (add_prefix)
14696
{
14697
oa->write_character(to_char_type('L')); // int64
14698
}
14699
write_number(static_cast<std::int64_t>(n));
14700
}
14701
// LCOV_EXCL_START
14702
else
14703
{
14704
if (add_prefix)
14705
{
14706
oa->write_character(to_char_type('H')); // high-precision number
14707
}
14708
14709
const auto number = BasicJsonType(n).dump();
14710
write_number_with_ubjson_prefix(number.size(), true);
14711
for (std::size_t i = 0; i < number.size(); ++i)
14712
{
14713
oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
14714
}
14715
}
14716
// LCOV_EXCL_STOP
14717
}
14718
14719
/*!
14720
@brief determine the type prefix of container values
14721
*/
14722
CharType ubjson_prefix(const BasicJsonType& j) const noexcept
14723
{
14724
switch (j.type())
14725
{
14726
case value_t::null:
14727
return 'Z';
14728
14729
case value_t::boolean:
14730
return j.m_value.boolean ? 'T' : 'F';
14731
14732
case value_t::number_integer:
14733
{
14734
if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
14735
{
14736
return 'i';
14737
}
14738
if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
14739
{
14740
return 'U';
14741
}
14742
if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
14743
{
14744
return 'I';
14745
}
14746
if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
14747
{
14748
return 'l';
14749
}
14750
if ((std::numeric_limits<std::int64_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
14751
{
14752
return 'L';
14753
}
14754
// anything else is treated as high-precision number
14755
return 'H'; // LCOV_EXCL_LINE
14756
}
14757
14758
case value_t::number_unsigned:
14759
{
14760
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
14761
{
14762
return 'i';
14763
}
14764
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
14765
{
14766
return 'U';
14767
}
14768
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
14769
{
14770
return 'I';
14771
}
14772
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14773
{
14774
return 'l';
14775
}
14776
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14777
{
14778
return 'L';
14779
}
14780
// anything else is treated as high-precision number
14781
return 'H'; // LCOV_EXCL_LINE
14782
}
14783
14784
case value_t::number_float:
14785
return get_ubjson_float_prefix(j.m_value.number_float);
14786
14787
case value_t::string:
14788
return 'S';
14789
14790
case value_t::array: // fallthrough
14791
case value_t::binary:
14792
return '[';
14793
14794
case value_t::object:
14795
return '{';
14796
14797
case value_t::discarded:
14798
default: // discarded values
14799
return 'N';
14800
}
14801
}
14802
14803
static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
14804
{
14805
return 'd'; // float 32
14806
}
14807
14808
static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
14809
{
14810
return 'D'; // float 64
14811
}
14812
14813
///////////////////////
14814
// Utility functions //
14815
///////////////////////
14816
14817
/*
14818
@brief write a number to output input
14819
@param[in] n number of type @a NumberType
14820
@tparam NumberType the type of the number
14821
@tparam OutputIsLittleEndian Set to true if output data is
14822
required to be little endian
14823
14824
@note This function needs to respect the system's endianness, because bytes
14825
in CBOR, MessagePack, and UBJSON are stored in network order (big
14826
endian) and therefore need reordering on little endian systems.
14827
*/
14828
template<typename NumberType, bool OutputIsLittleEndian = false>
14829
void write_number(const NumberType n)
14830
{
14831
// step 1: write number to array of length NumberType
14832
std::array<CharType, sizeof(NumberType)> vec{};
14833
std::memcpy(vec.data(), &n, sizeof(NumberType));
14834
14835
// step 2: write array to output (with possible reordering)
14836
if (is_little_endian != OutputIsLittleEndian)
14837
{
14838
// reverse byte order prior to conversion if necessary
14839
std::reverse(vec.begin(), vec.end());
14840
}
14841
14842
oa->write_characters(vec.data(), sizeof(NumberType));
14843
}
14844
14845
void write_compact_float(const number_float_t n, detail::input_format_t format)
14846
{
14847
#ifdef __GNUC__
14848
#pragma GCC diagnostic push
14849
#pragma GCC diagnostic ignored "-Wfloat-equal"
14850
#endif
14851
if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
14852
static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
14853
static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
14854
{
14855
oa->write_character(format == detail::input_format_t::cbor
14856
? get_cbor_float_prefix(static_cast<float>(n))
14857
: get_msgpack_float_prefix(static_cast<float>(n)));
14858
write_number(static_cast<float>(n));
14859
}
14860
else
14861
{
14862
oa->write_character(format == detail::input_format_t::cbor
14863
? get_cbor_float_prefix(n)
14864
: get_msgpack_float_prefix(n));
14865
write_number(n);
14866
}
14867
#ifdef __GNUC__
14868
#pragma GCC diagnostic pop
14869
#endif
14870
}
14871
14872
public:
14873
// The following to_char_type functions are implement the conversion
14874
// between uint8_t and CharType. In case CharType is not unsigned,
14875
// such a conversion is required to allow values greater than 128.
14876
// See <https://github.com/nlohmann/json/issues/1286> for a discussion.
14877
template < typename C = CharType,
14878
enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
14879
static constexpr CharType to_char_type(std::uint8_t x) noexcept
14880
{
14881
return *reinterpret_cast<char*>(&x);
14882
}
14883
14884
template < typename C = CharType,
14885
enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
14886
static CharType to_char_type(std::uint8_t x) noexcept
14887
{
14888
static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
14889
static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
14890
CharType result;
14891
std::memcpy(&result, &x, sizeof(x));
14892
return result;
14893
}
14894
14895
template<typename C = CharType,
14896
enable_if_t<std::is_unsigned<C>::value>* = nullptr>
14897
static constexpr CharType to_char_type(std::uint8_t x) noexcept
14898
{
14899
return x;
14900
}
14901
14902
template < typename InputCharType, typename C = CharType,
14903
enable_if_t <
14904
std::is_signed<C>::value &&
14905
std::is_signed<char>::value &&
14906
std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
14907
> * = nullptr >
14908
static constexpr CharType to_char_type(InputCharType x) noexcept
14909
{
14910
return x;
14911
}
14912
14913
private:
14914
/// whether we can assume little endianness
14915
const bool is_little_endian = little_endianness();
14916
14917
/// the output
14918
output_adapter_t<CharType> oa = nullptr;
14919
};
14920
} // namespace detail
14921
} // namespace nlohmann
14922
14923
// #include <nlohmann/detail/output/output_adapters.hpp>
14924
14925
// #include <nlohmann/detail/output/serializer.hpp>
14926
14927
14928
#include <algorithm> // reverse, remove, fill, find, none_of
14929
#include <array> // array
14930
#include <clocale> // localeconv, lconv
14931
#include <cmath> // labs, isfinite, isnan, signbit
14932
#include <cstddef> // size_t, ptrdiff_t
14933
#include <cstdint> // uint8_t
14934
#include <cstdio> // snprintf
14935
#include <limits> // numeric_limits
14936
#include <string> // string, char_traits
14937
#include <iomanip> // setfill, setw
14938
#include <sstream> // stringstream
14939
#include <type_traits> // is_same
14940
#include <utility> // move
14941
14942
// #include <nlohmann/detail/conversions/to_chars.hpp>
14943
14944
14945
#include <array> // array
14946
#include <cmath> // signbit, isfinite
14947
#include <cstdint> // intN_t, uintN_t
14948
#include <cstring> // memcpy, memmove
14949
#include <limits> // numeric_limits
14950
#include <type_traits> // conditional
14951
14952
// #include <nlohmann/detail/macro_scope.hpp>
14953
14954
14955
namespace nlohmann
14956
{
14957
namespace detail
14958
{
14959
14960
/*!
14961
@brief implements the Grisu2 algorithm for binary to decimal floating-point
14962
conversion.
14963
14964
This implementation is a slightly modified version of the reference
14965
implementation which may be obtained from
14966
http://florian.loitsch.com/publications (bench.tar.gz).
14967
14968
The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
14969
14970
For a detailed description of the algorithm see:
14971
14972
[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
14973
Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
14974
Language Design and Implementation, PLDI 2010
14975
[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
14976
Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
14977
Design and Implementation, PLDI 1996
14978
*/
14979
namespace dtoa_impl
14980
{
14981
14982
template<typename Target, typename Source>
14983
Target reinterpret_bits(const Source source)
14984
{
14985
static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
14986
14987
Target target;
14988
std::memcpy(&target, &source, sizeof(Source));
14989
return target;
14990
}
14991
14992
struct diyfp // f * 2^e
14993
{
14994
static constexpr int kPrecision = 64; // = q
14995
14996
std::uint64_t f = 0;
14997
int e = 0;
14998
14999
constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
15000
15001
/*!
15002
@brief returns x - y
15003
@pre x.e == y.e and x.f >= y.f
15004
*/
15005
static diyfp sub(const diyfp& x, const diyfp& y) noexcept
15006
{
15007
JSON_ASSERT(x.e == y.e);
15008
JSON_ASSERT(x.f >= y.f);
15009
15010
return {x.f - y.f, x.e};
15011
}
15012
15013
/*!
15014
@brief returns x * y
15015
@note The result is rounded. (Only the upper q bits are returned.)
15016
*/
15017
static diyfp mul(const diyfp& x, const diyfp& y) noexcept
15018
{
15019
static_assert(kPrecision == 64, "internal error");
15020
15021
// Computes:
15022
// f = round((x.f * y.f) / 2^q)
15023
// e = x.e + y.e + q
15024
15025
// Emulate the 64-bit * 64-bit multiplication:
15026
//
15027
// p = u * v
15028
// = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
15029
// = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
15030
// = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
15031
// = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
15032
// = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
15033
// = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
15034
// = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
15035
//
15036
// (Since Q might be larger than 2^32 - 1)
15037
//
15038
// = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
15039
//
15040
// (Q_hi + H does not overflow a 64-bit int)
15041
//
15042
// = p_lo + 2^64 p_hi
15043
15044
const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
15045
const std::uint64_t u_hi = x.f >> 32u;
15046
const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
15047
const std::uint64_t v_hi = y.f >> 32u;
15048
15049
const std::uint64_t p0 = u_lo * v_lo;
15050
const std::uint64_t p1 = u_lo * v_hi;
15051
const std::uint64_t p2 = u_hi * v_lo;
15052
const std::uint64_t p3 = u_hi * v_hi;
15053
15054
const std::uint64_t p0_hi = p0 >> 32u;
15055
const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
15056
const std::uint64_t p1_hi = p1 >> 32u;
15057
const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
15058
const std::uint64_t p2_hi = p2 >> 32u;
15059
15060
std::uint64_t Q = p0_hi + p1_lo + p2_lo;
15061
15062
// The full product might now be computed as
15063
//
15064
// p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
15065
// p_lo = p0_lo + (Q << 32)
15066
//
15067
// But in this particular case here, the full p_lo is not required.
15068
// Effectively we only need to add the highest bit in p_lo to p_hi (and
15069
// Q_hi + 1 does not overflow).
15070
15071
Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
15072
15073
const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
15074
15075
return {h, x.e + y.e + 64};
15076
}
15077
15078
/*!
15079
@brief normalize x such that the significand is >= 2^(q-1)
15080
@pre x.f != 0
15081
*/
15082
static diyfp normalize(diyfp x) noexcept
15083
{
15084
JSON_ASSERT(x.f != 0);
15085
15086
while ((x.f >> 63u) == 0)
15087
{
15088
x.f <<= 1u;
15089
x.e--;
15090
}
15091
15092
return x;
15093
}
15094
15095
/*!
15096
@brief normalize x such that the result has the exponent E
15097
@pre e >= x.e and the upper e - x.e bits of x.f must be zero.
15098
*/
15099
static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
15100
{
15101
const int delta = x.e - target_exponent;
15102
15103
JSON_ASSERT(delta >= 0);
15104
JSON_ASSERT(((x.f << delta) >> delta) == x.f);
15105
15106
return {x.f << delta, target_exponent};
15107
}
15108
};
15109
15110
struct boundaries
15111
{
15112
diyfp w;
15113
diyfp minus;
15114
diyfp plus;
15115
};
15116
15117
/*!
15118
Compute the (normalized) diyfp representing the input number 'value' and its
15119
boundaries.
15120
15121
@pre value must be finite and positive
15122
*/
15123
template<typename FloatType>
15124
boundaries compute_boundaries(FloatType value)
15125
{
15126
JSON_ASSERT(std::isfinite(value));
15127
JSON_ASSERT(value > 0);
15128
15129
// Convert the IEEE representation into a diyfp.
15130
//
15131
// If v is denormal:
15132
// value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
15133
// If v is normalized:
15134
// value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
15135
15136
static_assert(std::numeric_limits<FloatType>::is_iec559,
15137
"internal error: dtoa_short requires an IEEE-754 floating-point implementation");
15138
15139
constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
15140
constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
15141
constexpr int kMinExp = 1 - kBias;
15142
constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
15143
15144
using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
15145
15146
const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
15147
const std::uint64_t E = bits >> (kPrecision - 1);
15148
const std::uint64_t F = bits & (kHiddenBit - 1);
15149
15150
const bool is_denormal = E == 0;
15151
const diyfp v = is_denormal
15152
? diyfp(F, kMinExp)
15153
: diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
15154
15155
// Compute the boundaries m- and m+ of the floating-point value
15156
// v = f * 2^e.
15157
//
15158
// Determine v- and v+, the floating-point predecessor and successor if v,
15159
// respectively.
15160
//
15161
// v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
15162
// = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
15163
//
15164
// v+ = v + 2^e
15165
//
15166
// Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
15167
// between m- and m+ round to v, regardless of how the input rounding
15168
// algorithm breaks ties.
15169
//
15170
// ---+-------------+-------------+-------------+-------------+--- (A)
15171
// v- m- v m+ v+
15172
//
15173
// -----------------+------+------+-------------+-------------+--- (B)
15174
// v- m- v m+ v+
15175
15176
const bool lower_boundary_is_closer = F == 0 && E > 1;
15177
const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
15178
const diyfp m_minus = lower_boundary_is_closer
15179
? diyfp(4 * v.f - 1, v.e - 2) // (B)
15180
: diyfp(2 * v.f - 1, v.e - 1); // (A)
15181
15182
// Determine the normalized w+ = m+.
15183
const diyfp w_plus = diyfp::normalize(m_plus);
15184
15185
// Determine w- = m- such that e_(w-) = e_(w+).
15186
const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
15187
15188
return {diyfp::normalize(v), w_minus, w_plus};
15189
}
15190
15191
// Given normalized diyfp w, Grisu needs to find a (normalized) cached
15192
// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
15193
// within a certain range [alpha, gamma] (Definition 3.2 from [1])
15194
//
15195
// alpha <= e = e_c + e_w + q <= gamma
15196
//
15197
// or
15198
//
15199
// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
15200
// <= f_c * f_w * 2^gamma
15201
//
15202
// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
15203
//
15204
// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
15205
//
15206
// or
15207
//
15208
// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
15209
//
15210
// The choice of (alpha,gamma) determines the size of the table and the form of
15211
// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
15212
// in practice:
15213
//
15214
// The idea is to cut the number c * w = f * 2^e into two parts, which can be
15215
// processed independently: An integral part p1, and a fractional part p2:
15216
//
15217
// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
15218
// = (f div 2^-e) + (f mod 2^-e) * 2^e
15219
// = p1 + p2 * 2^e
15220
//
15221
// The conversion of p1 into decimal form requires a series of divisions and
15222
// modulos by (a power of) 10. These operations are faster for 32-bit than for
15223
// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
15224
// achieved by choosing
15225
//
15226
// -e >= 32 or e <= -32 := gamma
15227
//
15228
// In order to convert the fractional part
15229
//
15230
// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
15231
//
15232
// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
15233
// d[-i] are extracted in order:
15234
//
15235
// (10 * p2) div 2^-e = d[-1]
15236
// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
15237
//
15238
// The multiplication by 10 must not overflow. It is sufficient to choose
15239
//
15240
// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
15241
//
15242
// Since p2 = f mod 2^-e < 2^-e,
15243
//
15244
// -e <= 60 or e >= -60 := alpha
15245
15246
constexpr int kAlpha = -60;
15247
constexpr int kGamma = -32;
15248
15249
struct cached_power // c = f * 2^e ~= 10^k
15250
{
15251
std::uint64_t f;
15252
int e;
15253
int k;
15254
};
15255
15256
/*!
15257
For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
15258
power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
15259
satisfies (Definition 3.2 from [1])
15260
15261
alpha <= e_c + e + q <= gamma.
15262
*/
15263
inline cached_power get_cached_power_for_binary_exponent(int e)
15264
{
15265
// Now
15266
//
15267
// alpha <= e_c + e + q <= gamma (1)
15268
// ==> f_c * 2^alpha <= c * 2^e * 2^q
15269
//
15270
// and since the c's are normalized, 2^(q-1) <= f_c,
15271
//
15272
// ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
15273
// ==> 2^(alpha - e - 1) <= c
15274
//
15275
// If c were an exact power of ten, i.e. c = 10^k, one may determine k as
15276
//
15277
// k = ceil( log_10( 2^(alpha - e - 1) ) )
15278
// = ceil( (alpha - e - 1) * log_10(2) )
15279
//
15280
// From the paper:
15281
// "In theory the result of the procedure could be wrong since c is rounded,
15282
// and the computation itself is approximated [...]. In practice, however,
15283
// this simple function is sufficient."
15284
//
15285
// For IEEE double precision floating-point numbers converted into
15286
// normalized diyfp's w = f * 2^e, with q = 64,
15287
//
15288
// e >= -1022 (min IEEE exponent)
15289
// -52 (p - 1)
15290
// -52 (p - 1, possibly normalize denormal IEEE numbers)
15291
// -11 (normalize the diyfp)
15292
// = -1137
15293
//
15294
// and
15295
//
15296
// e <= +1023 (max IEEE exponent)
15297
// -52 (p - 1)
15298
// -11 (normalize the diyfp)
15299
// = 960
15300
//
15301
// This binary exponent range [-1137,960] results in a decimal exponent
15302
// range [-307,324]. One does not need to store a cached power for each
15303
// k in this range. For each such k it suffices to find a cached power
15304
// such that the exponent of the product lies in [alpha,gamma].
15305
// This implies that the difference of the decimal exponents of adjacent
15306
// table entries must be less than or equal to
15307
//
15308
// floor( (gamma - alpha) * log_10(2) ) = 8.
15309
//
15310
// (A smaller distance gamma-alpha would require a larger table.)
15311
15312
// NB:
15313
// Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
15314
15315
constexpr int kCachedPowersMinDecExp = -300;
15316
constexpr int kCachedPowersDecStep = 8;
15317
15318
static constexpr std::array<cached_power, 79> kCachedPowers =
15319
{
15320
{
15321
{ 0xAB70FE17C79AC6CA, -1060, -300 },
15322
{ 0xFF77B1FCBEBCDC4F, -1034, -292 },
15323
{ 0xBE5691EF416BD60C, -1007, -284 },
15324
{ 0x8DD01FAD907FFC3C, -980, -276 },
15325
{ 0xD3515C2831559A83, -954, -268 },
15326
{ 0x9D71AC8FADA6C9B5, -927, -260 },
15327
{ 0xEA9C227723EE8BCB, -901, -252 },
15328
{ 0xAECC49914078536D, -874, -244 },
15329
{ 0x823C12795DB6CE57, -847, -236 },
15330
{ 0xC21094364DFB5637, -821, -228 },
15331
{ 0x9096EA6F3848984F, -794, -220 },
15332
{ 0xD77485CB25823AC7, -768, -212 },
15333
{ 0xA086CFCD97BF97F4, -741, -204 },
15334
{ 0xEF340A98172AACE5, -715, -196 },
15335
{ 0xB23867FB2A35B28E, -688, -188 },
15336
{ 0x84C8D4DFD2C63F3B, -661, -180 },
15337
{ 0xC5DD44271AD3CDBA, -635, -172 },
15338
{ 0x936B9FCEBB25C996, -608, -164 },
15339
{ 0xDBAC6C247D62A584, -582, -156 },
15340
{ 0xA3AB66580D5FDAF6, -555, -148 },
15341
{ 0xF3E2F893DEC3F126, -529, -140 },
15342
{ 0xB5B5ADA8AAFF80B8, -502, -132 },
15343
{ 0x87625F056C7C4A8B, -475, -124 },
15344
{ 0xC9BCFF6034C13053, -449, -116 },
15345
{ 0x964E858C91BA2655, -422, -108 },
15346
{ 0xDFF9772470297EBD, -396, -100 },
15347
{ 0xA6DFBD9FB8E5B88F, -369, -92 },
15348
{ 0xF8A95FCF88747D94, -343, -84 },
15349
{ 0xB94470938FA89BCF, -316, -76 },
15350
{ 0x8A08F0F8BF0F156B, -289, -68 },
15351
{ 0xCDB02555653131B6, -263, -60 },
15352
{ 0x993FE2C6D07B7FAC, -236, -52 },
15353
{ 0xE45C10C42A2B3B06, -210, -44 },
15354
{ 0xAA242499697392D3, -183, -36 },
15355
{ 0xFD87B5F28300CA0E, -157, -28 },
15356
{ 0xBCE5086492111AEB, -130, -20 },
15357
{ 0x8CBCCC096F5088CC, -103, -12 },
15358
{ 0xD1B71758E219652C, -77, -4 },
15359
{ 0x9C40000000000000, -50, 4 },
15360
{ 0xE8D4A51000000000, -24, 12 },
15361
{ 0xAD78EBC5AC620000, 3, 20 },
15362
{ 0x813F3978F8940984, 30, 28 },
15363
{ 0xC097CE7BC90715B3, 56, 36 },
15364
{ 0x8F7E32CE7BEA5C70, 83, 44 },
15365
{ 0xD5D238A4ABE98068, 109, 52 },
15366
{ 0x9F4F2726179A2245, 136, 60 },
15367
{ 0xED63A231D4C4FB27, 162, 68 },
15368
{ 0xB0DE65388CC8ADA8, 189, 76 },
15369
{ 0x83C7088E1AAB65DB, 216, 84 },
15370
{ 0xC45D1DF942711D9A, 242, 92 },
15371
{ 0x924D692CA61BE758, 269, 100 },
15372
{ 0xDA01EE641A708DEA, 295, 108 },
15373
{ 0xA26DA3999AEF774A, 322, 116 },
15374
{ 0xF209787BB47D6B85, 348, 124 },
15375
{ 0xB454E4A179DD1877, 375, 132 },
15376
{ 0x865B86925B9BC5C2, 402, 140 },
15377
{ 0xC83553C5C8965D3D, 428, 148 },
15378
{ 0x952AB45CFA97A0B3, 455, 156 },
15379
{ 0xDE469FBD99A05FE3, 481, 164 },
15380
{ 0xA59BC234DB398C25, 508, 172 },
15381
{ 0xF6C69A72A3989F5C, 534, 180 },
15382
{ 0xB7DCBF5354E9BECE, 561, 188 },
15383
{ 0x88FCF317F22241E2, 588, 196 },
15384
{ 0xCC20CE9BD35C78A5, 614, 204 },
15385
{ 0x98165AF37B2153DF, 641, 212 },
15386
{ 0xE2A0B5DC971F303A, 667, 220 },
15387
{ 0xA8D9D1535CE3B396, 694, 228 },
15388
{ 0xFB9B7CD9A4A7443C, 720, 236 },
15389
{ 0xBB764C4CA7A44410, 747, 244 },
15390
{ 0x8BAB8EEFB6409C1A, 774, 252 },
15391
{ 0xD01FEF10A657842C, 800, 260 },
15392
{ 0x9B10A4E5E9913129, 827, 268 },
15393
{ 0xE7109BFBA19C0C9D, 853, 276 },
15394
{ 0xAC2820D9623BF429, 880, 284 },
15395
{ 0x80444B5E7AA7CF85, 907, 292 },
15396
{ 0xBF21E44003ACDD2D, 933, 300 },
15397
{ 0x8E679C2F5E44FF8F, 960, 308 },
15398
{ 0xD433179D9C8CB841, 986, 316 },
15399
{ 0x9E19DB92B4E31BA9, 1013, 324 },
15400
}
15401
};
15402
15403
// This computation gives exactly the same results for k as
15404
// k = ceil((kAlpha - e - 1) * 0.30102999566398114)
15405
// for |e| <= 1500, but doesn't require floating-point operations.
15406
// NB: log_10(2) ~= 78913 / 2^18
15407
JSON_ASSERT(e >= -1500);
15408
JSON_ASSERT(e <= 1500);
15409
const int f = kAlpha - e - 1;
15410
const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
15411
15412
const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
15413
JSON_ASSERT(index >= 0);
15414
JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
15415
15416
const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
15417
JSON_ASSERT(kAlpha <= cached.e + e + 64);
15418
JSON_ASSERT(kGamma >= cached.e + e + 64);
15419
15420
return cached;
15421
}
15422
15423
/*!
15424
For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
15425
For n == 0, returns 1 and sets pow10 := 1.
15426
*/
15427
inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
15428
{
15429
// LCOV_EXCL_START
15430
if (n >= 1000000000)
15431
{
15432
pow10 = 1000000000;
15433
return 10;
15434
}
15435
// LCOV_EXCL_STOP
15436
if (n >= 100000000)
15437
{
15438
pow10 = 100000000;
15439
return 9;
15440
}
15441
if (n >= 10000000)
15442
{
15443
pow10 = 10000000;
15444
return 8;
15445
}
15446
if (n >= 1000000)
15447
{
15448
pow10 = 1000000;
15449
return 7;
15450
}
15451
if (n >= 100000)
15452
{
15453
pow10 = 100000;
15454
return 6;
15455
}
15456
if (n >= 10000)
15457
{
15458
pow10 = 10000;
15459
return 5;
15460
}
15461
if (n >= 1000)
15462
{
15463
pow10 = 1000;
15464
return 4;
15465
}
15466
if (n >= 100)
15467
{
15468
pow10 = 100;
15469
return 3;
15470
}
15471
if (n >= 10)
15472
{
15473
pow10 = 10;
15474
return 2;
15475
}
15476
15477
pow10 = 1;
15478
return 1;
15479
}
15480
15481
inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
15482
std::uint64_t rest, std::uint64_t ten_k)
15483
{
15484
JSON_ASSERT(len >= 1);
15485
JSON_ASSERT(dist <= delta);
15486
JSON_ASSERT(rest <= delta);
15487
JSON_ASSERT(ten_k > 0);
15488
15489
// <--------------------------- delta ---->
15490
// <---- dist --------->
15491
// --------------[------------------+-------------------]--------------
15492
// M- w M+
15493
//
15494
// ten_k
15495
// <------>
15496
// <---- rest ---->
15497
// --------------[------------------+----+--------------]--------------
15498
// w V
15499
// = buf * 10^k
15500
//
15501
// ten_k represents a unit-in-the-last-place in the decimal representation
15502
// stored in buf.
15503
// Decrement buf by ten_k while this takes buf closer to w.
15504
15505
// The tests are written in this order to avoid overflow in unsigned
15506
// integer arithmetic.
15507
15508
while (rest < dist
15509
&& delta - rest >= ten_k
15510
&& (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
15511
{
15512
JSON_ASSERT(buf[len - 1] != '0');
15513
buf[len - 1]--;
15514
rest += ten_k;
15515
}
15516
}
15517
15518
/*!
15519
Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
15520
M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
15521
*/
15522
inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
15523
diyfp M_minus, diyfp w, diyfp M_plus)
15524
{
15525
static_assert(kAlpha >= -60, "internal error");
15526
static_assert(kGamma <= -32, "internal error");
15527
15528
// Generates the digits (and the exponent) of a decimal floating-point
15529
// number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
15530
// w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
15531
//
15532
// <--------------------------- delta ---->
15533
// <---- dist --------->
15534
// --------------[------------------+-------------------]--------------
15535
// M- w M+
15536
//
15537
// Grisu2 generates the digits of M+ from left to right and stops as soon as
15538
// V is in [M-,M+].
15539
15540
JSON_ASSERT(M_plus.e >= kAlpha);
15541
JSON_ASSERT(M_plus.e <= kGamma);
15542
15543
std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
15544
std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
15545
15546
// Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
15547
//
15548
// M+ = f * 2^e
15549
// = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
15550
// = ((p1 ) * 2^-e + (p2 )) * 2^e
15551
// = p1 + p2 * 2^e
15552
15553
const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
15554
15555
auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
15556
std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
15557
15558
// 1)
15559
//
15560
// Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
15561
15562
JSON_ASSERT(p1 > 0);
15563
15564
std::uint32_t pow10{};
15565
const int k = find_largest_pow10(p1, pow10);
15566
15567
// 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
15568
//
15569
// p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
15570
// = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
15571
//
15572
// M+ = p1 + p2 * 2^e
15573
// = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
15574
// = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
15575
// = d[k-1] * 10^(k-1) + ( rest) * 2^e
15576
//
15577
// Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
15578
//
15579
// p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
15580
//
15581
// but stop as soon as
15582
//
15583
// rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
15584
15585
int n = k;
15586
while (n > 0)
15587
{
15588
// Invariants:
15589
// M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
15590
// pow10 = 10^(n-1) <= p1 < 10^n
15591
//
15592
const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
15593
const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
15594
//
15595
// M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
15596
// = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
15597
//
15598
JSON_ASSERT(d <= 9);
15599
buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
15600
//
15601
// M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
15602
//
15603
p1 = r;
15604
n--;
15605
//
15606
// M+ = buffer * 10^n + (p1 + p2 * 2^e)
15607
// pow10 = 10^n
15608
//
15609
15610
// Now check if enough digits have been generated.
15611
// Compute
15612
//
15613
// p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
15614
//
15615
// Note:
15616
// Since rest and delta share the same exponent e, it suffices to
15617
// compare the significands.
15618
const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
15619
if (rest <= delta)
15620
{
15621
// V = buffer * 10^n, with M- <= V <= M+.
15622
15623
decimal_exponent += n;
15624
15625
// We may now just stop. But instead look if the buffer could be
15626
// decremented to bring V closer to w.
15627
//
15628
// pow10 = 10^n is now 1 ulp in the decimal representation V.
15629
// The rounding procedure works with diyfp's with an implicit
15630
// exponent of e.
15631
//
15632
// 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
15633
//
15634
const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
15635
grisu2_round(buffer, length, dist, delta, rest, ten_n);
15636
15637
return;
15638
}
15639
15640
pow10 /= 10;
15641
//
15642
// pow10 = 10^(n-1) <= p1 < 10^n
15643
// Invariants restored.
15644
}
15645
15646
// 2)
15647
//
15648
// The digits of the integral part have been generated:
15649
//
15650
// M+ = d[k-1]...d[1]d[0] + p2 * 2^e
15651
// = buffer + p2 * 2^e
15652
//
15653
// Now generate the digits of the fractional part p2 * 2^e.
15654
//
15655
// Note:
15656
// No decimal point is generated: the exponent is adjusted instead.
15657
//
15658
// p2 actually represents the fraction
15659
//
15660
// p2 * 2^e
15661
// = p2 / 2^-e
15662
// = d[-1] / 10^1 + d[-2] / 10^2 + ...
15663
//
15664
// Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
15665
//
15666
// p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
15667
// + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
15668
//
15669
// using
15670
//
15671
// 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
15672
// = ( d) * 2^-e + ( r)
15673
//
15674
// or
15675
// 10^m * p2 * 2^e = d + r * 2^e
15676
//
15677
// i.e.
15678
//
15679
// M+ = buffer + p2 * 2^e
15680
// = buffer + 10^-m * (d + r * 2^e)
15681
// = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
15682
//
15683
// and stop as soon as 10^-m * r * 2^e <= delta * 2^e
15684
15685
JSON_ASSERT(p2 > delta);
15686
15687
int m = 0;
15688
for (;;)
15689
{
15690
// Invariant:
15691
// M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
15692
// = buffer * 10^-m + 10^-m * (p2 ) * 2^e
15693
// = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
15694
// = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
15695
//
15696
JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
15697
p2 *= 10;
15698
const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
15699
const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
15700
//
15701
// M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
15702
// = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
15703
// = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
15704
//
15705
JSON_ASSERT(d <= 9);
15706
buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
15707
//
15708
// M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
15709
//
15710
p2 = r;
15711
m++;
15712
//
15713
// M+ = buffer * 10^-m + 10^-m * p2 * 2^e
15714
// Invariant restored.
15715
15716
// Check if enough digits have been generated.
15717
//
15718
// 10^-m * p2 * 2^e <= delta * 2^e
15719
// p2 * 2^e <= 10^m * delta * 2^e
15720
// p2 <= 10^m * delta
15721
delta *= 10;
15722
dist *= 10;
15723
if (p2 <= delta)
15724
{
15725
break;
15726
}
15727
}
15728
15729
// V = buffer * 10^-m, with M- <= V <= M+.
15730
15731
decimal_exponent -= m;
15732
15733
// 1 ulp in the decimal representation is now 10^-m.
15734
// Since delta and dist are now scaled by 10^m, we need to do the
15735
// same with ulp in order to keep the units in sync.
15736
//
15737
// 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
15738
//
15739
const std::uint64_t ten_m = one.f;
15740
grisu2_round(buffer, length, dist, delta, p2, ten_m);
15741
15742
// By construction this algorithm generates the shortest possible decimal
15743
// number (Loitsch, Theorem 6.2) which rounds back to w.
15744
// For an input number of precision p, at least
15745
//
15746
// N = 1 + ceil(p * log_10(2))
15747
//
15748
// decimal digits are sufficient to identify all binary floating-point
15749
// numbers (Matula, "In-and-Out conversions").
15750
// This implies that the algorithm does not produce more than N decimal
15751
// digits.
15752
//
15753
// N = 17 for p = 53 (IEEE double precision)
15754
// N = 9 for p = 24 (IEEE single precision)
15755
}
15756
15757
/*!
15758
v = buf * 10^decimal_exponent
15759
len is the length of the buffer (number of decimal digits)
15760
The buffer must be large enough, i.e. >= max_digits10.
15761
*/
15762
JSON_HEDLEY_NON_NULL(1)
15763
inline void grisu2(char* buf, int& len, int& decimal_exponent,
15764
diyfp m_minus, diyfp v, diyfp m_plus)
15765
{
15766
JSON_ASSERT(m_plus.e == m_minus.e);
15767
JSON_ASSERT(m_plus.e == v.e);
15768
15769
// --------(-----------------------+-----------------------)-------- (A)
15770
// m- v m+
15771
//
15772
// --------------------(-----------+-----------------------)-------- (B)
15773
// m- v m+
15774
//
15775
// First scale v (and m- and m+) such that the exponent is in the range
15776
// [alpha, gamma].
15777
15778
const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
15779
15780
const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
15781
15782
// The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
15783
const diyfp w = diyfp::mul(v, c_minus_k);
15784
const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
15785
const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
15786
15787
// ----(---+---)---------------(---+---)---------------(---+---)----
15788
// w- w w+
15789
// = c*m- = c*v = c*m+
15790
//
15791
// diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
15792
// w+ are now off by a small amount.
15793
// In fact:
15794
//
15795
// w - v * 10^k < 1 ulp
15796
//
15797
// To account for this inaccuracy, add resp. subtract 1 ulp.
15798
//
15799
// --------+---[---------------(---+---)---------------]---+--------
15800
// w- M- w M+ w+
15801
//
15802
// Now any number in [M-, M+] (bounds included) will round to w when input,
15803
// regardless of how the input rounding algorithm breaks ties.
15804
//
15805
// And digit_gen generates the shortest possible such number in [M-, M+].
15806
// Note that this does not mean that Grisu2 always generates the shortest
15807
// possible number in the interval (m-, m+).
15808
const diyfp M_minus(w_minus.f + 1, w_minus.e);
15809
const diyfp M_plus (w_plus.f - 1, w_plus.e );
15810
15811
decimal_exponent = -cached.k; // = -(-k) = k
15812
15813
grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
15814
}
15815
15816
/*!
15817
v = buf * 10^decimal_exponent
15818
len is the length of the buffer (number of decimal digits)
15819
The buffer must be large enough, i.e. >= max_digits10.
15820
*/
15821
template<typename FloatType>
15822
JSON_HEDLEY_NON_NULL(1)
15823
void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
15824
{
15825
static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
15826
"internal error: not enough precision");
15827
15828
JSON_ASSERT(std::isfinite(value));
15829
JSON_ASSERT(value > 0);
15830
15831
// If the neighbors (and boundaries) of 'value' are always computed for double-precision
15832
// numbers, all float's can be recovered using strtod (and strtof). However, the resulting
15833
// decimal representations are not exactly "short".
15834
//
15835
// The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
15836
// says "value is converted to a string as if by std::sprintf in the default ("C") locale"
15837
// and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
15838
// does.
15839
// On the other hand, the documentation for 'std::to_chars' requires that "parsing the
15840
// representation using the corresponding std::from_chars function recovers value exactly". That
15841
// indicates that single precision floating-point numbers should be recovered using
15842
// 'std::strtof'.
15843
//
15844
// NB: If the neighbors are computed for single-precision numbers, there is a single float
15845
// (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
15846
// value is off by 1 ulp.
15847
#if 0
15848
const boundaries w = compute_boundaries(static_cast<double>(value));
15849
#else
15850
const boundaries w = compute_boundaries(value);
15851
#endif
15852
15853
grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
15854
}
15855
15856
/*!
15857
@brief appends a decimal representation of e to buf
15858
@return a pointer to the element following the exponent.
15859
@pre -1000 < e < 1000
15860
*/
15861
JSON_HEDLEY_NON_NULL(1)
15862
JSON_HEDLEY_RETURNS_NON_NULL
15863
inline char* append_exponent(char* buf, int e)
15864
{
15865
JSON_ASSERT(e > -1000);
15866
JSON_ASSERT(e < 1000);
15867
15868
if (e < 0)
15869
{
15870
e = -e;
15871
*buf++ = '-';
15872
}
15873
else
15874
{
15875
*buf++ = '+';
15876
}
15877
15878
auto k = static_cast<std::uint32_t>(e);
15879
if (k < 10)
15880
{
15881
// Always print at least two digits in the exponent.
15882
// This is for compatibility with printf("%g").
15883
*buf++ = '0';
15884
*buf++ = static_cast<char>('0' + k);
15885
}
15886
else if (k < 100)
15887
{
15888
*buf++ = static_cast<char>('0' + k / 10);
15889
k %= 10;
15890
*buf++ = static_cast<char>('0' + k);
15891
}
15892
else
15893
{
15894
*buf++ = static_cast<char>('0' + k / 100);
15895
k %= 100;
15896
*buf++ = static_cast<char>('0' + k / 10);
15897
k %= 10;
15898
*buf++ = static_cast<char>('0' + k);
15899
}
15900
15901
return buf;
15902
}
15903
15904
/*!
15905
@brief prettify v = buf * 10^decimal_exponent
15906
15907
If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
15908
notation. Otherwise it will be printed in exponential notation.
15909
15910
@pre min_exp < 0
15911
@pre max_exp > 0
15912
*/
15913
JSON_HEDLEY_NON_NULL(1)
15914
JSON_HEDLEY_RETURNS_NON_NULL
15915
inline char* format_buffer(char* buf, int len, int decimal_exponent,
15916
int min_exp, int max_exp)
15917
{
15918
JSON_ASSERT(min_exp < 0);
15919
JSON_ASSERT(max_exp > 0);
15920
15921
const int k = len;
15922
const int n = len + decimal_exponent;
15923
15924
// v = buf * 10^(n-k)
15925
// k is the length of the buffer (number of decimal digits)
15926
// n is the position of the decimal point relative to the start of the buffer.
15927
15928
if (k <= n && n <= max_exp)
15929
{
15930
// digits[000]
15931
// len <= max_exp + 2
15932
15933
std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
15934
// Make it look like a floating-point number (#362, #378)
15935
buf[n + 0] = '.';
15936
buf[n + 1] = '0';
15937
return buf + (static_cast<size_t>(n) + 2);
15938
}
15939
15940
if (0 < n && n <= max_exp)
15941
{
15942
// dig.its
15943
// len <= max_digits10 + 1
15944
15945
JSON_ASSERT(k > n);
15946
15947
std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
15948
buf[n] = '.';
15949
return buf + (static_cast<size_t>(k) + 1U);
15950
}
15951
15952
if (min_exp < n && n <= 0)
15953
{
15954
// 0.[000]digits
15955
// len <= 2 + (-min_exp - 1) + max_digits10
15956
15957
std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
15958
buf[0] = '0';
15959
buf[1] = '.';
15960
std::memset(buf + 2, '0', static_cast<size_t>(-n));
15961
return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
15962
}
15963
15964
if (k == 1)
15965
{
15966
// dE+123
15967
// len <= 1 + 5
15968
15969
buf += 1;
15970
}
15971
else
15972
{
15973
// d.igitsE+123
15974
// len <= max_digits10 + 1 + 5
15975
15976
std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
15977
buf[1] = '.';
15978
buf += 1 + static_cast<size_t>(k);
15979
}
15980
15981
*buf++ = 'e';
15982
return append_exponent(buf, n - 1);
15983
}
15984
15985
} // namespace dtoa_impl
15986
15987
/*!
15988
@brief generates a decimal representation of the floating-point number value in [first, last).
15989
15990
The format of the resulting decimal representation is similar to printf's %g
15991
format. Returns an iterator pointing past-the-end of the decimal representation.
15992
15993
@note The input number must be finite, i.e. NaN's and Inf's are not supported.
15994
@note The buffer must be large enough.
15995
@note The result is NOT null-terminated.
15996
*/
15997
template<typename FloatType>
15998
JSON_HEDLEY_NON_NULL(1, 2)
15999
JSON_HEDLEY_RETURNS_NON_NULL
16000
char* to_chars(char* first, const char* last, FloatType value)
16001
{
16002
static_cast<void>(last); // maybe unused - fix warning
16003
JSON_ASSERT(std::isfinite(value));
16004
16005
// Use signbit(value) instead of (value < 0) since signbit works for -0.
16006
if (std::signbit(value))
16007
{
16008
value = -value;
16009
*first++ = '-';
16010
}
16011
16012
#ifdef __GNUC__
16013
#pragma GCC diagnostic push
16014
#pragma GCC diagnostic ignored "-Wfloat-equal"
16015
#endif
16016
if (value == 0) // +-0
16017
{
16018
*first++ = '0';
16019
// Make it look like a floating-point number (#362, #378)
16020
*first++ = '.';
16021
*first++ = '0';
16022
return first;
16023
}
16024
#ifdef __GNUC__
16025
#pragma GCC diagnostic pop
16026
#endif
16027
16028
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
16029
16030
// Compute v = buffer * 10^decimal_exponent.
16031
// The decimal digits are stored in the buffer, which needs to be interpreted
16032
// as an unsigned decimal integer.
16033
// len is the length of the buffer, i.e. the number of decimal digits.
16034
int len = 0;
16035
int decimal_exponent = 0;
16036
dtoa_impl::grisu2(first, len, decimal_exponent, value);
16037
16038
JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
16039
16040
// Format the buffer like printf("%.*g", prec, value)
16041
constexpr int kMinExp = -4;
16042
// Use digits10 here to increase compatibility with version 2.
16043
constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
16044
16045
JSON_ASSERT(last - first >= kMaxExp + 2);
16046
JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
16047
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
16048
16049
return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
16050
}
16051
16052
} // namespace detail
16053
} // namespace nlohmann
16054
16055
// #include <nlohmann/detail/exceptions.hpp>
16056
16057
// #include <nlohmann/detail/macro_scope.hpp>
16058
16059
// #include <nlohmann/detail/meta/cpp_future.hpp>
16060
16061
// #include <nlohmann/detail/output/binary_writer.hpp>
16062
16063
// #include <nlohmann/detail/output/output_adapters.hpp>
16064
16065
// #include <nlohmann/detail/value_t.hpp>
16066
16067
16068
namespace nlohmann
16069
{
16070
namespace detail
16071
{
16072
///////////////////
16073
// serialization //
16074
///////////////////
16075
16076
/// how to treat decoding errors
16077
enum class error_handler_t
16078
{
16079
strict, ///< throw a type_error exception in case of invalid UTF-8
16080
replace, ///< replace invalid UTF-8 sequences with U+FFFD
16081
ignore ///< ignore invalid UTF-8 sequences
16082
};
16083
16084
template<typename BasicJsonType>
16085
class serializer
16086
{
16087
using string_t = typename BasicJsonType::string_t;
16088
using number_float_t = typename BasicJsonType::number_float_t;
16089
using number_integer_t = typename BasicJsonType::number_integer_t;
16090
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
16091
using binary_char_t = typename BasicJsonType::binary_t::value_type;
16092
static constexpr std::uint8_t UTF8_ACCEPT = 0;
16093
static constexpr std::uint8_t UTF8_REJECT = 1;
16094
16095
public:
16096
/*!
16097
@param[in] s output stream to serialize to
16098
@param[in] ichar indentation character to use
16099
@param[in] error_handler_ how to react on decoding errors
16100
*/
16101
serializer(output_adapter_t<char> s, const char ichar,
16102
error_handler_t error_handler_ = error_handler_t::strict)
16103
: o(std::move(s))
16104
, loc(std::localeconv())
16105
, thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
16106
, decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
16107
, indent_char(ichar)
16108
, indent_string(512, indent_char)
16109
, error_handler(error_handler_)
16110
{}
16111
16112
// delete because of pointer members
16113
serializer(const serializer&) = delete;
16114
serializer& operator=(const serializer&) = delete;
16115
serializer(serializer&&) = delete;
16116
serializer& operator=(serializer&&) = delete;
16117
~serializer() = default;
16118
16119
/*!
16120
@brief internal implementation of the serialization function
16121
16122
This function is called by the public member function dump and organizes
16123
the serialization internally. The indentation level is propagated as
16124
additional parameter. In case of arrays and objects, the function is
16125
called recursively.
16126
16127
- strings and object keys are escaped using `escape_string()`
16128
- integer numbers are converted implicitly via `operator<<`
16129
- floating-point numbers are converted to a string using `"%g"` format
16130
- binary values are serialized as objects containing the subtype and the
16131
byte array
16132
16133
@param[in] val value to serialize
16134
@param[in] pretty_print whether the output shall be pretty-printed
16135
@param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
16136
in the output are escaped with `\uXXXX` sequences, and the result consists
16137
of ASCII characters only.
16138
@param[in] indent_step the indent level
16139
@param[in] current_indent the current indent level (only used internally)
16140
*/
16141
void dump(const BasicJsonType& val,
16142
const bool pretty_print,
16143
const bool ensure_ascii,
16144
const unsigned int indent_step,
16145
const unsigned int current_indent = 0)
16146
{
16147
switch (val.m_type)
16148
{
16149
case value_t::object:
16150
{
16151
if (val.m_value.object->empty())
16152
{
16153
o->write_characters("{}", 2);
16154
return;
16155
}
16156
16157
if (pretty_print)
16158
{
16159
o->write_characters("{\n", 2);
16160
16161
// variable to hold indentation for recursive calls
16162
const auto new_indent = current_indent + indent_step;
16163
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
16164
{
16165
indent_string.resize(indent_string.size() * 2, ' ');
16166
}
16167
16168
// first n-1 elements
16169
auto i = val.m_value.object->cbegin();
16170
for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
16171
{
16172
o->write_characters(indent_string.c_str(), new_indent);
16173
o->write_character('\"');
16174
dump_escaped(i->first, ensure_ascii);
16175
o->write_characters("\": ", 3);
16176
dump(i->second, true, ensure_ascii, indent_step, new_indent);
16177
o->write_characters(",\n", 2);
16178
}
16179
16180
// last element
16181
JSON_ASSERT(i != val.m_value.object->cend());
16182
JSON_ASSERT(std::next(i) == val.m_value.object->cend());
16183
o->write_characters(indent_string.c_str(), new_indent);
16184
o->write_character('\"');
16185
dump_escaped(i->first, ensure_ascii);
16186
o->write_characters("\": ", 3);
16187
dump(i->second, true, ensure_ascii, indent_step, new_indent);
16188
16189
o->write_character('\n');
16190
o->write_characters(indent_string.c_str(), current_indent);
16191
o->write_character('}');
16192
}
16193
else
16194
{
16195
o->write_character('{');
16196
16197
// first n-1 elements
16198
auto i = val.m_value.object->cbegin();
16199
for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
16200
{
16201
o->write_character('\"');
16202
dump_escaped(i->first, ensure_ascii);
16203
o->write_characters("\":", 2);
16204
dump(i->second, false, ensure_ascii, indent_step, current_indent);
16205
o->write_character(',');
16206
}
16207
16208
// last element
16209
JSON_ASSERT(i != val.m_value.object->cend());
16210
JSON_ASSERT(std::next(i) == val.m_value.object->cend());
16211
o->write_character('\"');
16212
dump_escaped(i->first, ensure_ascii);
16213
o->write_characters("\":", 2);
16214
dump(i->second, false, ensure_ascii, indent_step, current_indent);
16215
16216
o->write_character('}');
16217
}
16218
16219
return;
16220
}
16221
16222
case value_t::array:
16223
{
16224
if (val.m_value.array->empty())
16225
{
16226
o->write_characters("[]", 2);
16227
return;
16228
}
16229
16230
if (pretty_print)
16231
{
16232
o->write_characters("[\n", 2);
16233
16234
// variable to hold indentation for recursive calls
16235
const auto new_indent = current_indent + indent_step;
16236
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
16237
{
16238
indent_string.resize(indent_string.size() * 2, ' ');
16239
}
16240
16241
// first n-1 elements
16242
for (auto i = val.m_value.array->cbegin();
16243
i != val.m_value.array->cend() - 1; ++i)
16244
{
16245
o->write_characters(indent_string.c_str(), new_indent);
16246
dump(*i, true, ensure_ascii, indent_step, new_indent);
16247
o->write_characters(",\n", 2);
16248
}
16249
16250
// last element
16251
JSON_ASSERT(!val.m_value.array->empty());
16252
o->write_characters(indent_string.c_str(), new_indent);
16253
dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
16254
16255
o->write_character('\n');
16256
o->write_characters(indent_string.c_str(), current_indent);
16257
o->write_character(']');
16258
}
16259
else
16260
{
16261
o->write_character('[');
16262
16263
// first n-1 elements
16264
for (auto i = val.m_value.array->cbegin();
16265
i != val.m_value.array->cend() - 1; ++i)
16266
{
16267
dump(*i, false, ensure_ascii, indent_step, current_indent);
16268
o->write_character(',');
16269
}
16270
16271
// last element
16272
JSON_ASSERT(!val.m_value.array->empty());
16273
dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
16274
16275
o->write_character(']');
16276
}
16277
16278
return;
16279
}
16280
16281
case value_t::string:
16282
{
16283
o->write_character('\"');
16284
dump_escaped(*val.m_value.string, ensure_ascii);
16285
o->write_character('\"');
16286
return;
16287
}
16288
16289
case value_t::binary:
16290
{
16291
if (pretty_print)
16292
{
16293
o->write_characters("{\n", 2);
16294
16295
// variable to hold indentation for recursive calls
16296
const auto new_indent = current_indent + indent_step;
16297
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
16298
{
16299
indent_string.resize(indent_string.size() * 2, ' ');
16300
}
16301
16302
o->write_characters(indent_string.c_str(), new_indent);
16303
16304
o->write_characters("\"bytes\": [", 10);
16305
16306
if (!val.m_value.binary->empty())
16307
{
16308
for (auto i = val.m_value.binary->cbegin();
16309
i != val.m_value.binary->cend() - 1; ++i)
16310
{
16311
dump_integer(*i);
16312
o->write_characters(", ", 2);
16313
}
16314
dump_integer(val.m_value.binary->back());
16315
}
16316
16317
o->write_characters("],\n", 3);
16318
o->write_characters(indent_string.c_str(), new_indent);
16319
16320
o->write_characters("\"subtype\": ", 11);
16321
if (val.m_value.binary->has_subtype())
16322
{
16323
dump_integer(val.m_value.binary->subtype());
16324
}
16325
else
16326
{
16327
o->write_characters("null", 4);
16328
}
16329
o->write_character('\n');
16330
o->write_characters(indent_string.c_str(), current_indent);
16331
o->write_character('}');
16332
}
16333
else
16334
{
16335
o->write_characters("{\"bytes\":[", 10);
16336
16337
if (!val.m_value.binary->empty())
16338
{
16339
for (auto i = val.m_value.binary->cbegin();
16340
i != val.m_value.binary->cend() - 1; ++i)
16341
{
16342
dump_integer(*i);
16343
o->write_character(',');
16344
}
16345
dump_integer(val.m_value.binary->back());
16346
}
16347
16348
o->write_characters("],\"subtype\":", 12);
16349
if (val.m_value.binary->has_subtype())
16350
{
16351
dump_integer(val.m_value.binary->subtype());
16352
o->write_character('}');
16353
}
16354
else
16355
{
16356
o->write_characters("null}", 5);
16357
}
16358
}
16359
return;
16360
}
16361
16362
case value_t::boolean:
16363
{
16364
if (val.m_value.boolean)
16365
{
16366
o->write_characters("true", 4);
16367
}
16368
else
16369
{
16370
o->write_characters("false", 5);
16371
}
16372
return;
16373
}
16374
16375
case value_t::number_integer:
16376
{
16377
dump_integer(val.m_value.number_integer);
16378
return;
16379
}
16380
16381
case value_t::number_unsigned:
16382
{
16383
dump_integer(val.m_value.number_unsigned);
16384
return;
16385
}
16386
16387
case value_t::number_float:
16388
{
16389
dump_float(val.m_value.number_float);
16390
return;
16391
}
16392
16393
case value_t::discarded:
16394
{
16395
o->write_characters("<discarded>", 11);
16396
return;
16397
}
16398
16399
case value_t::null:
16400
{
16401
o->write_characters("null", 4);
16402
return;
16403
}
16404
16405
default: // LCOV_EXCL_LINE
16406
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16407
}
16408
}
16409
16410
JSON_PRIVATE_UNLESS_TESTED:
16411
/*!
16412
@brief dump escaped string
16413
16414
Escape a string by replacing certain special characters by a sequence of an
16415
escape character (backslash) and another character and other control
16416
characters by a sequence of "\u" followed by a four-digit hex
16417
representation. The escaped string is written to output stream @a o.
16418
16419
@param[in] s the string to escape
16420
@param[in] ensure_ascii whether to escape non-ASCII characters with
16421
\uXXXX sequences
16422
16423
@complexity Linear in the length of string @a s.
16424
*/
16425
void dump_escaped(const string_t& s, const bool ensure_ascii)
16426
{
16427
std::uint32_t codepoint{};
16428
std::uint8_t state = UTF8_ACCEPT;
16429
std::size_t bytes = 0; // number of bytes written to string_buffer
16430
16431
// number of bytes written at the point of the last valid byte
16432
std::size_t bytes_after_last_accept = 0;
16433
std::size_t undumped_chars = 0;
16434
16435
for (std::size_t i = 0; i < s.size(); ++i)
16436
{
16437
const auto byte = static_cast<std::uint8_t>(s[i]);
16438
16439
switch (decode(state, codepoint, byte))
16440
{
16441
case UTF8_ACCEPT: // decode found a new code point
16442
{
16443
switch (codepoint)
16444
{
16445
case 0x08: // backspace
16446
{
16447
string_buffer[bytes++] = '\\';
16448
string_buffer[bytes++] = 'b';
16449
break;
16450
}
16451
16452
case 0x09: // horizontal tab
16453
{
16454
string_buffer[bytes++] = '\\';
16455
string_buffer[bytes++] = 't';
16456
break;
16457
}
16458
16459
case 0x0A: // newline
16460
{
16461
string_buffer[bytes++] = '\\';
16462
string_buffer[bytes++] = 'n';
16463
break;
16464
}
16465
16466
case 0x0C: // formfeed
16467
{
16468
string_buffer[bytes++] = '\\';
16469
string_buffer[bytes++] = 'f';
16470
break;
16471
}
16472
16473
case 0x0D: // carriage return
16474
{
16475
string_buffer[bytes++] = '\\';
16476
string_buffer[bytes++] = 'r';
16477
break;
16478
}
16479
16480
case 0x22: // quotation mark
16481
{
16482
string_buffer[bytes++] = '\\';
16483
string_buffer[bytes++] = '\"';
16484
break;
16485
}
16486
16487
case 0x5C: // reverse solidus
16488
{
16489
string_buffer[bytes++] = '\\';
16490
string_buffer[bytes++] = '\\';
16491
break;
16492
}
16493
16494
default:
16495
{
16496
// escape control characters (0x00..0x1F) or, if
16497
// ensure_ascii parameter is used, non-ASCII characters
16498
if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
16499
{
16500
if (codepoint <= 0xFFFF)
16501
{
16502
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
16503
static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
16504
static_cast<std::uint16_t>(codepoint)));
16505
bytes += 6;
16506
}
16507
else
16508
{
16509
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
16510
static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
16511
static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
16512
static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
16513
bytes += 12;
16514
}
16515
}
16516
else
16517
{
16518
// copy byte to buffer (all previous bytes
16519
// been copied have in default case above)
16520
string_buffer[bytes++] = s[i];
16521
}
16522
break;
16523
}
16524
}
16525
16526
// write buffer and reset index; there must be 13 bytes
16527
// left, as this is the maximal number of bytes to be
16528
// written ("\uxxxx\uxxxx\0") for one code point
16529
if (string_buffer.size() - bytes < 13)
16530
{
16531
o->write_characters(string_buffer.data(), bytes);
16532
bytes = 0;
16533
}
16534
16535
// remember the byte position of this accept
16536
bytes_after_last_accept = bytes;
16537
undumped_chars = 0;
16538
break;
16539
}
16540
16541
case UTF8_REJECT: // decode found invalid UTF-8 byte
16542
{
16543
switch (error_handler)
16544
{
16545
case error_handler_t::strict:
16546
{
16547
std::stringstream ss;
16548
ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (byte | 0);
16549
JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + ss.str(), BasicJsonType()));
16550
}
16551
16552
case error_handler_t::ignore:
16553
case error_handler_t::replace:
16554
{
16555
// in case we saw this character the first time, we
16556
// would like to read it again, because the byte
16557
// may be OK for itself, but just not OK for the
16558
// previous sequence
16559
if (undumped_chars > 0)
16560
{
16561
--i;
16562
}
16563
16564
// reset length buffer to the last accepted index;
16565
// thus removing/ignoring the invalid characters
16566
bytes = bytes_after_last_accept;
16567
16568
if (error_handler == error_handler_t::replace)
16569
{
16570
// add a replacement character
16571
if (ensure_ascii)
16572
{
16573
string_buffer[bytes++] = '\\';
16574
string_buffer[bytes++] = 'u';
16575
string_buffer[bytes++] = 'f';
16576
string_buffer[bytes++] = 'f';
16577
string_buffer[bytes++] = 'f';
16578
string_buffer[bytes++] = 'd';
16579
}
16580
else
16581
{
16582
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
16583
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
16584
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
16585
}
16586
16587
// write buffer and reset index; there must be 13 bytes
16588
// left, as this is the maximal number of bytes to be
16589
// written ("\uxxxx\uxxxx\0") for one code point
16590
if (string_buffer.size() - bytes < 13)
16591
{
16592
o->write_characters(string_buffer.data(), bytes);
16593
bytes = 0;
16594
}
16595
16596
bytes_after_last_accept = bytes;
16597
}
16598
16599
undumped_chars = 0;
16600
16601
// continue processing the string
16602
state = UTF8_ACCEPT;
16603
break;
16604
}
16605
16606
default: // LCOV_EXCL_LINE
16607
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16608
}
16609
break;
16610
}
16611
16612
default: // decode found yet incomplete multi-byte code point
16613
{
16614
if (!ensure_ascii)
16615
{
16616
// code point will not be escaped - copy byte to buffer
16617
string_buffer[bytes++] = s[i];
16618
}
16619
++undumped_chars;
16620
break;
16621
}
16622
}
16623
}
16624
16625
// we finished processing the string
16626
if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
16627
{
16628
// write buffer
16629
if (bytes > 0)
16630
{
16631
o->write_characters(string_buffer.data(), bytes);
16632
}
16633
}
16634
else
16635
{
16636
// we finish reading, but do not accept: string was incomplete
16637
switch (error_handler)
16638
{
16639
case error_handler_t::strict:
16640
{
16641
std::stringstream ss;
16642
ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (static_cast<std::uint8_t>(s.back()) | 0);
16643
JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + ss.str(), BasicJsonType()));
16644
}
16645
16646
case error_handler_t::ignore:
16647
{
16648
// write all accepted bytes
16649
o->write_characters(string_buffer.data(), bytes_after_last_accept);
16650
break;
16651
}
16652
16653
case error_handler_t::replace:
16654
{
16655
// write all accepted bytes
16656
o->write_characters(string_buffer.data(), bytes_after_last_accept);
16657
// add a replacement character
16658
if (ensure_ascii)
16659
{
16660
o->write_characters("\\ufffd", 6);
16661
}
16662
else
16663
{
16664
o->write_characters("\xEF\xBF\xBD", 3);
16665
}
16666
break;
16667
}
16668
16669
default: // LCOV_EXCL_LINE
16670
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16671
}
16672
}
16673
}
16674
16675
private:
16676
/*!
16677
@brief count digits
16678
16679
Count the number of decimal (base 10) digits for an input unsigned integer.
16680
16681
@param[in] x unsigned integer number to count its digits
16682
@return number of decimal digits
16683
*/
16684
inline unsigned int count_digits(number_unsigned_t x) noexcept
16685
{
16686
unsigned int n_digits = 1;
16687
for (;;)
16688
{
16689
if (x < 10)
16690
{
16691
return n_digits;
16692
}
16693
if (x < 100)
16694
{
16695
return n_digits + 1;
16696
}
16697
if (x < 1000)
16698
{
16699
return n_digits + 2;
16700
}
16701
if (x < 10000)
16702
{
16703
return n_digits + 3;
16704
}
16705
x = x / 10000u;
16706
n_digits += 4;
16707
}
16708
}
16709
16710
// templates to avoid warnings about useless casts
16711
template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
16712
bool is_negative_number(NumberType x)
16713
{
16714
return x < 0;
16715
}
16716
16717
template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
16718
bool is_negative_number(NumberType /*unused*/)
16719
{
16720
return false;
16721
}
16722
16723
/*!
16724
@brief dump an integer
16725
16726
Dump a given integer to output stream @a o. Works internally with
16727
@a number_buffer.
16728
16729
@param[in] x integer number (signed or unsigned) to dump
16730
@tparam NumberType either @a number_integer_t or @a number_unsigned_t
16731
*/
16732
template < typename NumberType, detail::enable_if_t <
16733
std::is_integral<NumberType>::value ||
16734
std::is_same<NumberType, number_unsigned_t>::value ||
16735
std::is_same<NumberType, number_integer_t>::value ||
16736
std::is_same<NumberType, binary_char_t>::value,
16737
int > = 0 >
16738
void dump_integer(NumberType x)
16739
{
16740
static constexpr std::array<std::array<char, 2>, 100> digits_to_99
16741
{
16742
{
16743
{{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
16744
{{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
16745
{{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
16746
{{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
16747
{{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
16748
{{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
16749
{{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
16750
{{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
16751
{{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
16752
{{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
16753
}
16754
};
16755
16756
// special case for "0"
16757
if (x == 0)
16758
{
16759
o->write_character('0');
16760
return;
16761
}
16762
16763
// use a pointer to fill the buffer
16764
auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
16765
16766
number_unsigned_t abs_value;
16767
16768
unsigned int n_chars{};
16769
16770
if (is_negative_number(x))
16771
{
16772
*buffer_ptr = '-';
16773
abs_value = remove_sign(static_cast<number_integer_t>(x));
16774
16775
// account one more byte for the minus sign
16776
n_chars = 1 + count_digits(abs_value);
16777
}
16778
else
16779
{
16780
abs_value = static_cast<number_unsigned_t>(x);
16781
n_chars = count_digits(abs_value);
16782
}
16783
16784
// spare 1 byte for '\0'
16785
JSON_ASSERT(n_chars < number_buffer.size() - 1);
16786
16787
// jump to the end to generate the string from backward,
16788
// so we later avoid reversing the result
16789
buffer_ptr += n_chars;
16790
16791
// Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
16792
// See: https://www.youtube.com/watch?v=o4-CwDo2zpg
16793
while (abs_value >= 100)
16794
{
16795
const auto digits_index = static_cast<unsigned>((abs_value % 100));
16796
abs_value /= 100;
16797
*(--buffer_ptr) = digits_to_99[digits_index][1];
16798
*(--buffer_ptr) = digits_to_99[digits_index][0];
16799
}
16800
16801
if (abs_value >= 10)
16802
{
16803
const auto digits_index = static_cast<unsigned>(abs_value);
16804
*(--buffer_ptr) = digits_to_99[digits_index][1];
16805
*(--buffer_ptr) = digits_to_99[digits_index][0];
16806
}
16807
else
16808
{
16809
*(--buffer_ptr) = static_cast<char>('0' + abs_value);
16810
}
16811
16812
o->write_characters(number_buffer.data(), n_chars);
16813
}
16814
16815
/*!
16816
@brief dump a floating-point number
16817
16818
Dump a given floating-point number to output stream @a o. Works internally
16819
with @a number_buffer.
16820
16821
@param[in] x floating-point number to dump
16822
*/
16823
void dump_float(number_float_t x)
16824
{
16825
// NaN / inf
16826
if (!std::isfinite(x))
16827
{
16828
o->write_characters("null", 4);
16829
return;
16830
}
16831
16832
// If number_float_t is an IEEE-754 single or double precision number,
16833
// use the Grisu2 algorithm to produce short numbers which are
16834
// guaranteed to round-trip, using strtof and strtod, resp.
16835
//
16836
// NB: The test below works if <long double> == <double>.
16837
static constexpr bool is_ieee_single_or_double
16838
= (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
16839
(std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
16840
16841
dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
16842
}
16843
16844
void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
16845
{
16846
auto* begin = number_buffer.data();
16847
auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
16848
16849
o->write_characters(begin, static_cast<size_t>(end - begin));
16850
}
16851
16852
void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
16853
{
16854
// get number of digits for a float -> text -> float round-trip
16855
static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
16856
16857
// the actual conversion
16858
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
16859
std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
16860
16861
// negative value indicates an error
16862
JSON_ASSERT(len > 0);
16863
// check if buffer was large enough
16864
JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
16865
16866
// erase thousands separator
16867
if (thousands_sep != '\0')
16868
{
16869
// NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
16870
const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
16871
std::fill(end, number_buffer.end(), '\0');
16872
JSON_ASSERT((end - number_buffer.begin()) <= len);
16873
len = (end - number_buffer.begin());
16874
}
16875
16876
// convert decimal point to '.'
16877
if (decimal_point != '\0' && decimal_point != '.')
16878
{
16879
// NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
16880
const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
16881
if (dec_pos != number_buffer.end())
16882
{
16883
*dec_pos = '.';
16884
}
16885
}
16886
16887
o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
16888
16889
// determine if we need to append ".0"
16890
const bool value_is_int_like =
16891
std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
16892
[](char c)
16893
{
16894
return c == '.' || c == 'e';
16895
});
16896
16897
if (value_is_int_like)
16898
{
16899
o->write_characters(".0", 2);
16900
}
16901
}
16902
16903
/*!
16904
@brief check whether a string is UTF-8 encoded
16905
16906
The function checks each byte of a string whether it is UTF-8 encoded. The
16907
result of the check is stored in the @a state parameter. The function must
16908
be called initially with state 0 (accept). State 1 means the string must
16909
be rejected, because the current byte is not allowed. If the string is
16910
completely processed, but the state is non-zero, the string ended
16911
prematurely; that is, the last byte indicated more bytes should have
16912
followed.
16913
16914
@param[in,out] state the state of the decoding
16915
@param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
16916
@param[in] byte next byte to decode
16917
@return new state
16918
16919
@note The function has been edited: a std::array is used.
16920
16921
@copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <[email protected]>
16922
@sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
16923
*/
16924
static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
16925
{
16926
static const std::array<std::uint8_t, 400> utf8d =
16927
{
16928
{
16929
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
16930
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
16931
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
16932
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
16933
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
16934
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
16935
8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
16936
0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
16937
0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
16938
0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
16939
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
16940
1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
16941
1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
16942
1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
16943
}
16944
};
16945
16946
JSON_ASSERT(byte < utf8d.size());
16947
const std::uint8_t type = utf8d[byte];
16948
16949
codep = (state != UTF8_ACCEPT)
16950
? (byte & 0x3fu) | (codep << 6u)
16951
: (0xFFu >> type) & (byte);
16952
16953
std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
16954
JSON_ASSERT(index < 400);
16955
state = utf8d[index];
16956
return state;
16957
}
16958
16959
/*
16960
* Overload to make the compiler happy while it is instantiating
16961
* dump_integer for number_unsigned_t.
16962
* Must never be called.
16963
*/
16964
number_unsigned_t remove_sign(number_unsigned_t x)
16965
{
16966
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
16967
return x; // LCOV_EXCL_LINE
16968
}
16969
16970
/*
16971
* Helper function for dump_integer
16972
*
16973
* This function takes a negative signed integer and returns its absolute
16974
* value as unsigned integer. The plus/minus shuffling is necessary as we can
16975
* not directly remove the sign of an arbitrary signed integer as the
16976
* absolute values of INT_MIN and INT_MAX are usually not the same. See
16977
* #1708 for details.
16978
*/
16979
inline number_unsigned_t remove_sign(number_integer_t x) noexcept
16980
{
16981
JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
16982
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
16983
}
16984
16985
private:
16986
/// the output of the serializer
16987
output_adapter_t<char> o = nullptr;
16988
16989
/// a (hopefully) large enough character buffer
16990
std::array<char, 64> number_buffer{{}};
16991
16992
/// the locale
16993
const std::lconv* loc = nullptr;
16994
/// the locale's thousand separator character
16995
const char thousands_sep = '\0';
16996
/// the locale's decimal point character
16997
const char decimal_point = '\0';
16998
16999
/// string buffer
17000
std::array<char, 512> string_buffer{{}};
17001
17002
/// the indentation character
17003
const char indent_char;
17004
/// the indentation string
17005
string_t indent_string;
17006
17007
/// error_handler how to react on decoding errors
17008
const error_handler_t error_handler;
17009
};
17010
} // namespace detail
17011
} // namespace nlohmann
17012
17013
// #include <nlohmann/detail/value_t.hpp>
17014
17015
// #include <nlohmann/json_fwd.hpp>
17016
17017
// #include <nlohmann/ordered_map.hpp>
17018
17019
17020
#include <functional> // less
17021
#include <initializer_list> // initializer_list
17022
#include <iterator> // input_iterator_tag, iterator_traits
17023
#include <memory> // allocator
17024
#include <stdexcept> // for out_of_range
17025
#include <type_traits> // enable_if, is_convertible
17026
#include <utility> // pair
17027
#include <vector> // vector
17028
17029
// #include <nlohmann/detail/macro_scope.hpp>
17030
17031
17032
namespace nlohmann
17033
{
17034
17035
/// ordered_map: a minimal map-like container that preserves insertion order
17036
/// for use within nlohmann::basic_json<ordered_map>
17037
template <class Key, class T, class IgnoredLess = std::less<Key>,
17038
class Allocator = std::allocator<std::pair<const Key, T>>>
17039
struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
17040
{
17041
using key_type = Key;
17042
using mapped_type = T;
17043
using Container = std::vector<std::pair<const Key, T>, Allocator>;
17044
using iterator = typename Container::iterator;
17045
using const_iterator = typename Container::const_iterator;
17046
using size_type = typename Container::size_type;
17047
using value_type = typename Container::value_type;
17048
17049
// Explicit constructors instead of `using Container::Container`
17050
// otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
17051
ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {}
17052
template <class It>
17053
ordered_map(It first, It last, const Allocator& alloc = Allocator())
17054
: Container{first, last, alloc} {}
17055
ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator() )
17056
: Container{init, alloc} {}
17057
17058
std::pair<iterator, bool> emplace(const key_type& key, T&& t)
17059
{
17060
for (auto it = this->begin(); it != this->end(); ++it)
17061
{
17062
if (it->first == key)
17063
{
17064
return {it, false};
17065
}
17066
}
17067
Container::emplace_back(key, t);
17068
return {--this->end(), true};
17069
}
17070
17071
T& operator[](const Key& key)
17072
{
17073
return emplace(key, T{}).first->second;
17074
}
17075
17076
const T& operator[](const Key& key) const
17077
{
17078
return at(key);
17079
}
17080
17081
T& at(const Key& key)
17082
{
17083
for (auto it = this->begin(); it != this->end(); ++it)
17084
{
17085
if (it->first == key)
17086
{
17087
return it->second;
17088
}
17089
}
17090
17091
JSON_THROW(std::out_of_range("key not found"));
17092
}
17093
17094
const T& at(const Key& key) const
17095
{
17096
for (auto it = this->begin(); it != this->end(); ++it)
17097
{
17098
if (it->first == key)
17099
{
17100
return it->second;
17101
}
17102
}
17103
17104
JSON_THROW(std::out_of_range("key not found"));
17105
}
17106
17107
size_type erase(const Key& key)
17108
{
17109
for (auto it = this->begin(); it != this->end(); ++it)
17110
{
17111
if (it->first == key)
17112
{
17113
// Since we cannot move const Keys, re-construct them in place
17114
for (auto next = it; ++next != this->end(); ++it)
17115
{
17116
it->~value_type(); // Destroy but keep allocation
17117
new (&*it) value_type{std::move(*next)};
17118
}
17119
Container::pop_back();
17120
return 1;
17121
}
17122
}
17123
return 0;
17124
}
17125
17126
iterator erase(iterator pos)
17127
{
17128
return erase(pos, std::next(pos));
17129
}
17130
17131
iterator erase(iterator first, iterator last)
17132
{
17133
const auto elements_affected = std::distance(first, last);
17134
const auto offset = std::distance(Container::begin(), first);
17135
17136
// This is the start situation. We need to delete elements_affected
17137
// elements (3 in this example: e, f, g), and need to return an
17138
// iterator past the last deleted element (h in this example).
17139
// Note that offset is the distance from the start of the vector
17140
// to first. We will need this later.
17141
17142
// [ a, b, c, d, e, f, g, h, i, j ]
17143
// ^ ^
17144
// first last
17145
17146
// Since we cannot move const Keys, we re-construct them in place.
17147
// We start at first and re-construct (viz. copy) the elements from
17148
// the back of the vector. Example for first iteration:
17149
17150
// ,--------.
17151
// v | destroy e and re-construct with h
17152
// [ a, b, c, d, e, f, g, h, i, j ]
17153
// ^ ^
17154
// it it + elements_affected
17155
17156
for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
17157
{
17158
it->~value_type(); // destroy but keep allocation
17159
new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
17160
}
17161
17162
// [ a, b, c, d, h, i, j, h, i, j ]
17163
// ^ ^
17164
// first last
17165
17166
// remove the unneeded elements at the end of the vector
17167
Container::resize(this->size() - static_cast<size_type>(elements_affected));
17168
17169
// [ a, b, c, d, h, i, j ]
17170
// ^ ^
17171
// first last
17172
17173
// first is now pointing past the last deleted element, but we cannot
17174
// use this iterator, because it may have been invalidated by the
17175
// resize call. Instead, we can return begin() + offset.
17176
return Container::begin() + offset;
17177
}
17178
17179
size_type count(const Key& key) const
17180
{
17181
for (auto it = this->begin(); it != this->end(); ++it)
17182
{
17183
if (it->first == key)
17184
{
17185
return 1;
17186
}
17187
}
17188
return 0;
17189
}
17190
17191
iterator find(const Key& key)
17192
{
17193
for (auto it = this->begin(); it != this->end(); ++it)
17194
{
17195
if (it->first == key)
17196
{
17197
return it;
17198
}
17199
}
17200
return Container::end();
17201
}
17202
17203
const_iterator find(const Key& key) const
17204
{
17205
for (auto it = this->begin(); it != this->end(); ++it)
17206
{
17207
if (it->first == key)
17208
{
17209
return it;
17210
}
17211
}
17212
return Container::end();
17213
}
17214
17215
std::pair<iterator, bool> insert( value_type&& value )
17216
{
17217
return emplace(value.first, std::move(value.second));
17218
}
17219
17220
std::pair<iterator, bool> insert( const value_type& value )
17221
{
17222
for (auto it = this->begin(); it != this->end(); ++it)
17223
{
17224
if (it->first == value.first)
17225
{
17226
return {it, false};
17227
}
17228
}
17229
Container::push_back(value);
17230
return {--this->end(), true};
17231
}
17232
17233
template<typename InputIt>
17234
using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
17235
std::input_iterator_tag>::value>::type;
17236
17237
template<typename InputIt, typename = require_input_iter<InputIt>>
17238
void insert(InputIt first, InputIt last)
17239
{
17240
for (auto it = first; it != last; ++it)
17241
{
17242
insert(*it);
17243
}
17244
}
17245
};
17246
17247
} // namespace nlohmann
17248
17249
17250
#if defined(JSON_HAS_CPP_17)
17251
#include <string_view>
17252
#endif
17253
17254
/*!
17255
@brief namespace for Niels Lohmann
17256
@see https://github.com/nlohmann
17257
@since version 1.0.0
17258
*/
17259
namespace nlohmann
17260
{
17261
17262
/*!
17263
@brief a class to store JSON values
17264
17265
@internal
17266
@invariant The member variables @a m_value and @a m_type have the following
17267
relationship:
17268
- If `m_type == value_t::object`, then `m_value.object != nullptr`.
17269
- If `m_type == value_t::array`, then `m_value.array != nullptr`.
17270
- If `m_type == value_t::string`, then `m_value.string != nullptr`.
17271
The invariants are checked by member function assert_invariant().
17272
17273
@note ObjectType trick from https://stackoverflow.com/a/9860911
17274
@endinternal
17275
17276
@since version 1.0.0
17277
17278
@nosubgrouping
17279
*/
17280
NLOHMANN_BASIC_JSON_TPL_DECLARATION
17281
class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
17282
{
17283
private:
17284
template<detail::value_t> friend struct detail::external_constructor;
17285
friend ::nlohmann::json_pointer<basic_json>;
17286
17287
template<typename BasicJsonType, typename InputType>
17288
friend class ::nlohmann::detail::parser;
17289
friend ::nlohmann::detail::serializer<basic_json>;
17290
template<typename BasicJsonType>
17291
friend class ::nlohmann::detail::iter_impl;
17292
template<typename BasicJsonType, typename CharType>
17293
friend class ::nlohmann::detail::binary_writer;
17294
template<typename BasicJsonType, typename InputType, typename SAX>
17295
friend class ::nlohmann::detail::binary_reader;
17296
template<typename BasicJsonType>
17297
friend class ::nlohmann::detail::json_sax_dom_parser;
17298
template<typename BasicJsonType>
17299
friend class ::nlohmann::detail::json_sax_dom_callback_parser;
17300
friend class ::nlohmann::detail::exception;
17301
17302
/// workaround type for MSVC
17303
using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
17304
17305
JSON_PRIVATE_UNLESS_TESTED:
17306
// convenience aliases for types residing in namespace detail;
17307
using lexer = ::nlohmann::detail::lexer_base<basic_json>;
17308
17309
template<typename InputAdapterType>
17310
static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
17311
InputAdapterType adapter,
17312
detail::parser_callback_t<basic_json>cb = nullptr,
17313
const bool allow_exceptions = true,
17314
const bool ignore_comments = false
17315
)
17316
{
17317
return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
17318
std::move(cb), allow_exceptions, ignore_comments);
17319
}
17320
17321
private:
17322
using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
17323
template<typename BasicJsonType>
17324
using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
17325
template<typename BasicJsonType>
17326
using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
17327
template<typename Iterator>
17328
using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
17329
template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
17330
17331
template<typename CharType>
17332
using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
17333
17334
template<typename InputType>
17335
using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
17336
template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
17337
17338
JSON_PRIVATE_UNLESS_TESTED:
17339
using serializer = ::nlohmann::detail::serializer<basic_json>;
17340
17341
public:
17342
using value_t = detail::value_t;
17343
/// JSON Pointer, see @ref nlohmann::json_pointer
17344
using json_pointer = ::nlohmann::json_pointer<basic_json>;
17345
template<typename T, typename SFINAE>
17346
using json_serializer = JSONSerializer<T, SFINAE>;
17347
/// how to treat decoding errors
17348
using error_handler_t = detail::error_handler_t;
17349
/// how to treat CBOR tags
17350
using cbor_tag_handler_t = detail::cbor_tag_handler_t;
17351
/// helper type for initializer lists of basic_json values
17352
using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
17353
17354
using input_format_t = detail::input_format_t;
17355
/// SAX interface type, see @ref nlohmann::json_sax
17356
using json_sax_t = json_sax<basic_json>;
17357
17358
////////////////
17359
// exceptions //
17360
////////////////
17361
17362
/// @name exceptions
17363
/// Classes to implement user-defined exceptions.
17364
/// @{
17365
17366
using exception = detail::exception;
17367
using parse_error = detail::parse_error;
17368
using invalid_iterator = detail::invalid_iterator;
17369
using type_error = detail::type_error;
17370
using out_of_range = detail::out_of_range;
17371
using other_error = detail::other_error;
17372
17373
/// @}
17374
17375
17376
/////////////////////
17377
// container types //
17378
/////////////////////
17379
17380
/// @name container types
17381
/// The canonic container types to use @ref basic_json like any other STL
17382
/// container.
17383
/// @{
17384
17385
/// the type of elements in a basic_json container
17386
using value_type = basic_json;
17387
17388
/// the type of an element reference
17389
using reference = value_type&;
17390
/// the type of an element const reference
17391
using const_reference = const value_type&;
17392
17393
/// a type to represent differences between iterators
17394
using difference_type = std::ptrdiff_t;
17395
/// a type to represent container sizes
17396
using size_type = std::size_t;
17397
17398
/// the allocator type
17399
using allocator_type = AllocatorType<basic_json>;
17400
17401
/// the type of an element pointer
17402
using pointer = typename std::allocator_traits<allocator_type>::pointer;
17403
/// the type of an element const pointer
17404
using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
17405
17406
/// an iterator for a basic_json container
17407
using iterator = iter_impl<basic_json>;
17408
/// a const iterator for a basic_json container
17409
using const_iterator = iter_impl<const basic_json>;
17410
/// a reverse iterator for a basic_json container
17411
using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
17412
/// a const reverse iterator for a basic_json container
17413
using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
17414
17415
/// @}
17416
17417
17418
/// @brief returns the allocator associated with the container
17419
/// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
17420
static allocator_type get_allocator()
17421
{
17422
return allocator_type();
17423
}
17424
17425
/// @brief returns version information on the library
17426
/// @sa https://json.nlohmann.me/api/basic_json/meta/
17427
JSON_HEDLEY_WARN_UNUSED_RESULT
17428
static basic_json meta()
17429
{
17430
basic_json result;
17431
17432
result["copyright"] = "(C) 2013-2022 Niels Lohmann";
17433
result["name"] = "JSON for Modern C++";
17434
result["url"] = "https://github.com/nlohmann/json";
17435
result["version"]["string"] =
17436
std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
17437
std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
17438
std::to_string(NLOHMANN_JSON_VERSION_PATCH);
17439
result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
17440
result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
17441
result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
17442
17443
#ifdef _WIN32
17444
result["platform"] = "win32";
17445
#elif defined __linux__
17446
result["platform"] = "linux";
17447
#elif defined __APPLE__
17448
result["platform"] = "apple";
17449
#elif defined __unix__
17450
result["platform"] = "unix";
17451
#else
17452
result["platform"] = "unknown";
17453
#endif
17454
17455
#if defined(__ICC) || defined(__INTEL_COMPILER)
17456
result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
17457
#elif defined(__clang__)
17458
result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
17459
#elif defined(__GNUC__) || defined(__GNUG__)
17460
result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
17461
#elif defined(__HP_cc) || defined(__HP_aCC)
17462
result["compiler"] = "hp"
17463
#elif defined(__IBMCPP__)
17464
result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
17465
#elif defined(_MSC_VER)
17466
result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
17467
#elif defined(__PGI)
17468
result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
17469
#elif defined(__SUNPRO_CC)
17470
result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
17471
#else
17472
result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
17473
#endif
17474
17475
#ifdef __cplusplus
17476
result["compiler"]["c++"] = std::to_string(__cplusplus);
17477
#else
17478
result["compiler"]["c++"] = "unknown";
17479
#endif
17480
return result;
17481
}
17482
17483
17484
///////////////////////////
17485
// JSON value data types //
17486
///////////////////////////
17487
17488
/// @name JSON value data types
17489
/// The data types to store a JSON value. These types are derived from
17490
/// the template arguments passed to class @ref basic_json.
17491
/// @{
17492
17493
/// @brief object key comparator type
17494
/// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
17495
#if defined(JSON_HAS_CPP_14)
17496
// Use transparent comparator if possible, combined with perfect forwarding
17497
// on find() and count() calls prevents unnecessary string construction.
17498
using object_comparator_t = std::less<>;
17499
#else
17500
using object_comparator_t = std::less<StringType>;
17501
#endif
17502
17503
/// @brief a type for an object
17504
/// @sa https://json.nlohmann.me/api/basic_json/object_t/
17505
using object_t = ObjectType<StringType,
17506
basic_json,
17507
object_comparator_t,
17508
AllocatorType<std::pair<const StringType,
17509
basic_json>>>;
17510
17511
/// @brief a type for an array
17512
/// @sa https://json.nlohmann.me/api/basic_json/array_t/
17513
using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
17514
17515
/// @brief a type for a string
17516
/// @sa https://json.nlohmann.me/api/basic_json/string_t/
17517
using string_t = StringType;
17518
17519
/// @brief a type for a boolean
17520
/// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
17521
using boolean_t = BooleanType;
17522
17523
/// @brief a type for a number (integer)
17524
/// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
17525
using number_integer_t = NumberIntegerType;
17526
17527
/// @brief a type for a number (unsigned)
17528
/// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
17529
using number_unsigned_t = NumberUnsignedType;
17530
17531
/// @brief a type for a number (floating-point)
17532
/// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
17533
using number_float_t = NumberFloatType;
17534
17535
/// @brief a type for a packed binary type
17536
/// @sa https://json.nlohmann.me/api/basic_json/binary_t/
17537
using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
17538
17539
/// @}
17540
17541
private:
17542
17543
/// helper for exception-safe object creation
17544
template<typename T, typename... Args>
17545
JSON_HEDLEY_RETURNS_NON_NULL
17546
static T* create(Args&& ... args)
17547
{
17548
AllocatorType<T> alloc;
17549
using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
17550
17551
auto deleter = [&](T * obj)
17552
{
17553
AllocatorTraits::deallocate(alloc, obj, 1);
17554
};
17555
std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
17556
AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
17557
JSON_ASSERT(obj != nullptr);
17558
return obj.release();
17559
}
17560
17561
////////////////////////
17562
// JSON value storage //
17563
////////////////////////
17564
17565
JSON_PRIVATE_UNLESS_TESTED:
17566
/*!
17567
@brief a JSON value
17568
17569
The actual storage for a JSON value of the @ref basic_json class. This
17570
union combines the different storage types for the JSON value types
17571
defined in @ref value_t.
17572
17573
JSON type | value_t type | used type
17574
--------- | --------------- | ------------------------
17575
object | object | pointer to @ref object_t
17576
array | array | pointer to @ref array_t
17577
string | string | pointer to @ref string_t
17578
boolean | boolean | @ref boolean_t
17579
number | number_integer | @ref number_integer_t
17580
number | number_unsigned | @ref number_unsigned_t
17581
number | number_float | @ref number_float_t
17582
binary | binary | pointer to @ref binary_t
17583
null | null | *no value is stored*
17584
17585
@note Variable-length types (objects, arrays, and strings) are stored as
17586
pointers. The size of the union should not exceed 64 bits if the default
17587
value types are used.
17588
17589
@since version 1.0.0
17590
*/
17591
union json_value
17592
{
17593
/// object (stored with pointer to save storage)
17594
object_t* object;
17595
/// array (stored with pointer to save storage)
17596
array_t* array;
17597
/// string (stored with pointer to save storage)
17598
string_t* string;
17599
/// binary (stored with pointer to save storage)
17600
binary_t* binary;
17601
/// boolean
17602
boolean_t boolean;
17603
/// number (integer)
17604
number_integer_t number_integer;
17605
/// number (unsigned integer)
17606
number_unsigned_t number_unsigned;
17607
/// number (floating-point)
17608
number_float_t number_float;
17609
17610
/// default constructor (for null values)
17611
json_value() = default;
17612
/// constructor for booleans
17613
json_value(boolean_t v) noexcept : boolean(v) {}
17614
/// constructor for numbers (integer)
17615
json_value(number_integer_t v) noexcept : number_integer(v) {}
17616
/// constructor for numbers (unsigned)
17617
json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
17618
/// constructor for numbers (floating-point)
17619
json_value(number_float_t v) noexcept : number_float(v) {}
17620
/// constructor for empty values of a given type
17621
json_value(value_t t)
17622
{
17623
switch (t)
17624
{
17625
case value_t::object:
17626
{
17627
object = create<object_t>();
17628
break;
17629
}
17630
17631
case value_t::array:
17632
{
17633
array = create<array_t>();
17634
break;
17635
}
17636
17637
case value_t::string:
17638
{
17639
string = create<string_t>("");
17640
break;
17641
}
17642
17643
case value_t::binary:
17644
{
17645
binary = create<binary_t>();
17646
break;
17647
}
17648
17649
case value_t::boolean:
17650
{
17651
boolean = static_cast<boolean_t>(false);
17652
break;
17653
}
17654
17655
case value_t::number_integer:
17656
{
17657
number_integer = static_cast<number_integer_t>(0);
17658
break;
17659
}
17660
17661
case value_t::number_unsigned:
17662
{
17663
number_unsigned = static_cast<number_unsigned_t>(0);
17664
break;
17665
}
17666
17667
case value_t::number_float:
17668
{
17669
number_float = static_cast<number_float_t>(0.0);
17670
break;
17671
}
17672
17673
case value_t::null:
17674
{
17675
object = nullptr; // silence warning, see #821
17676
break;
17677
}
17678
17679
case value_t::discarded:
17680
default:
17681
{
17682
object = nullptr; // silence warning, see #821
17683
if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
17684
{
17685
JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5", basic_json())); // LCOV_EXCL_LINE
17686
}
17687
break;
17688
}
17689
}
17690
}
17691
17692
/// constructor for strings
17693
json_value(const string_t& value) : string(create<string_t>(value)) {}
17694
17695
/// constructor for rvalue strings
17696
json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
17697
17698
/// constructor for objects
17699
json_value(const object_t& value) : object(create<object_t>(value)) {}
17700
17701
/// constructor for rvalue objects
17702
json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
17703
17704
/// constructor for arrays
17705
json_value(const array_t& value) : array(create<array_t>(value)) {}
17706
17707
/// constructor for rvalue arrays
17708
json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
17709
17710
/// constructor for binary arrays
17711
json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
17712
17713
/// constructor for rvalue binary arrays
17714
json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
17715
17716
/// constructor for binary arrays (internal type)
17717
json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
17718
17719
/// constructor for rvalue binary arrays (internal type)
17720
json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
17721
17722
void destroy(value_t t)
17723
{
17724
if (t == value_t::array || t == value_t::object)
17725
{
17726
// flatten the current json_value to a heap-allocated stack
17727
std::vector<basic_json> stack;
17728
17729
// move the top-level items to stack
17730
if (t == value_t::array)
17731
{
17732
stack.reserve(array->size());
17733
std::move(array->begin(), array->end(), std::back_inserter(stack));
17734
}
17735
else
17736
{
17737
stack.reserve(object->size());
17738
for (auto&& it : *object)
17739
{
17740
stack.push_back(std::move(it.second));
17741
}
17742
}
17743
17744
while (!stack.empty())
17745
{
17746
// move the last item to local variable to be processed
17747
basic_json current_item(std::move(stack.back()));
17748
stack.pop_back();
17749
17750
// if current_item is array/object, move
17751
// its children to the stack to be processed later
17752
if (current_item.is_array())
17753
{
17754
std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack));
17755
17756
current_item.m_value.array->clear();
17757
}
17758
else if (current_item.is_object())
17759
{
17760
for (auto&& it : *current_item.m_value.object)
17761
{
17762
stack.push_back(std::move(it.second));
17763
}
17764
17765
current_item.m_value.object->clear();
17766
}
17767
17768
// it's now safe that current_item get destructed
17769
// since it doesn't have any children
17770
}
17771
}
17772
17773
switch (t)
17774
{
17775
case value_t::object:
17776
{
17777
AllocatorType<object_t> alloc;
17778
std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
17779
std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
17780
break;
17781
}
17782
17783
case value_t::array:
17784
{
17785
AllocatorType<array_t> alloc;
17786
std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
17787
std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
17788
break;
17789
}
17790
17791
case value_t::string:
17792
{
17793
AllocatorType<string_t> alloc;
17794
std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
17795
std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
17796
break;
17797
}
17798
17799
case value_t::binary:
17800
{
17801
AllocatorType<binary_t> alloc;
17802
std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
17803
std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
17804
break;
17805
}
17806
17807
case value_t::null:
17808
case value_t::boolean:
17809
case value_t::number_integer:
17810
case value_t::number_unsigned:
17811
case value_t::number_float:
17812
case value_t::discarded:
17813
default:
17814
{
17815
break;
17816
}
17817
}
17818
}
17819
};
17820
17821
private:
17822
/*!
17823
@brief checks the class invariants
17824
17825
This function asserts the class invariants. It needs to be called at the
17826
end of every constructor to make sure that created objects respect the
17827
invariant. Furthermore, it has to be called each time the type of a JSON
17828
value is changed, because the invariant expresses a relationship between
17829
@a m_type and @a m_value.
17830
17831
Furthermore, the parent relation is checked for arrays and objects: If
17832
@a check_parents true and the value is an array or object, then the
17833
container's elements must have the current value as parent.
17834
17835
@param[in] check_parents whether the parent relation should be checked.
17836
The value is true by default and should only be set to false
17837
during destruction of objects when the invariant does not
17838
need to hold.
17839
*/
17840
void assert_invariant(bool check_parents = true) const noexcept
17841
{
17842
JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
17843
JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
17844
JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
17845
JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
17846
17847
#if JSON_DIAGNOSTICS
17848
JSON_TRY
17849
{
17850
// cppcheck-suppress assertWithSideEffect
17851
JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
17852
{
17853
return j.m_parent == this;
17854
}));
17855
}
17856
JSON_CATCH(...) {} // LCOV_EXCL_LINE
17857
#endif
17858
static_cast<void>(check_parents);
17859
}
17860
17861
void set_parents()
17862
{
17863
#if JSON_DIAGNOSTICS
17864
switch (m_type)
17865
{
17866
case value_t::array:
17867
{
17868
for (auto& element : *m_value.array)
17869
{
17870
element.m_parent = this;
17871
}
17872
break;
17873
}
17874
17875
case value_t::object:
17876
{
17877
for (auto& element : *m_value.object)
17878
{
17879
element.second.m_parent = this;
17880
}
17881
break;
17882
}
17883
17884
case value_t::null:
17885
case value_t::string:
17886
case value_t::boolean:
17887
case value_t::number_integer:
17888
case value_t::number_unsigned:
17889
case value_t::number_float:
17890
case value_t::binary:
17891
case value_t::discarded:
17892
default:
17893
break;
17894
}
17895
#endif
17896
}
17897
17898
iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
17899
{
17900
#if JSON_DIAGNOSTICS
17901
for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
17902
{
17903
(it + i)->m_parent = this;
17904
}
17905
#else
17906
static_cast<void>(count_set_parents);
17907
#endif
17908
return it;
17909
}
17910
17911
reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
17912
{
17913
#if JSON_DIAGNOSTICS
17914
if (old_capacity != static_cast<std::size_t>(-1))
17915
{
17916
// see https://github.com/nlohmann/json/issues/2838
17917
JSON_ASSERT(type() == value_t::array);
17918
if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
17919
{
17920
// capacity has changed: update all parents
17921
set_parents();
17922
return j;
17923
}
17924
}
17925
17926
// ordered_json uses a vector internally, so pointers could have
17927
// been invalidated; see https://github.com/nlohmann/json/issues/2962
17928
#ifdef JSON_HEDLEY_MSVC_VERSION
17929
#pragma warning(push )
17930
#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
17931
#endif
17932
if (detail::is_ordered_map<object_t>::value)
17933
{
17934
set_parents();
17935
return j;
17936
}
17937
#ifdef JSON_HEDLEY_MSVC_VERSION
17938
#pragma warning( pop )
17939
#endif
17940
17941
j.m_parent = this;
17942
#else
17943
static_cast<void>(j);
17944
static_cast<void>(old_capacity);
17945
#endif
17946
return j;
17947
}
17948
17949
public:
17950
//////////////////////////
17951
// JSON parser callback //
17952
//////////////////////////
17953
17954
/// @brief parser event types
17955
/// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
17956
using parse_event_t = detail::parse_event_t;
17957
17958
/// @brief per-element parser callback type
17959
/// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
17960
using parser_callback_t = detail::parser_callback_t<basic_json>;
17961
17962
//////////////////
17963
// constructors //
17964
//////////////////
17965
17966
/// @name constructors and destructors
17967
/// Constructors of class @ref basic_json, copy/move constructor, copy
17968
/// assignment, static functions creating objects, and the destructor.
17969
/// @{
17970
17971
/// @brief create an empty value with a given type
17972
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
17973
basic_json(const value_t v)
17974
: m_type(v), m_value(v)
17975
{
17976
assert_invariant();
17977
}
17978
17979
/// @brief create a null object
17980
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
17981
basic_json(std::nullptr_t = nullptr) noexcept
17982
: basic_json(value_t::null)
17983
{
17984
assert_invariant();
17985
}
17986
17987
/// @brief create a JSON value from compatible types
17988
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
17989
template < typename CompatibleType,
17990
typename U = detail::uncvref_t<CompatibleType>,
17991
detail::enable_if_t <
17992
!detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
17993
basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
17994
JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
17995
std::forward<CompatibleType>(val))))
17996
{
17997
JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
17998
set_parents();
17999
assert_invariant();
18000
}
18001
18002
/// @brief create a JSON value from an existing one
18003
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18004
template < typename BasicJsonType,
18005
detail::enable_if_t <
18006
detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
18007
basic_json(const BasicJsonType& val)
18008
{
18009
using other_boolean_t = typename BasicJsonType::boolean_t;
18010
using other_number_float_t = typename BasicJsonType::number_float_t;
18011
using other_number_integer_t = typename BasicJsonType::number_integer_t;
18012
using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18013
using other_string_t = typename BasicJsonType::string_t;
18014
using other_object_t = typename BasicJsonType::object_t;
18015
using other_array_t = typename BasicJsonType::array_t;
18016
using other_binary_t = typename BasicJsonType::binary_t;
18017
18018
switch (val.type())
18019
{
18020
case value_t::boolean:
18021
JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
18022
break;
18023
case value_t::number_float:
18024
JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
18025
break;
18026
case value_t::number_integer:
18027
JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
18028
break;
18029
case value_t::number_unsigned:
18030
JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
18031
break;
18032
case value_t::string:
18033
JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
18034
break;
18035
case value_t::object:
18036
JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
18037
break;
18038
case value_t::array:
18039
JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
18040
break;
18041
case value_t::binary:
18042
JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
18043
break;
18044
case value_t::null:
18045
*this = nullptr;
18046
break;
18047
case value_t::discarded:
18048
m_type = value_t::discarded;
18049
break;
18050
default: // LCOV_EXCL_LINE
18051
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18052
}
18053
set_parents();
18054
assert_invariant();
18055
}
18056
18057
/// @brief create a container (array or object) from an initializer list
18058
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18059
basic_json(initializer_list_t init,
18060
bool type_deduction = true,
18061
value_t manual_type = value_t::array)
18062
{
18063
// check if each element is an array with two elements whose first
18064
// element is a string
18065
bool is_an_object = std::all_of(init.begin(), init.end(),
18066
[](const detail::json_ref<basic_json>& element_ref)
18067
{
18068
return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
18069
});
18070
18071
// adjust type if type deduction is not wanted
18072
if (!type_deduction)
18073
{
18074
// if array is wanted, do not create an object though possible
18075
if (manual_type == value_t::array)
18076
{
18077
is_an_object = false;
18078
}
18079
18080
// if object is wanted but impossible, throw an exception
18081
if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
18082
{
18083
JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json()));
18084
}
18085
}
18086
18087
if (is_an_object)
18088
{
18089
// the initializer list is a list of pairs -> create object
18090
m_type = value_t::object;
18091
m_value = value_t::object;
18092
18093
for (auto& element_ref : init)
18094
{
18095
auto element = element_ref.moved_or_copied();
18096
m_value.object->emplace(
18097
std::move(*((*element.m_value.array)[0].m_value.string)),
18098
std::move((*element.m_value.array)[1]));
18099
}
18100
}
18101
else
18102
{
18103
// the initializer list describes an array -> create array
18104
m_type = value_t::array;
18105
m_value.array = create<array_t>(init.begin(), init.end());
18106
}
18107
18108
set_parents();
18109
assert_invariant();
18110
}
18111
18112
/// @brief explicitly create a binary array (without subtype)
18113
/// @sa https://json.nlohmann.me/api/basic_json/binary/
18114
JSON_HEDLEY_WARN_UNUSED_RESULT
18115
static basic_json binary(const typename binary_t::container_type& init)
18116
{
18117
auto res = basic_json();
18118
res.m_type = value_t::binary;
18119
res.m_value = init;
18120
return res;
18121
}
18122
18123
/// @brief explicitly create a binary array (with subtype)
18124
/// @sa https://json.nlohmann.me/api/basic_json/binary/
18125
JSON_HEDLEY_WARN_UNUSED_RESULT
18126
static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
18127
{
18128
auto res = basic_json();
18129
res.m_type = value_t::binary;
18130
res.m_value = binary_t(init, subtype);
18131
return res;
18132
}
18133
18134
/// @brief explicitly create a binary array
18135
/// @sa https://json.nlohmann.me/api/basic_json/binary/
18136
JSON_HEDLEY_WARN_UNUSED_RESULT
18137
static basic_json binary(typename binary_t::container_type&& init)
18138
{
18139
auto res = basic_json();
18140
res.m_type = value_t::binary;
18141
res.m_value = std::move(init);
18142
return res;
18143
}
18144
18145
/// @brief explicitly create a binary array (with subtype)
18146
/// @sa https://json.nlohmann.me/api/basic_json/binary/
18147
JSON_HEDLEY_WARN_UNUSED_RESULT
18148
static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
18149
{
18150
auto res = basic_json();
18151
res.m_type = value_t::binary;
18152
res.m_value = binary_t(std::move(init), subtype);
18153
return res;
18154
}
18155
18156
/// @brief explicitly create an array from an initializer list
18157
/// @sa https://json.nlohmann.me/api/basic_json/array/
18158
JSON_HEDLEY_WARN_UNUSED_RESULT
18159
static basic_json array(initializer_list_t init = {})
18160
{
18161
return basic_json(init, false, value_t::array);
18162
}
18163
18164
/// @brief explicitly create an object from an initializer list
18165
/// @sa https://json.nlohmann.me/api/basic_json/object/
18166
JSON_HEDLEY_WARN_UNUSED_RESULT
18167
static basic_json object(initializer_list_t init = {})
18168
{
18169
return basic_json(init, false, value_t::object);
18170
}
18171
18172
/// @brief construct an array with count copies of given value
18173
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18174
basic_json(size_type cnt, const basic_json& val)
18175
: m_type(value_t::array)
18176
{
18177
m_value.array = create<array_t>(cnt, val);
18178
set_parents();
18179
assert_invariant();
18180
}
18181
18182
/// @brief construct a JSON container given an iterator range
18183
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18184
template < class InputIT, typename std::enable_if <
18185
std::is_same<InputIT, typename basic_json_t::iterator>::value ||
18186
std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
18187
basic_json(InputIT first, InputIT last)
18188
{
18189
JSON_ASSERT(first.m_object != nullptr);
18190
JSON_ASSERT(last.m_object != nullptr);
18191
18192
// make sure iterator fits the current value
18193
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
18194
{
18195
JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json()));
18196
}
18197
18198
// copy type from first iterator
18199
m_type = first.m_object->m_type;
18200
18201
// check if iterator range is complete for primitive values
18202
switch (m_type)
18203
{
18204
case value_t::boolean:
18205
case value_t::number_float:
18206
case value_t::number_integer:
18207
case value_t::number_unsigned:
18208
case value_t::string:
18209
{
18210
if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
18211
|| !last.m_it.primitive_iterator.is_end()))
18212
{
18213
JSON_THROW(invalid_iterator::create(204, "iterators out of range", *first.m_object));
18214
}
18215
break;
18216
}
18217
18218
case value_t::null:
18219
case value_t::object:
18220
case value_t::array:
18221
case value_t::binary:
18222
case value_t::discarded:
18223
default:
18224
break;
18225
}
18226
18227
switch (m_type)
18228
{
18229
case value_t::number_integer:
18230
{
18231
m_value.number_integer = first.m_object->m_value.number_integer;
18232
break;
18233
}
18234
18235
case value_t::number_unsigned:
18236
{
18237
m_value.number_unsigned = first.m_object->m_value.number_unsigned;
18238
break;
18239
}
18240
18241
case value_t::number_float:
18242
{
18243
m_value.number_float = first.m_object->m_value.number_float;
18244
break;
18245
}
18246
18247
case value_t::boolean:
18248
{
18249
m_value.boolean = first.m_object->m_value.boolean;
18250
break;
18251
}
18252
18253
case value_t::string:
18254
{
18255
m_value = *first.m_object->m_value.string;
18256
break;
18257
}
18258
18259
case value_t::object:
18260
{
18261
m_value.object = create<object_t>(first.m_it.object_iterator,
18262
last.m_it.object_iterator);
18263
break;
18264
}
18265
18266
case value_t::array:
18267
{
18268
m_value.array = create<array_t>(first.m_it.array_iterator,
18269
last.m_it.array_iterator);
18270
break;
18271
}
18272
18273
case value_t::binary:
18274
{
18275
m_value = *first.m_object->m_value.binary;
18276
break;
18277
}
18278
18279
case value_t::null:
18280
case value_t::discarded:
18281
default:
18282
JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), *first.m_object));
18283
}
18284
18285
set_parents();
18286
assert_invariant();
18287
}
18288
18289
18290
///////////////////////////////////////
18291
// other constructors and destructor //
18292
///////////////////////////////////////
18293
18294
template<typename JsonRef,
18295
detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
18296
std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
18297
basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
18298
18299
/// @brief copy constructor
18300
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18301
basic_json(const basic_json& other)
18302
: m_type(other.m_type)
18303
{
18304
// check of passed value is valid
18305
other.assert_invariant();
18306
18307
switch (m_type)
18308
{
18309
case value_t::object:
18310
{
18311
m_value = *other.m_value.object;
18312
break;
18313
}
18314
18315
case value_t::array:
18316
{
18317
m_value = *other.m_value.array;
18318
break;
18319
}
18320
18321
case value_t::string:
18322
{
18323
m_value = *other.m_value.string;
18324
break;
18325
}
18326
18327
case value_t::boolean:
18328
{
18329
m_value = other.m_value.boolean;
18330
break;
18331
}
18332
18333
case value_t::number_integer:
18334
{
18335
m_value = other.m_value.number_integer;
18336
break;
18337
}
18338
18339
case value_t::number_unsigned:
18340
{
18341
m_value = other.m_value.number_unsigned;
18342
break;
18343
}
18344
18345
case value_t::number_float:
18346
{
18347
m_value = other.m_value.number_float;
18348
break;
18349
}
18350
18351
case value_t::binary:
18352
{
18353
m_value = *other.m_value.binary;
18354
break;
18355
}
18356
18357
case value_t::null:
18358
case value_t::discarded:
18359
default:
18360
break;
18361
}
18362
18363
set_parents();
18364
assert_invariant();
18365
}
18366
18367
/// @brief move constructor
18368
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
18369
basic_json(basic_json&& other) noexcept
18370
: m_type(std::move(other.m_type)),
18371
m_value(std::move(other.m_value))
18372
{
18373
// check that passed value is valid
18374
other.assert_invariant(false);
18375
18376
// invalidate payload
18377
other.m_type = value_t::null;
18378
other.m_value = {};
18379
18380
set_parents();
18381
assert_invariant();
18382
}
18383
18384
/// @brief copy assignment
18385
/// @sa https://json.nlohmann.me/api/basic_json/operator=/
18386
basic_json& operator=(basic_json other) noexcept (
18387
std::is_nothrow_move_constructible<value_t>::value&&
18388
std::is_nothrow_move_assignable<value_t>::value&&
18389
std::is_nothrow_move_constructible<json_value>::value&&
18390
std::is_nothrow_move_assignable<json_value>::value
18391
)
18392
{
18393
// check that passed value is valid
18394
other.assert_invariant();
18395
18396
using std::swap;
18397
swap(m_type, other.m_type);
18398
swap(m_value, other.m_value);
18399
18400
set_parents();
18401
assert_invariant();
18402
return *this;
18403
}
18404
18405
/// @brief destructor
18406
/// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
18407
~basic_json() noexcept
18408
{
18409
assert_invariant(false);
18410
m_value.destroy(m_type);
18411
}
18412
18413
/// @}
18414
18415
public:
18416
///////////////////////
18417
// object inspection //
18418
///////////////////////
18419
18420
/// @name object inspection
18421
/// Functions to inspect the type of a JSON value.
18422
/// @{
18423
18424
/// @brief serialization
18425
/// @sa https://json.nlohmann.me/api/basic_json/dump/
18426
string_t dump(const int indent = -1,
18427
const char indent_char = ' ',
18428
const bool ensure_ascii = false,
18429
const error_handler_t error_handler = error_handler_t::strict) const
18430
{
18431
string_t result;
18432
serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
18433
18434
if (indent >= 0)
18435
{
18436
s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
18437
}
18438
else
18439
{
18440
s.dump(*this, false, ensure_ascii, 0);
18441
}
18442
18443
return result;
18444
}
18445
18446
/// @brief return the type of the JSON value (explicit)
18447
/// @sa https://json.nlohmann.me/api/basic_json/type/
18448
constexpr value_t type() const noexcept
18449
{
18450
return m_type;
18451
}
18452
18453
/// @brief return whether type is primitive
18454
/// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
18455
constexpr bool is_primitive() const noexcept
18456
{
18457
return is_null() || is_string() || is_boolean() || is_number() || is_binary();
18458
}
18459
18460
/// @brief return whether type is structured
18461
/// @sa https://json.nlohmann.me/api/basic_json/is_structured/
18462
constexpr bool is_structured() const noexcept
18463
{
18464
return is_array() || is_object();
18465
}
18466
18467
/// @brief return whether value is null
18468
/// @sa https://json.nlohmann.me/api/basic_json/is_null/
18469
constexpr bool is_null() const noexcept
18470
{
18471
return m_type == value_t::null;
18472
}
18473
18474
/// @brief return whether value is a boolean
18475
/// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
18476
constexpr bool is_boolean() const noexcept
18477
{
18478
return m_type == value_t::boolean;
18479
}
18480
18481
/// @brief return whether value is a number
18482
/// @sa https://json.nlohmann.me/api/basic_json/is_number/
18483
constexpr bool is_number() const noexcept
18484
{
18485
return is_number_integer() || is_number_float();
18486
}
18487
18488
/// @brief return whether value is an integer number
18489
/// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
18490
constexpr bool is_number_integer() const noexcept
18491
{
18492
return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
18493
}
18494
18495
/// @brief return whether value is an unsigned integer number
18496
/// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
18497
constexpr bool is_number_unsigned() const noexcept
18498
{
18499
return m_type == value_t::number_unsigned;
18500
}
18501
18502
/// @brief return whether value is a floating-point number
18503
/// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
18504
constexpr bool is_number_float() const noexcept
18505
{
18506
return m_type == value_t::number_float;
18507
}
18508
18509
/// @brief return whether value is an object
18510
/// @sa https://json.nlohmann.me/api/basic_json/is_object/
18511
constexpr bool is_object() const noexcept
18512
{
18513
return m_type == value_t::object;
18514
}
18515
18516
/// @brief return whether value is an array
18517
/// @sa https://json.nlohmann.me/api/basic_json/is_array/
18518
constexpr bool is_array() const noexcept
18519
{
18520
return m_type == value_t::array;
18521
}
18522
18523
/// @brief return whether value is a string
18524
/// @sa https://json.nlohmann.me/api/basic_json/is_string/
18525
constexpr bool is_string() const noexcept
18526
{
18527
return m_type == value_t::string;
18528
}
18529
18530
/// @brief return whether value is a binary array
18531
/// @sa https://json.nlohmann.me/api/basic_json/is_binary/
18532
constexpr bool is_binary() const noexcept
18533
{
18534
return m_type == value_t::binary;
18535
}
18536
18537
/// @brief return whether value is discarded
18538
/// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
18539
constexpr bool is_discarded() const noexcept
18540
{
18541
return m_type == value_t::discarded;
18542
}
18543
18544
/// @brief return the type of the JSON value (implicit)
18545
/// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
18546
constexpr operator value_t() const noexcept
18547
{
18548
return m_type;
18549
}
18550
18551
/// @}
18552
18553
private:
18554
//////////////////
18555
// value access //
18556
//////////////////
18557
18558
/// get a boolean (explicit)
18559
boolean_t get_impl(boolean_t* /*unused*/) const
18560
{
18561
if (JSON_HEDLEY_LIKELY(is_boolean()))
18562
{
18563
return m_value.boolean;
18564
}
18565
18566
JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this));
18567
}
18568
18569
/// get a pointer to the value (object)
18570
object_t* get_impl_ptr(object_t* /*unused*/) noexcept
18571
{
18572
return is_object() ? m_value.object : nullptr;
18573
}
18574
18575
/// get a pointer to the value (object)
18576
constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
18577
{
18578
return is_object() ? m_value.object : nullptr;
18579
}
18580
18581
/// get a pointer to the value (array)
18582
array_t* get_impl_ptr(array_t* /*unused*/) noexcept
18583
{
18584
return is_array() ? m_value.array : nullptr;
18585
}
18586
18587
/// get a pointer to the value (array)
18588
constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
18589
{
18590
return is_array() ? m_value.array : nullptr;
18591
}
18592
18593
/// get a pointer to the value (string)
18594
string_t* get_impl_ptr(string_t* /*unused*/) noexcept
18595
{
18596
return is_string() ? m_value.string : nullptr;
18597
}
18598
18599
/// get a pointer to the value (string)
18600
constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
18601
{
18602
return is_string() ? m_value.string : nullptr;
18603
}
18604
18605
/// get a pointer to the value (boolean)
18606
boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
18607
{
18608
return is_boolean() ? &m_value.boolean : nullptr;
18609
}
18610
18611
/// get a pointer to the value (boolean)
18612
constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
18613
{
18614
return is_boolean() ? &m_value.boolean : nullptr;
18615
}
18616
18617
/// get a pointer to the value (integer number)
18618
number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
18619
{
18620
return is_number_integer() ? &m_value.number_integer : nullptr;
18621
}
18622
18623
/// get a pointer to the value (integer number)
18624
constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
18625
{
18626
return is_number_integer() ? &m_value.number_integer : nullptr;
18627
}
18628
18629
/// get a pointer to the value (unsigned number)
18630
number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
18631
{
18632
return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
18633
}
18634
18635
/// get a pointer to the value (unsigned number)
18636
constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
18637
{
18638
return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
18639
}
18640
18641
/// get a pointer to the value (floating-point number)
18642
number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
18643
{
18644
return is_number_float() ? &m_value.number_float : nullptr;
18645
}
18646
18647
/// get a pointer to the value (floating-point number)
18648
constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
18649
{
18650
return is_number_float() ? &m_value.number_float : nullptr;
18651
}
18652
18653
/// get a pointer to the value (binary)
18654
binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
18655
{
18656
return is_binary() ? m_value.binary : nullptr;
18657
}
18658
18659
/// get a pointer to the value (binary)
18660
constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
18661
{
18662
return is_binary() ? m_value.binary : nullptr;
18663
}
18664
18665
/*!
18666
@brief helper function to implement get_ref()
18667
18668
This function helps to implement get_ref() without code duplication for
18669
const and non-const overloads
18670
18671
@tparam ThisType will be deduced as `basic_json` or `const basic_json`
18672
18673
@throw type_error.303 if ReferenceType does not match underlying value
18674
type of the current JSON
18675
*/
18676
template<typename ReferenceType, typename ThisType>
18677
static ReferenceType get_ref_impl(ThisType& obj)
18678
{
18679
// delegate the call to get_ptr<>()
18680
auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
18681
18682
if (JSON_HEDLEY_LIKELY(ptr != nullptr))
18683
{
18684
return *ptr;
18685
}
18686
18687
JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj));
18688
}
18689
18690
public:
18691
/// @name value access
18692
/// Direct access to the stored value of a JSON value.
18693
/// @{
18694
18695
/// @brief get a pointer value (implicit)
18696
/// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
18697
template<typename PointerType, typename std::enable_if<
18698
std::is_pointer<PointerType>::value, int>::type = 0>
18699
auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
18700
{
18701
// delegate the call to get_impl_ptr<>()
18702
return get_impl_ptr(static_cast<PointerType>(nullptr));
18703
}
18704
18705
/// @brief get a pointer value (implicit)
18706
/// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
18707
template < typename PointerType, typename std::enable_if <
18708
std::is_pointer<PointerType>::value&&
18709
std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
18710
constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
18711
{
18712
// delegate the call to get_impl_ptr<>() const
18713
return get_impl_ptr(static_cast<PointerType>(nullptr));
18714
}
18715
18716
private:
18717
/*!
18718
@brief get a value (explicit)
18719
18720
Explicit type conversion between the JSON value and a compatible value
18721
which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
18722
and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
18723
The value is converted by calling the @ref json_serializer<ValueType>
18724
`from_json()` method.
18725
18726
The function is equivalent to executing
18727
@code {.cpp}
18728
ValueType ret;
18729
JSONSerializer<ValueType>::from_json(*this, ret);
18730
return ret;
18731
@endcode
18732
18733
This overloads is chosen if:
18734
- @a ValueType is not @ref basic_json,
18735
- @ref json_serializer<ValueType> has a `from_json()` method of the form
18736
`void from_json(const basic_json&, ValueType&)`, and
18737
- @ref json_serializer<ValueType> does not have a `from_json()` method of
18738
the form `ValueType from_json(const basic_json&)`
18739
18740
@tparam ValueType the returned value type
18741
18742
@return copy of the JSON value, converted to @a ValueType
18743
18744
@throw what @ref json_serializer<ValueType> `from_json()` method throws
18745
18746
@liveexample{The example below shows several conversions from JSON values
18747
to other types. There a few things to note: (1) Floating-point numbers can
18748
be converted to integers\, (2) A JSON array can be converted to a standard
18749
`std::vector<short>`\, (3) A JSON object can be converted to C++
18750
associative containers such as `std::unordered_map<std::string\,
18751
json>`.,get__ValueType_const}
18752
18753
@since version 2.1.0
18754
*/
18755
template < typename ValueType,
18756
detail::enable_if_t <
18757
detail::is_default_constructible<ValueType>::value&&
18758
detail::has_from_json<basic_json_t, ValueType>::value,
18759
int > = 0 >
18760
ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
18761
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
18762
{
18763
auto ret = ValueType();
18764
JSONSerializer<ValueType>::from_json(*this, ret);
18765
return ret;
18766
}
18767
18768
/*!
18769
@brief get a value (explicit); special case
18770
18771
Explicit type conversion between the JSON value and a compatible value
18772
which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
18773
and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
18774
The value is converted by calling the @ref json_serializer<ValueType>
18775
`from_json()` method.
18776
18777
The function is equivalent to executing
18778
@code {.cpp}
18779
return JSONSerializer<ValueType>::from_json(*this);
18780
@endcode
18781
18782
This overloads is chosen if:
18783
- @a ValueType is not @ref basic_json and
18784
- @ref json_serializer<ValueType> has a `from_json()` method of the form
18785
`ValueType from_json(const basic_json&)`
18786
18787
@note If @ref json_serializer<ValueType> has both overloads of
18788
`from_json()`, this one is chosen.
18789
18790
@tparam ValueType the returned value type
18791
18792
@return copy of the JSON value, converted to @a ValueType
18793
18794
@throw what @ref json_serializer<ValueType> `from_json()` method throws
18795
18796
@since version 2.1.0
18797
*/
18798
template < typename ValueType,
18799
detail::enable_if_t <
18800
detail::has_non_default_from_json<basic_json_t, ValueType>::value,
18801
int > = 0 >
18802
ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
18803
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
18804
{
18805
return JSONSerializer<ValueType>::from_json(*this);
18806
}
18807
18808
/*!
18809
@brief get special-case overload
18810
18811
This overloads converts the current @ref basic_json in a different
18812
@ref basic_json type
18813
18814
@tparam BasicJsonType == @ref basic_json
18815
18816
@return a copy of *this, converted into @a BasicJsonType
18817
18818
@complexity Depending on the implementation of the called `from_json()`
18819
method.
18820
18821
@since version 3.2.0
18822
*/
18823
template < typename BasicJsonType,
18824
detail::enable_if_t <
18825
detail::is_basic_json<BasicJsonType>::value,
18826
int > = 0 >
18827
BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
18828
{
18829
return *this;
18830
}
18831
18832
/*!
18833
@brief get special-case overload
18834
18835
This overloads avoids a lot of template boilerplate, it can be seen as the
18836
identity method
18837
18838
@tparam BasicJsonType == @ref basic_json
18839
18840
@return a copy of *this
18841
18842
@complexity Constant.
18843
18844
@since version 2.1.0
18845
*/
18846
template<typename BasicJsonType,
18847
detail::enable_if_t<
18848
std::is_same<BasicJsonType, basic_json_t>::value,
18849
int> = 0>
18850
basic_json get_impl(detail::priority_tag<3> /*unused*/) const
18851
{
18852
return *this;
18853
}
18854
18855
/*!
18856
@brief get a pointer value (explicit)
18857
@copydoc get()
18858
*/
18859
template<typename PointerType,
18860
detail::enable_if_t<
18861
std::is_pointer<PointerType>::value,
18862
int> = 0>
18863
constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
18864
-> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
18865
{
18866
// delegate the call to get_ptr
18867
return get_ptr<PointerType>();
18868
}
18869
18870
public:
18871
/*!
18872
@brief get a (pointer) value (explicit)
18873
18874
Performs explicit type conversion between the JSON value and a compatible value if required.
18875
18876
- If the requested type is a pointer to the internally stored JSON value that pointer is returned.
18877
No copies are made.
18878
18879
- If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
18880
from the current @ref basic_json.
18881
18882
- Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
18883
method.
18884
18885
@tparam ValueTypeCV the provided value type
18886
@tparam ValueType the returned value type
18887
18888
@return copy of the JSON value, converted to @tparam ValueType if necessary
18889
18890
@throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
18891
18892
@since version 2.1.0
18893
*/
18894
template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
18895
#if defined(JSON_HAS_CPP_14)
18896
constexpr
18897
#endif
18898
auto get() const noexcept(
18899
noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
18900
-> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
18901
{
18902
// we cannot static_assert on ValueTypeCV being non-const, because
18903
// there is support for get<const basic_json_t>(), which is why we
18904
// still need the uncvref
18905
static_assert(!std::is_reference<ValueTypeCV>::value,
18906
"get() cannot be used with reference types, you might want to use get_ref()");
18907
return get_impl<ValueType>(detail::priority_tag<4> {});
18908
}
18909
18910
/*!
18911
@brief get a pointer value (explicit)
18912
18913
Explicit pointer access to the internally stored JSON value. No copies are
18914
made.
18915
18916
@warning The pointer becomes invalid if the underlying JSON object
18917
changes.
18918
18919
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
18920
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
18921
@ref number_unsigned_t, or @ref number_float_t.
18922
18923
@return pointer to the internally stored JSON value if the requested
18924
pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
18925
18926
@complexity Constant.
18927
18928
@liveexample{The example below shows how pointers to internal values of a
18929
JSON value can be requested. Note that no type conversions are made and a
18930
`nullptr` is returned if the value and the requested pointer type does not
18931
match.,get__PointerType}
18932
18933
@sa see @ref get_ptr() for explicit pointer-member access
18934
18935
@since version 1.0.0
18936
*/
18937
template<typename PointerType, typename std::enable_if<
18938
std::is_pointer<PointerType>::value, int>::type = 0>
18939
auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
18940
{
18941
// delegate the call to get_ptr
18942
return get_ptr<PointerType>();
18943
}
18944
18945
/// @brief get a value (explicit)
18946
/// @sa https://json.nlohmann.me/api/basic_json/get_to/
18947
template < typename ValueType,
18948
detail::enable_if_t <
18949
!detail::is_basic_json<ValueType>::value&&
18950
detail::has_from_json<basic_json_t, ValueType>::value,
18951
int > = 0 >
18952
ValueType & get_to(ValueType& v) const noexcept(noexcept(
18953
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
18954
{
18955
JSONSerializer<ValueType>::from_json(*this, v);
18956
return v;
18957
}
18958
18959
// specialization to allow calling get_to with a basic_json value
18960
// see https://github.com/nlohmann/json/issues/2175
18961
template<typename ValueType,
18962
detail::enable_if_t <
18963
detail::is_basic_json<ValueType>::value,
18964
int> = 0>
18965
ValueType & get_to(ValueType& v) const
18966
{
18967
v = *this;
18968
return v;
18969
}
18970
18971
template <
18972
typename T, std::size_t N,
18973
typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
18974
detail::enable_if_t <
18975
detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
18976
Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
18977
noexcept(noexcept(JSONSerializer<Array>::from_json(
18978
std::declval<const basic_json_t&>(), v)))
18979
{
18980
JSONSerializer<Array>::from_json(*this, v);
18981
return v;
18982
}
18983
18984
/// @brief get a reference value (implicit)
18985
/// @sa https://json.nlohmann.me/api/basic_json/get_ref/
18986
template<typename ReferenceType, typename std::enable_if<
18987
std::is_reference<ReferenceType>::value, int>::type = 0>
18988
ReferenceType get_ref()
18989
{
18990
// delegate call to get_ref_impl
18991
return get_ref_impl<ReferenceType>(*this);
18992
}
18993
18994
/// @brief get a reference value (implicit)
18995
/// @sa https://json.nlohmann.me/api/basic_json/get_ref/
18996
template < typename ReferenceType, typename std::enable_if <
18997
std::is_reference<ReferenceType>::value&&
18998
std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
18999
ReferenceType get_ref() const
19000
{
19001
// delegate call to get_ref_impl
19002
return get_ref_impl<ReferenceType>(*this);
19003
}
19004
19005
/*!
19006
@brief get a value (implicit)
19007
19008
Implicit type conversion between the JSON value and a compatible value.
19009
The call is realized by calling @ref get() const.
19010
19011
@tparam ValueType non-pointer type compatible to the JSON value, for
19012
instance `int` for JSON integer numbers, `bool` for JSON booleans, or
19013
`std::vector` types for JSON arrays. The character type of @ref string_t
19014
as well as an initializer list of this type is excluded to avoid
19015
ambiguities as these types implicitly convert to `std::string`.
19016
19017
@return copy of the JSON value, converted to type @a ValueType
19018
19019
@throw type_error.302 in case passed type @a ValueType is incompatible
19020
to the JSON value type (e.g., the JSON value is of type boolean, but a
19021
string is requested); see example below
19022
19023
@complexity Linear in the size of the JSON value.
19024
19025
@liveexample{The example below shows several conversions from JSON values
19026
to other types. There a few things to note: (1) Floating-point numbers can
19027
be converted to integers\, (2) A JSON array can be converted to a standard
19028
`std::vector<short>`\, (3) A JSON object can be converted to C++
19029
associative containers such as `std::unordered_map<std::string\,
19030
json>`.,operator__ValueType}
19031
19032
@since version 1.0.0
19033
*/
19034
template < typename ValueType, typename std::enable_if <
19035
detail::conjunction <
19036
detail::negation<std::is_pointer<ValueType>>,
19037
detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
19038
detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
19039
detail::negation<detail::is_basic_json<ValueType>>,
19040
detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
19041
19042
#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
19043
detail::negation<std::is_same<ValueType, std::string_view>>,
19044
#endif
19045
detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
19046
>::value, int >::type = 0 >
19047
JSON_EXPLICIT operator ValueType() const
19048
{
19049
// delegate the call to get<>() const
19050
return get<ValueType>();
19051
}
19052
19053
/// @brief get a binary value
19054
/// @sa https://json.nlohmann.me/api/basic_json/get_binary/
19055
binary_t& get_binary()
19056
{
19057
if (!is_binary())
19058
{
19059
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
19060
}
19061
19062
return *get_ptr<binary_t*>();
19063
}
19064
19065
/// @brief get a binary value
19066
/// @sa https://json.nlohmann.me/api/basic_json/get_binary/
19067
const binary_t& get_binary() const
19068
{
19069
if (!is_binary())
19070
{
19071
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
19072
}
19073
19074
return *get_ptr<const binary_t*>();
19075
}
19076
19077
/// @}
19078
19079
19080
////////////////////
19081
// element access //
19082
////////////////////
19083
19084
/// @name element access
19085
/// Access to the JSON value.
19086
/// @{
19087
19088
/// @brief access specified array element with bounds checking
19089
/// @sa https://json.nlohmann.me/api/basic_json/at/
19090
reference at(size_type idx)
19091
{
19092
// at only works for arrays
19093
if (JSON_HEDLEY_LIKELY(is_array()))
19094
{
19095
JSON_TRY
19096
{
19097
return set_parent(m_value.array->at(idx));
19098
}
19099
JSON_CATCH (std::out_of_range&)
19100
{
19101
// create better exception explanation
19102
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
19103
}
19104
}
19105
else
19106
{
19107
JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
19108
}
19109
}
19110
19111
/// @brief access specified array element with bounds checking
19112
/// @sa https://json.nlohmann.me/api/basic_json/at/
19113
const_reference at(size_type idx) const
19114
{
19115
// at only works for arrays
19116
if (JSON_HEDLEY_LIKELY(is_array()))
19117
{
19118
JSON_TRY
19119
{
19120
return m_value.array->at(idx);
19121
}
19122
JSON_CATCH (std::out_of_range&)
19123
{
19124
// create better exception explanation
19125
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
19126
}
19127
}
19128
else
19129
{
19130
JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
19131
}
19132
}
19133
19134
/// @brief access specified object element with bounds checking
19135
/// @sa https://json.nlohmann.me/api/basic_json/at/
19136
reference at(const typename object_t::key_type& key)
19137
{
19138
// at only works for objects
19139
if (JSON_HEDLEY_LIKELY(is_object()))
19140
{
19141
JSON_TRY
19142
{
19143
return set_parent(m_value.object->at(key));
19144
}
19145
JSON_CATCH (std::out_of_range&)
19146
{
19147
// create better exception explanation
19148
JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
19149
}
19150
}
19151
else
19152
{
19153
JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
19154
}
19155
}
19156
19157
/// @brief access specified object element with bounds checking
19158
/// @sa https://json.nlohmann.me/api/basic_json/at/
19159
const_reference at(const typename object_t::key_type& key) const
19160
{
19161
// at only works for objects
19162
if (JSON_HEDLEY_LIKELY(is_object()))
19163
{
19164
JSON_TRY
19165
{
19166
return m_value.object->at(key);
19167
}
19168
JSON_CATCH (std::out_of_range&)
19169
{
19170
// create better exception explanation
19171
JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
19172
}
19173
}
19174
else
19175
{
19176
JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
19177
}
19178
}
19179
19180
/// @brief access specified array element
19181
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19182
reference operator[](size_type idx)
19183
{
19184
// implicitly convert null value to an empty array
19185
if (is_null())
19186
{
19187
m_type = value_t::array;
19188
m_value.array = create<array_t>();
19189
assert_invariant();
19190
}
19191
19192
// operator[] only works for arrays
19193
if (JSON_HEDLEY_LIKELY(is_array()))
19194
{
19195
// fill up array with null values if given idx is outside range
19196
if (idx >= m_value.array->size())
19197
{
19198
#if JSON_DIAGNOSTICS
19199
// remember array size & capacity before resizing
19200
const auto old_size = m_value.array->size();
19201
const auto old_capacity = m_value.array->capacity();
19202
#endif
19203
m_value.array->resize(idx + 1);
19204
19205
#if JSON_DIAGNOSTICS
19206
if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
19207
{
19208
// capacity has changed: update all parents
19209
set_parents();
19210
}
19211
else
19212
{
19213
// set parent for values added above
19214
set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
19215
}
19216
#endif
19217
assert_invariant();
19218
}
19219
19220
return m_value.array->operator[](idx);
19221
}
19222
19223
JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
19224
}
19225
19226
/// @brief access specified array element
19227
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19228
const_reference operator[](size_type idx) const
19229
{
19230
// const operator[] only works for arrays
19231
if (JSON_HEDLEY_LIKELY(is_array()))
19232
{
19233
return m_value.array->operator[](idx);
19234
}
19235
19236
JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
19237
}
19238
19239
/// @brief access specified object element
19240
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19241
reference operator[](const typename object_t::key_type& key)
19242
{
19243
// implicitly convert null value to an empty object
19244
if (is_null())
19245
{
19246
m_type = value_t::object;
19247
m_value.object = create<object_t>();
19248
assert_invariant();
19249
}
19250
19251
// operator[] only works for objects
19252
if (JSON_HEDLEY_LIKELY(is_object()))
19253
{
19254
return set_parent(m_value.object->operator[](key));
19255
}
19256
19257
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
19258
}
19259
19260
/// @brief access specified object element
19261
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19262
const_reference operator[](const typename object_t::key_type& key) const
19263
{
19264
// const operator[] only works for objects
19265
if (JSON_HEDLEY_LIKELY(is_object()))
19266
{
19267
JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
19268
return m_value.object->find(key)->second;
19269
}
19270
19271
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
19272
}
19273
19274
/// @brief access specified object element
19275
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19276
template<typename T>
19277
JSON_HEDLEY_NON_NULL(2)
19278
reference operator[](T* key)
19279
{
19280
// implicitly convert null to object
19281
if (is_null())
19282
{
19283
m_type = value_t::object;
19284
m_value = value_t::object;
19285
assert_invariant();
19286
}
19287
19288
// at only works for objects
19289
if (JSON_HEDLEY_LIKELY(is_object()))
19290
{
19291
return set_parent(m_value.object->operator[](key));
19292
}
19293
19294
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
19295
}
19296
19297
/// @brief access specified object element
19298
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
19299
template<typename T>
19300
JSON_HEDLEY_NON_NULL(2)
19301
const_reference operator[](T* key) const
19302
{
19303
// at only works for objects
19304
if (JSON_HEDLEY_LIKELY(is_object()))
19305
{
19306
JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
19307
return m_value.object->find(key)->second;
19308
}
19309
19310
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
19311
}
19312
19313
/// @brief access specified object element with default value
19314
/// @sa https://json.nlohmann.me/api/basic_json/value/
19315
/// using std::is_convertible in a std::enable_if will fail when using explicit conversions
19316
template < class ValueType, typename std::enable_if <
19317
detail::is_getable<basic_json_t, ValueType>::value
19318
&& !std::is_same<value_t, ValueType>::value, int >::type = 0 >
19319
ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
19320
{
19321
// at only works for objects
19322
if (JSON_HEDLEY_LIKELY(is_object()))
19323
{
19324
// if key is found, return value and given default value otherwise
19325
const auto it = find(key);
19326
if (it != end())
19327
{
19328
return it->template get<ValueType>();
19329
}
19330
19331
return default_value;
19332
}
19333
19334
JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
19335
}
19336
19337
/// @brief access specified object element with default value
19338
/// @sa https://json.nlohmann.me/api/basic_json/value/
19339
/// overload for a default value of type const char*
19340
string_t value(const typename object_t::key_type& key, const char* default_value) const
19341
{
19342
return value(key, string_t(default_value));
19343
}
19344
19345
/// @brief access specified object element via JSON Pointer with default value
19346
/// @sa https://json.nlohmann.me/api/basic_json/value/
19347
template<class ValueType, typename std::enable_if<
19348
detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
19349
ValueType value(const json_pointer& ptr, const ValueType& default_value) const
19350
{
19351
// at only works for objects
19352
if (JSON_HEDLEY_LIKELY(is_object()))
19353
{
19354
// if pointer resolves a value, return it or use default value
19355
JSON_TRY
19356
{
19357
return ptr.get_checked(this).template get<ValueType>();
19358
}
19359
JSON_INTERNAL_CATCH (out_of_range&)
19360
{
19361
return default_value;
19362
}
19363
}
19364
19365
JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
19366
}
19367
19368
/// @brief access specified object element via JSON Pointer with default value
19369
/// @sa https://json.nlohmann.me/api/basic_json/value/
19370
/// overload for a default value of type const char*
19371
JSON_HEDLEY_NON_NULL(3)
19372
string_t value(const json_pointer& ptr, const char* default_value) const
19373
{
19374
return value(ptr, string_t(default_value));
19375
}
19376
19377
/// @brief access the first element
19378
/// @sa https://json.nlohmann.me/api/basic_json/front/
19379
reference front()
19380
{
19381
return *begin();
19382
}
19383
19384
/// @brief access the first element
19385
/// @sa https://json.nlohmann.me/api/basic_json/front/
19386
const_reference front() const
19387
{
19388
return *cbegin();
19389
}
19390
19391
/// @brief access the last element
19392
/// @sa https://json.nlohmann.me/api/basic_json/back/
19393
reference back()
19394
{
19395
auto tmp = end();
19396
--tmp;
19397
return *tmp;
19398
}
19399
19400
/// @brief access the last element
19401
/// @sa https://json.nlohmann.me/api/basic_json/back/
19402
const_reference back() const
19403
{
19404
auto tmp = cend();
19405
--tmp;
19406
return *tmp;
19407
}
19408
19409
/// @brief remove element given an iterator
19410
/// @sa https://json.nlohmann.me/api/basic_json/erase/
19411
template < class IteratorType, typename std::enable_if <
19412
std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
19413
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
19414
= 0 >
19415
IteratorType erase(IteratorType pos)
19416
{
19417
// make sure iterator fits the current value
19418
if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
19419
{
19420
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
19421
}
19422
19423
IteratorType result = end();
19424
19425
switch (m_type)
19426
{
19427
case value_t::boolean:
19428
case value_t::number_float:
19429
case value_t::number_integer:
19430
case value_t::number_unsigned:
19431
case value_t::string:
19432
case value_t::binary:
19433
{
19434
if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
19435
{
19436
JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this));
19437
}
19438
19439
if (is_string())
19440
{
19441
AllocatorType<string_t> alloc;
19442
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
19443
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
19444
m_value.string = nullptr;
19445
}
19446
else if (is_binary())
19447
{
19448
AllocatorType<binary_t> alloc;
19449
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
19450
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
19451
m_value.binary = nullptr;
19452
}
19453
19454
m_type = value_t::null;
19455
assert_invariant();
19456
break;
19457
}
19458
19459
case value_t::object:
19460
{
19461
result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
19462
break;
19463
}
19464
19465
case value_t::array:
19466
{
19467
result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
19468
break;
19469
}
19470
19471
case value_t::null:
19472
case value_t::discarded:
19473
default:
19474
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
19475
}
19476
19477
return result;
19478
}
19479
19480
/// @brief remove elements given an iterator range
19481
/// @sa https://json.nlohmann.me/api/basic_json/erase/
19482
template < class IteratorType, typename std::enable_if <
19483
std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
19484
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
19485
= 0 >
19486
IteratorType erase(IteratorType first, IteratorType last)
19487
{
19488
// make sure iterator fits the current value
19489
if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
19490
{
19491
JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this));
19492
}
19493
19494
IteratorType result = end();
19495
19496
switch (m_type)
19497
{
19498
case value_t::boolean:
19499
case value_t::number_float:
19500
case value_t::number_integer:
19501
case value_t::number_unsigned:
19502
case value_t::string:
19503
case value_t::binary:
19504
{
19505
if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
19506
|| !last.m_it.primitive_iterator.is_end()))
19507
{
19508
JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this));
19509
}
19510
19511
if (is_string())
19512
{
19513
AllocatorType<string_t> alloc;
19514
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
19515
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
19516
m_value.string = nullptr;
19517
}
19518
else if (is_binary())
19519
{
19520
AllocatorType<binary_t> alloc;
19521
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
19522
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
19523
m_value.binary = nullptr;
19524
}
19525
19526
m_type = value_t::null;
19527
assert_invariant();
19528
break;
19529
}
19530
19531
case value_t::object:
19532
{
19533
result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
19534
last.m_it.object_iterator);
19535
break;
19536
}
19537
19538
case value_t::array:
19539
{
19540
result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
19541
last.m_it.array_iterator);
19542
break;
19543
}
19544
19545
case value_t::null:
19546
case value_t::discarded:
19547
default:
19548
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
19549
}
19550
19551
return result;
19552
}
19553
19554
/// @brief remove element from a JSON object given a key
19555
/// @sa https://json.nlohmann.me/api/basic_json/erase/
19556
size_type erase(const typename object_t::key_type& key)
19557
{
19558
// this erase only works for objects
19559
if (JSON_HEDLEY_LIKELY(is_object()))
19560
{
19561
return m_value.object->erase(key);
19562
}
19563
19564
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
19565
}
19566
19567
/// @brief remove element from a JSON array given an index
19568
/// @sa https://json.nlohmann.me/api/basic_json/erase/
19569
void erase(const size_type idx)
19570
{
19571
// this erase only works for arrays
19572
if (JSON_HEDLEY_LIKELY(is_array()))
19573
{
19574
if (JSON_HEDLEY_UNLIKELY(idx >= size()))
19575
{
19576
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
19577
}
19578
19579
m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
19580
}
19581
else
19582
{
19583
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
19584
}
19585
}
19586
19587
/// @}
19588
19589
19590
////////////
19591
// lookup //
19592
////////////
19593
19594
/// @name lookup
19595
/// @{
19596
19597
/// @brief find an element in a JSON object
19598
/// @sa https://json.nlohmann.me/api/basic_json/find/
19599
template<typename KeyT>
19600
iterator find(KeyT&& key)
19601
{
19602
auto result = end();
19603
19604
if (is_object())
19605
{
19606
result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
19607
}
19608
19609
return result;
19610
}
19611
19612
/// @brief find an element in a JSON object
19613
/// @sa https://json.nlohmann.me/api/basic_json/find/
19614
template<typename KeyT>
19615
const_iterator find(KeyT&& key) const
19616
{
19617
auto result = cend();
19618
19619
if (is_object())
19620
{
19621
result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
19622
}
19623
19624
return result;
19625
}
19626
19627
/// @brief returns the number of occurrences of a key in a JSON object
19628
/// @sa https://json.nlohmann.me/api/basic_json/count/
19629
template<typename KeyT>
19630
size_type count(KeyT&& key) const
19631
{
19632
// return 0 for all nonobject types
19633
return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
19634
}
19635
19636
/// @brief check the existence of an element in a JSON object
19637
/// @sa https://json.nlohmann.me/api/basic_json/contains/
19638
template < typename KeyT, typename std::enable_if <
19639
!std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int >::type = 0 >
19640
bool contains(KeyT && key) const
19641
{
19642
return is_object() && m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
19643
}
19644
19645
/// @brief check the existence of an element in a JSON object given a JSON pointer
19646
/// @sa https://json.nlohmann.me/api/basic_json/contains/
19647
bool contains(const json_pointer& ptr) const
19648
{
19649
return ptr.contains(this);
19650
}
19651
19652
/// @}
19653
19654
19655
///////////////
19656
// iterators //
19657
///////////////
19658
19659
/// @name iterators
19660
/// @{
19661
19662
/// @brief returns an iterator to the first element
19663
/// @sa https://json.nlohmann.me/api/basic_json/begin/
19664
iterator begin() noexcept
19665
{
19666
iterator result(this);
19667
result.set_begin();
19668
return result;
19669
}
19670
19671
/// @brief returns an iterator to the first element
19672
/// @sa https://json.nlohmann.me/api/basic_json/begin/
19673
const_iterator begin() const noexcept
19674
{
19675
return cbegin();
19676
}
19677
19678
/// @brief returns a const iterator to the first element
19679
/// @sa https://json.nlohmann.me/api/basic_json/cbegin/
19680
const_iterator cbegin() const noexcept
19681
{
19682
const_iterator result(this);
19683
result.set_begin();
19684
return result;
19685
}
19686
19687
/// @brief returns an iterator to one past the last element
19688
/// @sa https://json.nlohmann.me/api/basic_json/end/
19689
iterator end() noexcept
19690
{
19691
iterator result(this);
19692
result.set_end();
19693
return result;
19694
}
19695
19696
/// @brief returns an iterator to one past the last element
19697
/// @sa https://json.nlohmann.me/api/basic_json/end/
19698
const_iterator end() const noexcept
19699
{
19700
return cend();
19701
}
19702
19703
/// @brief returns an iterator to one past the last element
19704
/// @sa https://json.nlohmann.me/api/basic_json/cend/
19705
const_iterator cend() const noexcept
19706
{
19707
const_iterator result(this);
19708
result.set_end();
19709
return result;
19710
}
19711
19712
/// @brief returns an iterator to the reverse-beginning
19713
/// @sa https://json.nlohmann.me/api/basic_json/rbegin/
19714
reverse_iterator rbegin() noexcept
19715
{
19716
return reverse_iterator(end());
19717
}
19718
19719
/// @brief returns an iterator to the reverse-beginning
19720
/// @sa https://json.nlohmann.me/api/basic_json/rbegin/
19721
const_reverse_iterator rbegin() const noexcept
19722
{
19723
return crbegin();
19724
}
19725
19726
/// @brief returns an iterator to the reverse-end
19727
/// @sa https://json.nlohmann.me/api/basic_json/rend/
19728
reverse_iterator rend() noexcept
19729
{
19730
return reverse_iterator(begin());
19731
}
19732
19733
/// @brief returns an iterator to the reverse-end
19734
/// @sa https://json.nlohmann.me/api/basic_json/rend/
19735
const_reverse_iterator rend() const noexcept
19736
{
19737
return crend();
19738
}
19739
19740
/// @brief returns a const reverse iterator to the last element
19741
/// @sa https://json.nlohmann.me/api/basic_json/crbegin/
19742
const_reverse_iterator crbegin() const noexcept
19743
{
19744
return const_reverse_iterator(cend());
19745
}
19746
19747
/// @brief returns a const reverse iterator to one before the first
19748
/// @sa https://json.nlohmann.me/api/basic_json/crend/
19749
const_reverse_iterator crend() const noexcept
19750
{
19751
return const_reverse_iterator(cbegin());
19752
}
19753
19754
public:
19755
/// @brief wrapper to access iterator member functions in range-based for
19756
/// @sa https://json.nlohmann.me/api/basic_json/items/
19757
/// @deprecated This function is deprecated since 3.1.0 and will be removed in
19758
/// version 4.0.0 of the library. Please use @ref items() instead;
19759
/// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
19760
JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
19761
static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
19762
{
19763
return ref.items();
19764
}
19765
19766
/// @brief wrapper to access iterator member functions in range-based for
19767
/// @sa https://json.nlohmann.me/api/basic_json/items/
19768
/// @deprecated This function is deprecated since 3.1.0 and will be removed in
19769
/// version 4.0.0 of the library. Please use @ref items() instead;
19770
/// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
19771
JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
19772
static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
19773
{
19774
return ref.items();
19775
}
19776
19777
/// @brief helper to access iterator member functions in range-based for
19778
/// @sa https://json.nlohmann.me/api/basic_json/items/
19779
iteration_proxy<iterator> items() noexcept
19780
{
19781
return iteration_proxy<iterator>(*this);
19782
}
19783
19784
/// @brief helper to access iterator member functions in range-based for
19785
/// @sa https://json.nlohmann.me/api/basic_json/items/
19786
iteration_proxy<const_iterator> items() const noexcept
19787
{
19788
return iteration_proxy<const_iterator>(*this);
19789
}
19790
19791
/// @}
19792
19793
19794
//////////////
19795
// capacity //
19796
//////////////
19797
19798
/// @name capacity
19799
/// @{
19800
19801
/// @brief checks whether the container is empty.
19802
/// @sa https://json.nlohmann.me/api/basic_json/empty/
19803
bool empty() const noexcept
19804
{
19805
switch (m_type)
19806
{
19807
case value_t::null:
19808
{
19809
// null values are empty
19810
return true;
19811
}
19812
19813
case value_t::array:
19814
{
19815
// delegate call to array_t::empty()
19816
return m_value.array->empty();
19817
}
19818
19819
case value_t::object:
19820
{
19821
// delegate call to object_t::empty()
19822
return m_value.object->empty();
19823
}
19824
19825
case value_t::string:
19826
case value_t::boolean:
19827
case value_t::number_integer:
19828
case value_t::number_unsigned:
19829
case value_t::number_float:
19830
case value_t::binary:
19831
case value_t::discarded:
19832
default:
19833
{
19834
// all other types are nonempty
19835
return false;
19836
}
19837
}
19838
}
19839
19840
/// @brief returns the number of elements
19841
/// @sa https://json.nlohmann.me/api/basic_json/size/
19842
size_type size() const noexcept
19843
{
19844
switch (m_type)
19845
{
19846
case value_t::null:
19847
{
19848
// null values are empty
19849
return 0;
19850
}
19851
19852
case value_t::array:
19853
{
19854
// delegate call to array_t::size()
19855
return m_value.array->size();
19856
}
19857
19858
case value_t::object:
19859
{
19860
// delegate call to object_t::size()
19861
return m_value.object->size();
19862
}
19863
19864
case value_t::string:
19865
case value_t::boolean:
19866
case value_t::number_integer:
19867
case value_t::number_unsigned:
19868
case value_t::number_float:
19869
case value_t::binary:
19870
case value_t::discarded:
19871
default:
19872
{
19873
// all other types have size 1
19874
return 1;
19875
}
19876
}
19877
}
19878
19879
/// @brief returns the maximum possible number of elements
19880
/// @sa https://json.nlohmann.me/api/basic_json/max_size/
19881
size_type max_size() const noexcept
19882
{
19883
switch (m_type)
19884
{
19885
case value_t::array:
19886
{
19887
// delegate call to array_t::max_size()
19888
return m_value.array->max_size();
19889
}
19890
19891
case value_t::object:
19892
{
19893
// delegate call to object_t::max_size()
19894
return m_value.object->max_size();
19895
}
19896
19897
case value_t::null:
19898
case value_t::string:
19899
case value_t::boolean:
19900
case value_t::number_integer:
19901
case value_t::number_unsigned:
19902
case value_t::number_float:
19903
case value_t::binary:
19904
case value_t::discarded:
19905
default:
19906
{
19907
// all other types have max_size() == size()
19908
return size();
19909
}
19910
}
19911
}
19912
19913
/// @}
19914
19915
19916
///////////////
19917
// modifiers //
19918
///////////////
19919
19920
/// @name modifiers
19921
/// @{
19922
19923
/// @brief clears the contents
19924
/// @sa https://json.nlohmann.me/api/basic_json/clear/
19925
void clear() noexcept
19926
{
19927
switch (m_type)
19928
{
19929
case value_t::number_integer:
19930
{
19931
m_value.number_integer = 0;
19932
break;
19933
}
19934
19935
case value_t::number_unsigned:
19936
{
19937
m_value.number_unsigned = 0;
19938
break;
19939
}
19940
19941
case value_t::number_float:
19942
{
19943
m_value.number_float = 0.0;
19944
break;
19945
}
19946
19947
case value_t::boolean:
19948
{
19949
m_value.boolean = false;
19950
break;
19951
}
19952
19953
case value_t::string:
19954
{
19955
m_value.string->clear();
19956
break;
19957
}
19958
19959
case value_t::binary:
19960
{
19961
m_value.binary->clear();
19962
break;
19963
}
19964
19965
case value_t::array:
19966
{
19967
m_value.array->clear();
19968
break;
19969
}
19970
19971
case value_t::object:
19972
{
19973
m_value.object->clear();
19974
break;
19975
}
19976
19977
case value_t::null:
19978
case value_t::discarded:
19979
default:
19980
break;
19981
}
19982
}
19983
19984
/// @brief add an object to an array
19985
/// @sa https://json.nlohmann.me/api/basic_json/push_back/
19986
void push_back(basic_json&& val)
19987
{
19988
// push_back only works for null objects or arrays
19989
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
19990
{
19991
JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
19992
}
19993
19994
// transform null object into an array
19995
if (is_null())
19996
{
19997
m_type = value_t::array;
19998
m_value = value_t::array;
19999
assert_invariant();
20000
}
20001
20002
// add element to array (move semantics)
20003
const auto old_capacity = m_value.array->capacity();
20004
m_value.array->push_back(std::move(val));
20005
set_parent(m_value.array->back(), old_capacity);
20006
// if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
20007
}
20008
20009
/// @brief add an object to an array
20010
/// @sa https://json.nlohmann.me/api/basic_json/operator+=/
20011
reference operator+=(basic_json&& val)
20012
{
20013
push_back(std::move(val));
20014
return *this;
20015
}
20016
20017
/// @brief add an object to an array
20018
/// @sa https://json.nlohmann.me/api/basic_json/push_back/
20019
void push_back(const basic_json& val)
20020
{
20021
// push_back only works for null objects or arrays
20022
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
20023
{
20024
JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
20025
}
20026
20027
// transform null object into an array
20028
if (is_null())
20029
{
20030
m_type = value_t::array;
20031
m_value = value_t::array;
20032
assert_invariant();
20033
}
20034
20035
// add element to array
20036
const auto old_capacity = m_value.array->capacity();
20037
m_value.array->push_back(val);
20038
set_parent(m_value.array->back(), old_capacity);
20039
}
20040
20041
/// @brief add an object to an array
20042
/// @sa https://json.nlohmann.me/api/basic_json/operator+=/
20043
reference operator+=(const basic_json& val)
20044
{
20045
push_back(val);
20046
return *this;
20047
}
20048
20049
/// @brief add an object to an object
20050
/// @sa https://json.nlohmann.me/api/basic_json/push_back/
20051
void push_back(const typename object_t::value_type& val)
20052
{
20053
// push_back only works for null objects or objects
20054
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
20055
{
20056
JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
20057
}
20058
20059
// transform null object into an object
20060
if (is_null())
20061
{
20062
m_type = value_t::object;
20063
m_value = value_t::object;
20064
assert_invariant();
20065
}
20066
20067
// add element to object
20068
auto res = m_value.object->insert(val);
20069
set_parent(res.first->second);
20070
}
20071
20072
/// @brief add an object to an object
20073
/// @sa https://json.nlohmann.me/api/basic_json/operator+=/
20074
reference operator+=(const typename object_t::value_type& val)
20075
{
20076
push_back(val);
20077
return *this;
20078
}
20079
20080
/// @brief add an object to an object
20081
/// @sa https://json.nlohmann.me/api/basic_json/push_back/
20082
void push_back(initializer_list_t init)
20083
{
20084
if (is_object() && init.size() == 2 && (*init.begin())->is_string())
20085
{
20086
basic_json&& key = init.begin()->moved_or_copied();
20087
push_back(typename object_t::value_type(
20088
std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
20089
}
20090
else
20091
{
20092
push_back(basic_json(init));
20093
}
20094
}
20095
20096
/// @brief add an object to an object
20097
/// @sa https://json.nlohmann.me/api/basic_json/operator+=/
20098
reference operator+=(initializer_list_t init)
20099
{
20100
push_back(init);
20101
return *this;
20102
}
20103
20104
/// @brief add an object to an array
20105
/// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
20106
template<class... Args>
20107
reference emplace_back(Args&& ... args)
20108
{
20109
// emplace_back only works for null objects or arrays
20110
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
20111
{
20112
JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this));
20113
}
20114
20115
// transform null object into an array
20116
if (is_null())
20117
{
20118
m_type = value_t::array;
20119
m_value = value_t::array;
20120
assert_invariant();
20121
}
20122
20123
// add element to array (perfect forwarding)
20124
const auto old_capacity = m_value.array->capacity();
20125
m_value.array->emplace_back(std::forward<Args>(args)...);
20126
return set_parent(m_value.array->back(), old_capacity);
20127
}
20128
20129
/// @brief add an object to an object if key does not exist
20130
/// @sa https://json.nlohmann.me/api/basic_json/emplace/
20131
template<class... Args>
20132
std::pair<iterator, bool> emplace(Args&& ... args)
20133
{
20134
// emplace only works for null objects or arrays
20135
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
20136
{
20137
JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this));
20138
}
20139
20140
// transform null object into an object
20141
if (is_null())
20142
{
20143
m_type = value_t::object;
20144
m_value = value_t::object;
20145
assert_invariant();
20146
}
20147
20148
// add element to array (perfect forwarding)
20149
auto res = m_value.object->emplace(std::forward<Args>(args)...);
20150
set_parent(res.first->second);
20151
20152
// create result iterator and set iterator to the result of emplace
20153
auto it = begin();
20154
it.m_it.object_iterator = res.first;
20155
20156
// return pair of iterator and boolean
20157
return {it, res.second};
20158
}
20159
20160
/// Helper for insertion of an iterator
20161
/// @note: This uses std::distance to support GCC 4.8,
20162
/// see https://github.com/nlohmann/json/pull/1257
20163
template<typename... Args>
20164
iterator insert_iterator(const_iterator pos, Args&& ... args)
20165
{
20166
iterator result(this);
20167
JSON_ASSERT(m_value.array != nullptr);
20168
20169
auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
20170
m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
20171
result.m_it.array_iterator = m_value.array->begin() + insert_pos;
20172
20173
// This could have been written as:
20174
// result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
20175
// but the return value of insert is missing in GCC 4.8, so it is written this way instead.
20176
20177
set_parents();
20178
return result;
20179
}
20180
20181
/// @brief inserts element into array
20182
/// @sa https://json.nlohmann.me/api/basic_json/insert/
20183
iterator insert(const_iterator pos, const basic_json& val)
20184
{
20185
// insert only works for arrays
20186
if (JSON_HEDLEY_LIKELY(is_array()))
20187
{
20188
// check if iterator pos fits to this JSON value
20189
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
20190
{
20191
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
20192
}
20193
20194
// insert to array and return iterator
20195
return insert_iterator(pos, val);
20196
}
20197
20198
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20199
}
20200
20201
/// @brief inserts element into array
20202
/// @sa https://json.nlohmann.me/api/basic_json/insert/
20203
iterator insert(const_iterator pos, basic_json&& val)
20204
{
20205
return insert(pos, val);
20206
}
20207
20208
/// @brief inserts copies of element into array
20209
/// @sa https://json.nlohmann.me/api/basic_json/insert/
20210
iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
20211
{
20212
// insert only works for arrays
20213
if (JSON_HEDLEY_LIKELY(is_array()))
20214
{
20215
// check if iterator pos fits to this JSON value
20216
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
20217
{
20218
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
20219
}
20220
20221
// insert to array and return iterator
20222
return insert_iterator(pos, cnt, val);
20223
}
20224
20225
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20226
}
20227
20228
/// @brief inserts range of elements into array
20229
/// @sa https://json.nlohmann.me/api/basic_json/insert/
20230
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
20231
{
20232
// insert only works for arrays
20233
if (JSON_HEDLEY_UNLIKELY(!is_array()))
20234
{
20235
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20236
}
20237
20238
// check if iterator pos fits to this JSON value
20239
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
20240
{
20241
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
20242
}
20243
20244
// check if range iterators belong to the same JSON object
20245
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20246
{
20247
JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
20248
}
20249
20250
if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
20251
{
20252
JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this));
20253
}
20254
20255
// insert to array and return iterator
20256
return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
20257
}
20258
20259
/// @brief inserts elements from initializer list into array
20260
/// @sa https://json.nlohmann.me/api/basic_json/insert/
20261
iterator insert(const_iterator pos, initializer_list_t ilist)
20262
{
20263
// insert only works for arrays
20264
if (JSON_HEDLEY_UNLIKELY(!is_array()))
20265
{
20266
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20267
}
20268
20269
// check if iterator pos fits to this JSON value
20270
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
20271
{
20272
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
20273
}
20274
20275
// insert to array and return iterator
20276
return insert_iterator(pos, ilist.begin(), ilist.end());
20277
}
20278
20279
/// @brief inserts range of elements into object
20280
/// @sa https://json.nlohmann.me/api/basic_json/insert/
20281
void insert(const_iterator first, const_iterator last)
20282
{
20283
// insert only works for objects
20284
if (JSON_HEDLEY_UNLIKELY(!is_object()))
20285
{
20286
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
20287
}
20288
20289
// check if range iterators belong to the same JSON object
20290
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20291
{
20292
JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
20293
}
20294
20295
// passed iterators must belong to objects
20296
if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
20297
{
20298
JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this));
20299
}
20300
20301
m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
20302
}
20303
20304
/// @brief updates a JSON object from another object, overwriting existing keys
20305
/// @sa https://json.nlohmann.me/api/basic_json/update/
20306
void update(const_reference j, bool merge_objects = false)
20307
{
20308
update(j.begin(), j.end(), merge_objects);
20309
}
20310
20311
/// @brief updates a JSON object from another object, overwriting existing keys
20312
/// @sa https://json.nlohmann.me/api/basic_json/update/
20313
void update(const_iterator first, const_iterator last, bool merge_objects = false)
20314
{
20315
// implicitly convert null value to an empty object
20316
if (is_null())
20317
{
20318
m_type = value_t::object;
20319
m_value.object = create<object_t>();
20320
assert_invariant();
20321
}
20322
20323
if (JSON_HEDLEY_UNLIKELY(!is_object()))
20324
{
20325
JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this));
20326
}
20327
20328
// check if range iterators belong to the same JSON object
20329
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20330
{
20331
JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
20332
}
20333
20334
// passed iterators must belong to objects
20335
if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
20336
{
20337
JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(first.m_object->type_name()), *first.m_object));
20338
}
20339
20340
for (auto it = first; it != last; ++it)
20341
{
20342
if (merge_objects && it.value().is_object())
20343
{
20344
auto it2 = m_value.object->find(it.key());
20345
if (it2 != m_value.object->end())
20346
{
20347
it2->second.update(it.value(), true);
20348
continue;
20349
}
20350
}
20351
m_value.object->operator[](it.key()) = it.value();
20352
#if JSON_DIAGNOSTICS
20353
m_value.object->operator[](it.key()).m_parent = this;
20354
#endif
20355
}
20356
}
20357
20358
/// @brief exchanges the values
20359
/// @sa https://json.nlohmann.me/api/basic_json/swap/
20360
void swap(reference other) noexcept (
20361
std::is_nothrow_move_constructible<value_t>::value&&
20362
std::is_nothrow_move_assignable<value_t>::value&&
20363
std::is_nothrow_move_constructible<json_value>::value&&
20364
std::is_nothrow_move_assignable<json_value>::value
20365
)
20366
{
20367
std::swap(m_type, other.m_type);
20368
std::swap(m_value, other.m_value);
20369
20370
set_parents();
20371
other.set_parents();
20372
assert_invariant();
20373
}
20374
20375
/// @brief exchanges the values
20376
/// @sa https://json.nlohmann.me/api/basic_json/swap/
20377
friend void swap(reference left, reference right) noexcept (
20378
std::is_nothrow_move_constructible<value_t>::value&&
20379
std::is_nothrow_move_assignable<value_t>::value&&
20380
std::is_nothrow_move_constructible<json_value>::value&&
20381
std::is_nothrow_move_assignable<json_value>::value
20382
)
20383
{
20384
left.swap(right);
20385
}
20386
20387
/// @brief exchanges the values
20388
/// @sa https://json.nlohmann.me/api/basic_json/swap/
20389
void swap(array_t& other) // NOLINT(bugprone-exception-escape)
20390
{
20391
// swap only works for arrays
20392
if (JSON_HEDLEY_LIKELY(is_array()))
20393
{
20394
std::swap(*(m_value.array), other);
20395
}
20396
else
20397
{
20398
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20399
}
20400
}
20401
20402
/// @brief exchanges the values
20403
/// @sa https://json.nlohmann.me/api/basic_json/swap/
20404
void swap(object_t& other) // NOLINT(bugprone-exception-escape)
20405
{
20406
// swap only works for objects
20407
if (JSON_HEDLEY_LIKELY(is_object()))
20408
{
20409
std::swap(*(m_value.object), other);
20410
}
20411
else
20412
{
20413
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20414
}
20415
}
20416
20417
/// @brief exchanges the values
20418
/// @sa https://json.nlohmann.me/api/basic_json/swap/
20419
void swap(string_t& other) // NOLINT(bugprone-exception-escape)
20420
{
20421
// swap only works for strings
20422
if (JSON_HEDLEY_LIKELY(is_string()))
20423
{
20424
std::swap(*(m_value.string), other);
20425
}
20426
else
20427
{
20428
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20429
}
20430
}
20431
20432
/// @brief exchanges the values
20433
/// @sa https://json.nlohmann.me/api/basic_json/swap/
20434
void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
20435
{
20436
// swap only works for strings
20437
if (JSON_HEDLEY_LIKELY(is_binary()))
20438
{
20439
std::swap(*(m_value.binary), other);
20440
}
20441
else
20442
{
20443
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20444
}
20445
}
20446
20447
/// @brief exchanges the values
20448
/// @sa https://json.nlohmann.me/api/basic_json/swap/
20449
void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
20450
{
20451
// swap only works for strings
20452
if (JSON_HEDLEY_LIKELY(is_binary()))
20453
{
20454
std::swap(*(m_value.binary), other);
20455
}
20456
else
20457
{
20458
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
20459
}
20460
}
20461
20462
/// @}
20463
20464
public:
20465
//////////////////////////////////////////
20466
// lexicographical comparison operators //
20467
//////////////////////////////////////////
20468
20469
/// @name lexicographical comparison operators
20470
/// @{
20471
20472
/// @brief comparison: equal
20473
/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
20474
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
20475
{
20476
#ifdef __GNUC__
20477
#pragma GCC diagnostic push
20478
#pragma GCC diagnostic ignored "-Wfloat-equal"
20479
#endif
20480
const auto lhs_type = lhs.type();
20481
const auto rhs_type = rhs.type();
20482
20483
if (lhs_type == rhs_type)
20484
{
20485
switch (lhs_type)
20486
{
20487
case value_t::array:
20488
return *lhs.m_value.array == *rhs.m_value.array;
20489
20490
case value_t::object:
20491
return *lhs.m_value.object == *rhs.m_value.object;
20492
20493
case value_t::null:
20494
return true;
20495
20496
case value_t::string:
20497
return *lhs.m_value.string == *rhs.m_value.string;
20498
20499
case value_t::boolean:
20500
return lhs.m_value.boolean == rhs.m_value.boolean;
20501
20502
case value_t::number_integer:
20503
return lhs.m_value.number_integer == rhs.m_value.number_integer;
20504
20505
case value_t::number_unsigned:
20506
return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
20507
20508
case value_t::number_float:
20509
return lhs.m_value.number_float == rhs.m_value.number_float;
20510
20511
case value_t::binary:
20512
return *lhs.m_value.binary == *rhs.m_value.binary;
20513
20514
case value_t::discarded:
20515
default:
20516
return false;
20517
}
20518
}
20519
else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
20520
{
20521
return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
20522
}
20523
else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
20524
{
20525
return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
20526
}
20527
else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
20528
{
20529
return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
20530
}
20531
else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
20532
{
20533
return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
20534
}
20535
else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
20536
{
20537
return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
20538
}
20539
else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
20540
{
20541
return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
20542
}
20543
20544
return false;
20545
#ifdef __GNUC__
20546
#pragma GCC diagnostic pop
20547
#endif
20548
}
20549
20550
/// @brief comparison: equal
20551
/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
20552
template<typename ScalarType, typename std::enable_if<
20553
std::is_scalar<ScalarType>::value, int>::type = 0>
20554
friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
20555
{
20556
return lhs == basic_json(rhs);
20557
}
20558
20559
/// @brief comparison: equal
20560
/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
20561
template<typename ScalarType, typename std::enable_if<
20562
std::is_scalar<ScalarType>::value, int>::type = 0>
20563
friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
20564
{
20565
return basic_json(lhs) == rhs;
20566
}
20567
20568
/// @brief comparison: not equal
20569
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
20570
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
20571
{
20572
return !(lhs == rhs);
20573
}
20574
20575
/// @brief comparison: not equal
20576
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
20577
template<typename ScalarType, typename std::enable_if<
20578
std::is_scalar<ScalarType>::value, int>::type = 0>
20579
friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
20580
{
20581
return lhs != basic_json(rhs);
20582
}
20583
20584
/// @brief comparison: not equal
20585
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
20586
template<typename ScalarType, typename std::enable_if<
20587
std::is_scalar<ScalarType>::value, int>::type = 0>
20588
friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
20589
{
20590
return basic_json(lhs) != rhs;
20591
}
20592
20593
/// @brief comparison: less than
20594
/// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
20595
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
20596
{
20597
const auto lhs_type = lhs.type();
20598
const auto rhs_type = rhs.type();
20599
20600
if (lhs_type == rhs_type)
20601
{
20602
switch (lhs_type)
20603
{
20604
case value_t::array:
20605
// note parentheses are necessary, see
20606
// https://github.com/nlohmann/json/issues/1530
20607
return (*lhs.m_value.array) < (*rhs.m_value.array);
20608
20609
case value_t::object:
20610
return (*lhs.m_value.object) < (*rhs.m_value.object);
20611
20612
case value_t::null:
20613
return false;
20614
20615
case value_t::string:
20616
return (*lhs.m_value.string) < (*rhs.m_value.string);
20617
20618
case value_t::boolean:
20619
return (lhs.m_value.boolean) < (rhs.m_value.boolean);
20620
20621
case value_t::number_integer:
20622
return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
20623
20624
case value_t::number_unsigned:
20625
return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned);
20626
20627
case value_t::number_float:
20628
return (lhs.m_value.number_float) < (rhs.m_value.number_float);
20629
20630
case value_t::binary:
20631
return (*lhs.m_value.binary) < (*rhs.m_value.binary);
20632
20633
case value_t::discarded:
20634
default:
20635
return false;
20636
}
20637
}
20638
else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
20639
{
20640
return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
20641
}
20642
else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
20643
{
20644
return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
20645
}
20646
else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
20647
{
20648
return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
20649
}
20650
else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
20651
{
20652
return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
20653
}
20654
else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
20655
{
20656
return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
20657
}
20658
else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
20659
{
20660
return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
20661
}
20662
20663
// We only reach this line if we cannot compare values. In that case,
20664
// we compare types. Note we have to call the operator explicitly,
20665
// because MSVC has problems otherwise.
20666
return operator<(lhs_type, rhs_type);
20667
}
20668
20669
/// @brief comparison: less than
20670
/// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
20671
template<typename ScalarType, typename std::enable_if<
20672
std::is_scalar<ScalarType>::value, int>::type = 0>
20673
friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
20674
{
20675
return lhs < basic_json(rhs);
20676
}
20677
20678
/// @brief comparison: less than
20679
/// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
20680
template<typename ScalarType, typename std::enable_if<
20681
std::is_scalar<ScalarType>::value, int>::type = 0>
20682
friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
20683
{
20684
return basic_json(lhs) < rhs;
20685
}
20686
20687
/// @brief comparison: less than or equal
20688
/// @sa https://json.nlohmann.me/api/basic_json/operator_le/
20689
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
20690
{
20691
return !(rhs < lhs);
20692
}
20693
20694
/// @brief comparison: less than or equal
20695
/// @sa https://json.nlohmann.me/api/basic_json/operator_le/
20696
template<typename ScalarType, typename std::enable_if<
20697
std::is_scalar<ScalarType>::value, int>::type = 0>
20698
friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
20699
{
20700
return lhs <= basic_json(rhs);
20701
}
20702
20703
/// @brief comparison: less than or equal
20704
/// @sa https://json.nlohmann.me/api/basic_json/operator_le/
20705
template<typename ScalarType, typename std::enable_if<
20706
std::is_scalar<ScalarType>::value, int>::type = 0>
20707
friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
20708
{
20709
return basic_json(lhs) <= rhs;
20710
}
20711
20712
/// @brief comparison: greater than
20713
/// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
20714
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
20715
{
20716
return !(lhs <= rhs);
20717
}
20718
20719
/// @brief comparison: greater than
20720
/// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
20721
template<typename ScalarType, typename std::enable_if<
20722
std::is_scalar<ScalarType>::value, int>::type = 0>
20723
friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
20724
{
20725
return lhs > basic_json(rhs);
20726
}
20727
20728
/// @brief comparison: greater than
20729
/// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
20730
template<typename ScalarType, typename std::enable_if<
20731
std::is_scalar<ScalarType>::value, int>::type = 0>
20732
friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
20733
{
20734
return basic_json(lhs) > rhs;
20735
}
20736
20737
/// @brief comparison: greater than or equal
20738
/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
20739
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
20740
{
20741
return !(lhs < rhs);
20742
}
20743
20744
/// @brief comparison: greater than or equal
20745
/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
20746
template<typename ScalarType, typename std::enable_if<
20747
std::is_scalar<ScalarType>::value, int>::type = 0>
20748
friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
20749
{
20750
return lhs >= basic_json(rhs);
20751
}
20752
20753
/// @brief comparison: greater than or equal
20754
/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
20755
template<typename ScalarType, typename std::enable_if<
20756
std::is_scalar<ScalarType>::value, int>::type = 0>
20757
friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
20758
{
20759
return basic_json(lhs) >= rhs;
20760
}
20761
20762
/// @}
20763
20764
///////////////////
20765
// serialization //
20766
///////////////////
20767
20768
/// @name serialization
20769
/// @{
20770
#ifndef JSON_NO_IO
20771
/// @brief serialize to stream
20772
/// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
20773
friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
20774
{
20775
// read width member and use it as indentation parameter if nonzero
20776
const bool pretty_print = o.width() > 0;
20777
const auto indentation = pretty_print ? o.width() : 0;
20778
20779
// reset width to 0 for subsequent calls to this stream
20780
o.width(0);
20781
20782
// do the actual serialization
20783
serializer s(detail::output_adapter<char>(o), o.fill());
20784
s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
20785
return o;
20786
}
20787
20788
/// @brief serialize to stream
20789
/// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
20790
/// @deprecated This function is deprecated since 3.0.0 and will be removed in
20791
/// version 4.0.0 of the library. Please use
20792
/// operator<<(std::ostream&, const basic_json&) instead; that is,
20793
/// replace calls like `j >> o;` with `o << j;`.
20794
JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
20795
friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
20796
{
20797
return o << j;
20798
}
20799
#endif // JSON_NO_IO
20800
/// @}
20801
20802
20803
/////////////////////
20804
// deserialization //
20805
/////////////////////
20806
20807
/// @name deserialization
20808
/// @{
20809
20810
/// @brief deserialize from a compatible input
20811
/// @sa https://json.nlohmann.me/api/basic_json/parse/
20812
template<typename InputType>
20813
JSON_HEDLEY_WARN_UNUSED_RESULT
20814
static basic_json parse(InputType&& i,
20815
const parser_callback_t cb = nullptr,
20816
const bool allow_exceptions = true,
20817
const bool ignore_comments = false)
20818
{
20819
basic_json result;
20820
parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
20821
return result;
20822
}
20823
20824
/// @brief deserialize from a pair of character iterators
20825
/// @sa https://json.nlohmann.me/api/basic_json/parse/
20826
template<typename IteratorType>
20827
JSON_HEDLEY_WARN_UNUSED_RESULT
20828
static basic_json parse(IteratorType first,
20829
IteratorType last,
20830
const parser_callback_t cb = nullptr,
20831
const bool allow_exceptions = true,
20832
const bool ignore_comments = false)
20833
{
20834
basic_json result;
20835
parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
20836
return result;
20837
}
20838
20839
JSON_HEDLEY_WARN_UNUSED_RESULT
20840
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
20841
static basic_json parse(detail::span_input_adapter&& i,
20842
const parser_callback_t cb = nullptr,
20843
const bool allow_exceptions = true,
20844
const bool ignore_comments = false)
20845
{
20846
basic_json result;
20847
parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
20848
return result;
20849
}
20850
20851
/// @brief check if the input is valid JSON
20852
/// @sa https://json.nlohmann.me/api/basic_json/accept/
20853
template<typename InputType>
20854
static bool accept(InputType&& i,
20855
const bool ignore_comments = false)
20856
{
20857
return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
20858
}
20859
20860
/// @brief check if the input is valid JSON
20861
/// @sa https://json.nlohmann.me/api/basic_json/accept/
20862
template<typename IteratorType>
20863
static bool accept(IteratorType first, IteratorType last,
20864
const bool ignore_comments = false)
20865
{
20866
return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
20867
}
20868
20869
JSON_HEDLEY_WARN_UNUSED_RESULT
20870
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
20871
static bool accept(detail::span_input_adapter&& i,
20872
const bool ignore_comments = false)
20873
{
20874
return parser(i.get(), nullptr, false, ignore_comments).accept(true);
20875
}
20876
20877
/// @brief generate SAX events
20878
/// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
20879
template <typename InputType, typename SAX>
20880
JSON_HEDLEY_NON_NULL(2)
20881
static bool sax_parse(InputType&& i, SAX* sax,
20882
input_format_t format = input_format_t::json,
20883
const bool strict = true,
20884
const bool ignore_comments = false)
20885
{
20886
auto ia = detail::input_adapter(std::forward<InputType>(i));
20887
return format == input_format_t::json
20888
? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
20889
: detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
20890
}
20891
20892
/// @brief generate SAX events
20893
/// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
20894
template<class IteratorType, class SAX>
20895
JSON_HEDLEY_NON_NULL(3)
20896
static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
20897
input_format_t format = input_format_t::json,
20898
const bool strict = true,
20899
const bool ignore_comments = false)
20900
{
20901
auto ia = detail::input_adapter(std::move(first), std::move(last));
20902
return format == input_format_t::json
20903
? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
20904
: detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
20905
}
20906
20907
/// @brief generate SAX events
20908
/// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
20909
/// @deprecated This function is deprecated since 3.8.0 and will be removed in
20910
/// version 4.0.0 of the library. Please use
20911
/// sax_parse(ptr, ptr + len) instead.
20912
template <typename SAX>
20913
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
20914
JSON_HEDLEY_NON_NULL(2)
20915
static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
20916
input_format_t format = input_format_t::json,
20917
const bool strict = true,
20918
const bool ignore_comments = false)
20919
{
20920
auto ia = i.get();
20921
return format == input_format_t::json
20922
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
20923
? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
20924
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
20925
: detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
20926
}
20927
#ifndef JSON_NO_IO
20928
/// @brief deserialize from stream
20929
/// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
20930
/// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
20931
/// version 4.0.0 of the library. Please use
20932
/// operator>>(std::istream&, basic_json&) instead; that is,
20933
/// replace calls like `j << i;` with `i >> j;`.
20934
JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
20935
friend std::istream& operator<<(basic_json& j, std::istream& i)
20936
{
20937
return operator>>(i, j);
20938
}
20939
20940
/// @brief deserialize from stream
20941
/// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
20942
friend std::istream& operator>>(std::istream& i, basic_json& j)
20943
{
20944
parser(detail::input_adapter(i)).parse(false, j);
20945
return i;
20946
}
20947
#endif // JSON_NO_IO
20948
/// @}
20949
20950
///////////////////////////
20951
// convenience functions //
20952
///////////////////////////
20953
20954
/// @brief return the type as string
20955
/// @sa https://json.nlohmann.me/api/basic_json/type_name/
20956
JSON_HEDLEY_RETURNS_NON_NULL
20957
const char* type_name() const noexcept
20958
{
20959
switch (m_type)
20960
{
20961
case value_t::null:
20962
return "null";
20963
case value_t::object:
20964
return "object";
20965
case value_t::array:
20966
return "array";
20967
case value_t::string:
20968
return "string";
20969
case value_t::boolean:
20970
return "boolean";
20971
case value_t::binary:
20972
return "binary";
20973
case value_t::discarded:
20974
return "discarded";
20975
case value_t::number_integer:
20976
case value_t::number_unsigned:
20977
case value_t::number_float:
20978
default:
20979
return "number";
20980
}
20981
}
20982
20983
20984
JSON_PRIVATE_UNLESS_TESTED:
20985
//////////////////////
20986
// member variables //
20987
//////////////////////
20988
20989
/// the type of the current element
20990
value_t m_type = value_t::null;
20991
20992
/// the value of the current element
20993
json_value m_value = {};
20994
20995
#if JSON_DIAGNOSTICS
20996
/// a pointer to a parent value (for debugging purposes)
20997
basic_json* m_parent = nullptr;
20998
#endif
20999
21000
//////////////////////////////////////////
21001
// binary serialization/deserialization //
21002
//////////////////////////////////////////
21003
21004
/// @name binary serialization/deserialization support
21005
/// @{
21006
21007
public:
21008
/// @brief create a CBOR serialization of a given JSON value
21009
/// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
21010
static std::vector<std::uint8_t> to_cbor(const basic_json& j)
21011
{
21012
std::vector<std::uint8_t> result;
21013
to_cbor(j, result);
21014
return result;
21015
}
21016
21017
/// @brief create a CBOR serialization of a given JSON value
21018
/// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
21019
static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
21020
{
21021
binary_writer<std::uint8_t>(o).write_cbor(j);
21022
}
21023
21024
/// @brief create a CBOR serialization of a given JSON value
21025
/// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
21026
static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
21027
{
21028
binary_writer<char>(o).write_cbor(j);
21029
}
21030
21031
/// @brief create a MessagePack serialization of a given JSON value
21032
/// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
21033
static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
21034
{
21035
std::vector<std::uint8_t> result;
21036
to_msgpack(j, result);
21037
return result;
21038
}
21039
21040
/// @brief create a MessagePack serialization of a given JSON value
21041
/// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
21042
static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
21043
{
21044
binary_writer<std::uint8_t>(o).write_msgpack(j);
21045
}
21046
21047
/// @brief create a MessagePack serialization of a given JSON value
21048
/// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
21049
static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
21050
{
21051
binary_writer<char>(o).write_msgpack(j);
21052
}
21053
21054
/// @brief create a UBJSON serialization of a given JSON value
21055
/// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
21056
static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
21057
const bool use_size = false,
21058
const bool use_type = false)
21059
{
21060
std::vector<std::uint8_t> result;
21061
to_ubjson(j, result, use_size, use_type);
21062
return result;
21063
}
21064
21065
/// @brief create a UBJSON serialization of a given JSON value
21066
/// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
21067
static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
21068
const bool use_size = false, const bool use_type = false)
21069
{
21070
binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
21071
}
21072
21073
/// @brief create a UBJSON serialization of a given JSON value
21074
/// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
21075
static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
21076
const bool use_size = false, const bool use_type = false)
21077
{
21078
binary_writer<char>(o).write_ubjson(j, use_size, use_type);
21079
}
21080
21081
/// @brief create a BSON serialization of a given JSON value
21082
/// @sa https://json.nlohmann.me/api/basic_json/to_bson/
21083
static std::vector<std::uint8_t> to_bson(const basic_json& j)
21084
{
21085
std::vector<std::uint8_t> result;
21086
to_bson(j, result);
21087
return result;
21088
}
21089
21090
/// @brief create a BSON serialization of a given JSON value
21091
/// @sa https://json.nlohmann.me/api/basic_json/to_bson/
21092
static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
21093
{
21094
binary_writer<std::uint8_t>(o).write_bson(j);
21095
}
21096
21097
/// @brief create a BSON serialization of a given JSON value
21098
/// @sa https://json.nlohmann.me/api/basic_json/to_bson/
21099
static void to_bson(const basic_json& j, detail::output_adapter<char> o)
21100
{
21101
binary_writer<char>(o).write_bson(j);
21102
}
21103
21104
/// @brief create a JSON value from an input in CBOR format
21105
/// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
21106
template<typename InputType>
21107
JSON_HEDLEY_WARN_UNUSED_RESULT
21108
static basic_json from_cbor(InputType&& i,
21109
const bool strict = true,
21110
const bool allow_exceptions = true,
21111
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
21112
{
21113
basic_json result;
21114
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21115
auto ia = detail::input_adapter(std::forward<InputType>(i));
21116
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
21117
return res ? result : basic_json(value_t::discarded);
21118
}
21119
21120
/// @brief create a JSON value from an input in CBOR format
21121
/// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
21122
template<typename IteratorType>
21123
JSON_HEDLEY_WARN_UNUSED_RESULT
21124
static basic_json from_cbor(IteratorType first, IteratorType last,
21125
const bool strict = true,
21126
const bool allow_exceptions = true,
21127
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
21128
{
21129
basic_json result;
21130
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21131
auto ia = detail::input_adapter(std::move(first), std::move(last));
21132
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
21133
return res ? result : basic_json(value_t::discarded);
21134
}
21135
21136
template<typename T>
21137
JSON_HEDLEY_WARN_UNUSED_RESULT
21138
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
21139
static basic_json from_cbor(const T* ptr, std::size_t len,
21140
const bool strict = true,
21141
const bool allow_exceptions = true,
21142
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
21143
{
21144
return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
21145
}
21146
21147
21148
JSON_HEDLEY_WARN_UNUSED_RESULT
21149
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
21150
static basic_json from_cbor(detail::span_input_adapter&& i,
21151
const bool strict = true,
21152
const bool allow_exceptions = true,
21153
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
21154
{
21155
basic_json result;
21156
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21157
auto ia = i.get();
21158
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21159
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
21160
return res ? result : basic_json(value_t::discarded);
21161
}
21162
21163
/// @brief create a JSON value from an input in MessagePack format
21164
/// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
21165
template<typename InputType>
21166
JSON_HEDLEY_WARN_UNUSED_RESULT
21167
static basic_json from_msgpack(InputType&& i,
21168
const bool strict = true,
21169
const bool allow_exceptions = true)
21170
{
21171
basic_json result;
21172
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21173
auto ia = detail::input_adapter(std::forward<InputType>(i));
21174
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
21175
return res ? result : basic_json(value_t::discarded);
21176
}
21177
21178
/// @brief create a JSON value from an input in MessagePack format
21179
/// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
21180
template<typename IteratorType>
21181
JSON_HEDLEY_WARN_UNUSED_RESULT
21182
static basic_json from_msgpack(IteratorType first, IteratorType last,
21183
const bool strict = true,
21184
const bool allow_exceptions = true)
21185
{
21186
basic_json result;
21187
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21188
auto ia = detail::input_adapter(std::move(first), std::move(last));
21189
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
21190
return res ? result : basic_json(value_t::discarded);
21191
}
21192
21193
template<typename T>
21194
JSON_HEDLEY_WARN_UNUSED_RESULT
21195
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
21196
static basic_json from_msgpack(const T* ptr, std::size_t len,
21197
const bool strict = true,
21198
const bool allow_exceptions = true)
21199
{
21200
return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
21201
}
21202
21203
JSON_HEDLEY_WARN_UNUSED_RESULT
21204
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
21205
static basic_json from_msgpack(detail::span_input_adapter&& i,
21206
const bool strict = true,
21207
const bool allow_exceptions = true)
21208
{
21209
basic_json result;
21210
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21211
auto ia = i.get();
21212
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21213
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
21214
return res ? result : basic_json(value_t::discarded);
21215
}
21216
21217
/// @brief create a JSON value from an input in UBJSON format
21218
/// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
21219
template<typename InputType>
21220
JSON_HEDLEY_WARN_UNUSED_RESULT
21221
static basic_json from_ubjson(InputType&& i,
21222
const bool strict = true,
21223
const bool allow_exceptions = true)
21224
{
21225
basic_json result;
21226
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21227
auto ia = detail::input_adapter(std::forward<InputType>(i));
21228
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
21229
return res ? result : basic_json(value_t::discarded);
21230
}
21231
21232
/// @brief create a JSON value from an input in UBJSON format
21233
/// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
21234
template<typename IteratorType>
21235
JSON_HEDLEY_WARN_UNUSED_RESULT
21236
static basic_json from_ubjson(IteratorType first, IteratorType last,
21237
const bool strict = true,
21238
const bool allow_exceptions = true)
21239
{
21240
basic_json result;
21241
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21242
auto ia = detail::input_adapter(std::move(first), std::move(last));
21243
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
21244
return res ? result : basic_json(value_t::discarded);
21245
}
21246
21247
template<typename T>
21248
JSON_HEDLEY_WARN_UNUSED_RESULT
21249
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
21250
static basic_json from_ubjson(const T* ptr, std::size_t len,
21251
const bool strict = true,
21252
const bool allow_exceptions = true)
21253
{
21254
return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
21255
}
21256
21257
JSON_HEDLEY_WARN_UNUSED_RESULT
21258
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
21259
static basic_json from_ubjson(detail::span_input_adapter&& i,
21260
const bool strict = true,
21261
const bool allow_exceptions = true)
21262
{
21263
basic_json result;
21264
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21265
auto ia = i.get();
21266
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21267
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
21268
return res ? result : basic_json(value_t::discarded);
21269
}
21270
21271
/// @brief create a JSON value from an input in BSON format
21272
/// @sa https://json.nlohmann.me/api/basic_json/from_bson/
21273
template<typename InputType>
21274
JSON_HEDLEY_WARN_UNUSED_RESULT
21275
static basic_json from_bson(InputType&& i,
21276
const bool strict = true,
21277
const bool allow_exceptions = true)
21278
{
21279
basic_json result;
21280
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21281
auto ia = detail::input_adapter(std::forward<InputType>(i));
21282
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
21283
return res ? result : basic_json(value_t::discarded);
21284
}
21285
21286
/// @brief create a JSON value from an input in BSON format
21287
/// @sa https://json.nlohmann.me/api/basic_json/from_bson/
21288
template<typename IteratorType>
21289
JSON_HEDLEY_WARN_UNUSED_RESULT
21290
static basic_json from_bson(IteratorType first, IteratorType last,
21291
const bool strict = true,
21292
const bool allow_exceptions = true)
21293
{
21294
basic_json result;
21295
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21296
auto ia = detail::input_adapter(std::move(first), std::move(last));
21297
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
21298
return res ? result : basic_json(value_t::discarded);
21299
}
21300
21301
template<typename T>
21302
JSON_HEDLEY_WARN_UNUSED_RESULT
21303
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
21304
static basic_json from_bson(const T* ptr, std::size_t len,
21305
const bool strict = true,
21306
const bool allow_exceptions = true)
21307
{
21308
return from_bson(ptr, ptr + len, strict, allow_exceptions);
21309
}
21310
21311
JSON_HEDLEY_WARN_UNUSED_RESULT
21312
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
21313
static basic_json from_bson(detail::span_input_adapter&& i,
21314
const bool strict = true,
21315
const bool allow_exceptions = true)
21316
{
21317
basic_json result;
21318
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21319
auto ia = i.get();
21320
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21321
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
21322
return res ? result : basic_json(value_t::discarded);
21323
}
21324
/// @}
21325
21326
//////////////////////////
21327
// JSON Pointer support //
21328
//////////////////////////
21329
21330
/// @name JSON Pointer functions
21331
/// @{
21332
21333
/// @brief access specified element via JSON Pointer
21334
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21335
reference operator[](const json_pointer& ptr)
21336
{
21337
return ptr.get_unchecked(this);
21338
}
21339
21340
/// @brief access specified element via JSON Pointer
21341
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21342
const_reference operator[](const json_pointer& ptr) const
21343
{
21344
return ptr.get_unchecked(this);
21345
}
21346
21347
/// @brief access specified element via JSON Pointer
21348
/// @sa https://json.nlohmann.me/api/basic_json/at/
21349
reference at(const json_pointer& ptr)
21350
{
21351
return ptr.get_checked(this);
21352
}
21353
21354
/// @brief access specified element via JSON Pointer
21355
/// @sa https://json.nlohmann.me/api/basic_json/at/
21356
const_reference at(const json_pointer& ptr) const
21357
{
21358
return ptr.get_checked(this);
21359
}
21360
21361
/// @brief return flattened JSON value
21362
/// @sa https://json.nlohmann.me/api/basic_json/flatten/
21363
basic_json flatten() const
21364
{
21365
basic_json result(value_t::object);
21366
json_pointer::flatten("", *this, result);
21367
return result;
21368
}
21369
21370
/// @brief unflatten a previously flattened JSON value
21371
/// @sa https://json.nlohmann.me/api/basic_json/unflatten/
21372
basic_json unflatten() const
21373
{
21374
return json_pointer::unflatten(*this);
21375
}
21376
21377
/// @}
21378
21379
//////////////////////////
21380
// JSON Patch functions //
21381
//////////////////////////
21382
21383
/// @name JSON Patch functions
21384
/// @{
21385
21386
/// @brief applies a JSON patch
21387
/// @sa https://json.nlohmann.me/api/basic_json/patch/
21388
basic_json patch(const basic_json& json_patch) const
21389
{
21390
// make a working copy to apply the patch to
21391
basic_json result = *this;
21392
21393
// the valid JSON Patch operations
21394
enum class patch_operations {add, remove, replace, move, copy, test, invalid};
21395
21396
const auto get_op = [](const std::string & op)
21397
{
21398
if (op == "add")
21399
{
21400
return patch_operations::add;
21401
}
21402
if (op == "remove")
21403
{
21404
return patch_operations::remove;
21405
}
21406
if (op == "replace")
21407
{
21408
return patch_operations::replace;
21409
}
21410
if (op == "move")
21411
{
21412
return patch_operations::move;
21413
}
21414
if (op == "copy")
21415
{
21416
return patch_operations::copy;
21417
}
21418
if (op == "test")
21419
{
21420
return patch_operations::test;
21421
}
21422
21423
return patch_operations::invalid;
21424
};
21425
21426
// wrapper for "add" operation; add value at ptr
21427
const auto operation_add = [&result](json_pointer & ptr, basic_json val)
21428
{
21429
// adding to the root of the target document means replacing it
21430
if (ptr.empty())
21431
{
21432
result = val;
21433
return;
21434
}
21435
21436
// make sure the top element of the pointer exists
21437
json_pointer top_pointer = ptr.top();
21438
if (top_pointer != ptr)
21439
{
21440
result.at(top_pointer);
21441
}
21442
21443
// get reference to parent of JSON pointer ptr
21444
const auto last_path = ptr.back();
21445
ptr.pop_back();
21446
basic_json& parent = result[ptr];
21447
21448
switch (parent.m_type)
21449
{
21450
case value_t::null:
21451
case value_t::object:
21452
{
21453
// use operator[] to add value
21454
parent[last_path] = val;
21455
break;
21456
}
21457
21458
case value_t::array:
21459
{
21460
if (last_path == "-")
21461
{
21462
// special case: append to back
21463
parent.push_back(val);
21464
}
21465
else
21466
{
21467
const auto idx = json_pointer::array_index(last_path);
21468
if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
21469
{
21470
// avoid undefined behavior
21471
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", parent));
21472
}
21473
21474
// default case: insert add offset
21475
parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
21476
}
21477
break;
21478
}
21479
21480
// if there exists a parent it cannot be primitive
21481
case value_t::string: // LCOV_EXCL_LINE
21482
case value_t::boolean: // LCOV_EXCL_LINE
21483
case value_t::number_integer: // LCOV_EXCL_LINE
21484
case value_t::number_unsigned: // LCOV_EXCL_LINE
21485
case value_t::number_float: // LCOV_EXCL_LINE
21486
case value_t::binary: // LCOV_EXCL_LINE
21487
case value_t::discarded: // LCOV_EXCL_LINE
21488
default: // LCOV_EXCL_LINE
21489
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
21490
}
21491
};
21492
21493
// wrapper for "remove" operation; remove value at ptr
21494
const auto operation_remove = [this, &result](json_pointer & ptr)
21495
{
21496
// get reference to parent of JSON pointer ptr
21497
const auto last_path = ptr.back();
21498
ptr.pop_back();
21499
basic_json& parent = result.at(ptr);
21500
21501
// remove child
21502
if (parent.is_object())
21503
{
21504
// perform range check
21505
auto it = parent.find(last_path);
21506
if (JSON_HEDLEY_LIKELY(it != parent.end()))
21507
{
21508
parent.erase(it);
21509
}
21510
else
21511
{
21512
JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", *this));
21513
}
21514
}
21515
else if (parent.is_array())
21516
{
21517
// note erase performs range check
21518
parent.erase(json_pointer::array_index(last_path));
21519
}
21520
};
21521
21522
// type check: top level value must be an array
21523
if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
21524
{
21525
JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", json_patch));
21526
}
21527
21528
// iterate and apply the operations
21529
for (const auto& val : json_patch)
21530
{
21531
// wrapper to get a value for an operation
21532
const auto get_value = [&val](const std::string & op,
21533
const std::string & member,
21534
bool string_type) -> basic_json &
21535
{
21536
// find value
21537
auto it = val.m_value.object->find(member);
21538
21539
// context-sensitive error message
21540
const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
21541
21542
// check if desired value is present
21543
if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
21544
{
21545
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
21546
JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", val));
21547
}
21548
21549
// check if result is of type string
21550
if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
21551
{
21552
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
21553
JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", val));
21554
}
21555
21556
// no error: return value
21557
return it->second;
21558
};
21559
21560
// type check: every element of the array must be an object
21561
if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
21562
{
21563
JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", val));
21564
}
21565
21566
// collect mandatory members
21567
const auto op = get_value("op", "op", true).template get<std::string>();
21568
const auto path = get_value(op, "path", true).template get<std::string>();
21569
json_pointer ptr(path);
21570
21571
switch (get_op(op))
21572
{
21573
case patch_operations::add:
21574
{
21575
operation_add(ptr, get_value("add", "value", false));
21576
break;
21577
}
21578
21579
case patch_operations::remove:
21580
{
21581
operation_remove(ptr);
21582
break;
21583
}
21584
21585
case patch_operations::replace:
21586
{
21587
// the "path" location must exist - use at()
21588
result.at(ptr) = get_value("replace", "value", false);
21589
break;
21590
}
21591
21592
case patch_operations::move:
21593
{
21594
const auto from_path = get_value("move", "from", true).template get<std::string>();
21595
json_pointer from_ptr(from_path);
21596
21597
// the "from" location must exist - use at()
21598
basic_json v = result.at(from_ptr);
21599
21600
// The move operation is functionally identical to a
21601
// "remove" operation on the "from" location, followed
21602
// immediately by an "add" operation at the target
21603
// location with the value that was just removed.
21604
operation_remove(from_ptr);
21605
operation_add(ptr, v);
21606
break;
21607
}
21608
21609
case patch_operations::copy:
21610
{
21611
const auto from_path = get_value("copy", "from", true).template get<std::string>();
21612
const json_pointer from_ptr(from_path);
21613
21614
// the "from" location must exist - use at()
21615
basic_json v = result.at(from_ptr);
21616
21617
// The copy is functionally identical to an "add"
21618
// operation at the target location using the value
21619
// specified in the "from" member.
21620
operation_add(ptr, v);
21621
break;
21622
}
21623
21624
case patch_operations::test:
21625
{
21626
bool success = false;
21627
JSON_TRY
21628
{
21629
// check if "value" matches the one at "path"
21630
// the "path" location must exist - use at()
21631
success = (result.at(ptr) == get_value("test", "value", false));
21632
}
21633
JSON_INTERNAL_CATCH (out_of_range&)
21634
{
21635
// ignore out of range errors: success remains false
21636
}
21637
21638
// throw an exception if test fails
21639
if (JSON_HEDLEY_UNLIKELY(!success))
21640
{
21641
JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), val));
21642
}
21643
21644
break;
21645
}
21646
21647
case patch_operations::invalid:
21648
default:
21649
{
21650
// op must be "add", "remove", "replace", "move", "copy", or
21651
// "test"
21652
JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid", val));
21653
}
21654
}
21655
}
21656
21657
return result;
21658
}
21659
21660
/// @brief creates a diff as a JSON patch
21661
/// @sa https://json.nlohmann.me/api/basic_json/diff/
21662
JSON_HEDLEY_WARN_UNUSED_RESULT
21663
static basic_json diff(const basic_json& source, const basic_json& target,
21664
const std::string& path = "")
21665
{
21666
// the patch
21667
basic_json result(value_t::array);
21668
21669
// if the values are the same, return empty patch
21670
if (source == target)
21671
{
21672
return result;
21673
}
21674
21675
if (source.type() != target.type())
21676
{
21677
// different types: replace value
21678
result.push_back(
21679
{
21680
{"op", "replace"}, {"path", path}, {"value", target}
21681
});
21682
return result;
21683
}
21684
21685
switch (source.type())
21686
{
21687
case value_t::array:
21688
{
21689
// first pass: traverse common elements
21690
std::size_t i = 0;
21691
while (i < source.size() && i < target.size())
21692
{
21693
// recursive call to compare array values at index i
21694
auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
21695
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
21696
++i;
21697
}
21698
21699
// We now reached the end of at least one array
21700
// in a second pass, traverse the remaining elements
21701
21702
// remove my remaining elements
21703
const auto end_index = static_cast<difference_type>(result.size());
21704
while (i < source.size())
21705
{
21706
// add operations in reverse order to avoid invalid
21707
// indices
21708
result.insert(result.begin() + end_index, object(
21709
{
21710
{"op", "remove"},
21711
{"path", path + "/" + std::to_string(i)}
21712
}));
21713
++i;
21714
}
21715
21716
// add other remaining elements
21717
while (i < target.size())
21718
{
21719
result.push_back(
21720
{
21721
{"op", "add"},
21722
{"path", path + "/-"},
21723
{"value", target[i]}
21724
});
21725
++i;
21726
}
21727
21728
break;
21729
}
21730
21731
case value_t::object:
21732
{
21733
// first pass: traverse this object's elements
21734
for (auto it = source.cbegin(); it != source.cend(); ++it)
21735
{
21736
// escape the key name to be used in a JSON patch
21737
const auto path_key = path + "/" + detail::escape(it.key());
21738
21739
if (target.find(it.key()) != target.end())
21740
{
21741
// recursive call to compare object values at key it
21742
auto temp_diff = diff(it.value(), target[it.key()], path_key);
21743
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
21744
}
21745
else
21746
{
21747
// found a key that is not in o -> remove it
21748
result.push_back(object(
21749
{
21750
{"op", "remove"}, {"path", path_key}
21751
}));
21752
}
21753
}
21754
21755
// second pass: traverse other object's elements
21756
for (auto it = target.cbegin(); it != target.cend(); ++it)
21757
{
21758
if (source.find(it.key()) == source.end())
21759
{
21760
// found a key that is not in this -> add it
21761
const auto path_key = path + "/" + detail::escape(it.key());
21762
result.push_back(
21763
{
21764
{"op", "add"}, {"path", path_key},
21765
{"value", it.value()}
21766
});
21767
}
21768
}
21769
21770
break;
21771
}
21772
21773
case value_t::null:
21774
case value_t::string:
21775
case value_t::boolean:
21776
case value_t::number_integer:
21777
case value_t::number_unsigned:
21778
case value_t::number_float:
21779
case value_t::binary:
21780
case value_t::discarded:
21781
default:
21782
{
21783
// both primitive type: replace value
21784
result.push_back(
21785
{
21786
{"op", "replace"}, {"path", path}, {"value", target}
21787
});
21788
break;
21789
}
21790
}
21791
21792
return result;
21793
}
21794
21795
/// @}
21796
21797
////////////////////////////////
21798
// JSON Merge Patch functions //
21799
////////////////////////////////
21800
21801
/// @name JSON Merge Patch functions
21802
/// @{
21803
21804
/// @brief applies a JSON Merge Patch
21805
/// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
21806
void merge_patch(const basic_json& apply_patch)
21807
{
21808
if (apply_patch.is_object())
21809
{
21810
if (!is_object())
21811
{
21812
*this = object();
21813
}
21814
for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
21815
{
21816
if (it.value().is_null())
21817
{
21818
erase(it.key());
21819
}
21820
else
21821
{
21822
operator[](it.key()).merge_patch(it.value());
21823
}
21824
}
21825
}
21826
else
21827
{
21828
*this = apply_patch;
21829
}
21830
}
21831
21832
/// @}
21833
};
21834
21835
/// @brief user-defined to_string function for JSON values
21836
/// @sa https://json.nlohmann.me/api/basic_json/to_string/
21837
NLOHMANN_BASIC_JSON_TPL_DECLARATION
21838
std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
21839
{
21840
return j.dump();
21841
}
21842
21843
} // namespace nlohmann
21844
21845
///////////////////////
21846
// nonmember support //
21847
///////////////////////
21848
21849
namespace std // NOLINT(cert-dcl58-cpp)
21850
{
21851
21852
/// @brief hash value for JSON objects
21853
/// @sa https://json.nlohmann.me/api/basic_json/std_hash/
21854
NLOHMANN_BASIC_JSON_TPL_DECLARATION
21855
struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL>
21856
{
21857
std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
21858
{
21859
return nlohmann::detail::hash(j);
21860
}
21861
};
21862
21863
// specialization for std::less<value_t>
21864
template<>
21865
struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
21866
{
21867
/*!
21868
@brief compare two value_t enum values
21869
@since version 3.0.0
21870
*/
21871
bool operator()(nlohmann::detail::value_t lhs,
21872
nlohmann::detail::value_t rhs) const noexcept
21873
{
21874
return nlohmann::detail::operator<(lhs, rhs);
21875
}
21876
};
21877
21878
// C++20 prohibit function specialization in the std namespace.
21879
#ifndef JSON_HAS_CPP_20
21880
21881
/// @brief exchanges the values of two JSON objects
21882
/// @sa https://json.nlohmann.me/api/basic_json/std_swap/
21883
NLOHMANN_BASIC_JSON_TPL_DECLARATION
21884
inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name)
21885
is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression)
21886
is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
21887
{
21888
j1.swap(j2);
21889
}
21890
21891
#endif
21892
21893
} // namespace std
21894
21895
/// @brief user-defined string literal for JSON values
21896
/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
21897
JSON_HEDLEY_NON_NULL(1)
21898
inline nlohmann::json operator "" _json(const char* s, std::size_t n)
21899
{
21900
return nlohmann::json::parse(s, s + n);
21901
}
21902
21903
/// @brief user-defined string literal for JSON pointer
21904
/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
21905
JSON_HEDLEY_NON_NULL(1)
21906
inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
21907
{
21908
return nlohmann::json::json_pointer(std::string(s, n));
21909
}
21910
21911
// #include <nlohmann/detail/macro_unscope.hpp>
21912
21913
21914
// restore clang diagnostic settings
21915
#if defined(__clang__)
21916
#pragma clang diagnostic pop
21917
#endif
21918
21919
// clean up
21920
#undef JSON_ASSERT
21921
#undef JSON_INTERNAL_CATCH
21922
#undef JSON_CATCH
21923
#undef JSON_THROW
21924
#undef JSON_TRY
21925
#undef JSON_PRIVATE_UNLESS_TESTED
21926
#undef JSON_HAS_CPP_11
21927
#undef JSON_HAS_CPP_14
21928
#undef JSON_HAS_CPP_17
21929
#undef JSON_HAS_CPP_20
21930
#undef JSON_HAS_FILESYSTEM
21931
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
21932
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
21933
#undef NLOHMANN_BASIC_JSON_TPL
21934
#undef JSON_EXPLICIT
21935
#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
21936
21937
// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
21938
21939
21940
#undef JSON_HEDLEY_ALWAYS_INLINE
21941
#undef JSON_HEDLEY_ARM_VERSION
21942
#undef JSON_HEDLEY_ARM_VERSION_CHECK
21943
#undef JSON_HEDLEY_ARRAY_PARAM
21944
#undef JSON_HEDLEY_ASSUME
21945
#undef JSON_HEDLEY_BEGIN_C_DECLS
21946
#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
21947
#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
21948
#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
21949
#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
21950
#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
21951
#undef JSON_HEDLEY_CLANG_HAS_FEATURE
21952
#undef JSON_HEDLEY_CLANG_HAS_WARNING
21953
#undef JSON_HEDLEY_COMPCERT_VERSION
21954
#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
21955
#undef JSON_HEDLEY_CONCAT
21956
#undef JSON_HEDLEY_CONCAT3
21957
#undef JSON_HEDLEY_CONCAT3_EX
21958
#undef JSON_HEDLEY_CONCAT_EX
21959
#undef JSON_HEDLEY_CONST
21960
#undef JSON_HEDLEY_CONSTEXPR
21961
#undef JSON_HEDLEY_CONST_CAST
21962
#undef JSON_HEDLEY_CPP_CAST
21963
#undef JSON_HEDLEY_CRAY_VERSION
21964
#undef JSON_HEDLEY_CRAY_VERSION_CHECK
21965
#undef JSON_HEDLEY_C_DECL
21966
#undef JSON_HEDLEY_DEPRECATED
21967
#undef JSON_HEDLEY_DEPRECATED_FOR
21968
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
21969
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
21970
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
21971
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
21972
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
21973
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
21974
#undef JSON_HEDLEY_DIAGNOSTIC_POP
21975
#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
21976
#undef JSON_HEDLEY_DMC_VERSION
21977
#undef JSON_HEDLEY_DMC_VERSION_CHECK
21978
#undef JSON_HEDLEY_EMPTY_BASES
21979
#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
21980
#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
21981
#undef JSON_HEDLEY_END_C_DECLS
21982
#undef JSON_HEDLEY_FLAGS
21983
#undef JSON_HEDLEY_FLAGS_CAST
21984
#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
21985
#undef JSON_HEDLEY_GCC_HAS_BUILTIN
21986
#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
21987
#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
21988
#undef JSON_HEDLEY_GCC_HAS_EXTENSION
21989
#undef JSON_HEDLEY_GCC_HAS_FEATURE
21990
#undef JSON_HEDLEY_GCC_HAS_WARNING
21991
#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
21992
#undef JSON_HEDLEY_GCC_VERSION
21993
#undef JSON_HEDLEY_GCC_VERSION_CHECK
21994
#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
21995
#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
21996
#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
21997
#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
21998
#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
21999
#undef JSON_HEDLEY_GNUC_HAS_FEATURE
22000
#undef JSON_HEDLEY_GNUC_HAS_WARNING
22001
#undef JSON_HEDLEY_GNUC_VERSION
22002
#undef JSON_HEDLEY_GNUC_VERSION_CHECK
22003
#undef JSON_HEDLEY_HAS_ATTRIBUTE
22004
#undef JSON_HEDLEY_HAS_BUILTIN
22005
#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
22006
#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
22007
#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
22008
#undef JSON_HEDLEY_HAS_EXTENSION
22009
#undef JSON_HEDLEY_HAS_FEATURE
22010
#undef JSON_HEDLEY_HAS_WARNING
22011
#undef JSON_HEDLEY_IAR_VERSION
22012
#undef JSON_HEDLEY_IAR_VERSION_CHECK
22013
#undef JSON_HEDLEY_IBM_VERSION
22014
#undef JSON_HEDLEY_IBM_VERSION_CHECK
22015
#undef JSON_HEDLEY_IMPORT
22016
#undef JSON_HEDLEY_INLINE
22017
#undef JSON_HEDLEY_INTEL_CL_VERSION
22018
#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
22019
#undef JSON_HEDLEY_INTEL_VERSION
22020
#undef JSON_HEDLEY_INTEL_VERSION_CHECK
22021
#undef JSON_HEDLEY_IS_CONSTANT
22022
#undef JSON_HEDLEY_IS_CONSTEXPR_
22023
#undef JSON_HEDLEY_LIKELY
22024
#undef JSON_HEDLEY_MALLOC
22025
#undef JSON_HEDLEY_MCST_LCC_VERSION
22026
#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
22027
#undef JSON_HEDLEY_MESSAGE
22028
#undef JSON_HEDLEY_MSVC_VERSION
22029
#undef JSON_HEDLEY_MSVC_VERSION_CHECK
22030
#undef JSON_HEDLEY_NEVER_INLINE
22031
#undef JSON_HEDLEY_NON_NULL
22032
#undef JSON_HEDLEY_NO_ESCAPE
22033
#undef JSON_HEDLEY_NO_RETURN
22034
#undef JSON_HEDLEY_NO_THROW
22035
#undef JSON_HEDLEY_NULL
22036
#undef JSON_HEDLEY_PELLES_VERSION
22037
#undef JSON_HEDLEY_PELLES_VERSION_CHECK
22038
#undef JSON_HEDLEY_PGI_VERSION
22039
#undef JSON_HEDLEY_PGI_VERSION_CHECK
22040
#undef JSON_HEDLEY_PREDICT
22041
#undef JSON_HEDLEY_PRINTF_FORMAT
22042
#undef JSON_HEDLEY_PRIVATE
22043
#undef JSON_HEDLEY_PUBLIC
22044
#undef JSON_HEDLEY_PURE
22045
#undef JSON_HEDLEY_REINTERPRET_CAST
22046
#undef JSON_HEDLEY_REQUIRE
22047
#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
22048
#undef JSON_HEDLEY_REQUIRE_MSG
22049
#undef JSON_HEDLEY_RESTRICT
22050
#undef JSON_HEDLEY_RETURNS_NON_NULL
22051
#undef JSON_HEDLEY_SENTINEL
22052
#undef JSON_HEDLEY_STATIC_ASSERT
22053
#undef JSON_HEDLEY_STATIC_CAST
22054
#undef JSON_HEDLEY_STRINGIFY
22055
#undef JSON_HEDLEY_STRINGIFY_EX
22056
#undef JSON_HEDLEY_SUNPRO_VERSION
22057
#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
22058
#undef JSON_HEDLEY_TINYC_VERSION
22059
#undef JSON_HEDLEY_TINYC_VERSION_CHECK
22060
#undef JSON_HEDLEY_TI_ARMCL_VERSION
22061
#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
22062
#undef JSON_HEDLEY_TI_CL2000_VERSION
22063
#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
22064
#undef JSON_HEDLEY_TI_CL430_VERSION
22065
#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
22066
#undef JSON_HEDLEY_TI_CL6X_VERSION
22067
#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
22068
#undef JSON_HEDLEY_TI_CL7X_VERSION
22069
#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
22070
#undef JSON_HEDLEY_TI_CLPRU_VERSION
22071
#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
22072
#undef JSON_HEDLEY_TI_VERSION
22073
#undef JSON_HEDLEY_TI_VERSION_CHECK
22074
#undef JSON_HEDLEY_UNAVAILABLE
22075
#undef JSON_HEDLEY_UNLIKELY
22076
#undef JSON_HEDLEY_UNPREDICTABLE
22077
#undef JSON_HEDLEY_UNREACHABLE
22078
#undef JSON_HEDLEY_UNREACHABLE_RETURN
22079
#undef JSON_HEDLEY_VERSION
22080
#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
22081
#undef JSON_HEDLEY_VERSION_DECODE_MINOR
22082
#undef JSON_HEDLEY_VERSION_DECODE_REVISION
22083
#undef JSON_HEDLEY_VERSION_ENCODE
22084
#undef JSON_HEDLEY_WARNING
22085
#undef JSON_HEDLEY_WARN_UNUSED_RESULT
22086
#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
22087
#undef JSON_HEDLEY_FALL_THROUGH
22088
22089
22090
22091
#endif // INCLUDE_NLOHMANN_JSON_HPP_
22092
22093