Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
TensorSpeech
GitHub Repository: TensorSpeech/TensorFlowTTS
Path: blob/master/examples/cppwin/TensorflowTTSCppInference/ext/json.hpp
1564 views
1
/*
2
__ _____ _____ _____
3
__| | __| | | | JSON for Modern C++
4
| | |__ | | | | | | version 3.9.1
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-2019 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
#ifndef INCLUDE_NLOHMANN_JSON_HPP_
31
#define INCLUDE_NLOHMANN_JSON_HPP_
32
33
#define NLOHMANN_JSON_VERSION_MAJOR 3
34
#define NLOHMANN_JSON_VERSION_MINOR 9
35
#define NLOHMANN_JSON_VERSION_PATCH 1
36
37
#include <algorithm> // all_of, find, for_each
38
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
39
#include <functional> // hash, less
40
#include <initializer_list> // initializer_list
41
#include <iosfwd> // istream, ostream
42
#include <iterator> // random_access_iterator_tag
43
#include <memory> // unique_ptr
44
#include <numeric> // accumulate
45
#include <string> // string, stoi, to_string
46
#include <utility> // declval, forward, move, pair, swap
47
#include <vector> // vector
48
49
// #include <nlohmann/adl_serializer.hpp>
50
51
52
#include <utility>
53
54
// #include <nlohmann/detail/conversions/from_json.hpp>
55
56
57
#include <algorithm> // transform
58
#include <array> // array
59
#include <forward_list> // forward_list
60
#include <iterator> // inserter, front_inserter, end
61
#include <map> // map
62
#include <string> // string
63
#include <tuple> // tuple, make_tuple
64
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
65
#include <unordered_map> // unordered_map
66
#include <utility> // pair, declval
67
#include <valarray> // valarray
68
69
// #include <nlohmann/detail/exceptions.hpp>
70
71
72
#include <exception> // exception
73
#include <stdexcept> // runtime_error
74
#include <string> // to_string
75
76
// #include <nlohmann/detail/input/position_t.hpp>
77
78
79
#include <cstddef> // size_t
80
81
namespace nlohmann
82
{
83
namespace detail
84
{
85
/// struct to capture the start position of the current token
86
struct position_t
87
{
88
/// the total number of characters read
89
std::size_t chars_read_total = 0;
90
/// the number of characters read in the current line
91
std::size_t chars_read_current_line = 0;
92
/// the number of lines read
93
std::size_t lines_read = 0;
94
95
/// conversion to size_t to preserve SAX interface
96
constexpr operator size_t() const
97
{
98
return chars_read_total;
99
}
100
};
101
102
} // namespace detail
103
} // namespace nlohmann
104
105
// #include <nlohmann/detail/macro_scope.hpp>
106
107
108
#include <utility> // pair
109
// #include <nlohmann/thirdparty/hedley/hedley.hpp>
110
/* Hedley - https://nemequ.github.io/hedley
111
* Created by Evan Nemerson <[email protected]>
112
*
113
* To the extent possible under law, the author(s) have dedicated all
114
* copyright and related and neighboring rights to this software to
115
* the public domain worldwide. This software is distributed without
116
* any warranty.
117
*
118
* For details, see <http://creativecommons.org/publicdomain/zero/1.0/>.
119
* SPDX-License-Identifier: CC0-1.0
120
*/
121
122
#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 13)
123
#if defined(JSON_HEDLEY_VERSION)
124
#undef JSON_HEDLEY_VERSION
125
#endif
126
#define JSON_HEDLEY_VERSION 13
127
128
#if defined(JSON_HEDLEY_STRINGIFY_EX)
129
#undef JSON_HEDLEY_STRINGIFY_EX
130
#endif
131
#define JSON_HEDLEY_STRINGIFY_EX(x) #x
132
133
#if defined(JSON_HEDLEY_STRINGIFY)
134
#undef JSON_HEDLEY_STRINGIFY
135
#endif
136
#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
137
138
#if defined(JSON_HEDLEY_CONCAT_EX)
139
#undef JSON_HEDLEY_CONCAT_EX
140
#endif
141
#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
142
143
#if defined(JSON_HEDLEY_CONCAT)
144
#undef JSON_HEDLEY_CONCAT
145
#endif
146
#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
147
148
#if defined(JSON_HEDLEY_CONCAT3_EX)
149
#undef JSON_HEDLEY_CONCAT3_EX
150
#endif
151
#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
152
153
#if defined(JSON_HEDLEY_CONCAT3)
154
#undef JSON_HEDLEY_CONCAT3
155
#endif
156
#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
157
158
#if defined(JSON_HEDLEY_VERSION_ENCODE)
159
#undef JSON_HEDLEY_VERSION_ENCODE
160
#endif
161
#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
162
163
#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
164
#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
165
#endif
166
#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
167
168
#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
169
#undef JSON_HEDLEY_VERSION_DECODE_MINOR
170
#endif
171
#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
172
173
#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
174
#undef JSON_HEDLEY_VERSION_DECODE_REVISION
175
#endif
176
#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
177
178
#if defined(JSON_HEDLEY_GNUC_VERSION)
179
#undef JSON_HEDLEY_GNUC_VERSION
180
#endif
181
#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
182
#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
183
#elif defined(__GNUC__)
184
#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
185
#endif
186
187
#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
188
#undef JSON_HEDLEY_GNUC_VERSION_CHECK
189
#endif
190
#if defined(JSON_HEDLEY_GNUC_VERSION)
191
#define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
192
#else
193
#define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
194
#endif
195
196
#if defined(JSON_HEDLEY_MSVC_VERSION)
197
#undef JSON_HEDLEY_MSVC_VERSION
198
#endif
199
#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000)
200
#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
201
#elif defined(_MSC_FULL_VER)
202
#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
203
#elif defined(_MSC_VER)
204
#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
205
#endif
206
207
#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
208
#undef JSON_HEDLEY_MSVC_VERSION_CHECK
209
#endif
210
#if !defined(_MSC_VER)
211
#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
212
#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
213
#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
214
#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
215
#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
216
#else
217
#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
218
#endif
219
220
#if defined(JSON_HEDLEY_INTEL_VERSION)
221
#undef JSON_HEDLEY_INTEL_VERSION
222
#endif
223
#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE)
224
#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
225
#elif defined(__INTEL_COMPILER)
226
#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
227
#endif
228
229
#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
230
#undef JSON_HEDLEY_INTEL_VERSION_CHECK
231
#endif
232
#if defined(JSON_HEDLEY_INTEL_VERSION)
233
#define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
234
#else
235
#define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
236
#endif
237
238
#if defined(JSON_HEDLEY_PGI_VERSION)
239
#undef JSON_HEDLEY_PGI_VERSION
240
#endif
241
#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
242
#define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
243
#endif
244
245
#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
246
#undef JSON_HEDLEY_PGI_VERSION_CHECK
247
#endif
248
#if defined(JSON_HEDLEY_PGI_VERSION)
249
#define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
250
#else
251
#define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
252
#endif
253
254
#if defined(JSON_HEDLEY_SUNPRO_VERSION)
255
#undef JSON_HEDLEY_SUNPRO_VERSION
256
#endif
257
#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
258
#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)
259
#elif defined(__SUNPRO_C)
260
#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
261
#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
262
#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)
263
#elif defined(__SUNPRO_CC)
264
#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
265
#endif
266
267
#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
268
#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
269
#endif
270
#if defined(JSON_HEDLEY_SUNPRO_VERSION)
271
#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
272
#else
273
#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
274
#endif
275
276
#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
277
#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
278
#endif
279
#if defined(__EMSCRIPTEN__)
280
#define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
281
#endif
282
283
#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
284
#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
285
#endif
286
#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
287
#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
288
#else
289
#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
290
#endif
291
292
#if defined(JSON_HEDLEY_ARM_VERSION)
293
#undef JSON_HEDLEY_ARM_VERSION
294
#endif
295
#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
296
#define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
297
#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
298
#define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
299
#endif
300
301
#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
302
#undef JSON_HEDLEY_ARM_VERSION_CHECK
303
#endif
304
#if defined(JSON_HEDLEY_ARM_VERSION)
305
#define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
306
#else
307
#define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
308
#endif
309
310
#if defined(JSON_HEDLEY_IBM_VERSION)
311
#undef JSON_HEDLEY_IBM_VERSION
312
#endif
313
#if defined(__ibmxl__)
314
#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
315
#elif defined(__xlC__) && defined(__xlC_ver__)
316
#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
317
#elif defined(__xlC__)
318
#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
319
#endif
320
321
#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
322
#undef JSON_HEDLEY_IBM_VERSION_CHECK
323
#endif
324
#if defined(JSON_HEDLEY_IBM_VERSION)
325
#define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
326
#else
327
#define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
328
#endif
329
330
#if defined(JSON_HEDLEY_TI_VERSION)
331
#undef JSON_HEDLEY_TI_VERSION
332
#endif
333
#if \
334
defined(__TI_COMPILER_VERSION__) && \
335
( \
336
defined(__TMS470__) || defined(__TI_ARM__) || \
337
defined(__MSP430__) || \
338
defined(__TMS320C2000__) \
339
)
340
#if (__TI_COMPILER_VERSION__ >= 16000000)
341
#define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
342
#endif
343
#endif
344
345
#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
346
#undef JSON_HEDLEY_TI_VERSION_CHECK
347
#endif
348
#if defined(JSON_HEDLEY_TI_VERSION)
349
#define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
350
#else
351
#define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
352
#endif
353
354
#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
355
#undef JSON_HEDLEY_TI_CL2000_VERSION
356
#endif
357
#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
358
#define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
359
#endif
360
361
#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
362
#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
363
#endif
364
#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
365
#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
366
#else
367
#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
368
#endif
369
370
#if defined(JSON_HEDLEY_TI_CL430_VERSION)
371
#undef JSON_HEDLEY_TI_CL430_VERSION
372
#endif
373
#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
374
#define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
375
#endif
376
377
#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
378
#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
379
#endif
380
#if defined(JSON_HEDLEY_TI_CL430_VERSION)
381
#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
382
#else
383
#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
384
#endif
385
386
#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
387
#undef JSON_HEDLEY_TI_ARMCL_VERSION
388
#endif
389
#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
390
#define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
391
#endif
392
393
#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
394
#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
395
#endif
396
#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
397
#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
398
#else
399
#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
400
#endif
401
402
#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
403
#undef JSON_HEDLEY_TI_CL6X_VERSION
404
#endif
405
#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
406
#define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
407
#endif
408
409
#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
410
#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
411
#endif
412
#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
413
#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
414
#else
415
#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
416
#endif
417
418
#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
419
#undef JSON_HEDLEY_TI_CL7X_VERSION
420
#endif
421
#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
422
#define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
423
#endif
424
425
#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
426
#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
427
#endif
428
#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
429
#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
430
#else
431
#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
432
#endif
433
434
#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
435
#undef JSON_HEDLEY_TI_CLPRU_VERSION
436
#endif
437
#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
438
#define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
439
#endif
440
441
#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
442
#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
443
#endif
444
#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
445
#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
446
#else
447
#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
448
#endif
449
450
#if defined(JSON_HEDLEY_CRAY_VERSION)
451
#undef JSON_HEDLEY_CRAY_VERSION
452
#endif
453
#if defined(_CRAYC)
454
#if defined(_RELEASE_PATCHLEVEL)
455
#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
456
#else
457
#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
458
#endif
459
#endif
460
461
#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
462
#undef JSON_HEDLEY_CRAY_VERSION_CHECK
463
#endif
464
#if defined(JSON_HEDLEY_CRAY_VERSION)
465
#define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
466
#else
467
#define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
468
#endif
469
470
#if defined(JSON_HEDLEY_IAR_VERSION)
471
#undef JSON_HEDLEY_IAR_VERSION
472
#endif
473
#if defined(__IAR_SYSTEMS_ICC__)
474
#if __VER__ > 1000
475
#define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
476
#else
477
#define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(VER / 100, __VER__ % 100, 0)
478
#endif
479
#endif
480
481
#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
482
#undef JSON_HEDLEY_IAR_VERSION_CHECK
483
#endif
484
#if defined(JSON_HEDLEY_IAR_VERSION)
485
#define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
486
#else
487
#define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
488
#endif
489
490
#if defined(JSON_HEDLEY_TINYC_VERSION)
491
#undef JSON_HEDLEY_TINYC_VERSION
492
#endif
493
#if defined(__TINYC__)
494
#define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
495
#endif
496
497
#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
498
#undef JSON_HEDLEY_TINYC_VERSION_CHECK
499
#endif
500
#if defined(JSON_HEDLEY_TINYC_VERSION)
501
#define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
502
#else
503
#define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
504
#endif
505
506
#if defined(JSON_HEDLEY_DMC_VERSION)
507
#undef JSON_HEDLEY_DMC_VERSION
508
#endif
509
#if defined(__DMC__)
510
#define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
511
#endif
512
513
#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
514
#undef JSON_HEDLEY_DMC_VERSION_CHECK
515
#endif
516
#if defined(JSON_HEDLEY_DMC_VERSION)
517
#define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
518
#else
519
#define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
520
#endif
521
522
#if defined(JSON_HEDLEY_COMPCERT_VERSION)
523
#undef JSON_HEDLEY_COMPCERT_VERSION
524
#endif
525
#if defined(__COMPCERT_VERSION__)
526
#define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
527
#endif
528
529
#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
530
#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
531
#endif
532
#if defined(JSON_HEDLEY_COMPCERT_VERSION)
533
#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
534
#else
535
#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
536
#endif
537
538
#if defined(JSON_HEDLEY_PELLES_VERSION)
539
#undef JSON_HEDLEY_PELLES_VERSION
540
#endif
541
#if defined(__POCC__)
542
#define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
543
#endif
544
545
#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
546
#undef JSON_HEDLEY_PELLES_VERSION_CHECK
547
#endif
548
#if defined(JSON_HEDLEY_PELLES_VERSION)
549
#define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
550
#else
551
#define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
552
#endif
553
554
#if defined(JSON_HEDLEY_GCC_VERSION)
555
#undef JSON_HEDLEY_GCC_VERSION
556
#endif
557
#if \
558
defined(JSON_HEDLEY_GNUC_VERSION) && \
559
!defined(__clang__) && \
560
!defined(JSON_HEDLEY_INTEL_VERSION) && \
561
!defined(JSON_HEDLEY_PGI_VERSION) && \
562
!defined(JSON_HEDLEY_ARM_VERSION) && \
563
!defined(JSON_HEDLEY_TI_VERSION) && \
564
!defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
565
!defined(JSON_HEDLEY_TI_CL430_VERSION) && \
566
!defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
567
!defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
568
!defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
569
!defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
570
!defined(__COMPCERT__)
571
#define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
572
#endif
573
574
#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
575
#undef JSON_HEDLEY_GCC_VERSION_CHECK
576
#endif
577
#if defined(JSON_HEDLEY_GCC_VERSION)
578
#define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
579
#else
580
#define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
581
#endif
582
583
#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
584
#undef JSON_HEDLEY_HAS_ATTRIBUTE
585
#endif
586
#if defined(__has_attribute)
587
#define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
588
#else
589
#define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
590
#endif
591
592
#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
593
#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
594
#endif
595
#if defined(__has_attribute)
596
#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute)
597
#else
598
#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
599
#endif
600
601
#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
602
#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
603
#endif
604
#if defined(__has_attribute)
605
#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute)
606
#else
607
#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
608
#endif
609
610
#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
611
#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
612
#endif
613
#if \
614
defined(__has_cpp_attribute) && \
615
defined(__cplusplus) && \
616
(!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
617
#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
618
#else
619
#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
620
#endif
621
622
#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
623
#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
624
#endif
625
#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
626
#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
627
#elif \
628
!defined(JSON_HEDLEY_PGI_VERSION) && \
629
!defined(JSON_HEDLEY_IAR_VERSION) && \
630
(!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
631
(!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
632
#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
633
#else
634
#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
635
#endif
636
637
#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
638
#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
639
#endif
640
#if defined(__has_cpp_attribute) && defined(__cplusplus)
641
#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
642
#else
643
#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
644
#endif
645
646
#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
647
#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
648
#endif
649
#if defined(__has_cpp_attribute) && defined(__cplusplus)
650
#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
651
#else
652
#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
653
#endif
654
655
#if defined(JSON_HEDLEY_HAS_BUILTIN)
656
#undef JSON_HEDLEY_HAS_BUILTIN
657
#endif
658
#if defined(__has_builtin)
659
#define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
660
#else
661
#define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
662
#endif
663
664
#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
665
#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
666
#endif
667
#if defined(__has_builtin)
668
#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
669
#else
670
#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
671
#endif
672
673
#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
674
#undef JSON_HEDLEY_GCC_HAS_BUILTIN
675
#endif
676
#if defined(__has_builtin)
677
#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
678
#else
679
#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
680
#endif
681
682
#if defined(JSON_HEDLEY_HAS_FEATURE)
683
#undef JSON_HEDLEY_HAS_FEATURE
684
#endif
685
#if defined(__has_feature)
686
#define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
687
#else
688
#define JSON_HEDLEY_HAS_FEATURE(feature) (0)
689
#endif
690
691
#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
692
#undef JSON_HEDLEY_GNUC_HAS_FEATURE
693
#endif
694
#if defined(__has_feature)
695
#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
696
#else
697
#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
698
#endif
699
700
#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
701
#undef JSON_HEDLEY_GCC_HAS_FEATURE
702
#endif
703
#if defined(__has_feature)
704
#define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
705
#else
706
#define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
707
#endif
708
709
#if defined(JSON_HEDLEY_HAS_EXTENSION)
710
#undef JSON_HEDLEY_HAS_EXTENSION
711
#endif
712
#if defined(__has_extension)
713
#define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
714
#else
715
#define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
716
#endif
717
718
#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
719
#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
720
#endif
721
#if defined(__has_extension)
722
#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
723
#else
724
#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
725
#endif
726
727
#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
728
#undef JSON_HEDLEY_GCC_HAS_EXTENSION
729
#endif
730
#if defined(__has_extension)
731
#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
732
#else
733
#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
734
#endif
735
736
#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
737
#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
738
#endif
739
#if defined(__has_declspec_attribute)
740
#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
741
#else
742
#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
743
#endif
744
745
#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
746
#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
747
#endif
748
#if defined(__has_declspec_attribute)
749
#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
750
#else
751
#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
752
#endif
753
754
#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
755
#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
756
#endif
757
#if defined(__has_declspec_attribute)
758
#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
759
#else
760
#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
761
#endif
762
763
#if defined(JSON_HEDLEY_HAS_WARNING)
764
#undef JSON_HEDLEY_HAS_WARNING
765
#endif
766
#if defined(__has_warning)
767
#define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
768
#else
769
#define JSON_HEDLEY_HAS_WARNING(warning) (0)
770
#endif
771
772
#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
773
#undef JSON_HEDLEY_GNUC_HAS_WARNING
774
#endif
775
#if defined(__has_warning)
776
#define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
777
#else
778
#define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
779
#endif
780
781
#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
782
#undef JSON_HEDLEY_GCC_HAS_WARNING
783
#endif
784
#if defined(__has_warning)
785
#define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
786
#else
787
#define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
788
#endif
789
790
/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
791
HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
792
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
793
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
794
#endif
795
#if defined(__cplusplus)
796
# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
797
# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
798
# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
799
JSON_HEDLEY_DIAGNOSTIC_PUSH \
800
_Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
801
_Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
802
xpr \
803
JSON_HEDLEY_DIAGNOSTIC_POP
804
# else
805
# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
806
JSON_HEDLEY_DIAGNOSTIC_PUSH \
807
_Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
808
xpr \
809
JSON_HEDLEY_DIAGNOSTIC_POP
810
# endif
811
# endif
812
#endif
813
#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
814
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
815
#endif
816
817
#if defined(JSON_HEDLEY_CONST_CAST)
818
#undef JSON_HEDLEY_CONST_CAST
819
#endif
820
#if defined(__cplusplus)
821
# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
822
#elif \
823
JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
824
JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
825
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
826
# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
827
JSON_HEDLEY_DIAGNOSTIC_PUSH \
828
JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
829
((T) (expr)); \
830
JSON_HEDLEY_DIAGNOSTIC_POP \
831
}))
832
#else
833
# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
834
#endif
835
836
#if defined(JSON_HEDLEY_REINTERPRET_CAST)
837
#undef JSON_HEDLEY_REINTERPRET_CAST
838
#endif
839
#if defined(__cplusplus)
840
#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
841
#else
842
#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
843
#endif
844
845
#if defined(JSON_HEDLEY_STATIC_CAST)
846
#undef JSON_HEDLEY_STATIC_CAST
847
#endif
848
#if defined(__cplusplus)
849
#define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
850
#else
851
#define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
852
#endif
853
854
#if defined(JSON_HEDLEY_CPP_CAST)
855
#undef JSON_HEDLEY_CPP_CAST
856
#endif
857
#if defined(__cplusplus)
858
# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
859
# define JSON_HEDLEY_CPP_CAST(T, expr) \
860
JSON_HEDLEY_DIAGNOSTIC_PUSH \
861
_Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
862
((T) (expr)) \
863
JSON_HEDLEY_DIAGNOSTIC_POP
864
# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
865
# define JSON_HEDLEY_CPP_CAST(T, expr) \
866
JSON_HEDLEY_DIAGNOSTIC_PUSH \
867
_Pragma("diag_suppress=Pe137") \
868
JSON_HEDLEY_DIAGNOSTIC_POP \
869
# else
870
# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
871
# endif
872
#else
873
# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
874
#endif
875
876
#if \
877
(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
878
defined(__clang__) || \
879
JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
880
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
881
JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
882
JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
883
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
884
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
885
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
886
JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
887
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
888
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
889
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
890
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
891
JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
892
JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
893
JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
894
(JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
895
#define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
896
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
897
#define JSON_HEDLEY_PRAGMA(value) __pragma(value)
898
#else
899
#define JSON_HEDLEY_PRAGMA(value)
900
#endif
901
902
#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
903
#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
904
#endif
905
#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
906
#undef JSON_HEDLEY_DIAGNOSTIC_POP
907
#endif
908
#if defined(__clang__)
909
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
910
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
911
#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
912
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
913
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
914
#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
915
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
916
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
917
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
918
#define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
919
#define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
920
#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
921
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
922
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
923
#elif \
924
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
925
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
926
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
927
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
928
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
929
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
930
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
931
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
932
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
933
#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
934
#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
935
#else
936
#define JSON_HEDLEY_DIAGNOSTIC_PUSH
937
#define JSON_HEDLEY_DIAGNOSTIC_POP
938
#endif
939
940
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
941
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
942
#endif
943
#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
944
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
945
#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
946
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
947
#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
948
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
949
#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
950
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
951
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
952
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
953
#elif \
954
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
955
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
956
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
957
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
958
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
959
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
960
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
961
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
962
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
963
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
964
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
965
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
966
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
967
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
968
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
969
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
970
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
971
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
972
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
973
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
974
#else
975
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
976
#endif
977
978
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
979
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
980
#endif
981
#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
982
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
983
#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
984
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
985
#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
986
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
987
#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
988
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
989
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
990
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
991
#elif \
992
JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
993
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
994
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
995
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
996
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
997
#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
998
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
999
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1000
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1001
#else
1002
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1003
#endif
1004
1005
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1006
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1007
#endif
1008
#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1009
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1010
#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1011
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1012
#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1013
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1014
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1015
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1016
#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1017
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1018
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1019
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1020
#elif \
1021
JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1022
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1023
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1024
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1025
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1026
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1027
#else
1028
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1029
#endif
1030
1031
#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1032
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1033
#endif
1034
#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1035
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1036
#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1037
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1038
#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1039
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1040
#else
1041
#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1042
#endif
1043
1044
#if defined(JSON_HEDLEY_DEPRECATED)
1045
#undef JSON_HEDLEY_DEPRECATED
1046
#endif
1047
#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1048
#undef JSON_HEDLEY_DEPRECATED_FOR
1049
#endif
1050
#if JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0)
1051
#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1052
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1053
#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1054
#define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1055
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1056
#elif \
1057
JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || \
1058
JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1059
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1060
JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1061
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1062
JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1063
JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1064
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1065
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1066
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1067
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1068
#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1069
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1070
#elif \
1071
JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1072
JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1073
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1074
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1075
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1076
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1077
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1078
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1079
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1080
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1081
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1082
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1083
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1084
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1085
#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1086
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1087
#elif \
1088
JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1089
JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0)
1090
#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1091
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1092
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1093
#define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1094
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1095
#else
1096
#define JSON_HEDLEY_DEPRECATED(since)
1097
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1098
#endif
1099
1100
#if defined(JSON_HEDLEY_UNAVAILABLE)
1101
#undef JSON_HEDLEY_UNAVAILABLE
1102
#endif
1103
#if \
1104
JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1105
JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1106
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1107
#define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1108
#else
1109
#define JSON_HEDLEY_UNAVAILABLE(available_since)
1110
#endif
1111
1112
#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1113
#undef JSON_HEDLEY_WARN_UNUSED_RESULT
1114
#endif
1115
#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1116
#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1117
#endif
1118
#if (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1119
#define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1120
#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1121
#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1122
#define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1123
#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1124
#elif \
1125
JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1126
JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1127
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1128
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1129
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1130
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1131
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1132
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1133
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1134
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1135
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1136
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1137
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1138
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1139
(JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1140
JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1141
#define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1142
#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1143
#elif defined(_Check_return_) /* SAL */
1144
#define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1145
#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1146
#else
1147
#define JSON_HEDLEY_WARN_UNUSED_RESULT
1148
#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1149
#endif
1150
1151
#if defined(JSON_HEDLEY_SENTINEL)
1152
#undef JSON_HEDLEY_SENTINEL
1153
#endif
1154
#if \
1155
JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1156
JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1157
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1158
JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0)
1159
#define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1160
#else
1161
#define JSON_HEDLEY_SENTINEL(position)
1162
#endif
1163
1164
#if defined(JSON_HEDLEY_NO_RETURN)
1165
#undef JSON_HEDLEY_NO_RETURN
1166
#endif
1167
#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1168
#define JSON_HEDLEY_NO_RETURN __noreturn
1169
#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1170
#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1171
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1172
#define JSON_HEDLEY_NO_RETURN _Noreturn
1173
#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1174
#define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1175
#elif \
1176
JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1177
JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1178
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1179
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1180
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1181
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1182
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1183
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1184
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1185
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1186
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1187
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1188
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1189
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1190
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1191
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1192
#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1193
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1194
#define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1195
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0)
1196
#define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1197
#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1198
#define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1199
#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1200
#define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1201
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1202
#define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1203
#else
1204
#define JSON_HEDLEY_NO_RETURN
1205
#endif
1206
1207
#if defined(JSON_HEDLEY_NO_ESCAPE)
1208
#undef JSON_HEDLEY_NO_ESCAPE
1209
#endif
1210
#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1211
#define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1212
#else
1213
#define JSON_HEDLEY_NO_ESCAPE
1214
#endif
1215
1216
#if defined(JSON_HEDLEY_UNREACHABLE)
1217
#undef JSON_HEDLEY_UNREACHABLE
1218
#endif
1219
#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1220
#undef JSON_HEDLEY_UNREACHABLE_RETURN
1221
#endif
1222
#if defined(JSON_HEDLEY_ASSUME)
1223
#undef JSON_HEDLEY_ASSUME
1224
#endif
1225
#if \
1226
JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1227
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1228
#define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1229
#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1230
#define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1231
#elif \
1232
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1233
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1234
#if defined(__cplusplus)
1235
#define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1236
#else
1237
#define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1238
#endif
1239
#endif
1240
#if \
1241
(JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1242
JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1243
JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1244
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1245
JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5)
1246
#define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1247
#elif defined(JSON_HEDLEY_ASSUME)
1248
#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1249
#endif
1250
#if !defined(JSON_HEDLEY_ASSUME)
1251
#if defined(JSON_HEDLEY_UNREACHABLE)
1252
#define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1253
#else
1254
#define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1255
#endif
1256
#endif
1257
#if defined(JSON_HEDLEY_UNREACHABLE)
1258
#if \
1259
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1260
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1261
#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1262
#else
1263
#define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1264
#endif
1265
#else
1266
#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1267
#endif
1268
#if !defined(JSON_HEDLEY_UNREACHABLE)
1269
#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1270
#endif
1271
1272
JSON_HEDLEY_DIAGNOSTIC_PUSH
1273
#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1274
#pragma clang diagnostic ignored "-Wpedantic"
1275
#endif
1276
#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1277
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1278
#endif
1279
#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1280
#if defined(__clang__)
1281
#pragma clang diagnostic ignored "-Wvariadic-macros"
1282
#elif defined(JSON_HEDLEY_GCC_VERSION)
1283
#pragma GCC diagnostic ignored "-Wvariadic-macros"
1284
#endif
1285
#endif
1286
#if defined(JSON_HEDLEY_NON_NULL)
1287
#undef JSON_HEDLEY_NON_NULL
1288
#endif
1289
#if \
1290
JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1291
JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1292
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1293
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1294
#define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1295
#else
1296
#define JSON_HEDLEY_NON_NULL(...)
1297
#endif
1298
JSON_HEDLEY_DIAGNOSTIC_POP
1299
1300
#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1301
#undef JSON_HEDLEY_PRINTF_FORMAT
1302
#endif
1303
#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1304
#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1305
#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1306
#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1307
#elif \
1308
JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1309
JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1310
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1311
JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1312
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1313
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1314
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1315
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1316
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1317
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1318
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1319
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1320
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1321
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1322
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1323
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1324
#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1325
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1326
#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1327
#else
1328
#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1329
#endif
1330
1331
#if defined(JSON_HEDLEY_CONSTEXPR)
1332
#undef JSON_HEDLEY_CONSTEXPR
1333
#endif
1334
#if defined(__cplusplus)
1335
#if __cplusplus >= 201103L
1336
#define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1337
#endif
1338
#endif
1339
#if !defined(JSON_HEDLEY_CONSTEXPR)
1340
#define JSON_HEDLEY_CONSTEXPR
1341
#endif
1342
1343
#if defined(JSON_HEDLEY_PREDICT)
1344
#undef JSON_HEDLEY_PREDICT
1345
#endif
1346
#if defined(JSON_HEDLEY_LIKELY)
1347
#undef JSON_HEDLEY_LIKELY
1348
#endif
1349
#if defined(JSON_HEDLEY_UNLIKELY)
1350
#undef JSON_HEDLEY_UNLIKELY
1351
#endif
1352
#if defined(JSON_HEDLEY_UNPREDICTABLE)
1353
#undef JSON_HEDLEY_UNPREDICTABLE
1354
#endif
1355
#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1356
#define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1357
#endif
1358
#if \
1359
JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) || \
1360
JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0)
1361
# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1362
# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1363
# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1364
# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1365
# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1366
#elif \
1367
JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) || \
1368
JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1369
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1370
(JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1371
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1372
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1373
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1374
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1375
JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1376
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1377
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1378
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1379
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1380
JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1381
JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0)
1382
# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1383
(((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1384
# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1385
(__extension__ ({ \
1386
double hedley_probability_ = (probability); \
1387
((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1388
}))
1389
# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1390
(__extension__ ({ \
1391
double hedley_probability_ = (probability); \
1392
((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1393
}))
1394
# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1395
# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1396
#else
1397
# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1398
# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1399
# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1400
# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1401
# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1402
#endif
1403
#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1404
#define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1405
#endif
1406
1407
#if defined(JSON_HEDLEY_MALLOC)
1408
#undef JSON_HEDLEY_MALLOC
1409
#endif
1410
#if \
1411
JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1412
JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1413
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1414
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1415
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1416
JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1417
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1418
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1419
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1420
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1421
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1422
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1423
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1424
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1425
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1426
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1427
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1428
#define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1429
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1430
#define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1431
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0)
1432
#define JSON_HEDLEY_MALLOC __declspec(restrict)
1433
#else
1434
#define JSON_HEDLEY_MALLOC
1435
#endif
1436
1437
#if defined(JSON_HEDLEY_PURE)
1438
#undef JSON_HEDLEY_PURE
1439
#endif
1440
#if \
1441
JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1442
JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1443
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1444
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1445
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1446
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1447
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1448
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1449
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1450
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1451
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1452
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1453
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1454
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1455
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1456
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1457
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1458
JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1459
# define JSON_HEDLEY_PURE __attribute__((__pure__))
1460
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1461
# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1462
#elif defined(__cplusplus) && \
1463
( \
1464
JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1465
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1466
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1467
)
1468
# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1469
#else
1470
# define JSON_HEDLEY_PURE
1471
#endif
1472
1473
#if defined(JSON_HEDLEY_CONST)
1474
#undef JSON_HEDLEY_CONST
1475
#endif
1476
#if \
1477
JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1478
JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1479
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1480
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1481
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1482
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1483
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1484
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1485
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1486
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1487
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1488
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1489
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1490
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1491
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1492
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1493
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1494
JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1495
#define JSON_HEDLEY_CONST __attribute__((__const__))
1496
#elif \
1497
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1498
#define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1499
#else
1500
#define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1501
#endif
1502
1503
#if defined(JSON_HEDLEY_RESTRICT)
1504
#undef JSON_HEDLEY_RESTRICT
1505
#endif
1506
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1507
#define JSON_HEDLEY_RESTRICT restrict
1508
#elif \
1509
JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1510
JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1511
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1512
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1513
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1514
JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1515
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1516
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1517
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1518
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1519
(JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1520
JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1521
defined(__clang__)
1522
#define JSON_HEDLEY_RESTRICT __restrict
1523
#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1524
#define JSON_HEDLEY_RESTRICT _Restrict
1525
#else
1526
#define JSON_HEDLEY_RESTRICT
1527
#endif
1528
1529
#if defined(JSON_HEDLEY_INLINE)
1530
#undef JSON_HEDLEY_INLINE
1531
#endif
1532
#if \
1533
(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1534
(defined(__cplusplus) && (__cplusplus >= 199711L))
1535
#define JSON_HEDLEY_INLINE inline
1536
#elif \
1537
defined(JSON_HEDLEY_GCC_VERSION) || \
1538
JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1539
#define JSON_HEDLEY_INLINE __inline__
1540
#elif \
1541
JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1542
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1543
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1544
JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1545
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1546
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1547
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1548
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1549
#define JSON_HEDLEY_INLINE __inline
1550
#else
1551
#define JSON_HEDLEY_INLINE
1552
#endif
1553
1554
#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1555
#undef JSON_HEDLEY_ALWAYS_INLINE
1556
#endif
1557
#if \
1558
JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1559
JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1560
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1561
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1562
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1563
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1564
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1565
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1566
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1567
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1568
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1569
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1570
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1571
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1572
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1573
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1574
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1575
# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1576
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0)
1577
# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1578
#elif defined(__cplusplus) && \
1579
( \
1580
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1581
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1582
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1583
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1584
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1585
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1586
)
1587
# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1588
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1589
# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1590
#else
1591
# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1592
#endif
1593
1594
#if defined(JSON_HEDLEY_NEVER_INLINE)
1595
#undef JSON_HEDLEY_NEVER_INLINE
1596
#endif
1597
#if \
1598
JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1599
JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1600
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1601
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1602
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1603
JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1604
JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1605
(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1606
JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1607
(JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1608
JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1609
(JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1610
JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1611
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1612
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1613
JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1614
JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1615
#define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1616
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0)
1617
#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1618
#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1619
#define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1620
#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1621
#define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1622
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1623
#define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1624
#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1625
#define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1626
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1627
#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1628
#else
1629
#define JSON_HEDLEY_NEVER_INLINE
1630
#endif
1631
1632
#if defined(JSON_HEDLEY_PRIVATE)
1633
#undef JSON_HEDLEY_PRIVATE
1634
#endif
1635
#if defined(JSON_HEDLEY_PUBLIC)
1636
#undef JSON_HEDLEY_PUBLIC
1637
#endif
1638
#if defined(JSON_HEDLEY_IMPORT)
1639
#undef JSON_HEDLEY_IMPORT
1640
#endif
1641
#if defined(_WIN32) || defined(__CYGWIN__)
1642
# define JSON_HEDLEY_PRIVATE
1643
# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1644
# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1645
#else
1646
# if \
1647
JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1648
JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1649
JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1650
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1651
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1652
JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1653
( \
1654
defined(__TI_EABI__) && \
1655
( \
1656
(JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1657
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1658
) \
1659
)
1660
# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1661
# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1662
# else
1663
# define JSON_HEDLEY_PRIVATE
1664
# define JSON_HEDLEY_PUBLIC
1665
# endif
1666
# define JSON_HEDLEY_IMPORT extern
1667
#endif
1668
1669
#if defined(JSON_HEDLEY_NO_THROW)
1670
#undef JSON_HEDLEY_NO_THROW
1671
#endif
1672
#if \
1673
JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
1674
JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1675
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1676
#define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
1677
#elif \
1678
JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
1679
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1680
#define JSON_HEDLEY_NO_THROW __declspec(nothrow)
1681
#else
1682
#define JSON_HEDLEY_NO_THROW
1683
#endif
1684
1685
#if defined(JSON_HEDLEY_FALL_THROUGH)
1686
#undef JSON_HEDLEY_FALL_THROUGH
1687
#endif
1688
#if \
1689
JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
1690
JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0)
1691
#define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
1692
#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
1693
#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
1694
#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
1695
#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
1696
#elif defined(__fallthrough) /* SAL */
1697
#define JSON_HEDLEY_FALL_THROUGH __fallthrough
1698
#else
1699
#define JSON_HEDLEY_FALL_THROUGH
1700
#endif
1701
1702
#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
1703
#undef JSON_HEDLEY_RETURNS_NON_NULL
1704
#endif
1705
#if \
1706
JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
1707
JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
1708
#define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
1709
#elif defined(_Ret_notnull_) /* SAL */
1710
#define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
1711
#else
1712
#define JSON_HEDLEY_RETURNS_NON_NULL
1713
#endif
1714
1715
#if defined(JSON_HEDLEY_ARRAY_PARAM)
1716
#undef JSON_HEDLEY_ARRAY_PARAM
1717
#endif
1718
#if \
1719
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
1720
!defined(__STDC_NO_VLA__) && \
1721
!defined(__cplusplus) && \
1722
!defined(JSON_HEDLEY_PGI_VERSION) && \
1723
!defined(JSON_HEDLEY_TINYC_VERSION)
1724
#define JSON_HEDLEY_ARRAY_PARAM(name) (name)
1725
#else
1726
#define JSON_HEDLEY_ARRAY_PARAM(name)
1727
#endif
1728
1729
#if defined(JSON_HEDLEY_IS_CONSTANT)
1730
#undef JSON_HEDLEY_IS_CONSTANT
1731
#endif
1732
#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
1733
#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
1734
#endif
1735
/* JSON_HEDLEY_IS_CONSTEXPR_ is for
1736
HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1737
#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1738
#undef JSON_HEDLEY_IS_CONSTEXPR_
1739
#endif
1740
#if \
1741
JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
1742
JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1743
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1744
JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
1745
JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1746
JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1747
JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1748
(JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
1749
JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0)
1750
#define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
1751
#endif
1752
#if !defined(__cplusplus)
1753
# if \
1754
JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
1755
JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1756
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1757
JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1758
JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1759
JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1760
JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
1761
#if defined(__INTPTR_TYPE__)
1762
#define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
1763
#else
1764
#include <stdint.h>
1765
#define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
1766
#endif
1767
# elif \
1768
( \
1769
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
1770
!defined(JSON_HEDLEY_SUNPRO_VERSION) && \
1771
!defined(JSON_HEDLEY_PGI_VERSION) && \
1772
!defined(JSON_HEDLEY_IAR_VERSION)) || \
1773
JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) || \
1774
JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
1775
JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
1776
JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1777
JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
1778
#if defined(__INTPTR_TYPE__)
1779
#define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
1780
#else
1781
#include <stdint.h>
1782
#define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
1783
#endif
1784
# elif \
1785
defined(JSON_HEDLEY_GCC_VERSION) || \
1786
defined(JSON_HEDLEY_INTEL_VERSION) || \
1787
defined(JSON_HEDLEY_TINYC_VERSION) || \
1788
defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
1789
JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
1790
defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
1791
defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
1792
defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
1793
defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
1794
defined(__clang__)
1795
# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
1796
sizeof(void) != \
1797
sizeof(*( \
1798
1 ? \
1799
((void*) ((expr) * 0L) ) : \
1800
((struct { char v[sizeof(void) * 2]; } *) 1) \
1801
) \
1802
) \
1803
)
1804
# endif
1805
#endif
1806
#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1807
#if !defined(JSON_HEDLEY_IS_CONSTANT)
1808
#define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
1809
#endif
1810
#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
1811
#else
1812
#if !defined(JSON_HEDLEY_IS_CONSTANT)
1813
#define JSON_HEDLEY_IS_CONSTANT(expr) (0)
1814
#endif
1815
#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
1816
#endif
1817
1818
#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
1819
#undef JSON_HEDLEY_BEGIN_C_DECLS
1820
#endif
1821
#if defined(JSON_HEDLEY_END_C_DECLS)
1822
#undef JSON_HEDLEY_END_C_DECLS
1823
#endif
1824
#if defined(JSON_HEDLEY_C_DECL)
1825
#undef JSON_HEDLEY_C_DECL
1826
#endif
1827
#if defined(__cplusplus)
1828
#define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
1829
#define JSON_HEDLEY_END_C_DECLS }
1830
#define JSON_HEDLEY_C_DECL extern "C"
1831
#else
1832
#define JSON_HEDLEY_BEGIN_C_DECLS
1833
#define JSON_HEDLEY_END_C_DECLS
1834
#define JSON_HEDLEY_C_DECL
1835
#endif
1836
1837
#if defined(JSON_HEDLEY_STATIC_ASSERT)
1838
#undef JSON_HEDLEY_STATIC_ASSERT
1839
#endif
1840
#if \
1841
!defined(__cplusplus) && ( \
1842
(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
1843
JSON_HEDLEY_HAS_FEATURE(c_static_assert) || \
1844
JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
1845
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1846
defined(_Static_assert) \
1847
)
1848
# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
1849
#elif \
1850
(defined(__cplusplus) && (__cplusplus >= 201103L)) || \
1851
JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0)
1852
# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
1853
#else
1854
# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
1855
#endif
1856
1857
#if defined(JSON_HEDLEY_NULL)
1858
#undef JSON_HEDLEY_NULL
1859
#endif
1860
#if defined(__cplusplus)
1861
#if __cplusplus >= 201103L
1862
#define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
1863
#elif defined(NULL)
1864
#define JSON_HEDLEY_NULL NULL
1865
#else
1866
#define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
1867
#endif
1868
#elif defined(NULL)
1869
#define JSON_HEDLEY_NULL NULL
1870
#else
1871
#define JSON_HEDLEY_NULL ((void*) 0)
1872
#endif
1873
1874
#if defined(JSON_HEDLEY_MESSAGE)
1875
#undef JSON_HEDLEY_MESSAGE
1876
#endif
1877
#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1878
# define JSON_HEDLEY_MESSAGE(msg) \
1879
JSON_HEDLEY_DIAGNOSTIC_PUSH \
1880
JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
1881
JSON_HEDLEY_PRAGMA(message msg) \
1882
JSON_HEDLEY_DIAGNOSTIC_POP
1883
#elif \
1884
JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
1885
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1886
# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
1887
#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
1888
# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
1889
#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1890
# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
1891
#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
1892
# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
1893
#else
1894
# define JSON_HEDLEY_MESSAGE(msg)
1895
#endif
1896
1897
#if defined(JSON_HEDLEY_WARNING)
1898
#undef JSON_HEDLEY_WARNING
1899
#endif
1900
#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1901
# define JSON_HEDLEY_WARNING(msg) \
1902
JSON_HEDLEY_DIAGNOSTIC_PUSH \
1903
JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
1904
JSON_HEDLEY_PRAGMA(clang warning msg) \
1905
JSON_HEDLEY_DIAGNOSTIC_POP
1906
#elif \
1907
JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
1908
JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1909
JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1910
# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
1911
#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1912
# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
1913
#else
1914
# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
1915
#endif
1916
1917
#if defined(JSON_HEDLEY_REQUIRE)
1918
#undef JSON_HEDLEY_REQUIRE
1919
#endif
1920
#if defined(JSON_HEDLEY_REQUIRE_MSG)
1921
#undef JSON_HEDLEY_REQUIRE_MSG
1922
#endif
1923
#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
1924
# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
1925
# define JSON_HEDLEY_REQUIRE(expr) \
1926
JSON_HEDLEY_DIAGNOSTIC_PUSH \
1927
_Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
1928
__attribute__((diagnose_if(!(expr), #expr, "error"))) \
1929
JSON_HEDLEY_DIAGNOSTIC_POP
1930
# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
1931
JSON_HEDLEY_DIAGNOSTIC_PUSH \
1932
_Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
1933
__attribute__((diagnose_if(!(expr), msg, "error"))) \
1934
JSON_HEDLEY_DIAGNOSTIC_POP
1935
# else
1936
# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
1937
# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
1938
# endif
1939
#else
1940
# define JSON_HEDLEY_REQUIRE(expr)
1941
# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
1942
#endif
1943
1944
#if defined(JSON_HEDLEY_FLAGS)
1945
#undef JSON_HEDLEY_FLAGS
1946
#endif
1947
#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum)
1948
#define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
1949
#endif
1950
1951
#if defined(JSON_HEDLEY_FLAGS_CAST)
1952
#undef JSON_HEDLEY_FLAGS_CAST
1953
#endif
1954
#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
1955
# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
1956
JSON_HEDLEY_DIAGNOSTIC_PUSH \
1957
_Pragma("warning(disable:188)") \
1958
((T) (expr)); \
1959
JSON_HEDLEY_DIAGNOSTIC_POP \
1960
}))
1961
#else
1962
# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
1963
#endif
1964
1965
#if defined(JSON_HEDLEY_EMPTY_BASES)
1966
#undef JSON_HEDLEY_EMPTY_BASES
1967
#endif
1968
#if JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)
1969
#define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
1970
#else
1971
#define JSON_HEDLEY_EMPTY_BASES
1972
#endif
1973
1974
/* Remaining macros are deprecated. */
1975
1976
#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
1977
#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
1978
#endif
1979
#if defined(__clang__)
1980
#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
1981
#else
1982
#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1983
#endif
1984
1985
#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
1986
#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
1987
#endif
1988
#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
1989
1990
#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
1991
#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
1992
#endif
1993
#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
1994
1995
#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
1996
#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
1997
#endif
1998
#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
1999
2000
#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2001
#undef JSON_HEDLEY_CLANG_HAS_FEATURE
2002
#endif
2003
#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2004
2005
#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2006
#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2007
#endif
2008
#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2009
2010
#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2011
#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2012
#endif
2013
#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2014
2015
#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2016
#undef JSON_HEDLEY_CLANG_HAS_WARNING
2017
#endif
2018
#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2019
2020
#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2021
2022
2023
// This file contains all internal macro definitions
2024
// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2025
2026
// exclude unsupported compilers
2027
#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2028
#if defined(__clang__)
2029
#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2030
#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2031
#endif
2032
#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2033
#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2034
#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2035
#endif
2036
#endif
2037
#endif
2038
2039
// C++ language standard detection
2040
#if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2041
#define JSON_HAS_CPP_20
2042
#define JSON_HAS_CPP_17
2043
#define JSON_HAS_CPP_14
2044
#elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2045
#define JSON_HAS_CPP_17
2046
#define JSON_HAS_CPP_14
2047
#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2048
#define JSON_HAS_CPP_14
2049
#endif
2050
2051
// disable float-equal warnings on GCC/clang
2052
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
2053
#pragma GCC diagnostic push
2054
#pragma GCC diagnostic ignored "-Wfloat-equal"
2055
#endif
2056
2057
// disable documentation warnings on clang
2058
#if defined(__clang__)
2059
#pragma GCC diagnostic push
2060
#pragma GCC diagnostic ignored "-Wdocumentation"
2061
#endif
2062
2063
// allow to disable exceptions
2064
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2065
#define JSON_THROW(exception) throw exception
2066
#define JSON_TRY try
2067
#define JSON_CATCH(exception) catch(exception)
2068
#define JSON_INTERNAL_CATCH(exception) catch(exception)
2069
#else
2070
#include <cstdlib>
2071
#define JSON_THROW(exception) std::abort()
2072
#define JSON_TRY if(true)
2073
#define JSON_CATCH(exception) if(false)
2074
#define JSON_INTERNAL_CATCH(exception) if(false)
2075
#endif
2076
2077
// override exception macros
2078
#if defined(JSON_THROW_USER)
2079
#undef JSON_THROW
2080
#define JSON_THROW JSON_THROW_USER
2081
#endif
2082
#if defined(JSON_TRY_USER)
2083
#undef JSON_TRY
2084
#define JSON_TRY JSON_TRY_USER
2085
#endif
2086
#if defined(JSON_CATCH_USER)
2087
#undef JSON_CATCH
2088
#define JSON_CATCH JSON_CATCH_USER
2089
#undef JSON_INTERNAL_CATCH
2090
#define JSON_INTERNAL_CATCH JSON_CATCH_USER
2091
#endif
2092
#if defined(JSON_INTERNAL_CATCH_USER)
2093
#undef JSON_INTERNAL_CATCH
2094
#define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2095
#endif
2096
2097
// allow to override assert
2098
#if !defined(JSON_ASSERT)
2099
#include <cassert> // assert
2100
#define JSON_ASSERT(x) assert(x)
2101
#endif
2102
2103
/*!
2104
@brief macro to briefly define a mapping between an enum and JSON
2105
@def NLOHMANN_JSON_SERIALIZE_ENUM
2106
@since version 3.4.0
2107
*/
2108
#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2109
template<typename BasicJsonType> \
2110
inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2111
{ \
2112
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2113
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2114
auto it = std::find_if(std::begin(m), std::end(m), \
2115
[e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2116
{ \
2117
return ej_pair.first == e; \
2118
}); \
2119
j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2120
} \
2121
template<typename BasicJsonType> \
2122
inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2123
{ \
2124
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2125
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2126
auto it = std::find_if(std::begin(m), std::end(m), \
2127
[&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2128
{ \
2129
return ej_pair.second == j; \
2130
}); \
2131
e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2132
}
2133
2134
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2135
// may be removed in the future once the class is split.
2136
2137
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2138
template<template<typename, typename, typename...> class ObjectType, \
2139
template<typename, typename...> class ArrayType, \
2140
class StringType, class BooleanType, class NumberIntegerType, \
2141
class NumberUnsignedType, class NumberFloatType, \
2142
template<typename> class AllocatorType, \
2143
template<typename, typename = void> class JSONSerializer, \
2144
class BinaryType>
2145
2146
#define NLOHMANN_BASIC_JSON_TPL \
2147
basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2148
NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2149
AllocatorType, JSONSerializer, BinaryType>
2150
2151
// Macros to simplify conversion from/to types
2152
2153
#define NLOHMANN_JSON_EXPAND( x ) x
2154
#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
2155
#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2156
NLOHMANN_JSON_PASTE64, \
2157
NLOHMANN_JSON_PASTE63, \
2158
NLOHMANN_JSON_PASTE62, \
2159
NLOHMANN_JSON_PASTE61, \
2160
NLOHMANN_JSON_PASTE60, \
2161
NLOHMANN_JSON_PASTE59, \
2162
NLOHMANN_JSON_PASTE58, \
2163
NLOHMANN_JSON_PASTE57, \
2164
NLOHMANN_JSON_PASTE56, \
2165
NLOHMANN_JSON_PASTE55, \
2166
NLOHMANN_JSON_PASTE54, \
2167
NLOHMANN_JSON_PASTE53, \
2168
NLOHMANN_JSON_PASTE52, \
2169
NLOHMANN_JSON_PASTE51, \
2170
NLOHMANN_JSON_PASTE50, \
2171
NLOHMANN_JSON_PASTE49, \
2172
NLOHMANN_JSON_PASTE48, \
2173
NLOHMANN_JSON_PASTE47, \
2174
NLOHMANN_JSON_PASTE46, \
2175
NLOHMANN_JSON_PASTE45, \
2176
NLOHMANN_JSON_PASTE44, \
2177
NLOHMANN_JSON_PASTE43, \
2178
NLOHMANN_JSON_PASTE42, \
2179
NLOHMANN_JSON_PASTE41, \
2180
NLOHMANN_JSON_PASTE40, \
2181
NLOHMANN_JSON_PASTE39, \
2182
NLOHMANN_JSON_PASTE38, \
2183
NLOHMANN_JSON_PASTE37, \
2184
NLOHMANN_JSON_PASTE36, \
2185
NLOHMANN_JSON_PASTE35, \
2186
NLOHMANN_JSON_PASTE34, \
2187
NLOHMANN_JSON_PASTE33, \
2188
NLOHMANN_JSON_PASTE32, \
2189
NLOHMANN_JSON_PASTE31, \
2190
NLOHMANN_JSON_PASTE30, \
2191
NLOHMANN_JSON_PASTE29, \
2192
NLOHMANN_JSON_PASTE28, \
2193
NLOHMANN_JSON_PASTE27, \
2194
NLOHMANN_JSON_PASTE26, \
2195
NLOHMANN_JSON_PASTE25, \
2196
NLOHMANN_JSON_PASTE24, \
2197
NLOHMANN_JSON_PASTE23, \
2198
NLOHMANN_JSON_PASTE22, \
2199
NLOHMANN_JSON_PASTE21, \
2200
NLOHMANN_JSON_PASTE20, \
2201
NLOHMANN_JSON_PASTE19, \
2202
NLOHMANN_JSON_PASTE18, \
2203
NLOHMANN_JSON_PASTE17, \
2204
NLOHMANN_JSON_PASTE16, \
2205
NLOHMANN_JSON_PASTE15, \
2206
NLOHMANN_JSON_PASTE14, \
2207
NLOHMANN_JSON_PASTE13, \
2208
NLOHMANN_JSON_PASTE12, \
2209
NLOHMANN_JSON_PASTE11, \
2210
NLOHMANN_JSON_PASTE10, \
2211
NLOHMANN_JSON_PASTE9, \
2212
NLOHMANN_JSON_PASTE8, \
2213
NLOHMANN_JSON_PASTE7, \
2214
NLOHMANN_JSON_PASTE6, \
2215
NLOHMANN_JSON_PASTE5, \
2216
NLOHMANN_JSON_PASTE4, \
2217
NLOHMANN_JSON_PASTE3, \
2218
NLOHMANN_JSON_PASTE2, \
2219
NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2220
#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2221
#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2222
#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2223
#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2224
#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2225
#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)
2226
#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)
2227
#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)
2228
#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)
2229
#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)
2230
#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)
2231
#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)
2232
#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)
2233
#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)
2234
#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)
2235
#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)
2236
#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)
2237
#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)
2238
#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)
2239
#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)
2240
#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)
2241
#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)
2242
#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)
2243
#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)
2244
#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)
2245
#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)
2246
#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)
2247
#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)
2248
#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)
2249
#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)
2250
#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)
2251
#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)
2252
#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)
2253
#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)
2254
#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)
2255
#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)
2256
#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)
2257
#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)
2258
#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)
2259
#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)
2260
#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)
2261
#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)
2262
#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)
2263
#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)
2264
#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)
2265
#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)
2266
#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)
2267
#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)
2268
#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)
2269
#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)
2270
#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)
2271
#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)
2272
#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)
2273
#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)
2274
#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)
2275
#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)
2276
#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)
2277
#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)
2278
#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)
2279
#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)
2280
#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)
2281
#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)
2282
#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)
2283
2284
#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2285
#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2286
2287
/*!
2288
@brief macro
2289
@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
2290
@since version 3.9.0
2291
*/
2292
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2293
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__)) } \
2294
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__)) }
2295
2296
/*!
2297
@brief macro
2298
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
2299
@since version 3.9.0
2300
*/
2301
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2302
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__)) } \
2303
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__)) }
2304
2305
#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2306
#define JSON_USE_IMPLICIT_CONVERSIONS 1
2307
#endif
2308
2309
#if JSON_USE_IMPLICIT_CONVERSIONS
2310
#define JSON_EXPLICIT
2311
#else
2312
#define JSON_EXPLICIT explicit
2313
#endif
2314
2315
2316
namespace nlohmann
2317
{
2318
namespace detail
2319
{
2320
////////////////
2321
// exceptions //
2322
////////////////
2323
2324
/*!
2325
@brief general exception of the @ref basic_json class
2326
2327
This class is an extension of `std::exception` objects with a member @a id for
2328
exception ids. It is used as the base class for all exceptions thrown by the
2329
@ref basic_json class. This class can hence be used as "wildcard" to catch
2330
exceptions.
2331
2332
Subclasses:
2333
- @ref parse_error for exceptions indicating a parse error
2334
- @ref invalid_iterator for exceptions indicating errors with iterators
2335
- @ref type_error for exceptions indicating executing a member function with
2336
a wrong type
2337
- @ref out_of_range for exceptions indicating access out of the defined range
2338
- @ref other_error for exceptions indicating other library errors
2339
2340
@internal
2341
@note To have nothrow-copy-constructible exceptions, we internally use
2342
`std::runtime_error` which can cope with arbitrary-length error messages.
2343
Intermediate strings are built with static functions and then passed to
2344
the actual constructor.
2345
@endinternal
2346
2347
@liveexample{The following code shows how arbitrary library exceptions can be
2348
caught.,exception}
2349
2350
@since version 3.0.0
2351
*/
2352
class exception : public std::exception
2353
{
2354
public:
2355
/// returns the explanatory string
2356
JSON_HEDLEY_RETURNS_NON_NULL
2357
const char* what() const noexcept override
2358
{
2359
return m.what();
2360
}
2361
2362
/// the id of the exception
2363
const int id;
2364
2365
protected:
2366
JSON_HEDLEY_NON_NULL(3)
2367
exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
2368
2369
static std::string name(const std::string& ename, int id_)
2370
{
2371
return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
2372
}
2373
2374
private:
2375
/// an exception object as storage for error messages
2376
std::runtime_error m;
2377
};
2378
2379
/*!
2380
@brief exception indicating a parse error
2381
2382
This exception is thrown by the library when a parse error occurs. Parse errors
2383
can occur during the deserialization of JSON text, CBOR, MessagePack, as well
2384
as when using JSON Patch.
2385
2386
Member @a byte holds the byte index of the last read character in the input
2387
file.
2388
2389
Exceptions have ids 1xx.
2390
2391
name / id | example message | description
2392
------------------------------ | --------------- | -------------------------
2393
json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.
2394
json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.
2395
json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.
2396
json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects.
2397
json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors.
2398
json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`.
2399
json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.
2400
json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
2401
json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.
2402
json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.
2403
json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
2404
json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
2405
json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet).
2406
json.exception.parse_error.115 | parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A | A UBJSON high-precision number could not be parsed.
2407
2408
@note For an input with n bytes, 1 is the index of the first character and n+1
2409
is the index of the terminating null byte or the end of file. This also
2410
holds true when reading a byte vector (CBOR or MessagePack).
2411
2412
@liveexample{The following code shows how a `parse_error` exception can be
2413
caught.,parse_error}
2414
2415
@sa - @ref exception for the base class of the library exceptions
2416
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
2417
@sa - @ref type_error for exceptions indicating executing a member function with
2418
a wrong type
2419
@sa - @ref out_of_range for exceptions indicating access out of the defined range
2420
@sa - @ref other_error for exceptions indicating other library errors
2421
2422
@since version 3.0.0
2423
*/
2424
class parse_error : public exception
2425
{
2426
public:
2427
/*!
2428
@brief create a parse error exception
2429
@param[in] id_ the id of the exception
2430
@param[in] pos the position where the error occurred (or with
2431
chars_read_total=0 if the position cannot be
2432
determined)
2433
@param[in] what_arg the explanatory string
2434
@return parse_error object
2435
*/
2436
static parse_error create(int id_, const position_t& pos, const std::string& what_arg)
2437
{
2438
std::string w = exception::name("parse_error", id_) + "parse error" +
2439
position_string(pos) + ": " + what_arg;
2440
return parse_error(id_, pos.chars_read_total, w.c_str());
2441
}
2442
2443
static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)
2444
{
2445
std::string w = exception::name("parse_error", id_) + "parse error" +
2446
(byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
2447
": " + what_arg;
2448
return parse_error(id_, byte_, w.c_str());
2449
}
2450
2451
/*!
2452
@brief byte index of the parse error
2453
2454
The byte index of the last read character in the input file.
2455
2456
@note For an input with n bytes, 1 is the index of the first character and
2457
n+1 is the index of the terminating null byte or the end of file.
2458
This also holds true when reading a byte vector (CBOR or MessagePack).
2459
*/
2460
const std::size_t byte;
2461
2462
private:
2463
parse_error(int id_, std::size_t byte_, const char* what_arg)
2464
: exception(id_, what_arg), byte(byte_) {}
2465
2466
static std::string position_string(const position_t& pos)
2467
{
2468
return " at line " + std::to_string(pos.lines_read + 1) +
2469
", column " + std::to_string(pos.chars_read_current_line);
2470
}
2471
};
2472
2473
/*!
2474
@brief exception indicating errors with iterators
2475
2476
This exception is thrown if iterators passed to a library function do not match
2477
the expected semantics.
2478
2479
Exceptions have ids 2xx.
2480
2481
name / id | example message | description
2482
----------------------------------- | --------------- | -------------------------
2483
json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
2484
json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
2485
json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.
2486
json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.
2487
json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.
2488
json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.
2489
json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.
2490
json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
2491
json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
2492
json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
2493
json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to.
2494
json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container.
2495
json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered.
2496
json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().
2497
2498
@liveexample{The following code shows how an `invalid_iterator` exception can be
2499
caught.,invalid_iterator}
2500
2501
@sa - @ref exception for the base class of the library exceptions
2502
@sa - @ref parse_error for exceptions indicating a parse error
2503
@sa - @ref type_error for exceptions indicating executing a member function with
2504
a wrong type
2505
@sa - @ref out_of_range for exceptions indicating access out of the defined range
2506
@sa - @ref other_error for exceptions indicating other library errors
2507
2508
@since version 3.0.0
2509
*/
2510
class invalid_iterator : public exception
2511
{
2512
public:
2513
static invalid_iterator create(int id_, const std::string& what_arg)
2514
{
2515
std::string w = exception::name("invalid_iterator", id_) + what_arg;
2516
return invalid_iterator(id_, w.c_str());
2517
}
2518
2519
private:
2520
JSON_HEDLEY_NON_NULL(3)
2521
invalid_iterator(int id_, const char* what_arg)
2522
: exception(id_, what_arg) {}
2523
};
2524
2525
/*!
2526
@brief exception indicating executing a member function with a wrong type
2527
2528
This exception is thrown in case of a type error; that is, a library function is
2529
executed on a JSON value whose type does not match the expected semantics.
2530
2531
Exceptions have ids 3xx.
2532
2533
name / id | example message | description
2534
----------------------------- | --------------- | -------------------------
2535
json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
2536
json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
2537
json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &.
2538
json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
2539
json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
2540
json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
2541
json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.
2542
json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.
2543
json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.
2544
json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.
2545
json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types.
2546
json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.
2547
json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.
2548
json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.
2549
json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.
2550
json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. |
2551
json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) |
2552
2553
@liveexample{The following code shows how a `type_error` exception can be
2554
caught.,type_error}
2555
2556
@sa - @ref exception for the base class of the library exceptions
2557
@sa - @ref parse_error for exceptions indicating a parse error
2558
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
2559
@sa - @ref out_of_range for exceptions indicating access out of the defined range
2560
@sa - @ref other_error for exceptions indicating other library errors
2561
2562
@since version 3.0.0
2563
*/
2564
class type_error : public exception
2565
{
2566
public:
2567
static type_error create(int id_, const std::string& what_arg)
2568
{
2569
std::string w = exception::name("type_error", id_) + what_arg;
2570
return type_error(id_, w.c_str());
2571
}
2572
2573
private:
2574
JSON_HEDLEY_NON_NULL(3)
2575
type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
2576
};
2577
2578
/*!
2579
@brief exception indicating access out of the defined range
2580
2581
This exception is thrown in case a library function is called on an input
2582
parameter that exceeds the expected range, for instance in case of array
2583
indices or nonexisting object keys.
2584
2585
Exceptions have ids 4xx.
2586
2587
name / id | example message | description
2588
------------------------------- | --------------- | -------------------------
2589
json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.
2590
json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.
2591
json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.
2592
json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
2593
json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
2594
json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
2595
json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. (until version 3.8.0) |
2596
json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
2597
json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |
2598
2599
@liveexample{The following code shows how an `out_of_range` exception can be
2600
caught.,out_of_range}
2601
2602
@sa - @ref exception for the base class of the library exceptions
2603
@sa - @ref parse_error for exceptions indicating a parse error
2604
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
2605
@sa - @ref type_error for exceptions indicating executing a member function with
2606
a wrong type
2607
@sa - @ref other_error for exceptions indicating other library errors
2608
2609
@since version 3.0.0
2610
*/
2611
class out_of_range : public exception
2612
{
2613
public:
2614
static out_of_range create(int id_, const std::string& what_arg)
2615
{
2616
std::string w = exception::name("out_of_range", id_) + what_arg;
2617
return out_of_range(id_, w.c_str());
2618
}
2619
2620
private:
2621
JSON_HEDLEY_NON_NULL(3)
2622
out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
2623
};
2624
2625
/*!
2626
@brief exception indicating other library errors
2627
2628
This exception is thrown in case of errors that cannot be classified with the
2629
other exception types.
2630
2631
Exceptions have ids 5xx.
2632
2633
name / id | example message | description
2634
------------------------------ | --------------- | -------------------------
2635
json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
2636
2637
@sa - @ref exception for the base class of the library exceptions
2638
@sa - @ref parse_error for exceptions indicating a parse error
2639
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
2640
@sa - @ref type_error for exceptions indicating executing a member function with
2641
a wrong type
2642
@sa - @ref out_of_range for exceptions indicating access out of the defined range
2643
2644
@liveexample{The following code shows how an `other_error` exception can be
2645
caught.,other_error}
2646
2647
@since version 3.0.0
2648
*/
2649
class other_error : public exception
2650
{
2651
public:
2652
static other_error create(int id_, const std::string& what_arg)
2653
{
2654
std::string w = exception::name("other_error", id_) + what_arg;
2655
return other_error(id_, w.c_str());
2656
}
2657
2658
private:
2659
JSON_HEDLEY_NON_NULL(3)
2660
other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
2661
};
2662
} // namespace detail
2663
} // namespace nlohmann
2664
2665
// #include <nlohmann/detail/macro_scope.hpp>
2666
2667
// #include <nlohmann/detail/meta/cpp_future.hpp>
2668
2669
2670
#include <cstddef> // size_t
2671
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
2672
2673
namespace nlohmann
2674
{
2675
namespace detail
2676
{
2677
// alias templates to reduce boilerplate
2678
template<bool B, typename T = void>
2679
using enable_if_t = typename std::enable_if<B, T>::type;
2680
2681
template<typename T>
2682
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
2683
2684
// implementation of C++14 index_sequence and affiliates
2685
// source: https://stackoverflow.com/a/32223343
2686
template<std::size_t... Ints>
2687
struct index_sequence
2688
{
2689
using type = index_sequence;
2690
using value_type = std::size_t;
2691
static constexpr std::size_t size() noexcept
2692
{
2693
return sizeof...(Ints);
2694
}
2695
};
2696
2697
template<class Sequence1, class Sequence2>
2698
struct merge_and_renumber;
2699
2700
template<std::size_t... I1, std::size_t... I2>
2701
struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
2702
: index_sequence < I1..., (sizeof...(I1) + I2)... > {};
2703
2704
template<std::size_t N>
2705
struct make_index_sequence
2706
: merge_and_renumber < typename make_index_sequence < N / 2 >::type,
2707
typename make_index_sequence < N - N / 2 >::type > {};
2708
2709
template<> struct make_index_sequence<0> : index_sequence<> {};
2710
template<> struct make_index_sequence<1> : index_sequence<0> {};
2711
2712
template<typename... Ts>
2713
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
2714
2715
// dispatch utility (taken from ranges-v3)
2716
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
2717
template<> struct priority_tag<0> {};
2718
2719
// taken from ranges-v3
2720
template<typename T>
2721
struct static_const
2722
{
2723
static constexpr T value{};
2724
};
2725
2726
template<typename T>
2727
constexpr T static_const<T>::value;
2728
} // namespace detail
2729
} // namespace nlohmann
2730
2731
// #include <nlohmann/detail/meta/type_traits.hpp>
2732
2733
2734
#include <limits> // numeric_limits
2735
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
2736
#include <utility> // declval
2737
2738
// #include <nlohmann/detail/iterators/iterator_traits.hpp>
2739
2740
2741
#include <iterator> // random_access_iterator_tag
2742
2743
// #include <nlohmann/detail/meta/void_t.hpp>
2744
2745
2746
namespace nlohmann
2747
{
2748
namespace detail
2749
{
2750
template<typename ...Ts> struct make_void
2751
{
2752
using type = void;
2753
};
2754
template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
2755
} // namespace detail
2756
} // namespace nlohmann
2757
2758
// #include <nlohmann/detail/meta/cpp_future.hpp>
2759
2760
2761
namespace nlohmann
2762
{
2763
namespace detail
2764
{
2765
template<typename It, typename = void>
2766
struct iterator_types {};
2767
2768
template<typename It>
2769
struct iterator_types <
2770
It,
2771
void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
2772
typename It::reference, typename It::iterator_category >>
2773
{
2774
using difference_type = typename It::difference_type;
2775
using value_type = typename It::value_type;
2776
using pointer = typename It::pointer;
2777
using reference = typename It::reference;
2778
using iterator_category = typename It::iterator_category;
2779
};
2780
2781
// This is required as some compilers implement std::iterator_traits in a way that
2782
// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
2783
template<typename T, typename = void>
2784
struct iterator_traits
2785
{
2786
};
2787
2788
template<typename T>
2789
struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
2790
: iterator_types<T>
2791
{
2792
};
2793
2794
template<typename T>
2795
struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
2796
{
2797
using iterator_category = std::random_access_iterator_tag;
2798
using value_type = T;
2799
using difference_type = ptrdiff_t;
2800
using pointer = T*;
2801
using reference = T&;
2802
};
2803
} // namespace detail
2804
} // namespace nlohmann
2805
2806
// #include <nlohmann/detail/macro_scope.hpp>
2807
2808
// #include <nlohmann/detail/meta/cpp_future.hpp>
2809
2810
// #include <nlohmann/detail/meta/detected.hpp>
2811
2812
2813
#include <type_traits>
2814
2815
// #include <nlohmann/detail/meta/void_t.hpp>
2816
2817
2818
// https://en.cppreference.com/w/cpp/experimental/is_detected
2819
namespace nlohmann
2820
{
2821
namespace detail
2822
{
2823
struct nonesuch
2824
{
2825
nonesuch() = delete;
2826
~nonesuch() = delete;
2827
nonesuch(nonesuch const&) = delete;
2828
nonesuch(nonesuch const&&) = delete;
2829
void operator=(nonesuch const&) = delete;
2830
void operator=(nonesuch&&) = delete;
2831
};
2832
2833
template<class Default,
2834
class AlwaysVoid,
2835
template<class...> class Op,
2836
class... Args>
2837
struct detector
2838
{
2839
using value_t = std::false_type;
2840
using type = Default;
2841
};
2842
2843
template<class Default, template<class...> class Op, class... Args>
2844
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
2845
{
2846
using value_t = std::true_type;
2847
using type = Op<Args...>;
2848
};
2849
2850
template<template<class...> class Op, class... Args>
2851
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
2852
2853
template<template<class...> class Op, class... Args>
2854
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
2855
2856
template<class Default, template<class...> class Op, class... Args>
2857
using detected_or = detector<Default, void, Op, Args...>;
2858
2859
template<class Default, template<class...> class Op, class... Args>
2860
using detected_or_t = typename detected_or<Default, Op, Args...>::type;
2861
2862
template<class Expected, template<class...> class Op, class... Args>
2863
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
2864
2865
template<class To, template<class...> class Op, class... Args>
2866
using is_detected_convertible =
2867
std::is_convertible<detected_t<Op, Args...>, To>;
2868
} // namespace detail
2869
} // namespace nlohmann
2870
2871
// #include <nlohmann/json_fwd.hpp>
2872
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
2873
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
2874
2875
#include <cstdint> // int64_t, uint64_t
2876
#include <map> // map
2877
#include <memory> // allocator
2878
#include <string> // string
2879
#include <vector> // vector
2880
2881
/*!
2882
@brief namespace for Niels Lohmann
2883
@see https://github.com/nlohmann
2884
@since version 1.0.0
2885
*/
2886
namespace nlohmann
2887
{
2888
/*!
2889
@brief default JSONSerializer template argument
2890
2891
This serializer ignores the template arguments and uses ADL
2892
([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
2893
for serialization.
2894
*/
2895
template<typename T = void, typename SFINAE = void>
2896
struct adl_serializer;
2897
2898
template<template<typename U, typename V, typename... Args> class ObjectType =
2899
std::map,
2900
template<typename U, typename... Args> class ArrayType = std::vector,
2901
class StringType = std::string, class BooleanType = bool,
2902
class NumberIntegerType = std::int64_t,
2903
class NumberUnsignedType = std::uint64_t,
2904
class NumberFloatType = double,
2905
template<typename U> class AllocatorType = std::allocator,
2906
template<typename T, typename SFINAE = void> class JSONSerializer =
2907
adl_serializer,
2908
class BinaryType = std::vector<std::uint8_t>>
2909
class basic_json;
2910
2911
/*!
2912
@brief JSON Pointer
2913
2914
A JSON pointer defines a string syntax for identifying a specific value
2915
within a JSON document. It can be used with functions `at` and
2916
`operator[]`. Furthermore, JSON pointers are the base for JSON patches.
2917
2918
@sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
2919
2920
@since version 2.0.0
2921
*/
2922
template<typename BasicJsonType>
2923
class json_pointer;
2924
2925
/*!
2926
@brief default JSON class
2927
2928
This type is the default specialization of the @ref basic_json class which
2929
uses the standard template types.
2930
2931
@since version 1.0.0
2932
*/
2933
using json = basic_json<>;
2934
2935
template<class Key, class T, class IgnoredLess, class Allocator>
2936
struct ordered_map;
2937
2938
/*!
2939
@brief ordered JSON class
2940
2941
This type preserves the insertion order of object keys.
2942
2943
@since version 3.9.0
2944
*/
2945
using ordered_json = basic_json<nlohmann::ordered_map>;
2946
2947
} // namespace nlohmann
2948
2949
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
2950
2951
2952
namespace nlohmann
2953
{
2954
/*!
2955
@brief detail namespace with internal helper functions
2956
2957
This namespace collects functions that should not be exposed,
2958
implementations of some @ref basic_json methods, and meta-programming helpers.
2959
2960
@since version 2.1.0
2961
*/
2962
namespace detail
2963
{
2964
/////////////
2965
// helpers //
2966
/////////////
2967
2968
// Note to maintainers:
2969
//
2970
// Every trait in this file expects a non CV-qualified type.
2971
// The only exceptions are in the 'aliases for detected' section
2972
// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
2973
//
2974
// In this case, T has to be properly CV-qualified to constraint the function arguments
2975
// (e.g. to_json(BasicJsonType&, const T&))
2976
2977
template<typename> struct is_basic_json : std::false_type {};
2978
2979
NLOHMANN_BASIC_JSON_TPL_DECLARATION
2980
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
2981
2982
//////////////////////
2983
// json_ref helpers //
2984
//////////////////////
2985
2986
template<typename>
2987
class json_ref;
2988
2989
template<typename>
2990
struct is_json_ref : std::false_type {};
2991
2992
template<typename T>
2993
struct is_json_ref<json_ref<T>> : std::true_type {};
2994
2995
//////////////////////////
2996
// aliases for detected //
2997
//////////////////////////
2998
2999
template<typename T>
3000
using mapped_type_t = typename T::mapped_type;
3001
3002
template<typename T>
3003
using key_type_t = typename T::key_type;
3004
3005
template<typename T>
3006
using value_type_t = typename T::value_type;
3007
3008
template<typename T>
3009
using difference_type_t = typename T::difference_type;
3010
3011
template<typename T>
3012
using pointer_t = typename T::pointer;
3013
3014
template<typename T>
3015
using reference_t = typename T::reference;
3016
3017
template<typename T>
3018
using iterator_category_t = typename T::iterator_category;
3019
3020
template<typename T>
3021
using iterator_t = typename T::iterator;
3022
3023
template<typename T, typename... Args>
3024
using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3025
3026
template<typename T, typename... Args>
3027
using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3028
3029
template<typename T, typename U>
3030
using get_template_function = decltype(std::declval<T>().template get<U>());
3031
3032
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3033
template<typename BasicJsonType, typename T, typename = void>
3034
struct has_from_json : std::false_type {};
3035
3036
// trait checking if j.get<T> is valid
3037
// use this trait instead of std::is_constructible or std::is_convertible,
3038
// both rely on, or make use of implicit conversions, and thus fail when T
3039
// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3040
template <typename BasicJsonType, typename T>
3041
struct is_getable
3042
{
3043
static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3044
};
3045
3046
template<typename BasicJsonType, typename T>
3047
struct has_from_json < BasicJsonType, T,
3048
enable_if_t < !is_basic_json<T>::value >>
3049
{
3050
using serializer = typename BasicJsonType::template json_serializer<T, void>;
3051
3052
static constexpr bool value =
3053
is_detected_exact<void, from_json_function, serializer,
3054
const BasicJsonType&, T&>::value;
3055
};
3056
3057
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3058
// this overload is used for non-default-constructible user-defined-types
3059
template<typename BasicJsonType, typename T, typename = void>
3060
struct has_non_default_from_json : std::false_type {};
3061
3062
template<typename BasicJsonType, typename T>
3063
struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3064
{
3065
using serializer = typename BasicJsonType::template json_serializer<T, void>;
3066
3067
static constexpr bool value =
3068
is_detected_exact<T, from_json_function, serializer,
3069
const BasicJsonType&>::value;
3070
};
3071
3072
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3073
// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3074
template<typename BasicJsonType, typename T, typename = void>
3075
struct has_to_json : std::false_type {};
3076
3077
template<typename BasicJsonType, typename T>
3078
struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3079
{
3080
using serializer = typename BasicJsonType::template json_serializer<T, void>;
3081
3082
static constexpr bool value =
3083
is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3084
T>::value;
3085
};
3086
3087
3088
///////////////////
3089
// is_ functions //
3090
///////////////////
3091
3092
template<typename T, typename = void>
3093
struct is_iterator_traits : std::false_type {};
3094
3095
template<typename T>
3096
struct is_iterator_traits<iterator_traits<T>>
3097
{
3098
private:
3099
using traits = iterator_traits<T>;
3100
3101
public:
3102
static constexpr auto value =
3103
is_detected<value_type_t, traits>::value &&
3104
is_detected<difference_type_t, traits>::value &&
3105
is_detected<pointer_t, traits>::value &&
3106
is_detected<iterator_category_t, traits>::value &&
3107
is_detected<reference_t, traits>::value;
3108
};
3109
3110
// source: https://stackoverflow.com/a/37193089/4116453
3111
3112
template<typename T, typename = void>
3113
struct is_complete_type : std::false_type {};
3114
3115
template<typename T>
3116
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3117
3118
template<typename BasicJsonType, typename CompatibleObjectType,
3119
typename = void>
3120
struct is_compatible_object_type_impl : std::false_type {};
3121
3122
template<typename BasicJsonType, typename CompatibleObjectType>
3123
struct is_compatible_object_type_impl <
3124
BasicJsonType, CompatibleObjectType,
3125
enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3126
is_detected<key_type_t, CompatibleObjectType>::value >>
3127
{
3128
3129
using object_t = typename BasicJsonType::object_t;
3130
3131
// macOS's is_constructible does not play well with nonesuch...
3132
static constexpr bool value =
3133
std::is_constructible<typename object_t::key_type,
3134
typename CompatibleObjectType::key_type>::value &&
3135
std::is_constructible<typename object_t::mapped_type,
3136
typename CompatibleObjectType::mapped_type>::value;
3137
};
3138
3139
template<typename BasicJsonType, typename CompatibleObjectType>
3140
struct is_compatible_object_type
3141
: is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3142
3143
template<typename BasicJsonType, typename ConstructibleObjectType,
3144
typename = void>
3145
struct is_constructible_object_type_impl : std::false_type {};
3146
3147
template<typename BasicJsonType, typename ConstructibleObjectType>
3148
struct is_constructible_object_type_impl <
3149
BasicJsonType, ConstructibleObjectType,
3150
enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3151
is_detected<key_type_t, ConstructibleObjectType>::value >>
3152
{
3153
using object_t = typename BasicJsonType::object_t;
3154
3155
static constexpr bool value =
3156
(std::is_default_constructible<ConstructibleObjectType>::value &&
3157
(std::is_move_assignable<ConstructibleObjectType>::value ||
3158
std::is_copy_assignable<ConstructibleObjectType>::value) &&
3159
(std::is_constructible<typename ConstructibleObjectType::key_type,
3160
typename object_t::key_type>::value &&
3161
std::is_same <
3162
typename object_t::mapped_type,
3163
typename ConstructibleObjectType::mapped_type >::value)) ||
3164
(has_from_json<BasicJsonType,
3165
typename ConstructibleObjectType::mapped_type>::value ||
3166
has_non_default_from_json <
3167
BasicJsonType,
3168
typename ConstructibleObjectType::mapped_type >::value);
3169
};
3170
3171
template<typename BasicJsonType, typename ConstructibleObjectType>
3172
struct is_constructible_object_type
3173
: is_constructible_object_type_impl<BasicJsonType,
3174
ConstructibleObjectType> {};
3175
3176
template<typename BasicJsonType, typename CompatibleStringType,
3177
typename = void>
3178
struct is_compatible_string_type_impl : std::false_type {};
3179
3180
template<typename BasicJsonType, typename CompatibleStringType>
3181
struct is_compatible_string_type_impl <
3182
BasicJsonType, CompatibleStringType,
3183
enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
3184
value_type_t, CompatibleStringType>::value >>
3185
{
3186
static constexpr auto value =
3187
std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
3188
};
3189
3190
template<typename BasicJsonType, typename ConstructibleStringType>
3191
struct is_compatible_string_type
3192
: is_compatible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
3193
3194
template<typename BasicJsonType, typename ConstructibleStringType,
3195
typename = void>
3196
struct is_constructible_string_type_impl : std::false_type {};
3197
3198
template<typename BasicJsonType, typename ConstructibleStringType>
3199
struct is_constructible_string_type_impl <
3200
BasicJsonType, ConstructibleStringType,
3201
enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
3202
value_type_t, ConstructibleStringType>::value >>
3203
{
3204
static constexpr auto value =
3205
std::is_constructible<ConstructibleStringType,
3206
typename BasicJsonType::string_t>::value;
3207
};
3208
3209
template<typename BasicJsonType, typename ConstructibleStringType>
3210
struct is_constructible_string_type
3211
: is_constructible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
3212
3213
template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3214
struct is_compatible_array_type_impl : std::false_type {};
3215
3216
template<typename BasicJsonType, typename CompatibleArrayType>
3217
struct is_compatible_array_type_impl <
3218
BasicJsonType, CompatibleArrayType,
3219
enable_if_t < is_detected<value_type_t, CompatibleArrayType>::value&&
3220
is_detected<iterator_t, CompatibleArrayType>::value&&
3221
// This is needed because json_reverse_iterator has a ::iterator type...
3222
// Therefore it is detected as a CompatibleArrayType.
3223
// The real fix would be to have an Iterable concept.
3224
!is_iterator_traits <
3225
iterator_traits<CompatibleArrayType >>::value >>
3226
{
3227
static constexpr bool value =
3228
std::is_constructible<BasicJsonType,
3229
typename CompatibleArrayType::value_type>::value;
3230
};
3231
3232
template<typename BasicJsonType, typename CompatibleArrayType>
3233
struct is_compatible_array_type
3234
: is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3235
3236
template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3237
struct is_constructible_array_type_impl : std::false_type {};
3238
3239
template<typename BasicJsonType, typename ConstructibleArrayType>
3240
struct is_constructible_array_type_impl <
3241
BasicJsonType, ConstructibleArrayType,
3242
enable_if_t<std::is_same<ConstructibleArrayType,
3243
typename BasicJsonType::value_type>::value >>
3244
: std::true_type {};
3245
3246
template<typename BasicJsonType, typename ConstructibleArrayType>
3247
struct is_constructible_array_type_impl <
3248
BasicJsonType, ConstructibleArrayType,
3249
enable_if_t < !std::is_same<ConstructibleArrayType,
3250
typename BasicJsonType::value_type>::value&&
3251
std::is_default_constructible<ConstructibleArrayType>::value&&
3252
(std::is_move_assignable<ConstructibleArrayType>::value ||
3253
std::is_copy_assignable<ConstructibleArrayType>::value)&&
3254
is_detected<value_type_t, ConstructibleArrayType>::value&&
3255
is_detected<iterator_t, ConstructibleArrayType>::value&&
3256
is_complete_type <
3257
detected_t<value_type_t, ConstructibleArrayType >>::value >>
3258
{
3259
static constexpr bool value =
3260
// This is needed because json_reverse_iterator has a ::iterator type,
3261
// furthermore, std::back_insert_iterator (and other iterators) have a
3262
// base class `iterator`... Therefore it is detected as a
3263
// ConstructibleArrayType. The real fix would be to have an Iterable
3264
// concept.
3265
!is_iterator_traits<iterator_traits<ConstructibleArrayType>>::value &&
3266
3267
(std::is_same<typename ConstructibleArrayType::value_type,
3268
typename BasicJsonType::array_t::value_type>::value ||
3269
has_from_json<BasicJsonType,
3270
typename ConstructibleArrayType::value_type>::value ||
3271
has_non_default_from_json <
3272
BasicJsonType, typename ConstructibleArrayType::value_type >::value);
3273
};
3274
3275
template<typename BasicJsonType, typename ConstructibleArrayType>
3276
struct is_constructible_array_type
3277
: is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3278
3279
template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3280
typename = void>
3281
struct is_compatible_integer_type_impl : std::false_type {};
3282
3283
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3284
struct is_compatible_integer_type_impl <
3285
RealIntegerType, CompatibleNumberIntegerType,
3286
enable_if_t < std::is_integral<RealIntegerType>::value&&
3287
std::is_integral<CompatibleNumberIntegerType>::value&&
3288
!std::is_same<bool, CompatibleNumberIntegerType>::value >>
3289
{
3290
// is there an assert somewhere on overflows?
3291
using RealLimits = std::numeric_limits<RealIntegerType>;
3292
using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3293
3294
static constexpr auto value =
3295
std::is_constructible<RealIntegerType,
3296
CompatibleNumberIntegerType>::value &&
3297
CompatibleLimits::is_integer &&
3298
RealLimits::is_signed == CompatibleLimits::is_signed;
3299
};
3300
3301
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3302
struct is_compatible_integer_type
3303
: is_compatible_integer_type_impl<RealIntegerType,
3304
CompatibleNumberIntegerType> {};
3305
3306
template<typename BasicJsonType, typename CompatibleType, typename = void>
3307
struct is_compatible_type_impl: std::false_type {};
3308
3309
template<typename BasicJsonType, typename CompatibleType>
3310
struct is_compatible_type_impl <
3311
BasicJsonType, CompatibleType,
3312
enable_if_t<is_complete_type<CompatibleType>::value >>
3313
{
3314
static constexpr bool value =
3315
has_to_json<BasicJsonType, CompatibleType>::value;
3316
};
3317
3318
template<typename BasicJsonType, typename CompatibleType>
3319
struct is_compatible_type
3320
: is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3321
3322
// https://en.cppreference.com/w/cpp/types/conjunction
3323
template<class...> struct conjunction : std::true_type { };
3324
template<class B1> struct conjunction<B1> : B1 { };
3325
template<class B1, class... Bn>
3326
struct conjunction<B1, Bn...>
3327
: std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
3328
3329
template<typename T1, typename T2>
3330
struct is_constructible_tuple : std::false_type {};
3331
3332
template<typename T1, typename... Args>
3333
struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<std::is_constructible<T1, Args>...> {};
3334
} // namespace detail
3335
} // namespace nlohmann
3336
3337
// #include <nlohmann/detail/value_t.hpp>
3338
3339
3340
#include <array> // array
3341
#include <cstddef> // size_t
3342
#include <cstdint> // uint8_t
3343
#include <string> // string
3344
3345
namespace nlohmann
3346
{
3347
namespace detail
3348
{
3349
///////////////////////////
3350
// JSON type enumeration //
3351
///////////////////////////
3352
3353
/*!
3354
@brief the JSON type enumeration
3355
3356
This enumeration collects the different JSON types. It is internally used to
3357
distinguish the stored values, and the functions @ref basic_json::is_null(),
3358
@ref basic_json::is_object(), @ref basic_json::is_array(),
3359
@ref basic_json::is_string(), @ref basic_json::is_boolean(),
3360
@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
3361
@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
3362
@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
3363
@ref basic_json::is_structured() rely on it.
3364
3365
@note There are three enumeration entries (number_integer, number_unsigned, and
3366
number_float), because the library distinguishes these three types for numbers:
3367
@ref basic_json::number_unsigned_t is used for unsigned integers,
3368
@ref basic_json::number_integer_t is used for signed integers, and
3369
@ref basic_json::number_float_t is used for floating-point numbers or to
3370
approximate integers which do not fit in the limits of their respective type.
3371
3372
@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON
3373
value with the default value for a given type
3374
3375
@since version 1.0.0
3376
*/
3377
enum class value_t : std::uint8_t
3378
{
3379
null, ///< null value
3380
object, ///< object (unordered set of name/value pairs)
3381
array, ///< array (ordered collection of values)
3382
string, ///< string value
3383
boolean, ///< boolean value
3384
number_integer, ///< number value (signed integer)
3385
number_unsigned, ///< number value (unsigned integer)
3386
number_float, ///< number value (floating-point)
3387
binary, ///< binary array (ordered collection of bytes)
3388
discarded ///< discarded by the parser callback function
3389
};
3390
3391
/*!
3392
@brief comparison operator for JSON types
3393
3394
Returns an ordering that is similar to Python:
3395
- order: null < boolean < number < object < array < string < binary
3396
- furthermore, each type is not smaller than itself
3397
- discarded values are not comparable
3398
- binary is represented as a b"" string in python and directly comparable to a
3399
string; however, making a binary array directly comparable with a string would
3400
be surprising behavior in a JSON file.
3401
3402
@since version 1.0.0
3403
*/
3404
inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3405
{
3406
static constexpr std::array<std::uint8_t, 9> order = {{
3407
0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
3408
1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
3409
6 /* binary */
3410
}
3411
};
3412
3413
const auto l_index = static_cast<std::size_t>(lhs);
3414
const auto r_index = static_cast<std::size_t>(rhs);
3415
return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
3416
}
3417
} // namespace detail
3418
} // namespace nlohmann
3419
3420
3421
namespace nlohmann
3422
{
3423
namespace detail
3424
{
3425
template<typename BasicJsonType>
3426
void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
3427
{
3428
if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
3429
{
3430
JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
3431
}
3432
n = nullptr;
3433
}
3434
3435
// overloads for basic_json template parameters
3436
template < typename BasicJsonType, typename ArithmeticType,
3437
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
3438
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
3439
int > = 0 >
3440
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
3441
{
3442
switch (static_cast<value_t>(j))
3443
{
3444
case value_t::number_unsigned:
3445
{
3446
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
3447
break;
3448
}
3449
case value_t::number_integer:
3450
{
3451
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
3452
break;
3453
}
3454
case value_t::number_float:
3455
{
3456
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
3457
break;
3458
}
3459
3460
default:
3461
JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
3462
}
3463
}
3464
3465
template<typename BasicJsonType>
3466
void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
3467
{
3468
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
3469
{
3470
JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
3471
}
3472
b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
3473
}
3474
3475
template<typename BasicJsonType>
3476
void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
3477
{
3478
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
3479
{
3480
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
3481
}
3482
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
3483
}
3484
3485
template <
3486
typename BasicJsonType, typename ConstructibleStringType,
3487
enable_if_t <
3488
is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value&&
3489
!std::is_same<typename BasicJsonType::string_t,
3490
ConstructibleStringType>::value,
3491
int > = 0 >
3492
void from_json(const BasicJsonType& j, ConstructibleStringType& s)
3493
{
3494
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
3495
{
3496
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
3497
}
3498
3499
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
3500
}
3501
3502
template<typename BasicJsonType>
3503
void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
3504
{
3505
get_arithmetic_value(j, val);
3506
}
3507
3508
template<typename BasicJsonType>
3509
void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
3510
{
3511
get_arithmetic_value(j, val);
3512
}
3513
3514
template<typename BasicJsonType>
3515
void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
3516
{
3517
get_arithmetic_value(j, val);
3518
}
3519
3520
template<typename BasicJsonType, typename EnumType,
3521
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
3522
void from_json(const BasicJsonType& j, EnumType& e)
3523
{
3524
typename std::underlying_type<EnumType>::type val;
3525
get_arithmetic_value(j, val);
3526
e = static_cast<EnumType>(val);
3527
}
3528
3529
// forward_list doesn't have an insert method
3530
template<typename BasicJsonType, typename T, typename Allocator,
3531
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
3532
void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
3533
{
3534
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3535
{
3536
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
3537
}
3538
l.clear();
3539
std::transform(j.rbegin(), j.rend(),
3540
std::front_inserter(l), [](const BasicJsonType & i)
3541
{
3542
return i.template get<T>();
3543
});
3544
}
3545
3546
// valarray doesn't have an insert method
3547
template<typename BasicJsonType, typename T,
3548
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
3549
void from_json(const BasicJsonType& j, std::valarray<T>& l)
3550
{
3551
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3552
{
3553
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
3554
}
3555
l.resize(j.size());
3556
std::transform(j.begin(), j.end(), std::begin(l),
3557
[](const BasicJsonType & elem)
3558
{
3559
return elem.template get<T>();
3560
});
3561
}
3562
3563
template<typename BasicJsonType, typename T, std::size_t N>
3564
auto from_json(const BasicJsonType& j, T (&arr)[N])
3565
-> decltype(j.template get<T>(), void())
3566
{
3567
for (std::size_t i = 0; i < N; ++i)
3568
{
3569
arr[i] = j.at(i).template get<T>();
3570
}
3571
}
3572
3573
template<typename BasicJsonType>
3574
void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
3575
{
3576
arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
3577
}
3578
3579
template<typename BasicJsonType, typename T, std::size_t N>
3580
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
3581
priority_tag<2> /*unused*/)
3582
-> decltype(j.template get<T>(), void())
3583
{
3584
for (std::size_t i = 0; i < N; ++i)
3585
{
3586
arr[i] = j.at(i).template get<T>();
3587
}
3588
}
3589
3590
template<typename BasicJsonType, typename ConstructibleArrayType>
3591
auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
3592
-> decltype(
3593
arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
3594
j.template get<typename ConstructibleArrayType::value_type>(),
3595
void())
3596
{
3597
using std::end;
3598
3599
ConstructibleArrayType ret;
3600
ret.reserve(j.size());
3601
std::transform(j.begin(), j.end(),
3602
std::inserter(ret, end(ret)), [](const BasicJsonType & i)
3603
{
3604
// get<BasicJsonType>() returns *this, this won't call a from_json
3605
// method when value_type is BasicJsonType
3606
return i.template get<typename ConstructibleArrayType::value_type>();
3607
});
3608
arr = std::move(ret);
3609
}
3610
3611
template<typename BasicJsonType, typename ConstructibleArrayType>
3612
void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
3613
priority_tag<0> /*unused*/)
3614
{
3615
using std::end;
3616
3617
ConstructibleArrayType ret;
3618
std::transform(
3619
j.begin(), j.end(), std::inserter(ret, end(ret)),
3620
[](const BasicJsonType & i)
3621
{
3622
// get<BasicJsonType>() returns *this, this won't call a from_json
3623
// method when value_type is BasicJsonType
3624
return i.template get<typename ConstructibleArrayType::value_type>();
3625
});
3626
arr = std::move(ret);
3627
}
3628
3629
template < typename BasicJsonType, typename ConstructibleArrayType,
3630
enable_if_t <
3631
is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
3632
!is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
3633
!is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3634
!std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
3635
!is_basic_json<ConstructibleArrayType>::value,
3636
int > = 0 >
3637
auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
3638
-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
3639
j.template get<typename ConstructibleArrayType::value_type>(),
3640
void())
3641
{
3642
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3643
{
3644
JSON_THROW(type_error::create(302, "type must be array, but is " +
3645
std::string(j.type_name())));
3646
}
3647
3648
from_json_array_impl(j, arr, priority_tag<3> {});
3649
}
3650
3651
template<typename BasicJsonType>
3652
void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
3653
{
3654
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
3655
{
3656
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name())));
3657
}
3658
3659
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
3660
}
3661
3662
template<typename BasicJsonType, typename ConstructibleObjectType,
3663
enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
3664
void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
3665
{
3666
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
3667
{
3668
JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
3669
}
3670
3671
ConstructibleObjectType ret;
3672
auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
3673
using value_type = typename ConstructibleObjectType::value_type;
3674
std::transform(
3675
inner_object->begin(), inner_object->end(),
3676
std::inserter(ret, ret.begin()),
3677
[](typename BasicJsonType::object_t::value_type const & p)
3678
{
3679
return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
3680
});
3681
obj = std::move(ret);
3682
}
3683
3684
// overload for arithmetic types, not chosen for basic_json template arguments
3685
// (BooleanType, etc..); note: Is it really necessary to provide explicit
3686
// overloads for boolean_t etc. in case of a custom BooleanType which is not
3687
// an arithmetic type?
3688
template < typename BasicJsonType, typename ArithmeticType,
3689
enable_if_t <
3690
std::is_arithmetic<ArithmeticType>::value&&
3691
!std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
3692
!std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
3693
!std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
3694
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
3695
int > = 0 >
3696
void from_json(const BasicJsonType& j, ArithmeticType& val)
3697
{
3698
switch (static_cast<value_t>(j))
3699
{
3700
case value_t::number_unsigned:
3701
{
3702
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
3703
break;
3704
}
3705
case value_t::number_integer:
3706
{
3707
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
3708
break;
3709
}
3710
case value_t::number_float:
3711
{
3712
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
3713
break;
3714
}
3715
case value_t::boolean:
3716
{
3717
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
3718
break;
3719
}
3720
3721
default:
3722
JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
3723
}
3724
}
3725
3726
template<typename BasicJsonType, typename A1, typename A2>
3727
void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
3728
{
3729
p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
3730
}
3731
3732
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
3733
void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...> /*unused*/)
3734
{
3735
t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
3736
}
3737
3738
template<typename BasicJsonType, typename... Args>
3739
void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
3740
{
3741
from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
3742
}
3743
3744
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
3745
typename = enable_if_t < !std::is_constructible <
3746
typename BasicJsonType::string_t, Key >::value >>
3747
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
3748
{
3749
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3750
{
3751
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
3752
}
3753
m.clear();
3754
for (const auto& p : j)
3755
{
3756
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
3757
{
3758
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
3759
}
3760
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
3761
}
3762
}
3763
3764
template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
3765
typename = enable_if_t < !std::is_constructible <
3766
typename BasicJsonType::string_t, Key >::value >>
3767
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
3768
{
3769
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3770
{
3771
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
3772
}
3773
m.clear();
3774
for (const auto& p : j)
3775
{
3776
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
3777
{
3778
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
3779
}
3780
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
3781
}
3782
}
3783
3784
struct from_json_fn
3785
{
3786
template<typename BasicJsonType, typename T>
3787
auto operator()(const BasicJsonType& j, T& val) const
3788
noexcept(noexcept(from_json(j, val)))
3789
-> decltype(from_json(j, val), void())
3790
{
3791
return from_json(j, val);
3792
}
3793
};
3794
} // namespace detail
3795
3796
/// namespace to hold default `from_json` function
3797
/// to see why this is required:
3798
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
3799
namespace
3800
{
3801
constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
3802
} // namespace
3803
} // namespace nlohmann
3804
3805
// #include <nlohmann/detail/conversions/to_json.hpp>
3806
3807
3808
#include <algorithm> // copy
3809
#include <iterator> // begin, end
3810
#include <string> // string
3811
#include <tuple> // tuple, get
3812
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
3813
#include <utility> // move, forward, declval, pair
3814
#include <valarray> // valarray
3815
#include <vector> // vector
3816
3817
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
3818
3819
3820
#include <cstddef> // size_t
3821
#include <iterator> // input_iterator_tag
3822
#include <string> // string, to_string
3823
#include <tuple> // tuple_size, get, tuple_element
3824
3825
// #include <nlohmann/detail/meta/type_traits.hpp>
3826
3827
// #include <nlohmann/detail/value_t.hpp>
3828
3829
3830
namespace nlohmann
3831
{
3832
namespace detail
3833
{
3834
template<typename string_type>
3835
void int_to_string( string_type& target, std::size_t value )
3836
{
3837
// For ADL
3838
using std::to_string;
3839
target = to_string(value);
3840
}
3841
template<typename IteratorType> class iteration_proxy_value
3842
{
3843
public:
3844
using difference_type = std::ptrdiff_t;
3845
using value_type = iteration_proxy_value;
3846
using pointer = value_type * ;
3847
using reference = value_type & ;
3848
using iterator_category = std::input_iterator_tag;
3849
using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
3850
3851
private:
3852
/// the iterator
3853
IteratorType anchor;
3854
/// an index for arrays (used to create key names)
3855
std::size_t array_index = 0;
3856
/// last stringified array index
3857
mutable std::size_t array_index_last = 0;
3858
/// a string representation of the array index
3859
mutable string_type array_index_str = "0";
3860
/// an empty string (to return a reference for primitive values)
3861
const string_type empty_str = "";
3862
3863
public:
3864
explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {}
3865
3866
/// dereference operator (needed for range-based for)
3867
iteration_proxy_value& operator*()
3868
{
3869
return *this;
3870
}
3871
3872
/// increment operator (needed for range-based for)
3873
iteration_proxy_value& operator++()
3874
{
3875
++anchor;
3876
++array_index;
3877
3878
return *this;
3879
}
3880
3881
/// equality operator (needed for InputIterator)
3882
bool operator==(const iteration_proxy_value& o) const
3883
{
3884
return anchor == o.anchor;
3885
}
3886
3887
/// inequality operator (needed for range-based for)
3888
bool operator!=(const iteration_proxy_value& o) const
3889
{
3890
return anchor != o.anchor;
3891
}
3892
3893
/// return key of the iterator
3894
const string_type& key() const
3895
{
3896
JSON_ASSERT(anchor.m_object != nullptr);
3897
3898
switch (anchor.m_object->type())
3899
{
3900
// use integer array index as key
3901
case value_t::array:
3902
{
3903
if (array_index != array_index_last)
3904
{
3905
int_to_string( array_index_str, array_index );
3906
array_index_last = array_index;
3907
}
3908
return array_index_str;
3909
}
3910
3911
// use key from the object
3912
case value_t::object:
3913
return anchor.key();
3914
3915
// use an empty key for all primitive types
3916
default:
3917
return empty_str;
3918
}
3919
}
3920
3921
/// return value of the iterator
3922
typename IteratorType::reference value() const
3923
{
3924
return anchor.value();
3925
}
3926
};
3927
3928
/// proxy class for the items() function
3929
template<typename IteratorType> class iteration_proxy
3930
{
3931
private:
3932
/// the container to iterate
3933
typename IteratorType::reference container;
3934
3935
public:
3936
/// construct iteration proxy from a container
3937
explicit iteration_proxy(typename IteratorType::reference cont) noexcept
3938
: container(cont) {}
3939
3940
/// return iterator begin (needed for range-based for)
3941
iteration_proxy_value<IteratorType> begin() noexcept
3942
{
3943
return iteration_proxy_value<IteratorType>(container.begin());
3944
}
3945
3946
/// return iterator end (needed for range-based for)
3947
iteration_proxy_value<IteratorType> end() noexcept
3948
{
3949
return iteration_proxy_value<IteratorType>(container.end());
3950
}
3951
};
3952
// Structured Bindings Support
3953
// For further reference see https://blog.tartanllama.xyz/structured-bindings/
3954
// And see https://github.com/nlohmann/json/pull/1391
3955
template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
3956
auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
3957
{
3958
return i.key();
3959
}
3960
// Structured Bindings Support
3961
// For further reference see https://blog.tartanllama.xyz/structured-bindings/
3962
// And see https://github.com/nlohmann/json/pull/1391
3963
template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
3964
auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
3965
{
3966
return i.value();
3967
}
3968
} // namespace detail
3969
} // namespace nlohmann
3970
3971
// The Addition to the STD Namespace is required to add
3972
// Structured Bindings Support to the iteration_proxy_value class
3973
// For further reference see https://blog.tartanllama.xyz/structured-bindings/
3974
// And see https://github.com/nlohmann/json/pull/1391
3975
namespace std
3976
{
3977
#if defined(__clang__)
3978
// Fix: https://github.com/nlohmann/json/issues/1401
3979
#pragma clang diagnostic push
3980
#pragma clang diagnostic ignored "-Wmismatched-tags"
3981
#endif
3982
template<typename IteratorType>
3983
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
3984
: public std::integral_constant<std::size_t, 2> {};
3985
3986
template<std::size_t N, typename IteratorType>
3987
class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
3988
{
3989
public:
3990
using type = decltype(
3991
get<N>(std::declval <
3992
::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
3993
};
3994
#if defined(__clang__)
3995
#pragma clang diagnostic pop
3996
#endif
3997
} // namespace std
3998
3999
// #include <nlohmann/detail/meta/cpp_future.hpp>
4000
4001
// #include <nlohmann/detail/meta/type_traits.hpp>
4002
4003
// #include <nlohmann/detail/value_t.hpp>
4004
4005
4006
namespace nlohmann
4007
{
4008
namespace detail
4009
{
4010
//////////////////
4011
// constructors //
4012
//////////////////
4013
4014
template<value_t> struct external_constructor;
4015
4016
template<>
4017
struct external_constructor<value_t::boolean>
4018
{
4019
template<typename BasicJsonType>
4020
static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
4021
{
4022
j.m_type = value_t::boolean;
4023
j.m_value = b;
4024
j.assert_invariant();
4025
}
4026
};
4027
4028
template<>
4029
struct external_constructor<value_t::string>
4030
{
4031
template<typename BasicJsonType>
4032
static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
4033
{
4034
j.m_type = value_t::string;
4035
j.m_value = s;
4036
j.assert_invariant();
4037
}
4038
4039
template<typename BasicJsonType>
4040
static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
4041
{
4042
j.m_type = value_t::string;
4043
j.m_value = std::move(s);
4044
j.assert_invariant();
4045
}
4046
4047
template < typename BasicJsonType, typename CompatibleStringType,
4048
enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
4049
int > = 0 >
4050
static void construct(BasicJsonType& j, const CompatibleStringType& str)
4051
{
4052
j.m_type = value_t::string;
4053
j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
4054
j.assert_invariant();
4055
}
4056
};
4057
4058
template<>
4059
struct external_constructor<value_t::binary>
4060
{
4061
template<typename BasicJsonType>
4062
static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
4063
{
4064
j.m_type = value_t::binary;
4065
typename BasicJsonType::binary_t value{b};
4066
j.m_value = value;
4067
j.assert_invariant();
4068
}
4069
4070
template<typename BasicJsonType>
4071
static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
4072
{
4073
j.m_type = value_t::binary;
4074
typename BasicJsonType::binary_t value{std::move(b)};
4075
j.m_value = value;
4076
j.assert_invariant();
4077
}
4078
};
4079
4080
template<>
4081
struct external_constructor<value_t::number_float>
4082
{
4083
template<typename BasicJsonType>
4084
static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
4085
{
4086
j.m_type = value_t::number_float;
4087
j.m_value = val;
4088
j.assert_invariant();
4089
}
4090
};
4091
4092
template<>
4093
struct external_constructor<value_t::number_unsigned>
4094
{
4095
template<typename BasicJsonType>
4096
static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
4097
{
4098
j.m_type = value_t::number_unsigned;
4099
j.m_value = val;
4100
j.assert_invariant();
4101
}
4102
};
4103
4104
template<>
4105
struct external_constructor<value_t::number_integer>
4106
{
4107
template<typename BasicJsonType>
4108
static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
4109
{
4110
j.m_type = value_t::number_integer;
4111
j.m_value = val;
4112
j.assert_invariant();
4113
}
4114
};
4115
4116
template<>
4117
struct external_constructor<value_t::array>
4118
{
4119
template<typename BasicJsonType>
4120
static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
4121
{
4122
j.m_type = value_t::array;
4123
j.m_value = arr;
4124
j.assert_invariant();
4125
}
4126
4127
template<typename BasicJsonType>
4128
static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
4129
{
4130
j.m_type = value_t::array;
4131
j.m_value = std::move(arr);
4132
j.assert_invariant();
4133
}
4134
4135
template < typename BasicJsonType, typename CompatibleArrayType,
4136
enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
4137
int > = 0 >
4138
static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
4139
{
4140
using std::begin;
4141
using std::end;
4142
j.m_type = value_t::array;
4143
j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
4144
j.assert_invariant();
4145
}
4146
4147
template<typename BasicJsonType>
4148
static void construct(BasicJsonType& j, const std::vector<bool>& arr)
4149
{
4150
j.m_type = value_t::array;
4151
j.m_value = value_t::array;
4152
j.m_value.array->reserve(arr.size());
4153
for (const bool x : arr)
4154
{
4155
j.m_value.array->push_back(x);
4156
}
4157
j.assert_invariant();
4158
}
4159
4160
template<typename BasicJsonType, typename T,
4161
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
4162
static void construct(BasicJsonType& j, const std::valarray<T>& arr)
4163
{
4164
j.m_type = value_t::array;
4165
j.m_value = value_t::array;
4166
j.m_value.array->resize(arr.size());
4167
if (arr.size() > 0)
4168
{
4169
std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
4170
}
4171
j.assert_invariant();
4172
}
4173
};
4174
4175
template<>
4176
struct external_constructor<value_t::object>
4177
{
4178
template<typename BasicJsonType>
4179
static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
4180
{
4181
j.m_type = value_t::object;
4182
j.m_value = obj;
4183
j.assert_invariant();
4184
}
4185
4186
template<typename BasicJsonType>
4187
static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
4188
{
4189
j.m_type = value_t::object;
4190
j.m_value = std::move(obj);
4191
j.assert_invariant();
4192
}
4193
4194
template < typename BasicJsonType, typename CompatibleObjectType,
4195
enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
4196
static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
4197
{
4198
using std::begin;
4199
using std::end;
4200
4201
j.m_type = value_t::object;
4202
j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
4203
j.assert_invariant();
4204
}
4205
};
4206
4207
/////////////
4208
// to_json //
4209
/////////////
4210
4211
template<typename BasicJsonType, typename T,
4212
enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
4213
void to_json(BasicJsonType& j, T b) noexcept
4214
{
4215
external_constructor<value_t::boolean>::construct(j, b);
4216
}
4217
4218
template<typename BasicJsonType, typename CompatibleString,
4219
enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
4220
void to_json(BasicJsonType& j, const CompatibleString& s)
4221
{
4222
external_constructor<value_t::string>::construct(j, s);
4223
}
4224
4225
template<typename BasicJsonType>
4226
void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
4227
{
4228
external_constructor<value_t::string>::construct(j, std::move(s));
4229
}
4230
4231
template<typename BasicJsonType, typename FloatType,
4232
enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
4233
void to_json(BasicJsonType& j, FloatType val) noexcept
4234
{
4235
external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
4236
}
4237
4238
template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
4239
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
4240
void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
4241
{
4242
external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
4243
}
4244
4245
template<typename BasicJsonType, typename CompatibleNumberIntegerType,
4246
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
4247
void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
4248
{
4249
external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
4250
}
4251
4252
template<typename BasicJsonType, typename EnumType,
4253
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4254
void to_json(BasicJsonType& j, EnumType e) noexcept
4255
{
4256
using underlying_type = typename std::underlying_type<EnumType>::type;
4257
external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
4258
}
4259
4260
template<typename BasicJsonType>
4261
void to_json(BasicJsonType& j, const std::vector<bool>& e)
4262
{
4263
external_constructor<value_t::array>::construct(j, e);
4264
}
4265
4266
template < typename BasicJsonType, typename CompatibleArrayType,
4267
enable_if_t < is_compatible_array_type<BasicJsonType,
4268
CompatibleArrayType>::value&&
4269
!is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
4270
!is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
4271
!std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
4272
!is_basic_json<CompatibleArrayType>::value,
4273
int > = 0 >
4274
void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
4275
{
4276
external_constructor<value_t::array>::construct(j, arr);
4277
}
4278
4279
template<typename BasicJsonType>
4280
void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
4281
{
4282
external_constructor<value_t::binary>::construct(j, bin);
4283
}
4284
4285
template<typename BasicJsonType, typename T,
4286
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
4287
void to_json(BasicJsonType& j, const std::valarray<T>& arr)
4288
{
4289
external_constructor<value_t::array>::construct(j, std::move(arr));
4290
}
4291
4292
template<typename BasicJsonType>
4293
void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
4294
{
4295
external_constructor<value_t::array>::construct(j, std::move(arr));
4296
}
4297
4298
template < typename BasicJsonType, typename CompatibleObjectType,
4299
enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
4300
void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
4301
{
4302
external_constructor<value_t::object>::construct(j, obj);
4303
}
4304
4305
template<typename BasicJsonType>
4306
void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
4307
{
4308
external_constructor<value_t::object>::construct(j, std::move(obj));
4309
}
4310
4311
template <
4312
typename BasicJsonType, typename T, std::size_t N,
4313
enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
4314
const T(&)[N]>::value,
4315
int > = 0 >
4316
void to_json(BasicJsonType& j, const T(&arr)[N])
4317
{
4318
external_constructor<value_t::array>::construct(j, arr);
4319
}
4320
4321
template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
4322
void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
4323
{
4324
j = { p.first, p.second };
4325
}
4326
4327
// for https://github.com/nlohmann/json/pull/1134
4328
template<typename BasicJsonType, typename T,
4329
enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
4330
void to_json(BasicJsonType& j, const T& b)
4331
{
4332
j = { {b.key(), b.value()} };
4333
}
4334
4335
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
4336
void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
4337
{
4338
j = { std::get<Idx>(t)... };
4339
}
4340
4341
template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
4342
void to_json(BasicJsonType& j, const T& t)
4343
{
4344
to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
4345
}
4346
4347
struct to_json_fn
4348
{
4349
template<typename BasicJsonType, typename T>
4350
auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
4351
-> decltype(to_json(j, std::forward<T>(val)), void())
4352
{
4353
return to_json(j, std::forward<T>(val));
4354
}
4355
};
4356
} // namespace detail
4357
4358
/// namespace to hold default `to_json` function
4359
namespace
4360
{
4361
constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
4362
} // namespace
4363
} // namespace nlohmann
4364
4365
4366
namespace nlohmann
4367
{
4368
4369
template<typename, typename>
4370
struct adl_serializer
4371
{
4372
/*!
4373
@brief convert a JSON value to any value type
4374
4375
This function is usually called by the `get()` function of the
4376
@ref basic_json class (either explicit or via conversion operators).
4377
4378
@param[in] j JSON value to read from
4379
@param[in,out] val value to write to
4380
*/
4381
template<typename BasicJsonType, typename ValueType>
4382
static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(
4383
noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
4384
-> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
4385
{
4386
::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
4387
}
4388
4389
/*!
4390
@brief convert any value type to a JSON value
4391
4392
This function is usually called by the constructors of the @ref basic_json
4393
class.
4394
4395
@param[in,out] j JSON value to write to
4396
@param[in] val value to read from
4397
*/
4398
template<typename BasicJsonType, typename ValueType>
4399
static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
4400
noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
4401
-> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)), void())
4402
{
4403
::nlohmann::to_json(j, std::forward<ValueType>(val));
4404
}
4405
};
4406
4407
} // namespace nlohmann
4408
4409
// #include <nlohmann/byte_container_with_subtype.hpp>
4410
4411
4412
#include <cstdint> // uint8_t
4413
#include <tuple> // tie
4414
#include <utility> // move
4415
4416
namespace nlohmann
4417
{
4418
4419
/*!
4420
@brief an internal type for a backed binary type
4421
4422
This type extends the template parameter @a BinaryType provided to `basic_json`
4423
with a subtype used by BSON and MessagePack. This type exists so that the user
4424
does not have to specify a type themselves with a specific naming scheme in
4425
order to override the binary type.
4426
4427
@tparam BinaryType container to store bytes (`std::vector<std::uint8_t>` by
4428
default)
4429
4430
@since version 3.8.0
4431
*/
4432
template<typename BinaryType>
4433
class byte_container_with_subtype : public BinaryType
4434
{
4435
public:
4436
/// the type of the underlying container
4437
using container_type = BinaryType;
4438
4439
byte_container_with_subtype() noexcept(noexcept(container_type()))
4440
: container_type()
4441
{}
4442
4443
byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
4444
: container_type(b)
4445
{}
4446
4447
byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
4448
: container_type(std::move(b))
4449
{}
4450
4451
byte_container_with_subtype(const container_type& b, std::uint8_t subtype) noexcept(noexcept(container_type(b)))
4452
: container_type(b)
4453
, m_subtype(subtype)
4454
, m_has_subtype(true)
4455
{}
4456
4457
byte_container_with_subtype(container_type&& b, std::uint8_t subtype) noexcept(noexcept(container_type(std::move(b))))
4458
: container_type(std::move(b))
4459
, m_subtype(subtype)
4460
, m_has_subtype(true)
4461
{}
4462
4463
bool operator==(const byte_container_with_subtype& rhs) const
4464
{
4465
return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
4466
std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
4467
}
4468
4469
bool operator!=(const byte_container_with_subtype& rhs) const
4470
{
4471
return !(rhs == *this);
4472
}
4473
4474
/*!
4475
@brief sets the binary subtype
4476
4477
Sets the binary subtype of the value, also flags a binary JSON value as
4478
having a subtype, which has implications for serialization.
4479
4480
@complexity Constant.
4481
4482
@exceptionsafety No-throw guarantee: this member function never throws
4483
exceptions.
4484
4485
@sa @ref subtype() -- return the binary subtype
4486
@sa @ref clear_subtype() -- clears the binary subtype
4487
@sa @ref has_subtype() -- returns whether or not the binary value has a
4488
subtype
4489
4490
@since version 3.8.0
4491
*/
4492
void set_subtype(std::uint8_t subtype) noexcept
4493
{
4494
m_subtype = subtype;
4495
m_has_subtype = true;
4496
}
4497
4498
/*!
4499
@brief return the binary subtype
4500
4501
Returns the numerical subtype of the value if it has a subtype. If it does
4502
not have a subtype, this function will return size_t(-1) as a sentinel
4503
value.
4504
4505
@return the numerical subtype of the binary value
4506
4507
@complexity Constant.
4508
4509
@exceptionsafety No-throw guarantee: this member function never throws
4510
exceptions.
4511
4512
@sa @ref set_subtype() -- sets the binary subtype
4513
@sa @ref clear_subtype() -- clears the binary subtype
4514
@sa @ref has_subtype() -- returns whether or not the binary value has a
4515
subtype
4516
4517
@since version 3.8.0
4518
*/
4519
constexpr std::uint8_t subtype() const noexcept
4520
{
4521
return m_subtype;
4522
}
4523
4524
/*!
4525
@brief return whether the value has a subtype
4526
4527
@return whether the value has a subtype
4528
4529
@complexity Constant.
4530
4531
@exceptionsafety No-throw guarantee: this member function never throws
4532
exceptions.
4533
4534
@sa @ref subtype() -- return the binary subtype
4535
@sa @ref set_subtype() -- sets the binary subtype
4536
@sa @ref clear_subtype() -- clears the binary subtype
4537
4538
@since version 3.8.0
4539
*/
4540
constexpr bool has_subtype() const noexcept
4541
{
4542
return m_has_subtype;
4543
}
4544
4545
/*!
4546
@brief clears the binary subtype
4547
4548
Clears the binary subtype and flags the value as not having a subtype, which
4549
has implications for serialization; for instance MessagePack will prefer the
4550
bin family over the ext family.
4551
4552
@complexity Constant.
4553
4554
@exceptionsafety No-throw guarantee: this member function never throws
4555
exceptions.
4556
4557
@sa @ref subtype() -- return the binary subtype
4558
@sa @ref set_subtype() -- sets the binary subtype
4559
@sa @ref has_subtype() -- returns whether or not the binary value has a
4560
subtype
4561
4562
@since version 3.8.0
4563
*/
4564
void clear_subtype() noexcept
4565
{
4566
m_subtype = 0;
4567
m_has_subtype = false;
4568
}
4569
4570
private:
4571
std::uint8_t m_subtype = 0;
4572
bool m_has_subtype = false;
4573
};
4574
4575
} // namespace nlohmann
4576
4577
// #include <nlohmann/detail/conversions/from_json.hpp>
4578
4579
// #include <nlohmann/detail/conversions/to_json.hpp>
4580
4581
// #include <nlohmann/detail/exceptions.hpp>
4582
4583
// #include <nlohmann/detail/hash.hpp>
4584
4585
4586
#include <cstddef> // size_t, uint8_t
4587
#include <functional> // hash
4588
4589
namespace nlohmann
4590
{
4591
namespace detail
4592
{
4593
4594
// boost::hash_combine
4595
inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
4596
{
4597
seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
4598
return seed;
4599
}
4600
4601
/*!
4602
@brief hash a JSON value
4603
4604
The hash function tries to rely on std::hash where possible. Furthermore, the
4605
type of the JSON value is taken into account to have different hash values for
4606
null, 0, 0U, and false, etc.
4607
4608
@tparam BasicJsonType basic_json specialization
4609
@param j JSON value to hash
4610
@return hash value of j
4611
*/
4612
template<typename BasicJsonType>
4613
std::size_t hash(const BasicJsonType& j)
4614
{
4615
using string_t = typename BasicJsonType::string_t;
4616
using number_integer_t = typename BasicJsonType::number_integer_t;
4617
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4618
using number_float_t = typename BasicJsonType::number_float_t;
4619
4620
const auto type = static_cast<std::size_t>(j.type());
4621
switch (j.type())
4622
{
4623
case BasicJsonType::value_t::null:
4624
case BasicJsonType::value_t::discarded:
4625
{
4626
return combine(type, 0);
4627
}
4628
4629
case BasicJsonType::value_t::object:
4630
{
4631
auto seed = combine(type, j.size());
4632
for (const auto& element : j.items())
4633
{
4634
const auto h = std::hash<string_t> {}(element.key());
4635
seed = combine(seed, h);
4636
seed = combine(seed, hash(element.value()));
4637
}
4638
return seed;
4639
}
4640
4641
case BasicJsonType::value_t::array:
4642
{
4643
auto seed = combine(type, j.size());
4644
for (const auto& element : j)
4645
{
4646
seed = combine(seed, hash(element));
4647
}
4648
return seed;
4649
}
4650
4651
case BasicJsonType::value_t::string:
4652
{
4653
const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
4654
return combine(type, h);
4655
}
4656
4657
case BasicJsonType::value_t::boolean:
4658
{
4659
const auto h = std::hash<bool> {}(j.template get<bool>());
4660
return combine(type, h);
4661
}
4662
4663
case BasicJsonType::value_t::number_integer:
4664
{
4665
const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
4666
return combine(type, h);
4667
}
4668
4669
case nlohmann::detail::value_t::number_unsigned:
4670
{
4671
const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
4672
return combine(type, h);
4673
}
4674
4675
case nlohmann::detail::value_t::number_float:
4676
{
4677
const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
4678
return combine(type, h);
4679
}
4680
4681
case nlohmann::detail::value_t::binary:
4682
{
4683
auto seed = combine(type, j.get_binary().size());
4684
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
4685
seed = combine(seed, h);
4686
seed = combine(seed, j.get_binary().subtype());
4687
for (const auto byte : j.get_binary())
4688
{
4689
seed = combine(seed, std::hash<std::uint8_t> {}(byte));
4690
}
4691
return seed;
4692
}
4693
4694
default: // LCOV_EXCL_LINE
4695
JSON_ASSERT(false); // LCOV_EXCL_LINE
4696
}
4697
}
4698
4699
} // namespace detail
4700
} // namespace nlohmann
4701
4702
// #include <nlohmann/detail/input/binary_reader.hpp>
4703
4704
4705
#include <algorithm> // generate_n
4706
#include <array> // array
4707
#include <cmath> // ldexp
4708
#include <cstddef> // size_t
4709
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
4710
#include <cstdio> // snprintf
4711
#include <cstring> // memcpy
4712
#include <iterator> // back_inserter
4713
#include <limits> // numeric_limits
4714
#include <string> // char_traits, string
4715
#include <utility> // make_pair, move
4716
4717
// #include <nlohmann/detail/exceptions.hpp>
4718
4719
// #include <nlohmann/detail/input/input_adapters.hpp>
4720
4721
4722
#include <array> // array
4723
#include <cstddef> // size_t
4724
#include <cstdio> //FILE *
4725
#include <cstring> // strlen
4726
#include <istream> // istream
4727
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
4728
#include <memory> // shared_ptr, make_shared, addressof
4729
#include <numeric> // accumulate
4730
#include <string> // string, char_traits
4731
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
4732
#include <utility> // pair, declval
4733
4734
// #include <nlohmann/detail/iterators/iterator_traits.hpp>
4735
4736
// #include <nlohmann/detail/macro_scope.hpp>
4737
4738
4739
namespace nlohmann
4740
{
4741
namespace detail
4742
{
4743
/// the supported input formats
4744
enum class input_format_t { json, cbor, msgpack, ubjson, bson };
4745
4746
////////////////////
4747
// input adapters //
4748
////////////////////
4749
4750
/*!
4751
Input adapter for stdio file access. This adapter read only 1 byte and do not use any
4752
buffer. This adapter is a very low level adapter.
4753
*/
4754
class file_input_adapter
4755
{
4756
public:
4757
using char_type = char;
4758
4759
JSON_HEDLEY_NON_NULL(2)
4760
explicit file_input_adapter(std::FILE* f) noexcept
4761
: m_file(f)
4762
{}
4763
4764
// make class move-only
4765
file_input_adapter(const file_input_adapter&) = delete;
4766
file_input_adapter(file_input_adapter&&) = default;
4767
file_input_adapter& operator=(const file_input_adapter&) = delete;
4768
file_input_adapter& operator=(file_input_adapter&&) = delete;
4769
4770
std::char_traits<char>::int_type get_character() noexcept
4771
{
4772
return std::fgetc(m_file);
4773
}
4774
4775
private:
4776
/// the file pointer to read from
4777
std::FILE* m_file;
4778
};
4779
4780
4781
/*!
4782
Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
4783
beginning of input. Does not support changing the underlying std::streambuf
4784
in mid-input. Maintains underlying std::istream and std::streambuf to support
4785
subsequent use of standard std::istream operations to process any input
4786
characters following those used in parsing the JSON input. Clears the
4787
std::istream flags; any input errors (e.g., EOF) will be detected by the first
4788
subsequent call for input from the std::istream.
4789
*/
4790
class input_stream_adapter
4791
{
4792
public:
4793
using char_type = char;
4794
4795
~input_stream_adapter()
4796
{
4797
// clear stream flags; we use underlying streambuf I/O, do not
4798
// maintain ifstream flags, except eof
4799
if (is != nullptr)
4800
{
4801
is->clear(is->rdstate() & std::ios::eofbit);
4802
}
4803
}
4804
4805
explicit input_stream_adapter(std::istream& i)
4806
: is(&i), sb(i.rdbuf())
4807
{}
4808
4809
// delete because of pointer members
4810
input_stream_adapter(const input_stream_adapter&) = delete;
4811
input_stream_adapter& operator=(input_stream_adapter&) = delete;
4812
input_stream_adapter& operator=(input_stream_adapter&& rhs) = delete;
4813
4814
input_stream_adapter(input_stream_adapter&& rhs) noexcept : is(rhs.is), sb(rhs.sb)
4815
{
4816
rhs.is = nullptr;
4817
rhs.sb = nullptr;
4818
}
4819
4820
// std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
4821
// ensure that std::char_traits<char>::eof() and the character 0xFF do not
4822
// end up as the same value, eg. 0xFFFFFFFF.
4823
std::char_traits<char>::int_type get_character()
4824
{
4825
auto res = sb->sbumpc();
4826
// set eof manually, as we don't use the istream interface.
4827
if (JSON_HEDLEY_UNLIKELY(res == EOF))
4828
{
4829
is->clear(is->rdstate() | std::ios::eofbit);
4830
}
4831
return res;
4832
}
4833
4834
private:
4835
/// the associated input stream
4836
std::istream* is = nullptr;
4837
std::streambuf* sb = nullptr;
4838
};
4839
4840
// General-purpose iterator-based adapter. It might not be as fast as
4841
// theoretically possible for some containers, but it is extremely versatile.
4842
template<typename IteratorType>
4843
class iterator_input_adapter
4844
{
4845
public:
4846
using char_type = typename std::iterator_traits<IteratorType>::value_type;
4847
4848
iterator_input_adapter(IteratorType first, IteratorType last)
4849
: current(std::move(first)), end(std::move(last)) {}
4850
4851
typename std::char_traits<char_type>::int_type get_character()
4852
{
4853
if (JSON_HEDLEY_LIKELY(current != end))
4854
{
4855
auto result = std::char_traits<char_type>::to_int_type(*current);
4856
std::advance(current, 1);
4857
return result;
4858
}
4859
else
4860
{
4861
return std::char_traits<char_type>::eof();
4862
}
4863
}
4864
4865
private:
4866
IteratorType current;
4867
IteratorType end;
4868
4869
template<typename BaseInputAdapter, size_t T>
4870
friend struct wide_string_input_helper;
4871
4872
bool empty() const
4873
{
4874
return current == end;
4875
}
4876
4877
};
4878
4879
4880
template<typename BaseInputAdapter, size_t T>
4881
struct wide_string_input_helper;
4882
4883
template<typename BaseInputAdapter>
4884
struct wide_string_input_helper<BaseInputAdapter, 4>
4885
{
4886
// UTF-32
4887
static void fill_buffer(BaseInputAdapter& input,
4888
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
4889
size_t& utf8_bytes_index,
4890
size_t& utf8_bytes_filled)
4891
{
4892
utf8_bytes_index = 0;
4893
4894
if (JSON_HEDLEY_UNLIKELY(input.empty()))
4895
{
4896
utf8_bytes[0] = std::char_traits<char>::eof();
4897
utf8_bytes_filled = 1;
4898
}
4899
else
4900
{
4901
// get the current character
4902
const auto wc = input.get_character();
4903
4904
// UTF-32 to UTF-8 encoding
4905
if (wc < 0x80)
4906
{
4907
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
4908
utf8_bytes_filled = 1;
4909
}
4910
else if (wc <= 0x7FF)
4911
{
4912
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
4913
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
4914
utf8_bytes_filled = 2;
4915
}
4916
else if (wc <= 0xFFFF)
4917
{
4918
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
4919
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
4920
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
4921
utf8_bytes_filled = 3;
4922
}
4923
else if (wc <= 0x10FFFF)
4924
{
4925
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
4926
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
4927
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
4928
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
4929
utf8_bytes_filled = 4;
4930
}
4931
else
4932
{
4933
// unknown character
4934
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
4935
utf8_bytes_filled = 1;
4936
}
4937
}
4938
}
4939
};
4940
4941
template<typename BaseInputAdapter>
4942
struct wide_string_input_helper<BaseInputAdapter, 2>
4943
{
4944
// UTF-16
4945
static void fill_buffer(BaseInputAdapter& input,
4946
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
4947
size_t& utf8_bytes_index,
4948
size_t& utf8_bytes_filled)
4949
{
4950
utf8_bytes_index = 0;
4951
4952
if (JSON_HEDLEY_UNLIKELY(input.empty()))
4953
{
4954
utf8_bytes[0] = std::char_traits<char>::eof();
4955
utf8_bytes_filled = 1;
4956
}
4957
else
4958
{
4959
// get the current character
4960
const auto wc = input.get_character();
4961
4962
// UTF-16 to UTF-8 encoding
4963
if (wc < 0x80)
4964
{
4965
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
4966
utf8_bytes_filled = 1;
4967
}
4968
else if (wc <= 0x7FF)
4969
{
4970
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
4971
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
4972
utf8_bytes_filled = 2;
4973
}
4974
else if (0xD800 > wc || wc >= 0xE000)
4975
{
4976
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
4977
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
4978
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
4979
utf8_bytes_filled = 3;
4980
}
4981
else
4982
{
4983
if (JSON_HEDLEY_UNLIKELY(!input.empty()))
4984
{
4985
const auto wc2 = static_cast<unsigned int>(input.get_character());
4986
const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
4987
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
4988
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
4989
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
4990
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
4991
utf8_bytes_filled = 4;
4992
}
4993
else
4994
{
4995
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
4996
utf8_bytes_filled = 1;
4997
}
4998
}
4999
}
5000
}
5001
};
5002
5003
// Wraps another input apdater to convert wide character types into individual bytes.
5004
template<typename BaseInputAdapter, typename WideCharType>
5005
class wide_string_input_adapter
5006
{
5007
public:
5008
using char_type = char;
5009
5010
wide_string_input_adapter(BaseInputAdapter base)
5011
: base_adapter(base) {}
5012
5013
typename std::char_traits<char>::int_type get_character() noexcept
5014
{
5015
// check if buffer needs to be filled
5016
if (utf8_bytes_index == utf8_bytes_filled)
5017
{
5018
fill_buffer<sizeof(WideCharType)>();
5019
5020
JSON_ASSERT(utf8_bytes_filled > 0);
5021
JSON_ASSERT(utf8_bytes_index == 0);
5022
}
5023
5024
// use buffer
5025
JSON_ASSERT(utf8_bytes_filled > 0);
5026
JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
5027
return utf8_bytes[utf8_bytes_index++];
5028
}
5029
5030
private:
5031
BaseInputAdapter base_adapter;
5032
5033
template<size_t T>
5034
void fill_buffer()
5035
{
5036
wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
5037
}
5038
5039
/// a buffer for UTF-8 bytes
5040
std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
5041
5042
/// index to the utf8_codes array for the next valid byte
5043
std::size_t utf8_bytes_index = 0;
5044
/// number of valid bytes in the utf8_codes array
5045
std::size_t utf8_bytes_filled = 0;
5046
};
5047
5048
5049
template<typename IteratorType, typename Enable = void>
5050
struct iterator_input_adapter_factory
5051
{
5052
using iterator_type = IteratorType;
5053
using char_type = typename std::iterator_traits<iterator_type>::value_type;
5054
using adapter_type = iterator_input_adapter<iterator_type>;
5055
5056
static adapter_type create(IteratorType first, IteratorType last)
5057
{
5058
return adapter_type(std::move(first), std::move(last));
5059
}
5060
};
5061
5062
template<typename T>
5063
struct is_iterator_of_multibyte
5064
{
5065
using value_type = typename std::iterator_traits<T>::value_type;
5066
enum
5067
{
5068
value = sizeof(value_type) > 1
5069
};
5070
};
5071
5072
template<typename IteratorType>
5073
struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
5074
{
5075
using iterator_type = IteratorType;
5076
using char_type = typename std::iterator_traits<iterator_type>::value_type;
5077
using base_adapter_type = iterator_input_adapter<iterator_type>;
5078
using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
5079
5080
static adapter_type create(IteratorType first, IteratorType last)
5081
{
5082
return adapter_type(base_adapter_type(std::move(first), std::move(last)));
5083
}
5084
};
5085
5086
// General purpose iterator-based input
5087
template<typename IteratorType>
5088
typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
5089
{
5090
using factory_type = iterator_input_adapter_factory<IteratorType>;
5091
return factory_type::create(first, last);
5092
}
5093
5094
// Convenience shorthand from container to iterator
5095
template<typename ContainerType>
5096
auto input_adapter(const ContainerType& container) -> decltype(input_adapter(begin(container), end(container)))
5097
{
5098
// Enable ADL
5099
using std::begin;
5100
using std::end;
5101
5102
return input_adapter(begin(container), end(container));
5103
}
5104
5105
// Special cases with fast paths
5106
inline file_input_adapter input_adapter(std::FILE* file)
5107
{
5108
return file_input_adapter(file);
5109
}
5110
5111
inline input_stream_adapter input_adapter(std::istream& stream)
5112
{
5113
return input_stream_adapter(stream);
5114
}
5115
5116
inline input_stream_adapter input_adapter(std::istream&& stream)
5117
{
5118
return input_stream_adapter(stream);
5119
}
5120
5121
using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
5122
5123
// Null-delimited strings, and the like.
5124
template < typename CharT,
5125
typename std::enable_if <
5126
std::is_pointer<CharT>::value&&
5127
!std::is_array<CharT>::value&&
5128
std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
5129
sizeof(typename std::remove_pointer<CharT>::type) == 1,
5130
int >::type = 0 >
5131
contiguous_bytes_input_adapter input_adapter(CharT b)
5132
{
5133
auto length = std::strlen(reinterpret_cast<const char*>(b));
5134
const auto* ptr = reinterpret_cast<const char*>(b);
5135
return input_adapter(ptr, ptr + length);
5136
}
5137
5138
template<typename T, std::size_t N>
5139
auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N))
5140
{
5141
return input_adapter(array, array + N);
5142
}
5143
5144
// This class only handles inputs of input_buffer_adapter type.
5145
// It's required so that expressions like {ptr, len} can be implicitely casted
5146
// to the correct adapter.
5147
class span_input_adapter
5148
{
5149
public:
5150
template < typename CharT,
5151
typename std::enable_if <
5152
std::is_pointer<CharT>::value&&
5153
std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
5154
sizeof(typename std::remove_pointer<CharT>::type) == 1,
5155
int >::type = 0 >
5156
span_input_adapter(CharT b, std::size_t l)
5157
: ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
5158
5159
template<class IteratorType,
5160
typename std::enable_if<
5161
std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
5162
int>::type = 0>
5163
span_input_adapter(IteratorType first, IteratorType last)
5164
: ia(input_adapter(first, last)) {}
5165
5166
contiguous_bytes_input_adapter&& get()
5167
{
5168
return std::move(ia);
5169
}
5170
5171
private:
5172
contiguous_bytes_input_adapter ia;
5173
};
5174
} // namespace detail
5175
} // namespace nlohmann
5176
5177
// #include <nlohmann/detail/input/json_sax.hpp>
5178
5179
5180
#include <cstddef>
5181
#include <string> // string
5182
#include <utility> // move
5183
#include <vector> // vector
5184
5185
// #include <nlohmann/detail/exceptions.hpp>
5186
5187
// #include <nlohmann/detail/macro_scope.hpp>
5188
5189
5190
namespace nlohmann
5191
{
5192
5193
/*!
5194
@brief SAX interface
5195
5196
This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
5197
Each function is called in different situations while the input is parsed. The
5198
boolean return value informs the parser whether to continue processing the
5199
input.
5200
*/
5201
template<typename BasicJsonType>
5202
struct json_sax
5203
{
5204
using number_integer_t = typename BasicJsonType::number_integer_t;
5205
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5206
using number_float_t = typename BasicJsonType::number_float_t;
5207
using string_t = typename BasicJsonType::string_t;
5208
using binary_t = typename BasicJsonType::binary_t;
5209
5210
/*!
5211
@brief a null value was read
5212
@return whether parsing should proceed
5213
*/
5214
virtual bool null() = 0;
5215
5216
/*!
5217
@brief a boolean value was read
5218
@param[in] val boolean value
5219
@return whether parsing should proceed
5220
*/
5221
virtual bool boolean(bool val) = 0;
5222
5223
/*!
5224
@brief an integer number was read
5225
@param[in] val integer value
5226
@return whether parsing should proceed
5227
*/
5228
virtual bool number_integer(number_integer_t val) = 0;
5229
5230
/*!
5231
@brief an unsigned integer number was read
5232
@param[in] val unsigned integer value
5233
@return whether parsing should proceed
5234
*/
5235
virtual bool number_unsigned(number_unsigned_t val) = 0;
5236
5237
/*!
5238
@brief an floating-point number was read
5239
@param[in] val floating-point value
5240
@param[in] s raw token value
5241
@return whether parsing should proceed
5242
*/
5243
virtual bool number_float(number_float_t val, const string_t& s) = 0;
5244
5245
/*!
5246
@brief a string was read
5247
@param[in] val string value
5248
@return whether parsing should proceed
5249
@note It is safe to move the passed string.
5250
*/
5251
virtual bool string(string_t& val) = 0;
5252
5253
/*!
5254
@brief a binary string was read
5255
@param[in] val binary value
5256
@return whether parsing should proceed
5257
@note It is safe to move the passed binary.
5258
*/
5259
virtual bool binary(binary_t& val) = 0;
5260
5261
/*!
5262
@brief the beginning of an object was read
5263
@param[in] elements number of object elements or -1 if unknown
5264
@return whether parsing should proceed
5265
@note binary formats may report the number of elements
5266
*/
5267
virtual bool start_object(std::size_t elements) = 0;
5268
5269
/*!
5270
@brief an object key was read
5271
@param[in] val object key
5272
@return whether parsing should proceed
5273
@note It is safe to move the passed string.
5274
*/
5275
virtual bool key(string_t& val) = 0;
5276
5277
/*!
5278
@brief the end of an object was read
5279
@return whether parsing should proceed
5280
*/
5281
virtual bool end_object() = 0;
5282
5283
/*!
5284
@brief the beginning of an array was read
5285
@param[in] elements number of array elements or -1 if unknown
5286
@return whether parsing should proceed
5287
@note binary formats may report the number of elements
5288
*/
5289
virtual bool start_array(std::size_t elements) = 0;
5290
5291
/*!
5292
@brief the end of an array was read
5293
@return whether parsing should proceed
5294
*/
5295
virtual bool end_array() = 0;
5296
5297
/*!
5298
@brief a parse error occurred
5299
@param[in] position the position in the input where the error occurs
5300
@param[in] last_token the last read token
5301
@param[in] ex an exception object describing the error
5302
@return whether parsing should proceed (must return false)
5303
*/
5304
virtual bool parse_error(std::size_t position,
5305
const std::string& last_token,
5306
const detail::exception& ex) = 0;
5307
5308
virtual ~json_sax() = default;
5309
};
5310
5311
5312
namespace detail
5313
{
5314
/*!
5315
@brief SAX implementation to create a JSON value from SAX events
5316
5317
This class implements the @ref json_sax interface and processes the SAX events
5318
to create a JSON value which makes it basically a DOM parser. The structure or
5319
hierarchy of the JSON value is managed by the stack `ref_stack` which contains
5320
a pointer to the respective array or object for each recursion depth.
5321
5322
After successful parsing, the value that is passed by reference to the
5323
constructor contains the parsed value.
5324
5325
@tparam BasicJsonType the JSON type
5326
*/
5327
template<typename BasicJsonType>
5328
class json_sax_dom_parser
5329
{
5330
public:
5331
using number_integer_t = typename BasicJsonType::number_integer_t;
5332
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5333
using number_float_t = typename BasicJsonType::number_float_t;
5334
using string_t = typename BasicJsonType::string_t;
5335
using binary_t = typename BasicJsonType::binary_t;
5336
5337
/*!
5338
@param[in, out] r reference to a JSON value that is manipulated while
5339
parsing
5340
@param[in] allow_exceptions_ whether parse errors yield exceptions
5341
*/
5342
explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
5343
: root(r), allow_exceptions(allow_exceptions_)
5344
{}
5345
5346
// make class move-only
5347
json_sax_dom_parser(const json_sax_dom_parser&) = delete;
5348
json_sax_dom_parser(json_sax_dom_parser&&) = default;
5349
json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
5350
json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default;
5351
~json_sax_dom_parser() = default;
5352
5353
bool null()
5354
{
5355
handle_value(nullptr);
5356
return true;
5357
}
5358
5359
bool boolean(bool val)
5360
{
5361
handle_value(val);
5362
return true;
5363
}
5364
5365
bool number_integer(number_integer_t val)
5366
{
5367
handle_value(val);
5368
return true;
5369
}
5370
5371
bool number_unsigned(number_unsigned_t val)
5372
{
5373
handle_value(val);
5374
return true;
5375
}
5376
5377
bool number_float(number_float_t val, const string_t& /*unused*/)
5378
{
5379
handle_value(val);
5380
return true;
5381
}
5382
5383
bool string(string_t& val)
5384
{
5385
handle_value(val);
5386
return true;
5387
}
5388
5389
bool binary(binary_t& val)
5390
{
5391
handle_value(std::move(val));
5392
return true;
5393
}
5394
5395
bool start_object(std::size_t len)
5396
{
5397
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
5398
5399
if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
5400
{
5401
JSON_THROW(out_of_range::create(408,
5402
"excessive object size: " + std::to_string(len)));
5403
}
5404
5405
return true;
5406
}
5407
5408
bool key(string_t& val)
5409
{
5410
// add null at given key and store the reference for later
5411
object_element = &(ref_stack.back()->m_value.object->operator[](val));
5412
return true;
5413
}
5414
5415
bool end_object()
5416
{
5417
ref_stack.pop_back();
5418
return true;
5419
}
5420
5421
bool start_array(std::size_t len)
5422
{
5423
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
5424
5425
if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
5426
{
5427
JSON_THROW(out_of_range::create(408,
5428
"excessive array size: " + std::to_string(len)));
5429
}
5430
5431
return true;
5432
}
5433
5434
bool end_array()
5435
{
5436
ref_stack.pop_back();
5437
return true;
5438
}
5439
5440
template<class Exception>
5441
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
5442
const Exception& ex)
5443
{
5444
errored = true;
5445
static_cast<void>(ex);
5446
if (allow_exceptions)
5447
{
5448
JSON_THROW(ex);
5449
}
5450
return false;
5451
}
5452
5453
constexpr bool is_errored() const
5454
{
5455
return errored;
5456
}
5457
5458
private:
5459
/*!
5460
@invariant If the ref stack is empty, then the passed value will be the new
5461
root.
5462
@invariant If the ref stack contains a value, then it is an array or an
5463
object to which we can add elements
5464
*/
5465
template<typename Value>
5466
JSON_HEDLEY_RETURNS_NON_NULL
5467
BasicJsonType* handle_value(Value&& v)
5468
{
5469
if (ref_stack.empty())
5470
{
5471
root = BasicJsonType(std::forward<Value>(v));
5472
return &root;
5473
}
5474
5475
JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
5476
5477
if (ref_stack.back()->is_array())
5478
{
5479
ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
5480
return &(ref_stack.back()->m_value.array->back());
5481
}
5482
5483
JSON_ASSERT(ref_stack.back()->is_object());
5484
JSON_ASSERT(object_element);
5485
*object_element = BasicJsonType(std::forward<Value>(v));
5486
return object_element;
5487
}
5488
5489
/// the parsed JSON value
5490
BasicJsonType& root;
5491
/// stack to model hierarchy of values
5492
std::vector<BasicJsonType*> ref_stack {};
5493
/// helper to hold the reference for the next object element
5494
BasicJsonType* object_element = nullptr;
5495
/// whether a syntax error occurred
5496
bool errored = false;
5497
/// whether to throw exceptions in case of errors
5498
const bool allow_exceptions = false;
5499
};
5500
5501
template<typename BasicJsonType>
5502
class json_sax_dom_callback_parser
5503
{
5504
public:
5505
using number_integer_t = typename BasicJsonType::number_integer_t;
5506
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5507
using number_float_t = typename BasicJsonType::number_float_t;
5508
using string_t = typename BasicJsonType::string_t;
5509
using binary_t = typename BasicJsonType::binary_t;
5510
using parser_callback_t = typename BasicJsonType::parser_callback_t;
5511
using parse_event_t = typename BasicJsonType::parse_event_t;
5512
5513
json_sax_dom_callback_parser(BasicJsonType& r,
5514
const parser_callback_t cb,
5515
const bool allow_exceptions_ = true)
5516
: root(r), callback(cb), allow_exceptions(allow_exceptions_)
5517
{
5518
keep_stack.push_back(true);
5519
}
5520
5521
// make class move-only
5522
json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
5523
json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default;
5524
json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
5525
json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default;
5526
~json_sax_dom_callback_parser() = default;
5527
5528
bool null()
5529
{
5530
handle_value(nullptr);
5531
return true;
5532
}
5533
5534
bool boolean(bool val)
5535
{
5536
handle_value(val);
5537
return true;
5538
}
5539
5540
bool number_integer(number_integer_t val)
5541
{
5542
handle_value(val);
5543
return true;
5544
}
5545
5546
bool number_unsigned(number_unsigned_t val)
5547
{
5548
handle_value(val);
5549
return true;
5550
}
5551
5552
bool number_float(number_float_t val, const string_t& /*unused*/)
5553
{
5554
handle_value(val);
5555
return true;
5556
}
5557
5558
bool string(string_t& val)
5559
{
5560
handle_value(val);
5561
return true;
5562
}
5563
5564
bool binary(binary_t& val)
5565
{
5566
handle_value(std::move(val));
5567
return true;
5568
}
5569
5570
bool start_object(std::size_t len)
5571
{
5572
// check callback for object start
5573
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
5574
keep_stack.push_back(keep);
5575
5576
auto val = handle_value(BasicJsonType::value_t::object, true);
5577
ref_stack.push_back(val.second);
5578
5579
// check object limit
5580
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
5581
{
5582
JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len)));
5583
}
5584
5585
return true;
5586
}
5587
5588
bool key(string_t& val)
5589
{
5590
BasicJsonType k = BasicJsonType(val);
5591
5592
// check callback for key
5593
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
5594
key_keep_stack.push_back(keep);
5595
5596
// add discarded value at given key and store the reference for later
5597
if (keep && ref_stack.back())
5598
{
5599
object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
5600
}
5601
5602
return true;
5603
}
5604
5605
bool end_object()
5606
{
5607
if (ref_stack.back() && !callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
5608
{
5609
// discard object
5610
*ref_stack.back() = discarded;
5611
}
5612
5613
JSON_ASSERT(!ref_stack.empty());
5614
JSON_ASSERT(!keep_stack.empty());
5615
ref_stack.pop_back();
5616
keep_stack.pop_back();
5617
5618
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
5619
{
5620
// remove discarded value
5621
for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
5622
{
5623
if (it->is_discarded())
5624
{
5625
ref_stack.back()->erase(it);
5626
break;
5627
}
5628
}
5629
}
5630
5631
return true;
5632
}
5633
5634
bool start_array(std::size_t len)
5635
{
5636
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
5637
keep_stack.push_back(keep);
5638
5639
auto val = handle_value(BasicJsonType::value_t::array, true);
5640
ref_stack.push_back(val.second);
5641
5642
// check array limit
5643
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
5644
{
5645
JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len)));
5646
}
5647
5648
return true;
5649
}
5650
5651
bool end_array()
5652
{
5653
bool keep = true;
5654
5655
if (ref_stack.back())
5656
{
5657
keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
5658
if (!keep)
5659
{
5660
// discard array
5661
*ref_stack.back() = discarded;
5662
}
5663
}
5664
5665
JSON_ASSERT(!ref_stack.empty());
5666
JSON_ASSERT(!keep_stack.empty());
5667
ref_stack.pop_back();
5668
keep_stack.pop_back();
5669
5670
// remove discarded value
5671
if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
5672
{
5673
ref_stack.back()->m_value.array->pop_back();
5674
}
5675
5676
return true;
5677
}
5678
5679
template<class Exception>
5680
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
5681
const Exception& ex)
5682
{
5683
errored = true;
5684
static_cast<void>(ex);
5685
if (allow_exceptions)
5686
{
5687
JSON_THROW(ex);
5688
}
5689
return false;
5690
}
5691
5692
constexpr bool is_errored() const
5693
{
5694
return errored;
5695
}
5696
5697
private:
5698
/*!
5699
@param[in] v value to add to the JSON value we build during parsing
5700
@param[in] skip_callback whether we should skip calling the callback
5701
function; this is required after start_array() and
5702
start_object() SAX events, because otherwise we would call the
5703
callback function with an empty array or object, respectively.
5704
5705
@invariant If the ref stack is empty, then the passed value will be the new
5706
root.
5707
@invariant If the ref stack contains a value, then it is an array or an
5708
object to which we can add elements
5709
5710
@return pair of boolean (whether value should be kept) and pointer (to the
5711
passed value in the ref_stack hierarchy; nullptr if not kept)
5712
*/
5713
template<typename Value>
5714
std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
5715
{
5716
JSON_ASSERT(!keep_stack.empty());
5717
5718
// do not handle this value if we know it would be added to a discarded
5719
// container
5720
if (!keep_stack.back())
5721
{
5722
return {false, nullptr};
5723
}
5724
5725
// create value
5726
auto value = BasicJsonType(std::forward<Value>(v));
5727
5728
// check callback
5729
const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
5730
5731
// do not handle this value if we just learnt it shall be discarded
5732
if (!keep)
5733
{
5734
return {false, nullptr};
5735
}
5736
5737
if (ref_stack.empty())
5738
{
5739
root = std::move(value);
5740
return {true, &root};
5741
}
5742
5743
// skip this value if we already decided to skip the parent
5744
// (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
5745
if (!ref_stack.back())
5746
{
5747
return {false, nullptr};
5748
}
5749
5750
// we now only expect arrays and objects
5751
JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
5752
5753
// array
5754
if (ref_stack.back()->is_array())
5755
{
5756
ref_stack.back()->m_value.array->push_back(std::move(value));
5757
return {true, &(ref_stack.back()->m_value.array->back())};
5758
}
5759
5760
// object
5761
JSON_ASSERT(ref_stack.back()->is_object());
5762
// check if we should store an element for the current key
5763
JSON_ASSERT(!key_keep_stack.empty());
5764
const bool store_element = key_keep_stack.back();
5765
key_keep_stack.pop_back();
5766
5767
if (!store_element)
5768
{
5769
return {false, nullptr};
5770
}
5771
5772
JSON_ASSERT(object_element);
5773
*object_element = std::move(value);
5774
return {true, object_element};
5775
}
5776
5777
/// the parsed JSON value
5778
BasicJsonType& root;
5779
/// stack to model hierarchy of values
5780
std::vector<BasicJsonType*> ref_stack {};
5781
/// stack to manage which values to keep
5782
std::vector<bool> keep_stack {};
5783
/// stack to manage which object keys to keep
5784
std::vector<bool> key_keep_stack {};
5785
/// helper to hold the reference for the next object element
5786
BasicJsonType* object_element = nullptr;
5787
/// whether a syntax error occurred
5788
bool errored = false;
5789
/// callback function
5790
const parser_callback_t callback = nullptr;
5791
/// whether to throw exceptions in case of errors
5792
const bool allow_exceptions = true;
5793
/// a discarded value for the callback
5794
BasicJsonType discarded = BasicJsonType::value_t::discarded;
5795
};
5796
5797
template<typename BasicJsonType>
5798
class json_sax_acceptor
5799
{
5800
public:
5801
using number_integer_t = typename BasicJsonType::number_integer_t;
5802
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5803
using number_float_t = typename BasicJsonType::number_float_t;
5804
using string_t = typename BasicJsonType::string_t;
5805
using binary_t = typename BasicJsonType::binary_t;
5806
5807
bool null()
5808
{
5809
return true;
5810
}
5811
5812
bool boolean(bool /*unused*/)
5813
{
5814
return true;
5815
}
5816
5817
bool number_integer(number_integer_t /*unused*/)
5818
{
5819
return true;
5820
}
5821
5822
bool number_unsigned(number_unsigned_t /*unused*/)
5823
{
5824
return true;
5825
}
5826
5827
bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
5828
{
5829
return true;
5830
}
5831
5832
bool string(string_t& /*unused*/)
5833
{
5834
return true;
5835
}
5836
5837
bool binary(binary_t& /*unused*/)
5838
{
5839
return true;
5840
}
5841
5842
bool start_object(std::size_t /*unused*/ = std::size_t(-1))
5843
{
5844
return true;
5845
}
5846
5847
bool key(string_t& /*unused*/)
5848
{
5849
return true;
5850
}
5851
5852
bool end_object()
5853
{
5854
return true;
5855
}
5856
5857
bool start_array(std::size_t /*unused*/ = std::size_t(-1))
5858
{
5859
return true;
5860
}
5861
5862
bool end_array()
5863
{
5864
return true;
5865
}
5866
5867
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
5868
{
5869
return false;
5870
}
5871
};
5872
} // namespace detail
5873
5874
} // namespace nlohmann
5875
5876
// #include <nlohmann/detail/input/lexer.hpp>
5877
5878
5879
#include <array> // array
5880
#include <clocale> // localeconv
5881
#include <cstddef> // size_t
5882
#include <cstdio> // snprintf
5883
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
5884
#include <initializer_list> // initializer_list
5885
#include <string> // char_traits, string
5886
#include <utility> // move
5887
#include <vector> // vector
5888
5889
// #include <nlohmann/detail/input/input_adapters.hpp>
5890
5891
// #include <nlohmann/detail/input/position_t.hpp>
5892
5893
// #include <nlohmann/detail/macro_scope.hpp>
5894
5895
5896
namespace nlohmann
5897
{
5898
namespace detail
5899
{
5900
///////////
5901
// lexer //
5902
///////////
5903
5904
template<typename BasicJsonType>
5905
class lexer_base
5906
{
5907
public:
5908
/// token types for the parser
5909
enum class token_type
5910
{
5911
uninitialized, ///< indicating the scanner is uninitialized
5912
literal_true, ///< the `true` literal
5913
literal_false, ///< the `false` literal
5914
literal_null, ///< the `null` literal
5915
value_string, ///< a string -- use get_string() for actual value
5916
value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
5917
value_integer, ///< a signed integer -- use get_number_integer() for actual value
5918
value_float, ///< an floating point number -- use get_number_float() for actual value
5919
begin_array, ///< the character for array begin `[`
5920
begin_object, ///< the character for object begin `{`
5921
end_array, ///< the character for array end `]`
5922
end_object, ///< the character for object end `}`
5923
name_separator, ///< the name separator `:`
5924
value_separator, ///< the value separator `,`
5925
parse_error, ///< indicating a parse error
5926
end_of_input, ///< indicating the end of the input buffer
5927
literal_or_value ///< a literal or the begin of a value (only for diagnostics)
5928
};
5929
5930
/// return name of values of type token_type (only used for errors)
5931
JSON_HEDLEY_RETURNS_NON_NULL
5932
JSON_HEDLEY_CONST
5933
static const char* token_type_name(const token_type t) noexcept
5934
{
5935
switch (t)
5936
{
5937
case token_type::uninitialized:
5938
return "<uninitialized>";
5939
case token_type::literal_true:
5940
return "true literal";
5941
case token_type::literal_false:
5942
return "false literal";
5943
case token_type::literal_null:
5944
return "null literal";
5945
case token_type::value_string:
5946
return "string literal";
5947
case token_type::value_unsigned:
5948
case token_type::value_integer:
5949
case token_type::value_float:
5950
return "number literal";
5951
case token_type::begin_array:
5952
return "'['";
5953
case token_type::begin_object:
5954
return "'{'";
5955
case token_type::end_array:
5956
return "']'";
5957
case token_type::end_object:
5958
return "'}'";
5959
case token_type::name_separator:
5960
return "':'";
5961
case token_type::value_separator:
5962
return "','";
5963
case token_type::parse_error:
5964
return "<parse error>";
5965
case token_type::end_of_input:
5966
return "end of input";
5967
case token_type::literal_or_value:
5968
return "'[', '{', or a literal";
5969
// LCOV_EXCL_START
5970
default: // catch non-enum values
5971
return "unknown token";
5972
// LCOV_EXCL_STOP
5973
}
5974
}
5975
};
5976
/*!
5977
@brief lexical analysis
5978
5979
This class organizes the lexical analysis during JSON deserialization.
5980
*/
5981
template<typename BasicJsonType, typename InputAdapterType>
5982
class lexer : public lexer_base<BasicJsonType>
5983
{
5984
using number_integer_t = typename BasicJsonType::number_integer_t;
5985
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5986
using number_float_t = typename BasicJsonType::number_float_t;
5987
using string_t = typename BasicJsonType::string_t;
5988
using char_type = typename InputAdapterType::char_type;
5989
using char_int_type = typename std::char_traits<char_type>::int_type;
5990
5991
public:
5992
using token_type = typename lexer_base<BasicJsonType>::token_type;
5993
5994
explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false)
5995
: ia(std::move(adapter))
5996
, ignore_comments(ignore_comments_)
5997
, decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
5998
{}
5999
6000
// delete because of pointer members
6001
lexer(const lexer&) = delete;
6002
lexer(lexer&&) = default;
6003
lexer& operator=(lexer&) = delete;
6004
lexer& operator=(lexer&&) = default;
6005
~lexer() = default;
6006
6007
private:
6008
/////////////////////
6009
// locales
6010
/////////////////////
6011
6012
/// return the locale-dependent decimal point
6013
JSON_HEDLEY_PURE
6014
static char get_decimal_point() noexcept
6015
{
6016
const auto* loc = localeconv();
6017
JSON_ASSERT(loc != nullptr);
6018
return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
6019
}
6020
6021
/////////////////////
6022
// scan functions
6023
/////////////////////
6024
6025
/*!
6026
@brief get codepoint from 4 hex characters following `\u`
6027
6028
For input "\u c1 c2 c3 c4" the codepoint is:
6029
(c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
6030
= (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
6031
6032
Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
6033
must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
6034
conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
6035
between the ASCII value of the character and the desired integer value.
6036
6037
@return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
6038
non-hex character)
6039
*/
6040
int get_codepoint()
6041
{
6042
// this function only makes sense after reading `\u`
6043
JSON_ASSERT(current == 'u');
6044
int codepoint = 0;
6045
6046
const auto factors = { 12u, 8u, 4u, 0u };
6047
for (const auto factor : factors)
6048
{
6049
get();
6050
6051
if (current >= '0' && current <= '9')
6052
{
6053
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
6054
}
6055
else if (current >= 'A' && current <= 'F')
6056
{
6057
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
6058
}
6059
else if (current >= 'a' && current <= 'f')
6060
{
6061
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
6062
}
6063
else
6064
{
6065
return -1;
6066
}
6067
}
6068
6069
JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
6070
return codepoint;
6071
}
6072
6073
/*!
6074
@brief check if the next byte(s) are inside a given range
6075
6076
Adds the current byte and, for each passed range, reads a new byte and
6077
checks if it is inside the range. If a violation was detected, set up an
6078
error message and return false. Otherwise, return true.
6079
6080
@param[in] ranges list of integers; interpreted as list of pairs of
6081
inclusive lower and upper bound, respectively
6082
6083
@pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
6084
1, 2, or 3 pairs. This precondition is enforced by an assertion.
6085
6086
@return true if and only if no range violation was detected
6087
*/
6088
bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
6089
{
6090
JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
6091
add(current);
6092
6093
for (auto range = ranges.begin(); range != ranges.end(); ++range)
6094
{
6095
get();
6096
if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
6097
{
6098
add(current);
6099
}
6100
else
6101
{
6102
error_message = "invalid string: ill-formed UTF-8 byte";
6103
return false;
6104
}
6105
}
6106
6107
return true;
6108
}
6109
6110
/*!
6111
@brief scan a string literal
6112
6113
This function scans a string according to Sect. 7 of RFC 7159. While
6114
scanning, bytes are escaped and copied into buffer token_buffer. Then the
6115
function returns successfully, token_buffer is *not* null-terminated (as it
6116
may contain \0 bytes), and token_buffer.size() is the number of bytes in the
6117
string.
6118
6119
@return token_type::value_string if string could be successfully scanned,
6120
token_type::parse_error otherwise
6121
6122
@note In case of errors, variable error_message contains a textual
6123
description.
6124
*/
6125
token_type scan_string()
6126
{
6127
// reset token_buffer (ignore opening quote)
6128
reset();
6129
6130
// we entered the function by reading an open quote
6131
JSON_ASSERT(current == '\"');
6132
6133
while (true)
6134
{
6135
// get next character
6136
switch (get())
6137
{
6138
// end of file while parsing string
6139
case std::char_traits<char_type>::eof():
6140
{
6141
error_message = "invalid string: missing closing quote";
6142
return token_type::parse_error;
6143
}
6144
6145
// closing quote
6146
case '\"':
6147
{
6148
return token_type::value_string;
6149
}
6150
6151
// escapes
6152
case '\\':
6153
{
6154
switch (get())
6155
{
6156
// quotation mark
6157
case '\"':
6158
add('\"');
6159
break;
6160
// reverse solidus
6161
case '\\':
6162
add('\\');
6163
break;
6164
// solidus
6165
case '/':
6166
add('/');
6167
break;
6168
// backspace
6169
case 'b':
6170
add('\b');
6171
break;
6172
// form feed
6173
case 'f':
6174
add('\f');
6175
break;
6176
// line feed
6177
case 'n':
6178
add('\n');
6179
break;
6180
// carriage return
6181
case 'r':
6182
add('\r');
6183
break;
6184
// tab
6185
case 't':
6186
add('\t');
6187
break;
6188
6189
// unicode escapes
6190
case 'u':
6191
{
6192
const int codepoint1 = get_codepoint();
6193
int codepoint = codepoint1; // start with codepoint1
6194
6195
if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
6196
{
6197
error_message = "invalid string: '\\u' must be followed by 4 hex digits";
6198
return token_type::parse_error;
6199
}
6200
6201
// check if code point is a high surrogate
6202
if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
6203
{
6204
// expect next \uxxxx entry
6205
if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
6206
{
6207
const int codepoint2 = get_codepoint();
6208
6209
if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
6210
{
6211
error_message = "invalid string: '\\u' must be followed by 4 hex digits";
6212
return token_type::parse_error;
6213
}
6214
6215
// check if codepoint2 is a low surrogate
6216
if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
6217
{
6218
// overwrite codepoint
6219
codepoint = static_cast<int>(
6220
// high surrogate occupies the most significant 22 bits
6221
(static_cast<unsigned int>(codepoint1) << 10u)
6222
// low surrogate occupies the least significant 15 bits
6223
+ static_cast<unsigned int>(codepoint2)
6224
// there is still the 0xD800, 0xDC00 and 0x10000 noise
6225
// in the result so we have to subtract with:
6226
// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6227
- 0x35FDC00u);
6228
}
6229
else
6230
{
6231
error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
6232
return token_type::parse_error;
6233
}
6234
}
6235
else
6236
{
6237
error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
6238
return token_type::parse_error;
6239
}
6240
}
6241
else
6242
{
6243
if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
6244
{
6245
error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
6246
return token_type::parse_error;
6247
}
6248
}
6249
6250
// result of the above calculation yields a proper codepoint
6251
JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
6252
6253
// translate codepoint into bytes
6254
if (codepoint < 0x80)
6255
{
6256
// 1-byte characters: 0xxxxxxx (ASCII)
6257
add(static_cast<char_int_type>(codepoint));
6258
}
6259
else if (codepoint <= 0x7FF)
6260
{
6261
// 2-byte characters: 110xxxxx 10xxxxxx
6262
add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
6263
add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6264
}
6265
else if (codepoint <= 0xFFFF)
6266
{
6267
// 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6268
add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
6269
add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
6270
add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6271
}
6272
else
6273
{
6274
// 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6275
add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
6276
add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
6277
add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
6278
add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6279
}
6280
6281
break;
6282
}
6283
6284
// other characters after escape
6285
default:
6286
error_message = "invalid string: forbidden character after backslash";
6287
return token_type::parse_error;
6288
}
6289
6290
break;
6291
}
6292
6293
// invalid control characters
6294
case 0x00:
6295
{
6296
error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
6297
return token_type::parse_error;
6298
}
6299
6300
case 0x01:
6301
{
6302
error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
6303
return token_type::parse_error;
6304
}
6305
6306
case 0x02:
6307
{
6308
error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
6309
return token_type::parse_error;
6310
}
6311
6312
case 0x03:
6313
{
6314
error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
6315
return token_type::parse_error;
6316
}
6317
6318
case 0x04:
6319
{
6320
error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
6321
return token_type::parse_error;
6322
}
6323
6324
case 0x05:
6325
{
6326
error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
6327
return token_type::parse_error;
6328
}
6329
6330
case 0x06:
6331
{
6332
error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
6333
return token_type::parse_error;
6334
}
6335
6336
case 0x07:
6337
{
6338
error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
6339
return token_type::parse_error;
6340
}
6341
6342
case 0x08:
6343
{
6344
error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
6345
return token_type::parse_error;
6346
}
6347
6348
case 0x09:
6349
{
6350
error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
6351
return token_type::parse_error;
6352
}
6353
6354
case 0x0A:
6355
{
6356
error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
6357
return token_type::parse_error;
6358
}
6359
6360
case 0x0B:
6361
{
6362
error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
6363
return token_type::parse_error;
6364
}
6365
6366
case 0x0C:
6367
{
6368
error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
6369
return token_type::parse_error;
6370
}
6371
6372
case 0x0D:
6373
{
6374
error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
6375
return token_type::parse_error;
6376
}
6377
6378
case 0x0E:
6379
{
6380
error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
6381
return token_type::parse_error;
6382
}
6383
6384
case 0x0F:
6385
{
6386
error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
6387
return token_type::parse_error;
6388
}
6389
6390
case 0x10:
6391
{
6392
error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
6393
return token_type::parse_error;
6394
}
6395
6396
case 0x11:
6397
{
6398
error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
6399
return token_type::parse_error;
6400
}
6401
6402
case 0x12:
6403
{
6404
error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
6405
return token_type::parse_error;
6406
}
6407
6408
case 0x13:
6409
{
6410
error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
6411
return token_type::parse_error;
6412
}
6413
6414
case 0x14:
6415
{
6416
error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
6417
return token_type::parse_error;
6418
}
6419
6420
case 0x15:
6421
{
6422
error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
6423
return token_type::parse_error;
6424
}
6425
6426
case 0x16:
6427
{
6428
error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
6429
return token_type::parse_error;
6430
}
6431
6432
case 0x17:
6433
{
6434
error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
6435
return token_type::parse_error;
6436
}
6437
6438
case 0x18:
6439
{
6440
error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
6441
return token_type::parse_error;
6442
}
6443
6444
case 0x19:
6445
{
6446
error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
6447
return token_type::parse_error;
6448
}
6449
6450
case 0x1A:
6451
{
6452
error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
6453
return token_type::parse_error;
6454
}
6455
6456
case 0x1B:
6457
{
6458
error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
6459
return token_type::parse_error;
6460
}
6461
6462
case 0x1C:
6463
{
6464
error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
6465
return token_type::parse_error;
6466
}
6467
6468
case 0x1D:
6469
{
6470
error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
6471
return token_type::parse_error;
6472
}
6473
6474
case 0x1E:
6475
{
6476
error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
6477
return token_type::parse_error;
6478
}
6479
6480
case 0x1F:
6481
{
6482
error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
6483
return token_type::parse_error;
6484
}
6485
6486
// U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
6487
case 0x20:
6488
case 0x21:
6489
case 0x23:
6490
case 0x24:
6491
case 0x25:
6492
case 0x26:
6493
case 0x27:
6494
case 0x28:
6495
case 0x29:
6496
case 0x2A:
6497
case 0x2B:
6498
case 0x2C:
6499
case 0x2D:
6500
case 0x2E:
6501
case 0x2F:
6502
case 0x30:
6503
case 0x31:
6504
case 0x32:
6505
case 0x33:
6506
case 0x34:
6507
case 0x35:
6508
case 0x36:
6509
case 0x37:
6510
case 0x38:
6511
case 0x39:
6512
case 0x3A:
6513
case 0x3B:
6514
case 0x3C:
6515
case 0x3D:
6516
case 0x3E:
6517
case 0x3F:
6518
case 0x40:
6519
case 0x41:
6520
case 0x42:
6521
case 0x43:
6522
case 0x44:
6523
case 0x45:
6524
case 0x46:
6525
case 0x47:
6526
case 0x48:
6527
case 0x49:
6528
case 0x4A:
6529
case 0x4B:
6530
case 0x4C:
6531
case 0x4D:
6532
case 0x4E:
6533
case 0x4F:
6534
case 0x50:
6535
case 0x51:
6536
case 0x52:
6537
case 0x53:
6538
case 0x54:
6539
case 0x55:
6540
case 0x56:
6541
case 0x57:
6542
case 0x58:
6543
case 0x59:
6544
case 0x5A:
6545
case 0x5B:
6546
case 0x5D:
6547
case 0x5E:
6548
case 0x5F:
6549
case 0x60:
6550
case 0x61:
6551
case 0x62:
6552
case 0x63:
6553
case 0x64:
6554
case 0x65:
6555
case 0x66:
6556
case 0x67:
6557
case 0x68:
6558
case 0x69:
6559
case 0x6A:
6560
case 0x6B:
6561
case 0x6C:
6562
case 0x6D:
6563
case 0x6E:
6564
case 0x6F:
6565
case 0x70:
6566
case 0x71:
6567
case 0x72:
6568
case 0x73:
6569
case 0x74:
6570
case 0x75:
6571
case 0x76:
6572
case 0x77:
6573
case 0x78:
6574
case 0x79:
6575
case 0x7A:
6576
case 0x7B:
6577
case 0x7C:
6578
case 0x7D:
6579
case 0x7E:
6580
case 0x7F:
6581
{
6582
add(current);
6583
break;
6584
}
6585
6586
// U+0080..U+07FF: bytes C2..DF 80..BF
6587
case 0xC2:
6588
case 0xC3:
6589
case 0xC4:
6590
case 0xC5:
6591
case 0xC6:
6592
case 0xC7:
6593
case 0xC8:
6594
case 0xC9:
6595
case 0xCA:
6596
case 0xCB:
6597
case 0xCC:
6598
case 0xCD:
6599
case 0xCE:
6600
case 0xCF:
6601
case 0xD0:
6602
case 0xD1:
6603
case 0xD2:
6604
case 0xD3:
6605
case 0xD4:
6606
case 0xD5:
6607
case 0xD6:
6608
case 0xD7:
6609
case 0xD8:
6610
case 0xD9:
6611
case 0xDA:
6612
case 0xDB:
6613
case 0xDC:
6614
case 0xDD:
6615
case 0xDE:
6616
case 0xDF:
6617
{
6618
if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
6619
{
6620
return token_type::parse_error;
6621
}
6622
break;
6623
}
6624
6625
// U+0800..U+0FFF: bytes E0 A0..BF 80..BF
6626
case 0xE0:
6627
{
6628
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
6629
{
6630
return token_type::parse_error;
6631
}
6632
break;
6633
}
6634
6635
// U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
6636
// U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
6637
case 0xE1:
6638
case 0xE2:
6639
case 0xE3:
6640
case 0xE4:
6641
case 0xE5:
6642
case 0xE6:
6643
case 0xE7:
6644
case 0xE8:
6645
case 0xE9:
6646
case 0xEA:
6647
case 0xEB:
6648
case 0xEC:
6649
case 0xEE:
6650
case 0xEF:
6651
{
6652
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
6653
{
6654
return token_type::parse_error;
6655
}
6656
break;
6657
}
6658
6659
// U+D000..U+D7FF: bytes ED 80..9F 80..BF
6660
case 0xED:
6661
{
6662
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
6663
{
6664
return token_type::parse_error;
6665
}
6666
break;
6667
}
6668
6669
// U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
6670
case 0xF0:
6671
{
6672
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
6673
{
6674
return token_type::parse_error;
6675
}
6676
break;
6677
}
6678
6679
// U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
6680
case 0xF1:
6681
case 0xF2:
6682
case 0xF3:
6683
{
6684
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
6685
{
6686
return token_type::parse_error;
6687
}
6688
break;
6689
}
6690
6691
// U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
6692
case 0xF4:
6693
{
6694
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
6695
{
6696
return token_type::parse_error;
6697
}
6698
break;
6699
}
6700
6701
// remaining bytes (80..C1 and F5..FF) are ill-formed
6702
default:
6703
{
6704
error_message = "invalid string: ill-formed UTF-8 byte";
6705
return token_type::parse_error;
6706
}
6707
}
6708
}
6709
}
6710
6711
/*!
6712
* @brief scan a comment
6713
* @return whether comment could be scanned successfully
6714
*/
6715
bool scan_comment()
6716
{
6717
switch (get())
6718
{
6719
// single-line comments skip input until a newline or EOF is read
6720
case '/':
6721
{
6722
while (true)
6723
{
6724
switch (get())
6725
{
6726
case '\n':
6727
case '\r':
6728
case std::char_traits<char_type>::eof():
6729
case '\0':
6730
return true;
6731
6732
default:
6733
break;
6734
}
6735
}
6736
}
6737
6738
// multi-line comments skip input until */ is read
6739
case '*':
6740
{
6741
while (true)
6742
{
6743
switch (get())
6744
{
6745
case std::char_traits<char_type>::eof():
6746
case '\0':
6747
{
6748
error_message = "invalid comment; missing closing '*/'";
6749
return false;
6750
}
6751
6752
case '*':
6753
{
6754
switch (get())
6755
{
6756
case '/':
6757
return true;
6758
6759
default:
6760
{
6761
unget();
6762
continue;
6763
}
6764
}
6765
}
6766
6767
default:
6768
continue;
6769
}
6770
}
6771
}
6772
6773
// unexpected character after reading '/'
6774
default:
6775
{
6776
error_message = "invalid comment; expecting '/' or '*' after '/'";
6777
return false;
6778
}
6779
}
6780
}
6781
6782
JSON_HEDLEY_NON_NULL(2)
6783
static void strtof(float& f, const char* str, char** endptr) noexcept
6784
{
6785
f = std::strtof(str, endptr);
6786
}
6787
6788
JSON_HEDLEY_NON_NULL(2)
6789
static void strtof(double& f, const char* str, char** endptr) noexcept
6790
{
6791
f = std::strtod(str, endptr);
6792
}
6793
6794
JSON_HEDLEY_NON_NULL(2)
6795
static void strtof(long double& f, const char* str, char** endptr) noexcept
6796
{
6797
f = std::strtold(str, endptr);
6798
}
6799
6800
/*!
6801
@brief scan a number literal
6802
6803
This function scans a string according to Sect. 6 of RFC 7159.
6804
6805
The function is realized with a deterministic finite state machine derived
6806
from the grammar described in RFC 7159. Starting in state "init", the
6807
input is read and used to determined the next state. Only state "done"
6808
accepts the number. State "error" is a trap state to model errors. In the
6809
table below, "anything" means any character but the ones listed before.
6810
6811
state | 0 | 1-9 | e E | + | - | . | anything
6812
---------|----------|----------|----------|---------|---------|----------|-----------
6813
init | zero | any1 | [error] | [error] | minus | [error] | [error]
6814
minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
6815
zero | done | done | exponent | done | done | decimal1 | done
6816
any1 | any1 | any1 | exponent | done | done | decimal1 | done
6817
decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error]
6818
decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
6819
exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
6820
sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
6821
any2 | any2 | any2 | done | done | done | done | done
6822
6823
The state machine is realized with one label per state (prefixed with
6824
"scan_number_") and `goto` statements between them. The state machine
6825
contains cycles, but any cycle can be left when EOF is read. Therefore,
6826
the function is guaranteed to terminate.
6827
6828
During scanning, the read bytes are stored in token_buffer. This string is
6829
then converted to a signed integer, an unsigned integer, or a
6830
floating-point number.
6831
6832
@return token_type::value_unsigned, token_type::value_integer, or
6833
token_type::value_float if number could be successfully scanned,
6834
token_type::parse_error otherwise
6835
6836
@note The scanner is independent of the current locale. Internally, the
6837
locale's decimal point is used instead of `.` to work with the
6838
locale-dependent converters.
6839
*/
6840
token_type scan_number() // lgtm [cpp/use-of-goto]
6841
{
6842
// reset token_buffer to store the number's bytes
6843
reset();
6844
6845
// the type of the parsed number; initially set to unsigned; will be
6846
// changed if minus sign, decimal point or exponent is read
6847
token_type number_type = token_type::value_unsigned;
6848
6849
// state (init): we just found out we need to scan a number
6850
switch (current)
6851
{
6852
case '-':
6853
{
6854
add(current);
6855
goto scan_number_minus;
6856
}
6857
6858
case '0':
6859
{
6860
add(current);
6861
goto scan_number_zero;
6862
}
6863
6864
case '1':
6865
case '2':
6866
case '3':
6867
case '4':
6868
case '5':
6869
case '6':
6870
case '7':
6871
case '8':
6872
case '9':
6873
{
6874
add(current);
6875
goto scan_number_any1;
6876
}
6877
6878
// all other characters are rejected outside scan_number()
6879
default: // LCOV_EXCL_LINE
6880
JSON_ASSERT(false); // LCOV_EXCL_LINE
6881
}
6882
6883
scan_number_minus:
6884
// state: we just parsed a leading minus sign
6885
number_type = token_type::value_integer;
6886
switch (get())
6887
{
6888
case '0':
6889
{
6890
add(current);
6891
goto scan_number_zero;
6892
}
6893
6894
case '1':
6895
case '2':
6896
case '3':
6897
case '4':
6898
case '5':
6899
case '6':
6900
case '7':
6901
case '8':
6902
case '9':
6903
{
6904
add(current);
6905
goto scan_number_any1;
6906
}
6907
6908
default:
6909
{
6910
error_message = "invalid number; expected digit after '-'";
6911
return token_type::parse_error;
6912
}
6913
}
6914
6915
scan_number_zero:
6916
// state: we just parse a zero (maybe with a leading minus sign)
6917
switch (get())
6918
{
6919
case '.':
6920
{
6921
add(decimal_point_char);
6922
goto scan_number_decimal1;
6923
}
6924
6925
case 'e':
6926
case 'E':
6927
{
6928
add(current);
6929
goto scan_number_exponent;
6930
}
6931
6932
default:
6933
goto scan_number_done;
6934
}
6935
6936
scan_number_any1:
6937
// state: we just parsed a number 0-9 (maybe with a leading minus sign)
6938
switch (get())
6939
{
6940
case '0':
6941
case '1':
6942
case '2':
6943
case '3':
6944
case '4':
6945
case '5':
6946
case '6':
6947
case '7':
6948
case '8':
6949
case '9':
6950
{
6951
add(current);
6952
goto scan_number_any1;
6953
}
6954
6955
case '.':
6956
{
6957
add(decimal_point_char);
6958
goto scan_number_decimal1;
6959
}
6960
6961
case 'e':
6962
case 'E':
6963
{
6964
add(current);
6965
goto scan_number_exponent;
6966
}
6967
6968
default:
6969
goto scan_number_done;
6970
}
6971
6972
scan_number_decimal1:
6973
// state: we just parsed a decimal point
6974
number_type = token_type::value_float;
6975
switch (get())
6976
{
6977
case '0':
6978
case '1':
6979
case '2':
6980
case '3':
6981
case '4':
6982
case '5':
6983
case '6':
6984
case '7':
6985
case '8':
6986
case '9':
6987
{
6988
add(current);
6989
goto scan_number_decimal2;
6990
}
6991
6992
default:
6993
{
6994
error_message = "invalid number; expected digit after '.'";
6995
return token_type::parse_error;
6996
}
6997
}
6998
6999
scan_number_decimal2:
7000
// we just parsed at least one number after a decimal point
7001
switch (get())
7002
{
7003
case '0':
7004
case '1':
7005
case '2':
7006
case '3':
7007
case '4':
7008
case '5':
7009
case '6':
7010
case '7':
7011
case '8':
7012
case '9':
7013
{
7014
add(current);
7015
goto scan_number_decimal2;
7016
}
7017
7018
case 'e':
7019
case 'E':
7020
{
7021
add(current);
7022
goto scan_number_exponent;
7023
}
7024
7025
default:
7026
goto scan_number_done;
7027
}
7028
7029
scan_number_exponent:
7030
// we just parsed an exponent
7031
number_type = token_type::value_float;
7032
switch (get())
7033
{
7034
case '+':
7035
case '-':
7036
{
7037
add(current);
7038
goto scan_number_sign;
7039
}
7040
7041
case '0':
7042
case '1':
7043
case '2':
7044
case '3':
7045
case '4':
7046
case '5':
7047
case '6':
7048
case '7':
7049
case '8':
7050
case '9':
7051
{
7052
add(current);
7053
goto scan_number_any2;
7054
}
7055
7056
default:
7057
{
7058
error_message =
7059
"invalid number; expected '+', '-', or digit after exponent";
7060
return token_type::parse_error;
7061
}
7062
}
7063
7064
scan_number_sign:
7065
// we just parsed an exponent sign
7066
switch (get())
7067
{
7068
case '0':
7069
case '1':
7070
case '2':
7071
case '3':
7072
case '4':
7073
case '5':
7074
case '6':
7075
case '7':
7076
case '8':
7077
case '9':
7078
{
7079
add(current);
7080
goto scan_number_any2;
7081
}
7082
7083
default:
7084
{
7085
error_message = "invalid number; expected digit after exponent sign";
7086
return token_type::parse_error;
7087
}
7088
}
7089
7090
scan_number_any2:
7091
// we just parsed a number after the exponent or exponent sign
7092
switch (get())
7093
{
7094
case '0':
7095
case '1':
7096
case '2':
7097
case '3':
7098
case '4':
7099
case '5':
7100
case '6':
7101
case '7':
7102
case '8':
7103
case '9':
7104
{
7105
add(current);
7106
goto scan_number_any2;
7107
}
7108
7109
default:
7110
goto scan_number_done;
7111
}
7112
7113
scan_number_done:
7114
// unget the character after the number (we only read it to know that
7115
// we are done scanning a number)
7116
unget();
7117
7118
char* endptr = nullptr;
7119
errno = 0;
7120
7121
// try to parse integers first and fall back to floats
7122
if (number_type == token_type::value_unsigned)
7123
{
7124
const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
7125
7126
// we checked the number format before
7127
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7128
7129
if (errno == 0)
7130
{
7131
value_unsigned = static_cast<number_unsigned_t>(x);
7132
if (value_unsigned == x)
7133
{
7134
return token_type::value_unsigned;
7135
}
7136
}
7137
}
7138
else if (number_type == token_type::value_integer)
7139
{
7140
const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
7141
7142
// we checked the number format before
7143
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7144
7145
if (errno == 0)
7146
{
7147
value_integer = static_cast<number_integer_t>(x);
7148
if (value_integer == x)
7149
{
7150
return token_type::value_integer;
7151
}
7152
}
7153
}
7154
7155
// this code is reached if we parse a floating-point number or if an
7156
// integer conversion above failed
7157
strtof(value_float, token_buffer.data(), &endptr);
7158
7159
// we checked the number format before
7160
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7161
7162
return token_type::value_float;
7163
}
7164
7165
/*!
7166
@param[in] literal_text the literal text to expect
7167
@param[in] length the length of the passed literal text
7168
@param[in] return_type the token type to return on success
7169
*/
7170
JSON_HEDLEY_NON_NULL(2)
7171
token_type scan_literal(const char_type* literal_text, const std::size_t length,
7172
token_type return_type)
7173
{
7174
JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
7175
for (std::size_t i = 1; i < length; ++i)
7176
{
7177
if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
7178
{
7179
error_message = "invalid literal";
7180
return token_type::parse_error;
7181
}
7182
}
7183
return return_type;
7184
}
7185
7186
/////////////////////
7187
// input management
7188
/////////////////////
7189
7190
/// reset token_buffer; current character is beginning of token
7191
void reset() noexcept
7192
{
7193
token_buffer.clear();
7194
token_string.clear();
7195
token_string.push_back(std::char_traits<char_type>::to_char_type(current));
7196
}
7197
7198
/*
7199
@brief get next character from the input
7200
7201
This function provides the interface to the used input adapter. It does
7202
not throw in case the input reached EOF, but returns a
7203
`std::char_traits<char>::eof()` in that case. Stores the scanned characters
7204
for use in error messages.
7205
7206
@return character read from the input
7207
*/
7208
char_int_type get()
7209
{
7210
++position.chars_read_total;
7211
++position.chars_read_current_line;
7212
7213
if (next_unget)
7214
{
7215
// just reset the next_unget variable and work with current
7216
next_unget = false;
7217
}
7218
else
7219
{
7220
current = ia.get_character();
7221
}
7222
7223
if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
7224
{
7225
token_string.push_back(std::char_traits<char_type>::to_char_type(current));
7226
}
7227
7228
if (current == '\n')
7229
{
7230
++position.lines_read;
7231
position.chars_read_current_line = 0;
7232
}
7233
7234
return current;
7235
}
7236
7237
/*!
7238
@brief unget current character (read it again on next get)
7239
7240
We implement unget by setting variable next_unget to true. The input is not
7241
changed - we just simulate ungetting by modifying chars_read_total,
7242
chars_read_current_line, and token_string. The next call to get() will
7243
behave as if the unget character is read again.
7244
*/
7245
void unget()
7246
{
7247
next_unget = true;
7248
7249
--position.chars_read_total;
7250
7251
// in case we "unget" a newline, we have to also decrement the lines_read
7252
if (position.chars_read_current_line == 0)
7253
{
7254
if (position.lines_read > 0)
7255
{
7256
--position.lines_read;
7257
}
7258
}
7259
else
7260
{
7261
--position.chars_read_current_line;
7262
}
7263
7264
if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
7265
{
7266
JSON_ASSERT(!token_string.empty());
7267
token_string.pop_back();
7268
}
7269
}
7270
7271
/// add a character to token_buffer
7272
void add(char_int_type c)
7273
{
7274
token_buffer.push_back(static_cast<typename string_t::value_type>(c));
7275
}
7276
7277
public:
7278
/////////////////////
7279
// value getters
7280
/////////////////////
7281
7282
/// return integer value
7283
constexpr number_integer_t get_number_integer() const noexcept
7284
{
7285
return value_integer;
7286
}
7287
7288
/// return unsigned integer value
7289
constexpr number_unsigned_t get_number_unsigned() const noexcept
7290
{
7291
return value_unsigned;
7292
}
7293
7294
/// return floating-point value
7295
constexpr number_float_t get_number_float() const noexcept
7296
{
7297
return value_float;
7298
}
7299
7300
/// return current string value (implicitly resets the token; useful only once)
7301
string_t& get_string()
7302
{
7303
return token_buffer;
7304
}
7305
7306
/////////////////////
7307
// diagnostics
7308
/////////////////////
7309
7310
/// return position of last read token
7311
constexpr position_t get_position() const noexcept
7312
{
7313
return position;
7314
}
7315
7316
/// return the last read token (for errors only). Will never contain EOF
7317
/// (an arbitrary value that is not a valid char value, often -1), because
7318
/// 255 may legitimately occur. May contain NUL, which should be escaped.
7319
std::string get_token_string() const
7320
{
7321
// escape control characters
7322
std::string result;
7323
for (const auto c : token_string)
7324
{
7325
if (static_cast<unsigned char>(c) <= '\x1F')
7326
{
7327
// escape control characters
7328
std::array<char, 9> cs{{}};
7329
(std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c));
7330
result += cs.data();
7331
}
7332
else
7333
{
7334
// add character as is
7335
result.push_back(static_cast<std::string::value_type>(c));
7336
}
7337
}
7338
7339
return result;
7340
}
7341
7342
/// return syntax error message
7343
JSON_HEDLEY_RETURNS_NON_NULL
7344
constexpr const char* get_error_message() const noexcept
7345
{
7346
return error_message;
7347
}
7348
7349
/////////////////////
7350
// actual scanner
7351
/////////////////////
7352
7353
/*!
7354
@brief skip the UTF-8 byte order mark
7355
@return true iff there is no BOM or the correct BOM has been skipped
7356
*/
7357
bool skip_bom()
7358
{
7359
if (get() == 0xEF)
7360
{
7361
// check if we completely parse the BOM
7362
return get() == 0xBB && get() == 0xBF;
7363
}
7364
7365
// the first character is not the beginning of the BOM; unget it to
7366
// process is later
7367
unget();
7368
return true;
7369
}
7370
7371
void skip_whitespace()
7372
{
7373
do
7374
{
7375
get();
7376
}
7377
while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
7378
}
7379
7380
token_type scan()
7381
{
7382
// initially, skip the BOM
7383
if (position.chars_read_total == 0 && !skip_bom())
7384
{
7385
error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
7386
return token_type::parse_error;
7387
}
7388
7389
// read next character and ignore whitespace
7390
skip_whitespace();
7391
7392
// ignore comments
7393
while (ignore_comments && current == '/')
7394
{
7395
if (!scan_comment())
7396
{
7397
return token_type::parse_error;
7398
}
7399
7400
// skip following whitespace
7401
skip_whitespace();
7402
}
7403
7404
switch (current)
7405
{
7406
// structural characters
7407
case '[':
7408
return token_type::begin_array;
7409
case ']':
7410
return token_type::end_array;
7411
case '{':
7412
return token_type::begin_object;
7413
case '}':
7414
return token_type::end_object;
7415
case ':':
7416
return token_type::name_separator;
7417
case ',':
7418
return token_type::value_separator;
7419
7420
// literals
7421
case 't':
7422
{
7423
std::array<char_type, 4> true_literal = {{'t', 'r', 'u', 'e'}};
7424
return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
7425
}
7426
case 'f':
7427
{
7428
std::array<char_type, 5> false_literal = {{'f', 'a', 'l', 's', 'e'}};
7429
return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
7430
}
7431
case 'n':
7432
{
7433
std::array<char_type, 4> null_literal = {{'n', 'u', 'l', 'l'}};
7434
return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
7435
}
7436
7437
// string
7438
case '\"':
7439
return scan_string();
7440
7441
// number
7442
case '-':
7443
case '0':
7444
case '1':
7445
case '2':
7446
case '3':
7447
case '4':
7448
case '5':
7449
case '6':
7450
case '7':
7451
case '8':
7452
case '9':
7453
return scan_number();
7454
7455
// end of input (the null byte is needed when parsing from
7456
// string literals)
7457
case '\0':
7458
case std::char_traits<char_type>::eof():
7459
return token_type::end_of_input;
7460
7461
// error
7462
default:
7463
error_message = "invalid literal";
7464
return token_type::parse_error;
7465
}
7466
}
7467
7468
private:
7469
/// input adapter
7470
InputAdapterType ia;
7471
7472
/// whether comments should be ignored (true) or signaled as errors (false)
7473
const bool ignore_comments = false;
7474
7475
/// the current character
7476
char_int_type current = std::char_traits<char_type>::eof();
7477
7478
/// whether the next get() call should just return current
7479
bool next_unget = false;
7480
7481
/// the start position of the current token
7482
position_t position {};
7483
7484
/// raw input token string (for error messages)
7485
std::vector<char_type> token_string {};
7486
7487
/// buffer for variable-length tokens (numbers, strings)
7488
string_t token_buffer {};
7489
7490
/// a description of occurred lexer errors
7491
const char* error_message = "";
7492
7493
// number values
7494
number_integer_t value_integer = 0;
7495
number_unsigned_t value_unsigned = 0;
7496
number_float_t value_float = 0;
7497
7498
/// the decimal point
7499
const char_int_type decimal_point_char = '.';
7500
};
7501
} // namespace detail
7502
} // namespace nlohmann
7503
7504
// #include <nlohmann/detail/macro_scope.hpp>
7505
7506
// #include <nlohmann/detail/meta/is_sax.hpp>
7507
7508
7509
#include <cstdint> // size_t
7510
#include <utility> // declval
7511
#include <string> // string
7512
7513
// #include <nlohmann/detail/meta/detected.hpp>
7514
7515
// #include <nlohmann/detail/meta/type_traits.hpp>
7516
7517
7518
namespace nlohmann
7519
{
7520
namespace detail
7521
{
7522
template<typename T>
7523
using null_function_t = decltype(std::declval<T&>().null());
7524
7525
template<typename T>
7526
using boolean_function_t =
7527
decltype(std::declval<T&>().boolean(std::declval<bool>()));
7528
7529
template<typename T, typename Integer>
7530
using number_integer_function_t =
7531
decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
7532
7533
template<typename T, typename Unsigned>
7534
using number_unsigned_function_t =
7535
decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
7536
7537
template<typename T, typename Float, typename String>
7538
using number_float_function_t = decltype(std::declval<T&>().number_float(
7539
std::declval<Float>(), std::declval<const String&>()));
7540
7541
template<typename T, typename String>
7542
using string_function_t =
7543
decltype(std::declval<T&>().string(std::declval<String&>()));
7544
7545
template<typename T, typename Binary>
7546
using binary_function_t =
7547
decltype(std::declval<T&>().binary(std::declval<Binary&>()));
7548
7549
template<typename T>
7550
using start_object_function_t =
7551
decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
7552
7553
template<typename T, typename String>
7554
using key_function_t =
7555
decltype(std::declval<T&>().key(std::declval<String&>()));
7556
7557
template<typename T>
7558
using end_object_function_t = decltype(std::declval<T&>().end_object());
7559
7560
template<typename T>
7561
using start_array_function_t =
7562
decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
7563
7564
template<typename T>
7565
using end_array_function_t = decltype(std::declval<T&>().end_array());
7566
7567
template<typename T, typename Exception>
7568
using parse_error_function_t = decltype(std::declval<T&>().parse_error(
7569
std::declval<std::size_t>(), std::declval<const std::string&>(),
7570
std::declval<const Exception&>()));
7571
7572
template<typename SAX, typename BasicJsonType>
7573
struct is_sax
7574
{
7575
private:
7576
static_assert(is_basic_json<BasicJsonType>::value,
7577
"BasicJsonType must be of type basic_json<...>");
7578
7579
using number_integer_t = typename BasicJsonType::number_integer_t;
7580
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7581
using number_float_t = typename BasicJsonType::number_float_t;
7582
using string_t = typename BasicJsonType::string_t;
7583
using binary_t = typename BasicJsonType::binary_t;
7584
using exception_t = typename BasicJsonType::exception;
7585
7586
public:
7587
static constexpr bool value =
7588
is_detected_exact<bool, null_function_t, SAX>::value &&
7589
is_detected_exact<bool, boolean_function_t, SAX>::value &&
7590
is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
7591
is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
7592
is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
7593
is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
7594
is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
7595
is_detected_exact<bool, start_object_function_t, SAX>::value &&
7596
is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
7597
is_detected_exact<bool, end_object_function_t, SAX>::value &&
7598
is_detected_exact<bool, start_array_function_t, SAX>::value &&
7599
is_detected_exact<bool, end_array_function_t, SAX>::value &&
7600
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
7601
};
7602
7603
template<typename SAX, typename BasicJsonType>
7604
struct is_sax_static_asserts
7605
{
7606
private:
7607
static_assert(is_basic_json<BasicJsonType>::value,
7608
"BasicJsonType must be of type basic_json<...>");
7609
7610
using number_integer_t = typename BasicJsonType::number_integer_t;
7611
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7612
using number_float_t = typename BasicJsonType::number_float_t;
7613
using string_t = typename BasicJsonType::string_t;
7614
using binary_t = typename BasicJsonType::binary_t;
7615
using exception_t = typename BasicJsonType::exception;
7616
7617
public:
7618
static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
7619
"Missing/invalid function: bool null()");
7620
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
7621
"Missing/invalid function: bool boolean(bool)");
7622
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
7623
"Missing/invalid function: bool boolean(bool)");
7624
static_assert(
7625
is_detected_exact<bool, number_integer_function_t, SAX,
7626
number_integer_t>::value,
7627
"Missing/invalid function: bool number_integer(number_integer_t)");
7628
static_assert(
7629
is_detected_exact<bool, number_unsigned_function_t, SAX,
7630
number_unsigned_t>::value,
7631
"Missing/invalid function: bool number_unsigned(number_unsigned_t)");
7632
static_assert(is_detected_exact<bool, number_float_function_t, SAX,
7633
number_float_t, string_t>::value,
7634
"Missing/invalid function: bool number_float(number_float_t, const string_t&)");
7635
static_assert(
7636
is_detected_exact<bool, string_function_t, SAX, string_t>::value,
7637
"Missing/invalid function: bool string(string_t&)");
7638
static_assert(
7639
is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
7640
"Missing/invalid function: bool binary(binary_t&)");
7641
static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
7642
"Missing/invalid function: bool start_object(std::size_t)");
7643
static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
7644
"Missing/invalid function: bool key(string_t&)");
7645
static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
7646
"Missing/invalid function: bool end_object()");
7647
static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
7648
"Missing/invalid function: bool start_array(std::size_t)");
7649
static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
7650
"Missing/invalid function: bool end_array()");
7651
static_assert(
7652
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
7653
"Missing/invalid function: bool parse_error(std::size_t, const "
7654
"std::string&, const exception&)");
7655
};
7656
} // namespace detail
7657
} // namespace nlohmann
7658
7659
// #include <nlohmann/detail/value_t.hpp>
7660
7661
7662
namespace nlohmann
7663
{
7664
namespace detail
7665
{
7666
7667
/// how to treat CBOR tags
7668
enum class cbor_tag_handler_t
7669
{
7670
error, ///< throw a parse_error exception in case of a tag
7671
ignore ///< ignore tags
7672
};
7673
7674
/*!
7675
@brief determine system byte order
7676
7677
@return true if and only if system's byte order is little endian
7678
7679
@note from https://stackoverflow.com/a/1001328/266378
7680
*/
7681
static inline bool little_endianess(int num = 1) noexcept
7682
{
7683
return *reinterpret_cast<char*>(&num) == 1;
7684
}
7685
7686
7687
///////////////////
7688
// binary reader //
7689
///////////////////
7690
7691
/*!
7692
@brief deserialization of CBOR, MessagePack, and UBJSON values
7693
*/
7694
template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
7695
class binary_reader
7696
{
7697
using number_integer_t = typename BasicJsonType::number_integer_t;
7698
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7699
using number_float_t = typename BasicJsonType::number_float_t;
7700
using string_t = typename BasicJsonType::string_t;
7701
using binary_t = typename BasicJsonType::binary_t;
7702
using json_sax_t = SAX;
7703
using char_type = typename InputAdapterType::char_type;
7704
using char_int_type = typename std::char_traits<char_type>::int_type;
7705
7706
public:
7707
/*!
7708
@brief create a binary reader
7709
7710
@param[in] adapter input adapter to read from
7711
*/
7712
explicit binary_reader(InputAdapterType&& adapter) : ia(std::move(adapter))
7713
{
7714
(void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
7715
}
7716
7717
// make class move-only
7718
binary_reader(const binary_reader&) = delete;
7719
binary_reader(binary_reader&&) = default;
7720
binary_reader& operator=(const binary_reader&) = delete;
7721
binary_reader& operator=(binary_reader&&) = default;
7722
~binary_reader() = default;
7723
7724
/*!
7725
@param[in] format the binary format to parse
7726
@param[in] sax_ a SAX event processor
7727
@param[in] strict whether to expect the input to be consumed completed
7728
@param[in] tag_handler how to treat CBOR tags
7729
7730
@return
7731
*/
7732
JSON_HEDLEY_NON_NULL(3)
7733
bool sax_parse(const input_format_t format,
7734
json_sax_t* sax_,
7735
const bool strict = true,
7736
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
7737
{
7738
sax = sax_;
7739
bool result = false;
7740
7741
switch (format)
7742
{
7743
case input_format_t::bson:
7744
result = parse_bson_internal();
7745
break;
7746
7747
case input_format_t::cbor:
7748
result = parse_cbor_internal(true, tag_handler);
7749
break;
7750
7751
case input_format_t::msgpack:
7752
result = parse_msgpack_internal();
7753
break;
7754
7755
case input_format_t::ubjson:
7756
result = parse_ubjson_internal();
7757
break;
7758
7759
default: // LCOV_EXCL_LINE
7760
JSON_ASSERT(false); // LCOV_EXCL_LINE
7761
}
7762
7763
// strict mode: next byte must be EOF
7764
if (result && strict)
7765
{
7766
if (format == input_format_t::ubjson)
7767
{
7768
get_ignore_noop();
7769
}
7770
else
7771
{
7772
get();
7773
}
7774
7775
if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
7776
{
7777
return sax->parse_error(chars_read, get_token_string(),
7778
parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value")));
7779
}
7780
}
7781
7782
return result;
7783
}
7784
7785
private:
7786
//////////
7787
// BSON //
7788
//////////
7789
7790
/*!
7791
@brief Reads in a BSON-object and passes it to the SAX-parser.
7792
@return whether a valid BSON-value was passed to the SAX parser
7793
*/
7794
bool parse_bson_internal()
7795
{
7796
std::int32_t document_size{};
7797
get_number<std::int32_t, true>(input_format_t::bson, document_size);
7798
7799
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
7800
{
7801
return false;
7802
}
7803
7804
if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
7805
{
7806
return false;
7807
}
7808
7809
return sax->end_object();
7810
}
7811
7812
/*!
7813
@brief Parses a C-style string from the BSON input.
7814
@param[in, out] result A reference to the string variable where the read
7815
string is to be stored.
7816
@return `true` if the \x00-byte indicating the end of the string was
7817
encountered before the EOF; false` indicates an unexpected EOF.
7818
*/
7819
bool get_bson_cstr(string_t& result)
7820
{
7821
auto out = std::back_inserter(result);
7822
while (true)
7823
{
7824
get();
7825
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
7826
{
7827
return false;
7828
}
7829
if (current == 0x00)
7830
{
7831
return true;
7832
}
7833
*out++ = static_cast<typename string_t::value_type>(current);
7834
}
7835
}
7836
7837
/*!
7838
@brief Parses a zero-terminated string of length @a len from the BSON
7839
input.
7840
@param[in] len The length (including the zero-byte at the end) of the
7841
string to be read.
7842
@param[in, out] result A reference to the string variable where the read
7843
string is to be stored.
7844
@tparam NumberType The type of the length @a len
7845
@pre len >= 1
7846
@return `true` if the string was successfully parsed
7847
*/
7848
template<typename NumberType>
7849
bool get_bson_string(const NumberType len, string_t& result)
7850
{
7851
if (JSON_HEDLEY_UNLIKELY(len < 1))
7852
{
7853
auto last_token = get_token_string();
7854
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")));
7855
}
7856
7857
return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
7858
}
7859
7860
/*!
7861
@brief Parses a byte array input of length @a len from the BSON input.
7862
@param[in] len The length of the byte array to be read.
7863
@param[in, out] result A reference to the binary variable where the read
7864
array is to be stored.
7865
@tparam NumberType The type of the length @a len
7866
@pre len >= 0
7867
@return `true` if the byte array was successfully parsed
7868
*/
7869
template<typename NumberType>
7870
bool get_bson_binary(const NumberType len, binary_t& result)
7871
{
7872
if (JSON_HEDLEY_UNLIKELY(len < 0))
7873
{
7874
auto last_token = get_token_string();
7875
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")));
7876
}
7877
7878
// All BSON binary values have a subtype
7879
std::uint8_t subtype{};
7880
get_number<std::uint8_t>(input_format_t::bson, subtype);
7881
result.set_subtype(subtype);
7882
7883
return get_binary(input_format_t::bson, len, result);
7884
}
7885
7886
/*!
7887
@brief Read a BSON document element of the given @a element_type.
7888
@param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
7889
@param[in] element_type_parse_position The position in the input stream,
7890
where the `element_type` was read.
7891
@warning Not all BSON element types are supported yet. An unsupported
7892
@a element_type will give rise to a parse_error.114:
7893
Unsupported BSON record type 0x...
7894
@return whether a valid BSON-object/array was passed to the SAX parser
7895
*/
7896
bool parse_bson_element_internal(const char_int_type element_type,
7897
const std::size_t element_type_parse_position)
7898
{
7899
switch (element_type)
7900
{
7901
case 0x01: // double
7902
{
7903
double number{};
7904
return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
7905
}
7906
7907
case 0x02: // string
7908
{
7909
std::int32_t len{};
7910
string_t value;
7911
return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
7912
}
7913
7914
case 0x03: // object
7915
{
7916
return parse_bson_internal();
7917
}
7918
7919
case 0x04: // array
7920
{
7921
return parse_bson_array();
7922
}
7923
7924
case 0x05: // binary
7925
{
7926
std::int32_t len{};
7927
binary_t value;
7928
return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
7929
}
7930
7931
case 0x08: // boolean
7932
{
7933
return sax->boolean(get() != 0);
7934
}
7935
7936
case 0x0A: // null
7937
{
7938
return sax->null();
7939
}
7940
7941
case 0x10: // int32
7942
{
7943
std::int32_t value{};
7944
return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
7945
}
7946
7947
case 0x12: // int64
7948
{
7949
std::int64_t value{};
7950
return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
7951
}
7952
7953
default: // anything else not supported (yet)
7954
{
7955
std::array<char, 3> cr{{}};
7956
(std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type));
7957
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())));
7958
}
7959
}
7960
}
7961
7962
/*!
7963
@brief Read a BSON element list (as specified in the BSON-spec)
7964
7965
The same binary layout is used for objects and arrays, hence it must be
7966
indicated with the argument @a is_array which one is expected
7967
(true --> array, false --> object).
7968
7969
@param[in] is_array Determines if the element list being read is to be
7970
treated as an object (@a is_array == false), or as an
7971
array (@a is_array == true).
7972
@return whether a valid BSON-object/array was passed to the SAX parser
7973
*/
7974
bool parse_bson_element_list(const bool is_array)
7975
{
7976
string_t key;
7977
7978
while (auto element_type = get())
7979
{
7980
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
7981
{
7982
return false;
7983
}
7984
7985
const std::size_t element_type_parse_position = chars_read;
7986
if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
7987
{
7988
return false;
7989
}
7990
7991
if (!is_array && !sax->key(key))
7992
{
7993
return false;
7994
}
7995
7996
if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
7997
{
7998
return false;
7999
}
8000
8001
// get_bson_cstr only appends
8002
key.clear();
8003
}
8004
8005
return true;
8006
}
8007
8008
/*!
8009
@brief Reads an array from the BSON input and passes it to the SAX-parser.
8010
@return whether a valid BSON-array was passed to the SAX parser
8011
*/
8012
bool parse_bson_array()
8013
{
8014
std::int32_t document_size{};
8015
get_number<std::int32_t, true>(input_format_t::bson, document_size);
8016
8017
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
8018
{
8019
return false;
8020
}
8021
8022
if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
8023
{
8024
return false;
8025
}
8026
8027
return sax->end_array();
8028
}
8029
8030
//////////
8031
// CBOR //
8032
//////////
8033
8034
/*!
8035
@param[in] get_char whether a new character should be retrieved from the
8036
input (true) or whether the last read character should
8037
be considered instead (false)
8038
@param[in] tag_handler how CBOR tags should be treated
8039
8040
@return whether a valid CBOR value was passed to the SAX parser
8041
*/
8042
bool parse_cbor_internal(const bool get_char,
8043
const cbor_tag_handler_t tag_handler)
8044
{
8045
switch (get_char ? get() : current)
8046
{
8047
// EOF
8048
case std::char_traits<char_type>::eof():
8049
return unexpect_eof(input_format_t::cbor, "value");
8050
8051
// Integer 0x00..0x17 (0..23)
8052
case 0x00:
8053
case 0x01:
8054
case 0x02:
8055
case 0x03:
8056
case 0x04:
8057
case 0x05:
8058
case 0x06:
8059
case 0x07:
8060
case 0x08:
8061
case 0x09:
8062
case 0x0A:
8063
case 0x0B:
8064
case 0x0C:
8065
case 0x0D:
8066
case 0x0E:
8067
case 0x0F:
8068
case 0x10:
8069
case 0x11:
8070
case 0x12:
8071
case 0x13:
8072
case 0x14:
8073
case 0x15:
8074
case 0x16:
8075
case 0x17:
8076
return sax->number_unsigned(static_cast<number_unsigned_t>(current));
8077
8078
case 0x18: // Unsigned integer (one-byte uint8_t follows)
8079
{
8080
std::uint8_t number{};
8081
return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8082
}
8083
8084
case 0x19: // Unsigned integer (two-byte uint16_t follows)
8085
{
8086
std::uint16_t number{};
8087
return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8088
}
8089
8090
case 0x1A: // Unsigned integer (four-byte uint32_t follows)
8091
{
8092
std::uint32_t number{};
8093
return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8094
}
8095
8096
case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
8097
{
8098
std::uint64_t number{};
8099
return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8100
}
8101
8102
// Negative integer -1-0x00..-1-0x17 (-1..-24)
8103
case 0x20:
8104
case 0x21:
8105
case 0x22:
8106
case 0x23:
8107
case 0x24:
8108
case 0x25:
8109
case 0x26:
8110
case 0x27:
8111
case 0x28:
8112
case 0x29:
8113
case 0x2A:
8114
case 0x2B:
8115
case 0x2C:
8116
case 0x2D:
8117
case 0x2E:
8118
case 0x2F:
8119
case 0x30:
8120
case 0x31:
8121
case 0x32:
8122
case 0x33:
8123
case 0x34:
8124
case 0x35:
8125
case 0x36:
8126
case 0x37:
8127
return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
8128
8129
case 0x38: // Negative integer (one-byte uint8_t follows)
8130
{
8131
std::uint8_t number{};
8132
return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8133
}
8134
8135
case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
8136
{
8137
std::uint16_t number{};
8138
return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8139
}
8140
8141
case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
8142
{
8143
std::uint32_t number{};
8144
return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8145
}
8146
8147
case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
8148
{
8149
std::uint64_t number{};
8150
return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
8151
- static_cast<number_integer_t>(number));
8152
}
8153
8154
// Binary data (0x00..0x17 bytes follow)
8155
case 0x40:
8156
case 0x41:
8157
case 0x42:
8158
case 0x43:
8159
case 0x44:
8160
case 0x45:
8161
case 0x46:
8162
case 0x47:
8163
case 0x48:
8164
case 0x49:
8165
case 0x4A:
8166
case 0x4B:
8167
case 0x4C:
8168
case 0x4D:
8169
case 0x4E:
8170
case 0x4F:
8171
case 0x50:
8172
case 0x51:
8173
case 0x52:
8174
case 0x53:
8175
case 0x54:
8176
case 0x55:
8177
case 0x56:
8178
case 0x57:
8179
case 0x58: // Binary data (one-byte uint8_t for n follows)
8180
case 0x59: // Binary data (two-byte uint16_t for n follow)
8181
case 0x5A: // Binary data (four-byte uint32_t for n follow)
8182
case 0x5B: // Binary data (eight-byte uint64_t for n follow)
8183
case 0x5F: // Binary data (indefinite length)
8184
{
8185
binary_t b;
8186
return get_cbor_binary(b) && sax->binary(b);
8187
}
8188
8189
// UTF-8 string (0x00..0x17 bytes follow)
8190
case 0x60:
8191
case 0x61:
8192
case 0x62:
8193
case 0x63:
8194
case 0x64:
8195
case 0x65:
8196
case 0x66:
8197
case 0x67:
8198
case 0x68:
8199
case 0x69:
8200
case 0x6A:
8201
case 0x6B:
8202
case 0x6C:
8203
case 0x6D:
8204
case 0x6E:
8205
case 0x6F:
8206
case 0x70:
8207
case 0x71:
8208
case 0x72:
8209
case 0x73:
8210
case 0x74:
8211
case 0x75:
8212
case 0x76:
8213
case 0x77:
8214
case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
8215
case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
8216
case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
8217
case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
8218
case 0x7F: // UTF-8 string (indefinite length)
8219
{
8220
string_t s;
8221
return get_cbor_string(s) && sax->string(s);
8222
}
8223
8224
// array (0x00..0x17 data items follow)
8225
case 0x80:
8226
case 0x81:
8227
case 0x82:
8228
case 0x83:
8229
case 0x84:
8230
case 0x85:
8231
case 0x86:
8232
case 0x87:
8233
case 0x88:
8234
case 0x89:
8235
case 0x8A:
8236
case 0x8B:
8237
case 0x8C:
8238
case 0x8D:
8239
case 0x8E:
8240
case 0x8F:
8241
case 0x90:
8242
case 0x91:
8243
case 0x92:
8244
case 0x93:
8245
case 0x94:
8246
case 0x95:
8247
case 0x96:
8248
case 0x97:
8249
return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
8250
8251
case 0x98: // array (one-byte uint8_t for n follows)
8252
{
8253
std::uint8_t len{};
8254
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8255
}
8256
8257
case 0x99: // array (two-byte uint16_t for n follow)
8258
{
8259
std::uint16_t len{};
8260
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8261
}
8262
8263
case 0x9A: // array (four-byte uint32_t for n follow)
8264
{
8265
std::uint32_t len{};
8266
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8267
}
8268
8269
case 0x9B: // array (eight-byte uint64_t for n follow)
8270
{
8271
std::uint64_t len{};
8272
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8273
}
8274
8275
case 0x9F: // array (indefinite length)
8276
return get_cbor_array(std::size_t(-1), tag_handler);
8277
8278
// map (0x00..0x17 pairs of data items follow)
8279
case 0xA0:
8280
case 0xA1:
8281
case 0xA2:
8282
case 0xA3:
8283
case 0xA4:
8284
case 0xA5:
8285
case 0xA6:
8286
case 0xA7:
8287
case 0xA8:
8288
case 0xA9:
8289
case 0xAA:
8290
case 0xAB:
8291
case 0xAC:
8292
case 0xAD:
8293
case 0xAE:
8294
case 0xAF:
8295
case 0xB0:
8296
case 0xB1:
8297
case 0xB2:
8298
case 0xB3:
8299
case 0xB4:
8300
case 0xB5:
8301
case 0xB6:
8302
case 0xB7:
8303
return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
8304
8305
case 0xB8: // map (one-byte uint8_t for n follows)
8306
{
8307
std::uint8_t len{};
8308
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8309
}
8310
8311
case 0xB9: // map (two-byte uint16_t for n follow)
8312
{
8313
std::uint16_t len{};
8314
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8315
}
8316
8317
case 0xBA: // map (four-byte uint32_t for n follow)
8318
{
8319
std::uint32_t len{};
8320
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8321
}
8322
8323
case 0xBB: // map (eight-byte uint64_t for n follow)
8324
{
8325
std::uint64_t len{};
8326
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8327
}
8328
8329
case 0xBF: // map (indefinite length)
8330
return get_cbor_object(std::size_t(-1), tag_handler);
8331
8332
case 0xC6: // tagged item
8333
case 0xC7:
8334
case 0xC8:
8335
case 0xC9:
8336
case 0xCA:
8337
case 0xCB:
8338
case 0xCC:
8339
case 0xCD:
8340
case 0xCE:
8341
case 0xCF:
8342
case 0xD0:
8343
case 0xD1:
8344
case 0xD2:
8345
case 0xD3:
8346
case 0xD4:
8347
case 0xD8: // tagged item (1 bytes follow)
8348
case 0xD9: // tagged item (2 bytes follow)
8349
case 0xDA: // tagged item (4 bytes follow)
8350
case 0xDB: // tagged item (8 bytes follow)
8351
{
8352
switch (tag_handler)
8353
{
8354
case cbor_tag_handler_t::error:
8355
{
8356
auto last_token = get_token_string();
8357
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")));
8358
}
8359
8360
case cbor_tag_handler_t::ignore:
8361
{
8362
switch (current)
8363
{
8364
case 0xD8:
8365
{
8366
std::uint8_t len{};
8367
get_number(input_format_t::cbor, len);
8368
break;
8369
}
8370
case 0xD9:
8371
{
8372
std::uint16_t len{};
8373
get_number(input_format_t::cbor, len);
8374
break;
8375
}
8376
case 0xDA:
8377
{
8378
std::uint32_t len{};
8379
get_number(input_format_t::cbor, len);
8380
break;
8381
}
8382
case 0xDB:
8383
{
8384
std::uint64_t len{};
8385
get_number(input_format_t::cbor, len);
8386
break;
8387
}
8388
default:
8389
break;
8390
}
8391
return parse_cbor_internal(true, tag_handler);
8392
}
8393
8394
default: // LCOV_EXCL_LINE
8395
JSON_ASSERT(false); // LCOV_EXCL_LINE
8396
}
8397
}
8398
8399
case 0xF4: // false
8400
return sax->boolean(false);
8401
8402
case 0xF5: // true
8403
return sax->boolean(true);
8404
8405
case 0xF6: // null
8406
return sax->null();
8407
8408
case 0xF9: // Half-Precision Float (two-byte IEEE 754)
8409
{
8410
const auto byte1_raw = get();
8411
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
8412
{
8413
return false;
8414
}
8415
const auto byte2_raw = get();
8416
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
8417
{
8418
return false;
8419
}
8420
8421
const auto byte1 = static_cast<unsigned char>(byte1_raw);
8422
const auto byte2 = static_cast<unsigned char>(byte2_raw);
8423
8424
// code from RFC 7049, Appendix D, Figure 3:
8425
// As half-precision floating-point numbers were only added
8426
// to IEEE 754 in 2008, today's programming platforms often
8427
// still only have limited support for them. It is very
8428
// easy to include at least decoding support for them even
8429
// without such support. An example of a small decoder for
8430
// half-precision floating-point numbers in the C language
8431
// is shown in Fig. 3.
8432
const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
8433
const double val = [&half]
8434
{
8435
const int exp = (half >> 10u) & 0x1Fu;
8436
const unsigned int mant = half & 0x3FFu;
8437
JSON_ASSERT(0 <= exp&& exp <= 32);
8438
JSON_ASSERT(mant <= 1024);
8439
switch (exp)
8440
{
8441
case 0:
8442
return std::ldexp(mant, -24);
8443
case 31:
8444
return (mant == 0)
8445
? std::numeric_limits<double>::infinity()
8446
: std::numeric_limits<double>::quiet_NaN();
8447
default:
8448
return std::ldexp(mant + 1024, exp - 25);
8449
}
8450
}();
8451
return sax->number_float((half & 0x8000u) != 0
8452
? static_cast<number_float_t>(-val)
8453
: static_cast<number_float_t>(val), "");
8454
}
8455
8456
case 0xFA: // Single-Precision Float (four-byte IEEE 754)
8457
{
8458
float number{};
8459
return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
8460
}
8461
8462
case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
8463
{
8464
double number{};
8465
return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
8466
}
8467
8468
default: // anything else (0xFF is handled inside the other types)
8469
{
8470
auto last_token = get_token_string();
8471
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")));
8472
}
8473
}
8474
}
8475
8476
/*!
8477
@brief reads a CBOR string
8478
8479
This function first reads starting bytes to determine the expected
8480
string length and then copies this number of bytes into a string.
8481
Additionally, CBOR's strings with indefinite lengths are supported.
8482
8483
@param[out] result created string
8484
8485
@return whether string creation completed
8486
*/
8487
bool get_cbor_string(string_t& result)
8488
{
8489
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
8490
{
8491
return false;
8492
}
8493
8494
switch (current)
8495
{
8496
// UTF-8 string (0x00..0x17 bytes follow)
8497
case 0x60:
8498
case 0x61:
8499
case 0x62:
8500
case 0x63:
8501
case 0x64:
8502
case 0x65:
8503
case 0x66:
8504
case 0x67:
8505
case 0x68:
8506
case 0x69:
8507
case 0x6A:
8508
case 0x6B:
8509
case 0x6C:
8510
case 0x6D:
8511
case 0x6E:
8512
case 0x6F:
8513
case 0x70:
8514
case 0x71:
8515
case 0x72:
8516
case 0x73:
8517
case 0x74:
8518
case 0x75:
8519
case 0x76:
8520
case 0x77:
8521
{
8522
return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
8523
}
8524
8525
case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
8526
{
8527
std::uint8_t len{};
8528
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
8529
}
8530
8531
case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
8532
{
8533
std::uint16_t len{};
8534
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
8535
}
8536
8537
case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
8538
{
8539
std::uint32_t len{};
8540
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
8541
}
8542
8543
case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
8544
{
8545
std::uint64_t len{};
8546
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
8547
}
8548
8549
case 0x7F: // UTF-8 string (indefinite length)
8550
{
8551
while (get() != 0xFF)
8552
{
8553
string_t chunk;
8554
if (!get_cbor_string(chunk))
8555
{
8556
return false;
8557
}
8558
result.append(chunk);
8559
}
8560
return true;
8561
}
8562
8563
default:
8564
{
8565
auto last_token = get_token_string();
8566
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")));
8567
}
8568
}
8569
}
8570
8571
/*!
8572
@brief reads a CBOR byte array
8573
8574
This function first reads starting bytes to determine the expected
8575
byte array length and then copies this number of bytes into the byte array.
8576
Additionally, CBOR's byte arrays with indefinite lengths are supported.
8577
8578
@param[out] result created byte array
8579
8580
@return whether byte array creation completed
8581
*/
8582
bool get_cbor_binary(binary_t& result)
8583
{
8584
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
8585
{
8586
return false;
8587
}
8588
8589
switch (current)
8590
{
8591
// Binary data (0x00..0x17 bytes follow)
8592
case 0x40:
8593
case 0x41:
8594
case 0x42:
8595
case 0x43:
8596
case 0x44:
8597
case 0x45:
8598
case 0x46:
8599
case 0x47:
8600
case 0x48:
8601
case 0x49:
8602
case 0x4A:
8603
case 0x4B:
8604
case 0x4C:
8605
case 0x4D:
8606
case 0x4E:
8607
case 0x4F:
8608
case 0x50:
8609
case 0x51:
8610
case 0x52:
8611
case 0x53:
8612
case 0x54:
8613
case 0x55:
8614
case 0x56:
8615
case 0x57:
8616
{
8617
return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
8618
}
8619
8620
case 0x58: // Binary data (one-byte uint8_t for n follows)
8621
{
8622
std::uint8_t len{};
8623
return get_number(input_format_t::cbor, len) &&
8624
get_binary(input_format_t::cbor, len, result);
8625
}
8626
8627
case 0x59: // Binary data (two-byte uint16_t for n follow)
8628
{
8629
std::uint16_t len{};
8630
return get_number(input_format_t::cbor, len) &&
8631
get_binary(input_format_t::cbor, len, result);
8632
}
8633
8634
case 0x5A: // Binary data (four-byte uint32_t for n follow)
8635
{
8636
std::uint32_t len{};
8637
return get_number(input_format_t::cbor, len) &&
8638
get_binary(input_format_t::cbor, len, result);
8639
}
8640
8641
case 0x5B: // Binary data (eight-byte uint64_t for n follow)
8642
{
8643
std::uint64_t len{};
8644
return get_number(input_format_t::cbor, len) &&
8645
get_binary(input_format_t::cbor, len, result);
8646
}
8647
8648
case 0x5F: // Binary data (indefinite length)
8649
{
8650
while (get() != 0xFF)
8651
{
8652
binary_t chunk;
8653
if (!get_cbor_binary(chunk))
8654
{
8655
return false;
8656
}
8657
result.insert(result.end(), chunk.begin(), chunk.end());
8658
}
8659
return true;
8660
}
8661
8662
default:
8663
{
8664
auto last_token = get_token_string();
8665
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")));
8666
}
8667
}
8668
}
8669
8670
/*!
8671
@param[in] len the length of the array or std::size_t(-1) for an
8672
array of indefinite size
8673
@param[in] tag_handler how CBOR tags should be treated
8674
@return whether array creation completed
8675
*/
8676
bool get_cbor_array(const std::size_t len,
8677
const cbor_tag_handler_t tag_handler)
8678
{
8679
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
8680
{
8681
return false;
8682
}
8683
8684
if (len != std::size_t(-1))
8685
{
8686
for (std::size_t i = 0; i < len; ++i)
8687
{
8688
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
8689
{
8690
return false;
8691
}
8692
}
8693
}
8694
else
8695
{
8696
while (get() != 0xFF)
8697
{
8698
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
8699
{
8700
return false;
8701
}
8702
}
8703
}
8704
8705
return sax->end_array();
8706
}
8707
8708
/*!
8709
@param[in] len the length of the object or std::size_t(-1) for an
8710
object of indefinite size
8711
@param[in] tag_handler how CBOR tags should be treated
8712
@return whether object creation completed
8713
*/
8714
bool get_cbor_object(const std::size_t len,
8715
const cbor_tag_handler_t tag_handler)
8716
{
8717
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
8718
{
8719
return false;
8720
}
8721
8722
string_t key;
8723
if (len != std::size_t(-1))
8724
{
8725
for (std::size_t i = 0; i < len; ++i)
8726
{
8727
get();
8728
if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
8729
{
8730
return false;
8731
}
8732
8733
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
8734
{
8735
return false;
8736
}
8737
key.clear();
8738
}
8739
}
8740
else
8741
{
8742
while (get() != 0xFF)
8743
{
8744
if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
8745
{
8746
return false;
8747
}
8748
8749
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
8750
{
8751
return false;
8752
}
8753
key.clear();
8754
}
8755
}
8756
8757
return sax->end_object();
8758
}
8759
8760
/////////////
8761
// MsgPack //
8762
/////////////
8763
8764
/*!
8765
@return whether a valid MessagePack value was passed to the SAX parser
8766
*/
8767
bool parse_msgpack_internal()
8768
{
8769
switch (get())
8770
{
8771
// EOF
8772
case std::char_traits<char_type>::eof():
8773
return unexpect_eof(input_format_t::msgpack, "value");
8774
8775
// positive fixint
8776
case 0x00:
8777
case 0x01:
8778
case 0x02:
8779
case 0x03:
8780
case 0x04:
8781
case 0x05:
8782
case 0x06:
8783
case 0x07:
8784
case 0x08:
8785
case 0x09:
8786
case 0x0A:
8787
case 0x0B:
8788
case 0x0C:
8789
case 0x0D:
8790
case 0x0E:
8791
case 0x0F:
8792
case 0x10:
8793
case 0x11:
8794
case 0x12:
8795
case 0x13:
8796
case 0x14:
8797
case 0x15:
8798
case 0x16:
8799
case 0x17:
8800
case 0x18:
8801
case 0x19:
8802
case 0x1A:
8803
case 0x1B:
8804
case 0x1C:
8805
case 0x1D:
8806
case 0x1E:
8807
case 0x1F:
8808
case 0x20:
8809
case 0x21:
8810
case 0x22:
8811
case 0x23:
8812
case 0x24:
8813
case 0x25:
8814
case 0x26:
8815
case 0x27:
8816
case 0x28:
8817
case 0x29:
8818
case 0x2A:
8819
case 0x2B:
8820
case 0x2C:
8821
case 0x2D:
8822
case 0x2E:
8823
case 0x2F:
8824
case 0x30:
8825
case 0x31:
8826
case 0x32:
8827
case 0x33:
8828
case 0x34:
8829
case 0x35:
8830
case 0x36:
8831
case 0x37:
8832
case 0x38:
8833
case 0x39:
8834
case 0x3A:
8835
case 0x3B:
8836
case 0x3C:
8837
case 0x3D:
8838
case 0x3E:
8839
case 0x3F:
8840
case 0x40:
8841
case 0x41:
8842
case 0x42:
8843
case 0x43:
8844
case 0x44:
8845
case 0x45:
8846
case 0x46:
8847
case 0x47:
8848
case 0x48:
8849
case 0x49:
8850
case 0x4A:
8851
case 0x4B:
8852
case 0x4C:
8853
case 0x4D:
8854
case 0x4E:
8855
case 0x4F:
8856
case 0x50:
8857
case 0x51:
8858
case 0x52:
8859
case 0x53:
8860
case 0x54:
8861
case 0x55:
8862
case 0x56:
8863
case 0x57:
8864
case 0x58:
8865
case 0x59:
8866
case 0x5A:
8867
case 0x5B:
8868
case 0x5C:
8869
case 0x5D:
8870
case 0x5E:
8871
case 0x5F:
8872
case 0x60:
8873
case 0x61:
8874
case 0x62:
8875
case 0x63:
8876
case 0x64:
8877
case 0x65:
8878
case 0x66:
8879
case 0x67:
8880
case 0x68:
8881
case 0x69:
8882
case 0x6A:
8883
case 0x6B:
8884
case 0x6C:
8885
case 0x6D:
8886
case 0x6E:
8887
case 0x6F:
8888
case 0x70:
8889
case 0x71:
8890
case 0x72:
8891
case 0x73:
8892
case 0x74:
8893
case 0x75:
8894
case 0x76:
8895
case 0x77:
8896
case 0x78:
8897
case 0x79:
8898
case 0x7A:
8899
case 0x7B:
8900
case 0x7C:
8901
case 0x7D:
8902
case 0x7E:
8903
case 0x7F:
8904
return sax->number_unsigned(static_cast<number_unsigned_t>(current));
8905
8906
// fixmap
8907
case 0x80:
8908
case 0x81:
8909
case 0x82:
8910
case 0x83:
8911
case 0x84:
8912
case 0x85:
8913
case 0x86:
8914
case 0x87:
8915
case 0x88:
8916
case 0x89:
8917
case 0x8A:
8918
case 0x8B:
8919
case 0x8C:
8920
case 0x8D:
8921
case 0x8E:
8922
case 0x8F:
8923
return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
8924
8925
// fixarray
8926
case 0x90:
8927
case 0x91:
8928
case 0x92:
8929
case 0x93:
8930
case 0x94:
8931
case 0x95:
8932
case 0x96:
8933
case 0x97:
8934
case 0x98:
8935
case 0x99:
8936
case 0x9A:
8937
case 0x9B:
8938
case 0x9C:
8939
case 0x9D:
8940
case 0x9E:
8941
case 0x9F:
8942
return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
8943
8944
// fixstr
8945
case 0xA0:
8946
case 0xA1:
8947
case 0xA2:
8948
case 0xA3:
8949
case 0xA4:
8950
case 0xA5:
8951
case 0xA6:
8952
case 0xA7:
8953
case 0xA8:
8954
case 0xA9:
8955
case 0xAA:
8956
case 0xAB:
8957
case 0xAC:
8958
case 0xAD:
8959
case 0xAE:
8960
case 0xAF:
8961
case 0xB0:
8962
case 0xB1:
8963
case 0xB2:
8964
case 0xB3:
8965
case 0xB4:
8966
case 0xB5:
8967
case 0xB6:
8968
case 0xB7:
8969
case 0xB8:
8970
case 0xB9:
8971
case 0xBA:
8972
case 0xBB:
8973
case 0xBC:
8974
case 0xBD:
8975
case 0xBE:
8976
case 0xBF:
8977
case 0xD9: // str 8
8978
case 0xDA: // str 16
8979
case 0xDB: // str 32
8980
{
8981
string_t s;
8982
return get_msgpack_string(s) && sax->string(s);
8983
}
8984
8985
case 0xC0: // nil
8986
return sax->null();
8987
8988
case 0xC2: // false
8989
return sax->boolean(false);
8990
8991
case 0xC3: // true
8992
return sax->boolean(true);
8993
8994
case 0xC4: // bin 8
8995
case 0xC5: // bin 16
8996
case 0xC6: // bin 32
8997
case 0xC7: // ext 8
8998
case 0xC8: // ext 16
8999
case 0xC9: // ext 32
9000
case 0xD4: // fixext 1
9001
case 0xD5: // fixext 2
9002
case 0xD6: // fixext 4
9003
case 0xD7: // fixext 8
9004
case 0xD8: // fixext 16
9005
{
9006
binary_t b;
9007
return get_msgpack_binary(b) && sax->binary(b);
9008
}
9009
9010
case 0xCA: // float 32
9011
{
9012
float number{};
9013
return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
9014
}
9015
9016
case 0xCB: // float 64
9017
{
9018
double number{};
9019
return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
9020
}
9021
9022
case 0xCC: // uint 8
9023
{
9024
std::uint8_t number{};
9025
return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9026
}
9027
9028
case 0xCD: // uint 16
9029
{
9030
std::uint16_t number{};
9031
return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9032
}
9033
9034
case 0xCE: // uint 32
9035
{
9036
std::uint32_t number{};
9037
return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9038
}
9039
9040
case 0xCF: // uint 64
9041
{
9042
std::uint64_t number{};
9043
return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9044
}
9045
9046
case 0xD0: // int 8
9047
{
9048
std::int8_t number{};
9049
return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9050
}
9051
9052
case 0xD1: // int 16
9053
{
9054
std::int16_t number{};
9055
return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9056
}
9057
9058
case 0xD2: // int 32
9059
{
9060
std::int32_t number{};
9061
return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9062
}
9063
9064
case 0xD3: // int 64
9065
{
9066
std::int64_t number{};
9067
return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9068
}
9069
9070
case 0xDC: // array 16
9071
{
9072
std::uint16_t len{};
9073
return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
9074
}
9075
9076
case 0xDD: // array 32
9077
{
9078
std::uint32_t len{};
9079
return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
9080
}
9081
9082
case 0xDE: // map 16
9083
{
9084
std::uint16_t len{};
9085
return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
9086
}
9087
9088
case 0xDF: // map 32
9089
{
9090
std::uint32_t len{};
9091
return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
9092
}
9093
9094
// negative fixint
9095
case 0xE0:
9096
case 0xE1:
9097
case 0xE2:
9098
case 0xE3:
9099
case 0xE4:
9100
case 0xE5:
9101
case 0xE6:
9102
case 0xE7:
9103
case 0xE8:
9104
case 0xE9:
9105
case 0xEA:
9106
case 0xEB:
9107
case 0xEC:
9108
case 0xED:
9109
case 0xEE:
9110
case 0xEF:
9111
case 0xF0:
9112
case 0xF1:
9113
case 0xF2:
9114
case 0xF3:
9115
case 0xF4:
9116
case 0xF5:
9117
case 0xF6:
9118
case 0xF7:
9119
case 0xF8:
9120
case 0xF9:
9121
case 0xFA:
9122
case 0xFB:
9123
case 0xFC:
9124
case 0xFD:
9125
case 0xFE:
9126
case 0xFF:
9127
return sax->number_integer(static_cast<std::int8_t>(current));
9128
9129
default: // anything else
9130
{
9131
auto last_token = get_token_string();
9132
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")));
9133
}
9134
}
9135
}
9136
9137
/*!
9138
@brief reads a MessagePack string
9139
9140
This function first reads starting bytes to determine the expected
9141
string length and then copies this number of bytes into a string.
9142
9143
@param[out] result created string
9144
9145
@return whether string creation completed
9146
*/
9147
bool get_msgpack_string(string_t& result)
9148
{
9149
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
9150
{
9151
return false;
9152
}
9153
9154
switch (current)
9155
{
9156
// fixstr
9157
case 0xA0:
9158
case 0xA1:
9159
case 0xA2:
9160
case 0xA3:
9161
case 0xA4:
9162
case 0xA5:
9163
case 0xA6:
9164
case 0xA7:
9165
case 0xA8:
9166
case 0xA9:
9167
case 0xAA:
9168
case 0xAB:
9169
case 0xAC:
9170
case 0xAD:
9171
case 0xAE:
9172
case 0xAF:
9173
case 0xB0:
9174
case 0xB1:
9175
case 0xB2:
9176
case 0xB3:
9177
case 0xB4:
9178
case 0xB5:
9179
case 0xB6:
9180
case 0xB7:
9181
case 0xB8:
9182
case 0xB9:
9183
case 0xBA:
9184
case 0xBB:
9185
case 0xBC:
9186
case 0xBD:
9187
case 0xBE:
9188
case 0xBF:
9189
{
9190
return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
9191
}
9192
9193
case 0xD9: // str 8
9194
{
9195
std::uint8_t len{};
9196
return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9197
}
9198
9199
case 0xDA: // str 16
9200
{
9201
std::uint16_t len{};
9202
return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9203
}
9204
9205
case 0xDB: // str 32
9206
{
9207
std::uint32_t len{};
9208
return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9209
}
9210
9211
default:
9212
{
9213
auto last_token = get_token_string();
9214
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")));
9215
}
9216
}
9217
}
9218
9219
/*!
9220
@brief reads a MessagePack byte array
9221
9222
This function first reads starting bytes to determine the expected
9223
byte array length and then copies this number of bytes into a byte array.
9224
9225
@param[out] result created byte array
9226
9227
@return whether byte array creation completed
9228
*/
9229
bool get_msgpack_binary(binary_t& result)
9230
{
9231
// helper function to set the subtype
9232
auto assign_and_return_true = [&result](std::int8_t subtype)
9233
{
9234
result.set_subtype(static_cast<std::uint8_t>(subtype));
9235
return true;
9236
};
9237
9238
switch (current)
9239
{
9240
case 0xC4: // bin 8
9241
{
9242
std::uint8_t len{};
9243
return get_number(input_format_t::msgpack, len) &&
9244
get_binary(input_format_t::msgpack, len, result);
9245
}
9246
9247
case 0xC5: // bin 16
9248
{
9249
std::uint16_t len{};
9250
return get_number(input_format_t::msgpack, len) &&
9251
get_binary(input_format_t::msgpack, len, result);
9252
}
9253
9254
case 0xC6: // bin 32
9255
{
9256
std::uint32_t len{};
9257
return get_number(input_format_t::msgpack, len) &&
9258
get_binary(input_format_t::msgpack, len, result);
9259
}
9260
9261
case 0xC7: // ext 8
9262
{
9263
std::uint8_t len{};
9264
std::int8_t subtype{};
9265
return get_number(input_format_t::msgpack, len) &&
9266
get_number(input_format_t::msgpack, subtype) &&
9267
get_binary(input_format_t::msgpack, len, result) &&
9268
assign_and_return_true(subtype);
9269
}
9270
9271
case 0xC8: // ext 16
9272
{
9273
std::uint16_t len{};
9274
std::int8_t subtype{};
9275
return get_number(input_format_t::msgpack, len) &&
9276
get_number(input_format_t::msgpack, subtype) &&
9277
get_binary(input_format_t::msgpack, len, result) &&
9278
assign_and_return_true(subtype);
9279
}
9280
9281
case 0xC9: // ext 32
9282
{
9283
std::uint32_t len{};
9284
std::int8_t subtype{};
9285
return get_number(input_format_t::msgpack, len) &&
9286
get_number(input_format_t::msgpack, subtype) &&
9287
get_binary(input_format_t::msgpack, len, result) &&
9288
assign_and_return_true(subtype);
9289
}
9290
9291
case 0xD4: // fixext 1
9292
{
9293
std::int8_t subtype{};
9294
return get_number(input_format_t::msgpack, subtype) &&
9295
get_binary(input_format_t::msgpack, 1, result) &&
9296
assign_and_return_true(subtype);
9297
}
9298
9299
case 0xD5: // fixext 2
9300
{
9301
std::int8_t subtype{};
9302
return get_number(input_format_t::msgpack, subtype) &&
9303
get_binary(input_format_t::msgpack, 2, result) &&
9304
assign_and_return_true(subtype);
9305
}
9306
9307
case 0xD6: // fixext 4
9308
{
9309
std::int8_t subtype{};
9310
return get_number(input_format_t::msgpack, subtype) &&
9311
get_binary(input_format_t::msgpack, 4, result) &&
9312
assign_and_return_true(subtype);
9313
}
9314
9315
case 0xD7: // fixext 8
9316
{
9317
std::int8_t subtype{};
9318
return get_number(input_format_t::msgpack, subtype) &&
9319
get_binary(input_format_t::msgpack, 8, result) &&
9320
assign_and_return_true(subtype);
9321
}
9322
9323
case 0xD8: // fixext 16
9324
{
9325
std::int8_t subtype{};
9326
return get_number(input_format_t::msgpack, subtype) &&
9327
get_binary(input_format_t::msgpack, 16, result) &&
9328
assign_and_return_true(subtype);
9329
}
9330
9331
default: // LCOV_EXCL_LINE
9332
return false; // LCOV_EXCL_LINE
9333
}
9334
}
9335
9336
/*!
9337
@param[in] len the length of the array
9338
@return whether array creation completed
9339
*/
9340
bool get_msgpack_array(const std::size_t len)
9341
{
9342
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
9343
{
9344
return false;
9345
}
9346
9347
for (std::size_t i = 0; i < len; ++i)
9348
{
9349
if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
9350
{
9351
return false;
9352
}
9353
}
9354
9355
return sax->end_array();
9356
}
9357
9358
/*!
9359
@param[in] len the length of the object
9360
@return whether object creation completed
9361
*/
9362
bool get_msgpack_object(const std::size_t len)
9363
{
9364
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
9365
{
9366
return false;
9367
}
9368
9369
string_t key;
9370
for (std::size_t i = 0; i < len; ++i)
9371
{
9372
get();
9373
if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
9374
{
9375
return false;
9376
}
9377
9378
if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
9379
{
9380
return false;
9381
}
9382
key.clear();
9383
}
9384
9385
return sax->end_object();
9386
}
9387
9388
////////////
9389
// UBJSON //
9390
////////////
9391
9392
/*!
9393
@param[in] get_char whether a new character should be retrieved from the
9394
input (true, default) or whether the last read
9395
character should be considered instead
9396
9397
@return whether a valid UBJSON value was passed to the SAX parser
9398
*/
9399
bool parse_ubjson_internal(const bool get_char = true)
9400
{
9401
return get_ubjson_value(get_char ? get_ignore_noop() : current);
9402
}
9403
9404
/*!
9405
@brief reads a UBJSON string
9406
9407
This function is either called after reading the 'S' byte explicitly
9408
indicating a string, or in case of an object key where the 'S' byte can be
9409
left out.
9410
9411
@param[out] result created string
9412
@param[in] get_char whether a new character should be retrieved from the
9413
input (true, default) or whether the last read
9414
character should be considered instead
9415
9416
@return whether string creation completed
9417
*/
9418
bool get_ubjson_string(string_t& result, const bool get_char = true)
9419
{
9420
if (get_char)
9421
{
9422
get(); // TODO(niels): may we ignore N here?
9423
}
9424
9425
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
9426
{
9427
return false;
9428
}
9429
9430
switch (current)
9431
{
9432
case 'U':
9433
{
9434
std::uint8_t len{};
9435
return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
9436
}
9437
9438
case 'i':
9439
{
9440
std::int8_t len{};
9441
return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
9442
}
9443
9444
case 'I':
9445
{
9446
std::int16_t len{};
9447
return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
9448
}
9449
9450
case 'l':
9451
{
9452
std::int32_t len{};
9453
return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
9454
}
9455
9456
case 'L':
9457
{
9458
std::int64_t len{};
9459
return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
9460
}
9461
9462
default:
9463
auto last_token = get_token_string();
9464
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")));
9465
}
9466
}
9467
9468
/*!
9469
@param[out] result determined size
9470
@return whether size determination completed
9471
*/
9472
bool get_ubjson_size_value(std::size_t& result)
9473
{
9474
switch (get_ignore_noop())
9475
{
9476
case 'U':
9477
{
9478
std::uint8_t number{};
9479
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
9480
{
9481
return false;
9482
}
9483
result = static_cast<std::size_t>(number);
9484
return true;
9485
}
9486
9487
case 'i':
9488
{
9489
std::int8_t number{};
9490
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
9491
{
9492
return false;
9493
}
9494
result = static_cast<std::size_t>(number);
9495
return true;
9496
}
9497
9498
case 'I':
9499
{
9500
std::int16_t number{};
9501
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
9502
{
9503
return false;
9504
}
9505
result = static_cast<std::size_t>(number);
9506
return true;
9507
}
9508
9509
case 'l':
9510
{
9511
std::int32_t number{};
9512
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
9513
{
9514
return false;
9515
}
9516
result = static_cast<std::size_t>(number);
9517
return true;
9518
}
9519
9520
case 'L':
9521
{
9522
std::int64_t number{};
9523
if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
9524
{
9525
return false;
9526
}
9527
result = static_cast<std::size_t>(number);
9528
return true;
9529
}
9530
9531
default:
9532
{
9533
auto last_token = get_token_string();
9534
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")));
9535
}
9536
}
9537
}
9538
9539
/*!
9540
@brief determine the type and size for a container
9541
9542
In the optimized UBJSON format, a type and a size can be provided to allow
9543
for a more compact representation.
9544
9545
@param[out] result pair of the size and the type
9546
9547
@return whether pair creation completed
9548
*/
9549
bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result)
9550
{
9551
result.first = string_t::npos; // size
9552
result.second = 0; // type
9553
9554
get_ignore_noop();
9555
9556
if (current == '$')
9557
{
9558
result.second = get(); // must not ignore 'N', because 'N' maybe the type
9559
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type")))
9560
{
9561
return false;
9562
}
9563
9564
get_ignore_noop();
9565
if (JSON_HEDLEY_UNLIKELY(current != '#'))
9566
{
9567
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
9568
{
9569
return false;
9570
}
9571
auto last_token = get_token_string();
9572
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")));
9573
}
9574
9575
return get_ubjson_size_value(result.first);
9576
}
9577
9578
if (current == '#')
9579
{
9580
return get_ubjson_size_value(result.first);
9581
}
9582
9583
return true;
9584
}
9585
9586
/*!
9587
@param prefix the previously read or set type prefix
9588
@return whether value creation completed
9589
*/
9590
bool get_ubjson_value(const char_int_type prefix)
9591
{
9592
switch (prefix)
9593
{
9594
case std::char_traits<char_type>::eof(): // EOF
9595
return unexpect_eof(input_format_t::ubjson, "value");
9596
9597
case 'T': // true
9598
return sax->boolean(true);
9599
case 'F': // false
9600
return sax->boolean(false);
9601
9602
case 'Z': // null
9603
return sax->null();
9604
9605
case 'U':
9606
{
9607
std::uint8_t number{};
9608
return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number);
9609
}
9610
9611
case 'i':
9612
{
9613
std::int8_t number{};
9614
return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
9615
}
9616
9617
case 'I':
9618
{
9619
std::int16_t number{};
9620
return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
9621
}
9622
9623
case 'l':
9624
{
9625
std::int32_t number{};
9626
return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
9627
}
9628
9629
case 'L':
9630
{
9631
std::int64_t number{};
9632
return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
9633
}
9634
9635
case 'd':
9636
{
9637
float number{};
9638
return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9639
}
9640
9641
case 'D':
9642
{
9643
double number{};
9644
return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9645
}
9646
9647
case 'H':
9648
{
9649
return get_ubjson_high_precision_number();
9650
}
9651
9652
case 'C': // char
9653
{
9654
get();
9655
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char")))
9656
{
9657
return false;
9658
}
9659
if (JSON_HEDLEY_UNLIKELY(current > 127))
9660
{
9661
auto last_token = get_token_string();
9662
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")));
9663
}
9664
string_t s(1, static_cast<typename string_t::value_type>(current));
9665
return sax->string(s);
9666
}
9667
9668
case 'S': // string
9669
{
9670
string_t s;
9671
return get_ubjson_string(s) && sax->string(s);
9672
}
9673
9674
case '[': // array
9675
return get_ubjson_array();
9676
9677
case '{': // object
9678
return get_ubjson_object();
9679
9680
default: // anything else
9681
{
9682
auto last_token = get_token_string();
9683
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")));
9684
}
9685
}
9686
}
9687
9688
/*!
9689
@return whether array creation completed
9690
*/
9691
bool get_ubjson_array()
9692
{
9693
std::pair<std::size_t, char_int_type> size_and_type;
9694
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
9695
{
9696
return false;
9697
}
9698
9699
if (size_and_type.first != string_t::npos)
9700
{
9701
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
9702
{
9703
return false;
9704
}
9705
9706
if (size_and_type.second != 0)
9707
{
9708
if (size_and_type.second != 'N')
9709
{
9710
for (std::size_t i = 0; i < size_and_type.first; ++i)
9711
{
9712
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
9713
{
9714
return false;
9715
}
9716
}
9717
}
9718
}
9719
else
9720
{
9721
for (std::size_t i = 0; i < size_and_type.first; ++i)
9722
{
9723
if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
9724
{
9725
return false;
9726
}
9727
}
9728
}
9729
}
9730
else
9731
{
9732
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
9733
{
9734
return false;
9735
}
9736
9737
while (current != ']')
9738
{
9739
if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
9740
{
9741
return false;
9742
}
9743
get_ignore_noop();
9744
}
9745
}
9746
9747
return sax->end_array();
9748
}
9749
9750
/*!
9751
@return whether object creation completed
9752
*/
9753
bool get_ubjson_object()
9754
{
9755
std::pair<std::size_t, char_int_type> size_and_type;
9756
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
9757
{
9758
return false;
9759
}
9760
9761
string_t key;
9762
if (size_and_type.first != string_t::npos)
9763
{
9764
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
9765
{
9766
return false;
9767
}
9768
9769
if (size_and_type.second != 0)
9770
{
9771
for (std::size_t i = 0; i < size_and_type.first; ++i)
9772
{
9773
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
9774
{
9775
return false;
9776
}
9777
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
9778
{
9779
return false;
9780
}
9781
key.clear();
9782
}
9783
}
9784
else
9785
{
9786
for (std::size_t i = 0; i < size_and_type.first; ++i)
9787
{
9788
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
9789
{
9790
return false;
9791
}
9792
if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
9793
{
9794
return false;
9795
}
9796
key.clear();
9797
}
9798
}
9799
}
9800
else
9801
{
9802
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
9803
{
9804
return false;
9805
}
9806
9807
while (current != '}')
9808
{
9809
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
9810
{
9811
return false;
9812
}
9813
if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
9814
{
9815
return false;
9816
}
9817
get_ignore_noop();
9818
key.clear();
9819
}
9820
}
9821
9822
return sax->end_object();
9823
}
9824
9825
// Note, no reader for UBJSON binary types is implemented because they do
9826
// not exist
9827
9828
bool get_ubjson_high_precision_number()
9829
{
9830
// get size of following number string
9831
std::size_t size{};
9832
auto res = get_ubjson_size_value(size);
9833
if (JSON_HEDLEY_UNLIKELY(!res))
9834
{
9835
return res;
9836
}
9837
9838
// get number string
9839
std::vector<char> number_vector;
9840
for (std::size_t i = 0; i < size; ++i)
9841
{
9842
get();
9843
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number")))
9844
{
9845
return false;
9846
}
9847
number_vector.push_back(static_cast<char>(current));
9848
}
9849
9850
// parse number string
9851
auto number_ia = detail::input_adapter(std::forward<decltype(number_vector)>(number_vector));
9852
auto number_lexer = detail::lexer<BasicJsonType, decltype(number_ia)>(std::move(number_ia), false);
9853
const auto result_number = number_lexer.scan();
9854
const auto number_string = number_lexer.get_token_string();
9855
const auto result_remainder = number_lexer.scan();
9856
9857
using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
9858
9859
if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
9860
{
9861
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")));
9862
}
9863
9864
switch (result_number)
9865
{
9866
case token_type::value_integer:
9867
return sax->number_integer(number_lexer.get_number_integer());
9868
case token_type::value_unsigned:
9869
return sax->number_unsigned(number_lexer.get_number_unsigned());
9870
case token_type::value_float:
9871
return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
9872
default:
9873
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")));
9874
}
9875
}
9876
9877
///////////////////////
9878
// Utility functions //
9879
///////////////////////
9880
9881
/*!
9882
@brief get next character from the input
9883
9884
This function provides the interface to the used input adapter. It does
9885
not throw in case the input reached EOF, but returns a -'ve valued
9886
`std::char_traits<char_type>::eof()` in that case.
9887
9888
@return character read from the input
9889
*/
9890
char_int_type get()
9891
{
9892
++chars_read;
9893
return current = ia.get_character();
9894
}
9895
9896
/*!
9897
@return character read from the input after ignoring all 'N' entries
9898
*/
9899
char_int_type get_ignore_noop()
9900
{
9901
do
9902
{
9903
get();
9904
}
9905
while (current == 'N');
9906
9907
return current;
9908
}
9909
9910
/*
9911
@brief read a number from the input
9912
9913
@tparam NumberType the type of the number
9914
@param[in] format the current format (for diagnostics)
9915
@param[out] result number of type @a NumberType
9916
9917
@return whether conversion completed
9918
9919
@note This function needs to respect the system's endianess, because
9920
bytes in CBOR, MessagePack, and UBJSON are stored in network order
9921
(big endian) and therefore need reordering on little endian systems.
9922
*/
9923
template<typename NumberType, bool InputIsLittleEndian = false>
9924
bool get_number(const input_format_t format, NumberType& result)
9925
{
9926
// step 1: read input into array with system's byte order
9927
std::array<std::uint8_t, sizeof(NumberType)> vec;
9928
for (std::size_t i = 0; i < sizeof(NumberType); ++i)
9929
{
9930
get();
9931
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
9932
{
9933
return false;
9934
}
9935
9936
// reverse byte order prior to conversion if necessary
9937
if (is_little_endian != InputIsLittleEndian)
9938
{
9939
vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
9940
}
9941
else
9942
{
9943
vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
9944
}
9945
}
9946
9947
// step 2: convert array into number of type T and return
9948
std::memcpy(&result, vec.data(), sizeof(NumberType));
9949
return true;
9950
}
9951
9952
/*!
9953
@brief create a string by reading characters from the input
9954
9955
@tparam NumberType the type of the number
9956
@param[in] format the current format (for diagnostics)
9957
@param[in] len number of characters to read
9958
@param[out] result string created by reading @a len bytes
9959
9960
@return whether string creation completed
9961
9962
@note We can not reserve @a len bytes for the result, because @a len
9963
may be too large. Usually, @ref unexpect_eof() detects the end of
9964
the input before we run out of string memory.
9965
*/
9966
template<typename NumberType>
9967
bool get_string(const input_format_t format,
9968
const NumberType len,
9969
string_t& result)
9970
{
9971
bool success = true;
9972
for (NumberType i = 0; i < len; i++)
9973
{
9974
get();
9975
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
9976
{
9977
success = false;
9978
break;
9979
}
9980
result.push_back(static_cast<typename string_t::value_type>(current));
9981
};
9982
return success;
9983
}
9984
9985
/*!
9986
@brief create a byte array by reading bytes from the input
9987
9988
@tparam NumberType the type of the number
9989
@param[in] format the current format (for diagnostics)
9990
@param[in] len number of bytes to read
9991
@param[out] result byte array created by reading @a len bytes
9992
9993
@return whether byte array creation completed
9994
9995
@note We can not reserve @a len bytes for the result, because @a len
9996
may be too large. Usually, @ref unexpect_eof() detects the end of
9997
the input before we run out of memory.
9998
*/
9999
template<typename NumberType>
10000
bool get_binary(const input_format_t format,
10001
const NumberType len,
10002
binary_t& result)
10003
{
10004
bool success = true;
10005
for (NumberType i = 0; i < len; i++)
10006
{
10007
get();
10008
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
10009
{
10010
success = false;
10011
break;
10012
}
10013
result.push_back(static_cast<std::uint8_t>(current));
10014
}
10015
return success;
10016
}
10017
10018
/*!
10019
@param[in] format the current format (for diagnostics)
10020
@param[in] context further context information (for diagnostics)
10021
@return whether the last read character is not EOF
10022
*/
10023
JSON_HEDLEY_NON_NULL(3)
10024
bool unexpect_eof(const input_format_t format, const char* context) const
10025
{
10026
if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
10027
{
10028
return sax->parse_error(chars_read, "<end of file>",
10029
parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context)));
10030
}
10031
return true;
10032
}
10033
10034
/*!
10035
@return a string representation of the last read byte
10036
*/
10037
std::string get_token_string() const
10038
{
10039
std::array<char, 3> cr{{}};
10040
(std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current));
10041
return std::string{cr.data()};
10042
}
10043
10044
/*!
10045
@param[in] format the current format
10046
@param[in] detail a detailed error message
10047
@param[in] context further context information
10048
@return a message string to use in the parse_error exceptions
10049
*/
10050
std::string exception_message(const input_format_t format,
10051
const std::string& detail,
10052
const std::string& context) const
10053
{
10054
std::string error_msg = "syntax error while parsing ";
10055
10056
switch (format)
10057
{
10058
case input_format_t::cbor:
10059
error_msg += "CBOR";
10060
break;
10061
10062
case input_format_t::msgpack:
10063
error_msg += "MessagePack";
10064
break;
10065
10066
case input_format_t::ubjson:
10067
error_msg += "UBJSON";
10068
break;
10069
10070
case input_format_t::bson:
10071
error_msg += "BSON";
10072
break;
10073
10074
default: // LCOV_EXCL_LINE
10075
JSON_ASSERT(false); // LCOV_EXCL_LINE
10076
}
10077
10078
return error_msg + " " + context + ": " + detail;
10079
}
10080
10081
private:
10082
/// input adapter
10083
InputAdapterType ia;
10084
10085
/// the current character
10086
char_int_type current = std::char_traits<char_type>::eof();
10087
10088
/// the number of characters read
10089
std::size_t chars_read = 0;
10090
10091
/// whether we can assume little endianess
10092
const bool is_little_endian = little_endianess();
10093
10094
/// the SAX parser
10095
json_sax_t* sax = nullptr;
10096
};
10097
} // namespace detail
10098
} // namespace nlohmann
10099
10100
// #include <nlohmann/detail/input/input_adapters.hpp>
10101
10102
// #include <nlohmann/detail/input/lexer.hpp>
10103
10104
// #include <nlohmann/detail/input/parser.hpp>
10105
10106
10107
#include <cmath> // isfinite
10108
#include <cstdint> // uint8_t
10109
#include <functional> // function
10110
#include <string> // string
10111
#include <utility> // move
10112
#include <vector> // vector
10113
10114
// #include <nlohmann/detail/exceptions.hpp>
10115
10116
// #include <nlohmann/detail/input/input_adapters.hpp>
10117
10118
// #include <nlohmann/detail/input/json_sax.hpp>
10119
10120
// #include <nlohmann/detail/input/lexer.hpp>
10121
10122
// #include <nlohmann/detail/macro_scope.hpp>
10123
10124
// #include <nlohmann/detail/meta/is_sax.hpp>
10125
10126
// #include <nlohmann/detail/value_t.hpp>
10127
10128
10129
namespace nlohmann
10130
{
10131
namespace detail
10132
{
10133
////////////
10134
// parser //
10135
////////////
10136
10137
enum class parse_event_t : uint8_t
10138
{
10139
/// the parser read `{` and started to process a JSON object
10140
object_start,
10141
/// the parser read `}` and finished processing a JSON object
10142
object_end,
10143
/// the parser read `[` and started to process a JSON array
10144
array_start,
10145
/// the parser read `]` and finished processing a JSON array
10146
array_end,
10147
/// the parser read a key of a value in an object
10148
key,
10149
/// the parser finished reading a JSON value
10150
value
10151
};
10152
10153
template<typename BasicJsonType>
10154
using parser_callback_t =
10155
std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
10156
10157
/*!
10158
@brief syntax analysis
10159
10160
This class implements a recursive descent parser.
10161
*/
10162
template<typename BasicJsonType, typename InputAdapterType>
10163
class parser
10164
{
10165
using number_integer_t = typename BasicJsonType::number_integer_t;
10166
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
10167
using number_float_t = typename BasicJsonType::number_float_t;
10168
using string_t = typename BasicJsonType::string_t;
10169
using lexer_t = lexer<BasicJsonType, InputAdapterType>;
10170
using token_type = typename lexer_t::token_type;
10171
10172
public:
10173
/// a parser reading from an input adapter
10174
explicit parser(InputAdapterType&& adapter,
10175
const parser_callback_t<BasicJsonType> cb = nullptr,
10176
const bool allow_exceptions_ = true,
10177
const bool skip_comments = false)
10178
: callback(cb)
10179
, m_lexer(std::move(adapter), skip_comments)
10180
, allow_exceptions(allow_exceptions_)
10181
{
10182
// read first token
10183
get_token();
10184
}
10185
10186
/*!
10187
@brief public parser interface
10188
10189
@param[in] strict whether to expect the last token to be EOF
10190
@param[in,out] result parsed JSON value
10191
10192
@throw parse_error.101 in case of an unexpected token
10193
@throw parse_error.102 if to_unicode fails or surrogate error
10194
@throw parse_error.103 if to_unicode fails
10195
*/
10196
void parse(const bool strict, BasicJsonType& result)
10197
{
10198
if (callback)
10199
{
10200
json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
10201
sax_parse_internal(&sdp);
10202
result.assert_invariant();
10203
10204
// in strict mode, input must be completely read
10205
if (strict && (get_token() != token_type::end_of_input))
10206
{
10207
sdp.parse_error(m_lexer.get_position(),
10208
m_lexer.get_token_string(),
10209
parse_error::create(101, m_lexer.get_position(),
10210
exception_message(token_type::end_of_input, "value")));
10211
}
10212
10213
// in case of an error, return discarded value
10214
if (sdp.is_errored())
10215
{
10216
result = value_t::discarded;
10217
return;
10218
}
10219
10220
// set top-level value to null if it was discarded by the callback
10221
// function
10222
if (result.is_discarded())
10223
{
10224
result = nullptr;
10225
}
10226
}
10227
else
10228
{
10229
json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
10230
sax_parse_internal(&sdp);
10231
result.assert_invariant();
10232
10233
// in strict mode, input must be completely read
10234
if (strict && (get_token() != token_type::end_of_input))
10235
{
10236
sdp.parse_error(m_lexer.get_position(),
10237
m_lexer.get_token_string(),
10238
parse_error::create(101, m_lexer.get_position(),
10239
exception_message(token_type::end_of_input, "value")));
10240
}
10241
10242
// in case of an error, return discarded value
10243
if (sdp.is_errored())
10244
{
10245
result = value_t::discarded;
10246
return;
10247
}
10248
}
10249
}
10250
10251
/*!
10252
@brief public accept interface
10253
10254
@param[in] strict whether to expect the last token to be EOF
10255
@return whether the input is a proper JSON text
10256
*/
10257
bool accept(const bool strict = true)
10258
{
10259
json_sax_acceptor<BasicJsonType> sax_acceptor;
10260
return sax_parse(&sax_acceptor, strict);
10261
}
10262
10263
template<typename SAX>
10264
JSON_HEDLEY_NON_NULL(2)
10265
bool sax_parse(SAX* sax, const bool strict = true)
10266
{
10267
(void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
10268
const bool result = sax_parse_internal(sax);
10269
10270
// strict mode: next byte must be EOF
10271
if (result && strict && (get_token() != token_type::end_of_input))
10272
{
10273
return sax->parse_error(m_lexer.get_position(),
10274
m_lexer.get_token_string(),
10275
parse_error::create(101, m_lexer.get_position(),
10276
exception_message(token_type::end_of_input, "value")));
10277
}
10278
10279
return result;
10280
}
10281
10282
private:
10283
template<typename SAX>
10284
JSON_HEDLEY_NON_NULL(2)
10285
bool sax_parse_internal(SAX* sax)
10286
{
10287
// stack to remember the hierarchy of structured values we are parsing
10288
// true = array; false = object
10289
std::vector<bool> states;
10290
// value to avoid a goto (see comment where set to true)
10291
bool skip_to_state_evaluation = false;
10292
10293
while (true)
10294
{
10295
if (!skip_to_state_evaluation)
10296
{
10297
// invariant: get_token() was called before each iteration
10298
switch (last_token)
10299
{
10300
case token_type::begin_object:
10301
{
10302
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
10303
{
10304
return false;
10305
}
10306
10307
// closing } -> we are done
10308
if (get_token() == token_type::end_object)
10309
{
10310
if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
10311
{
10312
return false;
10313
}
10314
break;
10315
}
10316
10317
// parse key
10318
if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
10319
{
10320
return sax->parse_error(m_lexer.get_position(),
10321
m_lexer.get_token_string(),
10322
parse_error::create(101, m_lexer.get_position(),
10323
exception_message(token_type::value_string, "object key")));
10324
}
10325
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
10326
{
10327
return false;
10328
}
10329
10330
// parse separator (:)
10331
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
10332
{
10333
return sax->parse_error(m_lexer.get_position(),
10334
m_lexer.get_token_string(),
10335
parse_error::create(101, m_lexer.get_position(),
10336
exception_message(token_type::name_separator, "object separator")));
10337
}
10338
10339
// remember we are now inside an object
10340
states.push_back(false);
10341
10342
// parse values
10343
get_token();
10344
continue;
10345
}
10346
10347
case token_type::begin_array:
10348
{
10349
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
10350
{
10351
return false;
10352
}
10353
10354
// closing ] -> we are done
10355
if (get_token() == token_type::end_array)
10356
{
10357
if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
10358
{
10359
return false;
10360
}
10361
break;
10362
}
10363
10364
// remember we are now inside an array
10365
states.push_back(true);
10366
10367
// parse values (no need to call get_token)
10368
continue;
10369
}
10370
10371
case token_type::value_float:
10372
{
10373
const auto res = m_lexer.get_number_float();
10374
10375
if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
10376
{
10377
return sax->parse_error(m_lexer.get_position(),
10378
m_lexer.get_token_string(),
10379
out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
10380
}
10381
10382
if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
10383
{
10384
return false;
10385
}
10386
10387
break;
10388
}
10389
10390
case token_type::literal_false:
10391
{
10392
if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
10393
{
10394
return false;
10395
}
10396
break;
10397
}
10398
10399
case token_type::literal_null:
10400
{
10401
if (JSON_HEDLEY_UNLIKELY(!sax->null()))
10402
{
10403
return false;
10404
}
10405
break;
10406
}
10407
10408
case token_type::literal_true:
10409
{
10410
if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
10411
{
10412
return false;
10413
}
10414
break;
10415
}
10416
10417
case token_type::value_integer:
10418
{
10419
if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
10420
{
10421
return false;
10422
}
10423
break;
10424
}
10425
10426
case token_type::value_string:
10427
{
10428
if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
10429
{
10430
return false;
10431
}
10432
break;
10433
}
10434
10435
case token_type::value_unsigned:
10436
{
10437
if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
10438
{
10439
return false;
10440
}
10441
break;
10442
}
10443
10444
case token_type::parse_error:
10445
{
10446
// using "uninitialized" to avoid "expected" message
10447
return sax->parse_error(m_lexer.get_position(),
10448
m_lexer.get_token_string(),
10449
parse_error::create(101, m_lexer.get_position(),
10450
exception_message(token_type::uninitialized, "value")));
10451
}
10452
10453
default: // the last token was unexpected
10454
{
10455
return sax->parse_error(m_lexer.get_position(),
10456
m_lexer.get_token_string(),
10457
parse_error::create(101, m_lexer.get_position(),
10458
exception_message(token_type::literal_or_value, "value")));
10459
}
10460
}
10461
}
10462
else
10463
{
10464
skip_to_state_evaluation = false;
10465
}
10466
10467
// we reached this line after we successfully parsed a value
10468
if (states.empty())
10469
{
10470
// empty stack: we reached the end of the hierarchy: done
10471
return true;
10472
}
10473
10474
if (states.back()) // array
10475
{
10476
// comma -> next value
10477
if (get_token() == token_type::value_separator)
10478
{
10479
// parse a new value
10480
get_token();
10481
continue;
10482
}
10483
10484
// closing ]
10485
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
10486
{
10487
if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
10488
{
10489
return false;
10490
}
10491
10492
// We are done with this array. Before we can parse a
10493
// new value, we need to evaluate the new state first.
10494
// By setting skip_to_state_evaluation to false, we
10495
// are effectively jumping to the beginning of this if.
10496
JSON_ASSERT(!states.empty());
10497
states.pop_back();
10498
skip_to_state_evaluation = true;
10499
continue;
10500
}
10501
10502
return sax->parse_error(m_lexer.get_position(),
10503
m_lexer.get_token_string(),
10504
parse_error::create(101, m_lexer.get_position(),
10505
exception_message(token_type::end_array, "array")));
10506
}
10507
else // object
10508
{
10509
// comma -> next value
10510
if (get_token() == token_type::value_separator)
10511
{
10512
// parse key
10513
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
10514
{
10515
return sax->parse_error(m_lexer.get_position(),
10516
m_lexer.get_token_string(),
10517
parse_error::create(101, m_lexer.get_position(),
10518
exception_message(token_type::value_string, "object key")));
10519
}
10520
10521
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
10522
{
10523
return false;
10524
}
10525
10526
// parse separator (:)
10527
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
10528
{
10529
return sax->parse_error(m_lexer.get_position(),
10530
m_lexer.get_token_string(),
10531
parse_error::create(101, m_lexer.get_position(),
10532
exception_message(token_type::name_separator, "object separator")));
10533
}
10534
10535
// parse values
10536
get_token();
10537
continue;
10538
}
10539
10540
// closing }
10541
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
10542
{
10543
if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
10544
{
10545
return false;
10546
}
10547
10548
// We are done with this object. Before we can parse a
10549
// new value, we need to evaluate the new state first.
10550
// By setting skip_to_state_evaluation to false, we
10551
// are effectively jumping to the beginning of this if.
10552
JSON_ASSERT(!states.empty());
10553
states.pop_back();
10554
skip_to_state_evaluation = true;
10555
continue;
10556
}
10557
10558
return sax->parse_error(m_lexer.get_position(),
10559
m_lexer.get_token_string(),
10560
parse_error::create(101, m_lexer.get_position(),
10561
exception_message(token_type::end_object, "object")));
10562
}
10563
}
10564
}
10565
10566
/// get next token from lexer
10567
token_type get_token()
10568
{
10569
return last_token = m_lexer.scan();
10570
}
10571
10572
std::string exception_message(const token_type expected, const std::string& context)
10573
{
10574
std::string error_msg = "syntax error ";
10575
10576
if (!context.empty())
10577
{
10578
error_msg += "while parsing " + context + " ";
10579
}
10580
10581
error_msg += "- ";
10582
10583
if (last_token == token_type::parse_error)
10584
{
10585
error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
10586
m_lexer.get_token_string() + "'";
10587
}
10588
else
10589
{
10590
error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
10591
}
10592
10593
if (expected != token_type::uninitialized)
10594
{
10595
error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
10596
}
10597
10598
return error_msg;
10599
}
10600
10601
private:
10602
/// callback function
10603
const parser_callback_t<BasicJsonType> callback = nullptr;
10604
/// the type of the last read token
10605
token_type last_token = token_type::uninitialized;
10606
/// the lexer
10607
lexer_t m_lexer;
10608
/// whether to throw exceptions in case of errors
10609
const bool allow_exceptions = true;
10610
};
10611
} // namespace detail
10612
} // namespace nlohmann
10613
10614
// #include <nlohmann/detail/iterators/internal_iterator.hpp>
10615
10616
10617
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
10618
10619
10620
#include <cstddef> // ptrdiff_t
10621
#include <limits> // numeric_limits
10622
10623
namespace nlohmann
10624
{
10625
namespace detail
10626
{
10627
/*
10628
@brief an iterator for primitive JSON types
10629
10630
This class models an iterator for primitive JSON types (boolean, number,
10631
string). It's only purpose is to allow the iterator/const_iterator classes
10632
to "iterate" over primitive values. Internally, the iterator is modeled by
10633
a `difference_type` variable. Value begin_value (`0`) models the begin,
10634
end_value (`1`) models past the end.
10635
*/
10636
class primitive_iterator_t
10637
{
10638
private:
10639
using difference_type = std::ptrdiff_t;
10640
static constexpr difference_type begin_value = 0;
10641
static constexpr difference_type end_value = begin_value + 1;
10642
10643
/// iterator as signed integer type
10644
difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
10645
10646
public:
10647
constexpr difference_type get_value() const noexcept
10648
{
10649
return m_it;
10650
}
10651
10652
/// set iterator to a defined beginning
10653
void set_begin() noexcept
10654
{
10655
m_it = begin_value;
10656
}
10657
10658
/// set iterator to a defined past the end
10659
void set_end() noexcept
10660
{
10661
m_it = end_value;
10662
}
10663
10664
/// return whether the iterator can be dereferenced
10665
constexpr bool is_begin() const noexcept
10666
{
10667
return m_it == begin_value;
10668
}
10669
10670
/// return whether the iterator is at end
10671
constexpr bool is_end() const noexcept
10672
{
10673
return m_it == end_value;
10674
}
10675
10676
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
10677
{
10678
return lhs.m_it == rhs.m_it;
10679
}
10680
10681
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
10682
{
10683
return lhs.m_it < rhs.m_it;
10684
}
10685
10686
primitive_iterator_t operator+(difference_type n) noexcept
10687
{
10688
auto result = *this;
10689
result += n;
10690
return result;
10691
}
10692
10693
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
10694
{
10695
return lhs.m_it - rhs.m_it;
10696
}
10697
10698
primitive_iterator_t& operator++() noexcept
10699
{
10700
++m_it;
10701
return *this;
10702
}
10703
10704
primitive_iterator_t const operator++(int) noexcept
10705
{
10706
auto result = *this;
10707
++m_it;
10708
return result;
10709
}
10710
10711
primitive_iterator_t& operator--() noexcept
10712
{
10713
--m_it;
10714
return *this;
10715
}
10716
10717
primitive_iterator_t const operator--(int) noexcept
10718
{
10719
auto result = *this;
10720
--m_it;
10721
return result;
10722
}
10723
10724
primitive_iterator_t& operator+=(difference_type n) noexcept
10725
{
10726
m_it += n;
10727
return *this;
10728
}
10729
10730
primitive_iterator_t& operator-=(difference_type n) noexcept
10731
{
10732
m_it -= n;
10733
return *this;
10734
}
10735
};
10736
} // namespace detail
10737
} // namespace nlohmann
10738
10739
10740
namespace nlohmann
10741
{
10742
namespace detail
10743
{
10744
/*!
10745
@brief an iterator value
10746
10747
@note This structure could easily be a union, but MSVC currently does not allow
10748
unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
10749
*/
10750
template<typename BasicJsonType> struct internal_iterator
10751
{
10752
/// iterator for JSON objects
10753
typename BasicJsonType::object_t::iterator object_iterator {};
10754
/// iterator for JSON arrays
10755
typename BasicJsonType::array_t::iterator array_iterator {};
10756
/// generic iterator for all other types
10757
primitive_iterator_t primitive_iterator {};
10758
};
10759
} // namespace detail
10760
} // namespace nlohmann
10761
10762
// #include <nlohmann/detail/iterators/iter_impl.hpp>
10763
10764
10765
#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
10766
#include <type_traits> // conditional, is_const, remove_const
10767
10768
// #include <nlohmann/detail/exceptions.hpp>
10769
10770
// #include <nlohmann/detail/iterators/internal_iterator.hpp>
10771
10772
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
10773
10774
// #include <nlohmann/detail/macro_scope.hpp>
10775
10776
// #include <nlohmann/detail/meta/cpp_future.hpp>
10777
10778
// #include <nlohmann/detail/meta/type_traits.hpp>
10779
10780
// #include <nlohmann/detail/value_t.hpp>
10781
10782
10783
namespace nlohmann
10784
{
10785
namespace detail
10786
{
10787
// forward declare, to be able to friend it later on
10788
template<typename IteratorType> class iteration_proxy;
10789
template<typename IteratorType> class iteration_proxy_value;
10790
10791
/*!
10792
@brief a template for a bidirectional iterator for the @ref basic_json class
10793
This class implements a both iterators (iterator and const_iterator) for the
10794
@ref basic_json class.
10795
@note An iterator is called *initialized* when a pointer to a JSON value has
10796
been set (e.g., by a constructor or a copy assignment). If the iterator is
10797
default-constructed, it is *uninitialized* and most methods are undefined.
10798
**The library uses assertions to detect calls on uninitialized iterators.**
10799
@requirement The class satisfies the following concept requirements:
10800
-
10801
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
10802
The iterator that can be moved can be moved in both directions (i.e.
10803
incremented and decremented).
10804
@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
10805
iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
10806
*/
10807
template<typename BasicJsonType>
10808
class iter_impl
10809
{
10810
/// allow basic_json to access private members
10811
friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
10812
friend BasicJsonType;
10813
friend iteration_proxy<iter_impl>;
10814
friend iteration_proxy_value<iter_impl>;
10815
10816
using object_t = typename BasicJsonType::object_t;
10817
using array_t = typename BasicJsonType::array_t;
10818
// make sure BasicJsonType is basic_json or const basic_json
10819
static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
10820
"iter_impl only accepts (const) basic_json");
10821
10822
public:
10823
10824
/// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
10825
/// The C++ Standard has never required user-defined iterators to derive from std::iterator.
10826
/// A user-defined iterator should provide publicly accessible typedefs named
10827
/// iterator_category, value_type, difference_type, pointer, and reference.
10828
/// Note that value_type is required to be non-const, even for constant iterators.
10829
using iterator_category = std::bidirectional_iterator_tag;
10830
10831
/// the type of the values when the iterator is dereferenced
10832
using value_type = typename BasicJsonType::value_type;
10833
/// a type to represent differences between iterators
10834
using difference_type = typename BasicJsonType::difference_type;
10835
/// defines a pointer to the type iterated over (value_type)
10836
using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
10837
typename BasicJsonType::const_pointer,
10838
typename BasicJsonType::pointer>::type;
10839
/// defines a reference to the type iterated over (value_type)
10840
using reference =
10841
typename std::conditional<std::is_const<BasicJsonType>::value,
10842
typename BasicJsonType::const_reference,
10843
typename BasicJsonType::reference>::type;
10844
10845
/// default constructor
10846
iter_impl() = default;
10847
10848
/*!
10849
@brief constructor for a given JSON instance
10850
@param[in] object pointer to a JSON object for this iterator
10851
@pre object != nullptr
10852
@post The iterator is initialized; i.e. `m_object != nullptr`.
10853
*/
10854
explicit iter_impl(pointer object) noexcept : m_object(object)
10855
{
10856
JSON_ASSERT(m_object != nullptr);
10857
10858
switch (m_object->m_type)
10859
{
10860
case value_t::object:
10861
{
10862
m_it.object_iterator = typename object_t::iterator();
10863
break;
10864
}
10865
10866
case value_t::array:
10867
{
10868
m_it.array_iterator = typename array_t::iterator();
10869
break;
10870
}
10871
10872
default:
10873
{
10874
m_it.primitive_iterator = primitive_iterator_t();
10875
break;
10876
}
10877
}
10878
}
10879
10880
/*!
10881
@note The conventional copy constructor and copy assignment are implicitly
10882
defined. Combined with the following converting constructor and
10883
assignment, they support: (1) copy from iterator to iterator, (2)
10884
copy from const iterator to const iterator, and (3) conversion from
10885
iterator to const iterator. However conversion from const iterator
10886
to iterator is not defined.
10887
*/
10888
10889
/*!
10890
@brief const copy constructor
10891
@param[in] other const iterator to copy from
10892
@note This copy constructor had to be defined explicitly to circumvent a bug
10893
occurring on msvc v19.0 compiler (VS 2015) debug build. For more
10894
information refer to: https://github.com/nlohmann/json/issues/1608
10895
*/
10896
iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
10897
: m_object(other.m_object), m_it(other.m_it)
10898
{}
10899
10900
/*!
10901
@brief converting assignment
10902
@param[in] other const iterator to copy from
10903
@return const/non-const iterator
10904
@note It is not checked whether @a other is initialized.
10905
*/
10906
iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
10907
{
10908
m_object = other.m_object;
10909
m_it = other.m_it;
10910
return *this;
10911
}
10912
10913
/*!
10914
@brief converting constructor
10915
@param[in] other non-const iterator to copy from
10916
@note It is not checked whether @a other is initialized.
10917
*/
10918
iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
10919
: m_object(other.m_object), m_it(other.m_it)
10920
{}
10921
10922
/*!
10923
@brief converting assignment
10924
@param[in] other non-const iterator to copy from
10925
@return const/non-const iterator
10926
@note It is not checked whether @a other is initialized.
10927
*/
10928
iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
10929
{
10930
m_object = other.m_object;
10931
m_it = other.m_it;
10932
return *this;
10933
}
10934
10935
private:
10936
/*!
10937
@brief set the iterator to the first value
10938
@pre The iterator is initialized; i.e. `m_object != nullptr`.
10939
*/
10940
void set_begin() noexcept
10941
{
10942
JSON_ASSERT(m_object != nullptr);
10943
10944
switch (m_object->m_type)
10945
{
10946
case value_t::object:
10947
{
10948
m_it.object_iterator = m_object->m_value.object->begin();
10949
break;
10950
}
10951
10952
case value_t::array:
10953
{
10954
m_it.array_iterator = m_object->m_value.array->begin();
10955
break;
10956
}
10957
10958
case value_t::null:
10959
{
10960
// set to end so begin()==end() is true: null is empty
10961
m_it.primitive_iterator.set_end();
10962
break;
10963
}
10964
10965
default:
10966
{
10967
m_it.primitive_iterator.set_begin();
10968
break;
10969
}
10970
}
10971
}
10972
10973
/*!
10974
@brief set the iterator past the last value
10975
@pre The iterator is initialized; i.e. `m_object != nullptr`.
10976
*/
10977
void set_end() noexcept
10978
{
10979
JSON_ASSERT(m_object != nullptr);
10980
10981
switch (m_object->m_type)
10982
{
10983
case value_t::object:
10984
{
10985
m_it.object_iterator = m_object->m_value.object->end();
10986
break;
10987
}
10988
10989
case value_t::array:
10990
{
10991
m_it.array_iterator = m_object->m_value.array->end();
10992
break;
10993
}
10994
10995
default:
10996
{
10997
m_it.primitive_iterator.set_end();
10998
break;
10999
}
11000
}
11001
}
11002
11003
public:
11004
/*!
11005
@brief return a reference to the value pointed to by the iterator
11006
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11007
*/
11008
reference operator*() const
11009
{
11010
JSON_ASSERT(m_object != nullptr);
11011
11012
switch (m_object->m_type)
11013
{
11014
case value_t::object:
11015
{
11016
JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
11017
return m_it.object_iterator->second;
11018
}
11019
11020
case value_t::array:
11021
{
11022
JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
11023
return *m_it.array_iterator;
11024
}
11025
11026
case value_t::null:
11027
JSON_THROW(invalid_iterator::create(214, "cannot get value"));
11028
11029
default:
11030
{
11031
if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
11032
{
11033
return *m_object;
11034
}
11035
11036
JSON_THROW(invalid_iterator::create(214, "cannot get value"));
11037
}
11038
}
11039
}
11040
11041
/*!
11042
@brief dereference the iterator
11043
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11044
*/
11045
pointer operator->() const
11046
{
11047
JSON_ASSERT(m_object != nullptr);
11048
11049
switch (m_object->m_type)
11050
{
11051
case value_t::object:
11052
{
11053
JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
11054
return &(m_it.object_iterator->second);
11055
}
11056
11057
case value_t::array:
11058
{
11059
JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
11060
return &*m_it.array_iterator;
11061
}
11062
11063
default:
11064
{
11065
if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
11066
{
11067
return m_object;
11068
}
11069
11070
JSON_THROW(invalid_iterator::create(214, "cannot get value"));
11071
}
11072
}
11073
}
11074
11075
/*!
11076
@brief post-increment (it++)
11077
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11078
*/
11079
iter_impl const operator++(int)
11080
{
11081
auto result = *this;
11082
++(*this);
11083
return result;
11084
}
11085
11086
/*!
11087
@brief pre-increment (++it)
11088
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11089
*/
11090
iter_impl& operator++()
11091
{
11092
JSON_ASSERT(m_object != nullptr);
11093
11094
switch (m_object->m_type)
11095
{
11096
case value_t::object:
11097
{
11098
std::advance(m_it.object_iterator, 1);
11099
break;
11100
}
11101
11102
case value_t::array:
11103
{
11104
std::advance(m_it.array_iterator, 1);
11105
break;
11106
}
11107
11108
default:
11109
{
11110
++m_it.primitive_iterator;
11111
break;
11112
}
11113
}
11114
11115
return *this;
11116
}
11117
11118
/*!
11119
@brief post-decrement (it--)
11120
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11121
*/
11122
iter_impl const operator--(int)
11123
{
11124
auto result = *this;
11125
--(*this);
11126
return result;
11127
}
11128
11129
/*!
11130
@brief pre-decrement (--it)
11131
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11132
*/
11133
iter_impl& operator--()
11134
{
11135
JSON_ASSERT(m_object != nullptr);
11136
11137
switch (m_object->m_type)
11138
{
11139
case value_t::object:
11140
{
11141
std::advance(m_it.object_iterator, -1);
11142
break;
11143
}
11144
11145
case value_t::array:
11146
{
11147
std::advance(m_it.array_iterator, -1);
11148
break;
11149
}
11150
11151
default:
11152
{
11153
--m_it.primitive_iterator;
11154
break;
11155
}
11156
}
11157
11158
return *this;
11159
}
11160
11161
/*!
11162
@brief comparison: equal
11163
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11164
*/
11165
bool operator==(const iter_impl& other) const
11166
{
11167
// if objects are not the same, the comparison is undefined
11168
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
11169
{
11170
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
11171
}
11172
11173
JSON_ASSERT(m_object != nullptr);
11174
11175
switch (m_object->m_type)
11176
{
11177
case value_t::object:
11178
return (m_it.object_iterator == other.m_it.object_iterator);
11179
11180
case value_t::array:
11181
return (m_it.array_iterator == other.m_it.array_iterator);
11182
11183
default:
11184
return (m_it.primitive_iterator == other.m_it.primitive_iterator);
11185
}
11186
}
11187
11188
/*!
11189
@brief comparison: not equal
11190
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11191
*/
11192
bool operator!=(const iter_impl& other) const
11193
{
11194
return !operator==(other);
11195
}
11196
11197
/*!
11198
@brief comparison: smaller
11199
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11200
*/
11201
bool operator<(const iter_impl& other) const
11202
{
11203
// if objects are not the same, the comparison is undefined
11204
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
11205
{
11206
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
11207
}
11208
11209
JSON_ASSERT(m_object != nullptr);
11210
11211
switch (m_object->m_type)
11212
{
11213
case value_t::object:
11214
JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
11215
11216
case value_t::array:
11217
return (m_it.array_iterator < other.m_it.array_iterator);
11218
11219
default:
11220
return (m_it.primitive_iterator < other.m_it.primitive_iterator);
11221
}
11222
}
11223
11224
/*!
11225
@brief comparison: less than or equal
11226
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11227
*/
11228
bool operator<=(const iter_impl& other) const
11229
{
11230
return !other.operator < (*this);
11231
}
11232
11233
/*!
11234
@brief comparison: greater than
11235
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11236
*/
11237
bool operator>(const iter_impl& other) const
11238
{
11239
return !operator<=(other);
11240
}
11241
11242
/*!
11243
@brief comparison: greater than or equal
11244
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11245
*/
11246
bool operator>=(const iter_impl& other) const
11247
{
11248
return !operator<(other);
11249
}
11250
11251
/*!
11252
@brief add to iterator
11253
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11254
*/
11255
iter_impl& operator+=(difference_type i)
11256
{
11257
JSON_ASSERT(m_object != nullptr);
11258
11259
switch (m_object->m_type)
11260
{
11261
case value_t::object:
11262
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
11263
11264
case value_t::array:
11265
{
11266
std::advance(m_it.array_iterator, i);
11267
break;
11268
}
11269
11270
default:
11271
{
11272
m_it.primitive_iterator += i;
11273
break;
11274
}
11275
}
11276
11277
return *this;
11278
}
11279
11280
/*!
11281
@brief subtract from iterator
11282
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11283
*/
11284
iter_impl& operator-=(difference_type i)
11285
{
11286
return operator+=(-i);
11287
}
11288
11289
/*!
11290
@brief add to iterator
11291
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11292
*/
11293
iter_impl operator+(difference_type i) const
11294
{
11295
auto result = *this;
11296
result += i;
11297
return result;
11298
}
11299
11300
/*!
11301
@brief addition of distance and iterator
11302
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11303
*/
11304
friend iter_impl operator+(difference_type i, const iter_impl& it)
11305
{
11306
auto result = it;
11307
result += i;
11308
return result;
11309
}
11310
11311
/*!
11312
@brief subtract from iterator
11313
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11314
*/
11315
iter_impl operator-(difference_type i) const
11316
{
11317
auto result = *this;
11318
result -= i;
11319
return result;
11320
}
11321
11322
/*!
11323
@brief return difference
11324
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11325
*/
11326
difference_type operator-(const iter_impl& other) const
11327
{
11328
JSON_ASSERT(m_object != nullptr);
11329
11330
switch (m_object->m_type)
11331
{
11332
case value_t::object:
11333
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
11334
11335
case value_t::array:
11336
return m_it.array_iterator - other.m_it.array_iterator;
11337
11338
default:
11339
return m_it.primitive_iterator - other.m_it.primitive_iterator;
11340
}
11341
}
11342
11343
/*!
11344
@brief access to successor
11345
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11346
*/
11347
reference operator[](difference_type n) const
11348
{
11349
JSON_ASSERT(m_object != nullptr);
11350
11351
switch (m_object->m_type)
11352
{
11353
case value_t::object:
11354
JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
11355
11356
case value_t::array:
11357
return *std::next(m_it.array_iterator, n);
11358
11359
case value_t::null:
11360
JSON_THROW(invalid_iterator::create(214, "cannot get value"));
11361
11362
default:
11363
{
11364
if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
11365
{
11366
return *m_object;
11367
}
11368
11369
JSON_THROW(invalid_iterator::create(214, "cannot get value"));
11370
}
11371
}
11372
}
11373
11374
/*!
11375
@brief return the key of an object iterator
11376
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11377
*/
11378
const typename object_t::key_type& key() const
11379
{
11380
JSON_ASSERT(m_object != nullptr);
11381
11382
if (JSON_HEDLEY_LIKELY(m_object->is_object()))
11383
{
11384
return m_it.object_iterator->first;
11385
}
11386
11387
JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
11388
}
11389
11390
/*!
11391
@brief return the value of an iterator
11392
@pre The iterator is initialized; i.e. `m_object != nullptr`.
11393
*/
11394
reference value() const
11395
{
11396
return operator*();
11397
}
11398
11399
private:
11400
/// associated JSON instance
11401
pointer m_object = nullptr;
11402
/// the actual iterator of the associated instance
11403
internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
11404
};
11405
} // namespace detail
11406
} // namespace nlohmann
11407
11408
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
11409
11410
// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
11411
11412
11413
#include <cstddef> // ptrdiff_t
11414
#include <iterator> // reverse_iterator
11415
#include <utility> // declval
11416
11417
namespace nlohmann
11418
{
11419
namespace detail
11420
{
11421
//////////////////////
11422
// reverse_iterator //
11423
//////////////////////
11424
11425
/*!
11426
@brief a template for a reverse iterator class
11427
11428
@tparam Base the base iterator type to reverse. Valid types are @ref
11429
iterator (to create @ref reverse_iterator) and @ref const_iterator (to
11430
create @ref const_reverse_iterator).
11431
11432
@requirement The class satisfies the following concept requirements:
11433
-
11434
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
11435
The iterator that can be moved can be moved in both directions (i.e.
11436
incremented and decremented).
11437
- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
11438
It is possible to write to the pointed-to element (only if @a Base is
11439
@ref iterator).
11440
11441
@since version 1.0.0
11442
*/
11443
template<typename Base>
11444
class json_reverse_iterator : public std::reverse_iterator<Base>
11445
{
11446
public:
11447
using difference_type = std::ptrdiff_t;
11448
/// shortcut to the reverse iterator adapter
11449
using base_iterator = std::reverse_iterator<Base>;
11450
/// the reference type for the pointed-to element
11451
using reference = typename Base::reference;
11452
11453
/// create reverse iterator from iterator
11454
explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
11455
: base_iterator(it) {}
11456
11457
/// create reverse iterator from base class
11458
explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
11459
11460
/// post-increment (it++)
11461
json_reverse_iterator const operator++(int)
11462
{
11463
return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
11464
}
11465
11466
/// pre-increment (++it)
11467
json_reverse_iterator& operator++()
11468
{
11469
return static_cast<json_reverse_iterator&>(base_iterator::operator++());
11470
}
11471
11472
/// post-decrement (it--)
11473
json_reverse_iterator const operator--(int)
11474
{
11475
return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
11476
}
11477
11478
/// pre-decrement (--it)
11479
json_reverse_iterator& operator--()
11480
{
11481
return static_cast<json_reverse_iterator&>(base_iterator::operator--());
11482
}
11483
11484
/// add to iterator
11485
json_reverse_iterator& operator+=(difference_type i)
11486
{
11487
return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
11488
}
11489
11490
/// add to iterator
11491
json_reverse_iterator operator+(difference_type i) const
11492
{
11493
return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
11494
}
11495
11496
/// subtract from iterator
11497
json_reverse_iterator operator-(difference_type i) const
11498
{
11499
return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
11500
}
11501
11502
/// return difference
11503
difference_type operator-(const json_reverse_iterator& other) const
11504
{
11505
return base_iterator(*this) - base_iterator(other);
11506
}
11507
11508
/// access to successor
11509
reference operator[](difference_type n) const
11510
{
11511
return *(this->operator+(n));
11512
}
11513
11514
/// return the key of an object iterator
11515
auto key() const -> decltype(std::declval<Base>().key())
11516
{
11517
auto it = --this->base();
11518
return it.key();
11519
}
11520
11521
/// return the value of an iterator
11522
reference value() const
11523
{
11524
auto it = --this->base();
11525
return it.operator * ();
11526
}
11527
};
11528
} // namespace detail
11529
} // namespace nlohmann
11530
11531
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
11532
11533
// #include <nlohmann/detail/json_pointer.hpp>
11534
11535
11536
#include <algorithm> // all_of
11537
#include <cctype> // isdigit
11538
#include <limits> // max
11539
#include <numeric> // accumulate
11540
#include <string> // string
11541
#include <utility> // move
11542
#include <vector> // vector
11543
11544
// #include <nlohmann/detail/exceptions.hpp>
11545
11546
// #include <nlohmann/detail/macro_scope.hpp>
11547
11548
// #include <nlohmann/detail/value_t.hpp>
11549
11550
11551
namespace nlohmann
11552
{
11553
template<typename BasicJsonType>
11554
class json_pointer
11555
{
11556
// allow basic_json to access private members
11557
NLOHMANN_BASIC_JSON_TPL_DECLARATION
11558
friend class basic_json;
11559
11560
public:
11561
/*!
11562
@brief create JSON pointer
11563
11564
Create a JSON pointer according to the syntax described in
11565
[Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).
11566
11567
@param[in] s string representing the JSON pointer; if omitted, the empty
11568
string is assumed which references the whole JSON value
11569
11570
@throw parse_error.107 if the given JSON pointer @a s is nonempty and does
11571
not begin with a slash (`/`); see example below
11572
11573
@throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is
11574
not followed by `0` (representing `~`) or `1` (representing `/`); see
11575
example below
11576
11577
@liveexample{The example shows the construction several valid JSON pointers
11578
as well as the exceptional behavior.,json_pointer}
11579
11580
@since version 2.0.0
11581
*/
11582
explicit json_pointer(const std::string& s = "")
11583
: reference_tokens(split(s))
11584
{}
11585
11586
/*!
11587
@brief return a string representation of the JSON pointer
11588
11589
@invariant For each JSON pointer `ptr`, it holds:
11590
@code {.cpp}
11591
ptr == json_pointer(ptr.to_string());
11592
@endcode
11593
11594
@return a string representation of the JSON pointer
11595
11596
@liveexample{The example shows the result of `to_string`.,json_pointer__to_string}
11597
11598
@since version 2.0.0
11599
*/
11600
std::string to_string() const
11601
{
11602
return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
11603
std::string{},
11604
[](const std::string & a, const std::string & b)
11605
{
11606
return a + "/" + escape(b);
11607
});
11608
}
11609
11610
/// @copydoc to_string()
11611
operator std::string() const
11612
{
11613
return to_string();
11614
}
11615
11616
/*!
11617
@brief append another JSON pointer at the end of this JSON pointer
11618
11619
@param[in] ptr JSON pointer to append
11620
@return JSON pointer with @a ptr appended
11621
11622
@liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
11623
11624
@complexity Linear in the length of @a ptr.
11625
11626
@sa @ref operator/=(std::string) to append a reference token
11627
@sa @ref operator/=(std::size_t) to append an array index
11628
@sa @ref operator/(const json_pointer&, const json_pointer&) for a binary operator
11629
11630
@since version 3.6.0
11631
*/
11632
json_pointer& operator/=(const json_pointer& ptr)
11633
{
11634
reference_tokens.insert(reference_tokens.end(),
11635
ptr.reference_tokens.begin(),
11636
ptr.reference_tokens.end());
11637
return *this;
11638
}
11639
11640
/*!
11641
@brief append an unescaped reference token at the end of this JSON pointer
11642
11643
@param[in] token reference token to append
11644
@return JSON pointer with @a token appended without escaping @a token
11645
11646
@liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
11647
11648
@complexity Amortized constant.
11649
11650
@sa @ref operator/=(const json_pointer&) to append a JSON pointer
11651
@sa @ref operator/=(std::size_t) to append an array index
11652
@sa @ref operator/(const json_pointer&, std::size_t) for a binary operator
11653
11654
@since version 3.6.0
11655
*/
11656
json_pointer& operator/=(std::string token)
11657
{
11658
push_back(std::move(token));
11659
return *this;
11660
}
11661
11662
/*!
11663
@brief append an array index at the end of this JSON pointer
11664
11665
@param[in] array_idx array index to append
11666
@return JSON pointer with @a array_idx appended
11667
11668
@liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
11669
11670
@complexity Amortized constant.
11671
11672
@sa @ref operator/=(const json_pointer&) to append a JSON pointer
11673
@sa @ref operator/=(std::string) to append a reference token
11674
@sa @ref operator/(const json_pointer&, std::string) for a binary operator
11675
11676
@since version 3.6.0
11677
*/
11678
json_pointer& operator/=(std::size_t array_idx)
11679
{
11680
return *this /= std::to_string(array_idx);
11681
}
11682
11683
/*!
11684
@brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
11685
11686
@param[in] lhs JSON pointer
11687
@param[in] rhs JSON pointer
11688
@return a new JSON pointer with @a rhs appended to @a lhs
11689
11690
@liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
11691
11692
@complexity Linear in the length of @a lhs and @a rhs.
11693
11694
@sa @ref operator/=(const json_pointer&) to append a JSON pointer
11695
11696
@since version 3.6.0
11697
*/
11698
friend json_pointer operator/(const json_pointer& lhs,
11699
const json_pointer& rhs)
11700
{
11701
return json_pointer(lhs) /= rhs;
11702
}
11703
11704
/*!
11705
@brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
11706
11707
@param[in] ptr JSON pointer
11708
@param[in] token reference token
11709
@return a new JSON pointer with unescaped @a token appended to @a ptr
11710
11711
@liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
11712
11713
@complexity Linear in the length of @a ptr.
11714
11715
@sa @ref operator/=(std::string) to append a reference token
11716
11717
@since version 3.6.0
11718
*/
11719
friend json_pointer operator/(const json_pointer& ptr, std::string token)
11720
{
11721
return json_pointer(ptr) /= std::move(token);
11722
}
11723
11724
/*!
11725
@brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
11726
11727
@param[in] ptr JSON pointer
11728
@param[in] array_idx array index
11729
@return a new JSON pointer with @a array_idx appended to @a ptr
11730
11731
@liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
11732
11733
@complexity Linear in the length of @a ptr.
11734
11735
@sa @ref operator/=(std::size_t) to append an array index
11736
11737
@since version 3.6.0
11738
*/
11739
friend json_pointer operator/(const json_pointer& ptr, std::size_t array_idx)
11740
{
11741
return json_pointer(ptr) /= array_idx;
11742
}
11743
11744
/*!
11745
@brief returns the parent of this JSON pointer
11746
11747
@return parent of this JSON pointer; in case this JSON pointer is the root,
11748
the root itself is returned
11749
11750
@complexity Linear in the length of the JSON pointer.
11751
11752
@liveexample{The example shows the result of `parent_pointer` for different
11753
JSON Pointers.,json_pointer__parent_pointer}
11754
11755
@since version 3.6.0
11756
*/
11757
json_pointer parent_pointer() const
11758
{
11759
if (empty())
11760
{
11761
return *this;
11762
}
11763
11764
json_pointer res = *this;
11765
res.pop_back();
11766
return res;
11767
}
11768
11769
/*!
11770
@brief remove last reference token
11771
11772
@pre not `empty()`
11773
11774
@liveexample{The example shows the usage of `pop_back`.,json_pointer__pop_back}
11775
11776
@complexity Constant.
11777
11778
@throw out_of_range.405 if JSON pointer has no parent
11779
11780
@since version 3.6.0
11781
*/
11782
void pop_back()
11783
{
11784
if (JSON_HEDLEY_UNLIKELY(empty()))
11785
{
11786
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
11787
}
11788
11789
reference_tokens.pop_back();
11790
}
11791
11792
/*!
11793
@brief return last reference token
11794
11795
@pre not `empty()`
11796
@return last reference token
11797
11798
@liveexample{The example shows the usage of `back`.,json_pointer__back}
11799
11800
@complexity Constant.
11801
11802
@throw out_of_range.405 if JSON pointer has no parent
11803
11804
@since version 3.6.0
11805
*/
11806
const std::string& back() const
11807
{
11808
if (JSON_HEDLEY_UNLIKELY(empty()))
11809
{
11810
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
11811
}
11812
11813
return reference_tokens.back();
11814
}
11815
11816
/*!
11817
@brief append an unescaped token at the end of the reference pointer
11818
11819
@param[in] token token to add
11820
11821
@complexity Amortized constant.
11822
11823
@liveexample{The example shows the result of `push_back` for different
11824
JSON Pointers.,json_pointer__push_back}
11825
11826
@since version 3.6.0
11827
*/
11828
void push_back(const std::string& token)
11829
{
11830
reference_tokens.push_back(token);
11831
}
11832
11833
/// @copydoc push_back(const std::string&)
11834
void push_back(std::string&& token)
11835
{
11836
reference_tokens.push_back(std::move(token));
11837
}
11838
11839
/*!
11840
@brief return whether pointer points to the root document
11841
11842
@return true iff the JSON pointer points to the root document
11843
11844
@complexity Constant.
11845
11846
@exceptionsafety No-throw guarantee: this function never throws exceptions.
11847
11848
@liveexample{The example shows the result of `empty` for different JSON
11849
Pointers.,json_pointer__empty}
11850
11851
@since version 3.6.0
11852
*/
11853
bool empty() const noexcept
11854
{
11855
return reference_tokens.empty();
11856
}
11857
11858
private:
11859
/*!
11860
@param[in] s reference token to be converted into an array index
11861
11862
@return integer representation of @a s
11863
11864
@throw parse_error.106 if an array index begins with '0'
11865
@throw parse_error.109 if an array index begins not with a digit
11866
@throw out_of_range.404 if string @a s could not be converted to an integer
11867
@throw out_of_range.410 if an array index exceeds size_type
11868
*/
11869
static typename BasicJsonType::size_type array_index(const std::string& s)
11870
{
11871
using size_type = typename BasicJsonType::size_type;
11872
11873
// error condition (cf. RFC 6901, Sect. 4)
11874
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
11875
{
11876
JSON_THROW(detail::parse_error::create(106, 0,
11877
"array index '" + s +
11878
"' must not begin with '0'"));
11879
}
11880
11881
// error condition (cf. RFC 6901, Sect. 4)
11882
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
11883
{
11884
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number"));
11885
}
11886
11887
std::size_t processed_chars = 0;
11888
unsigned long long res = 0;
11889
JSON_TRY
11890
{
11891
res = std::stoull(s, &processed_chars);
11892
}
11893
JSON_CATCH(std::out_of_range&)
11894
{
11895
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
11896
}
11897
11898
// check if the string was completely read
11899
if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
11900
{
11901
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
11902
}
11903
11904
// only triggered on special platforms (like 32bit), see also
11905
// https://github.com/nlohmann/json/pull/2203
11906
if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))
11907
{
11908
JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE
11909
}
11910
11911
return static_cast<size_type>(res);
11912
}
11913
11914
json_pointer top() const
11915
{
11916
if (JSON_HEDLEY_UNLIKELY(empty()))
11917
{
11918
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
11919
}
11920
11921
json_pointer result = *this;
11922
result.reference_tokens = {reference_tokens[0]};
11923
return result;
11924
}
11925
11926
/*!
11927
@brief create and return a reference to the pointed to value
11928
11929
@complexity Linear in the number of reference tokens.
11930
11931
@throw parse_error.109 if array index is not a number
11932
@throw type_error.313 if value cannot be unflattened
11933
*/
11934
BasicJsonType& get_and_create(BasicJsonType& j) const
11935
{
11936
auto result = &j;
11937
11938
// in case no reference tokens exist, return a reference to the JSON value
11939
// j which will be overwritten by a primitive value
11940
for (const auto& reference_token : reference_tokens)
11941
{
11942
switch (result->type())
11943
{
11944
case detail::value_t::null:
11945
{
11946
if (reference_token == "0")
11947
{
11948
// start a new array if reference token is 0
11949
result = &result->operator[](0);
11950
}
11951
else
11952
{
11953
// start a new object otherwise
11954
result = &result->operator[](reference_token);
11955
}
11956
break;
11957
}
11958
11959
case detail::value_t::object:
11960
{
11961
// create an entry in the object
11962
result = &result->operator[](reference_token);
11963
break;
11964
}
11965
11966
case detail::value_t::array:
11967
{
11968
// create an entry in the array
11969
result = &result->operator[](array_index(reference_token));
11970
break;
11971
}
11972
11973
/*
11974
The following code is only reached if there exists a reference
11975
token _and_ the current value is primitive. In this case, we have
11976
an error situation, because primitive values may only occur as
11977
single value; that is, with an empty list of reference tokens.
11978
*/
11979
default:
11980
JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
11981
}
11982
}
11983
11984
return *result;
11985
}
11986
11987
/*!
11988
@brief return a reference to the pointed to value
11989
11990
@note This version does not throw if a value is not present, but tries to
11991
create nested values instead. For instance, calling this function
11992
with pointer `"/this/that"` on a null value is equivalent to calling
11993
`operator[]("this").operator[]("that")` on that value, effectively
11994
changing the null value to an object.
11995
11996
@param[in] ptr a JSON value
11997
11998
@return reference to the JSON value pointed to by the JSON pointer
11999
12000
@complexity Linear in the length of the JSON pointer.
12001
12002
@throw parse_error.106 if an array index begins with '0'
12003
@throw parse_error.109 if an array index was not a number
12004
@throw out_of_range.404 if the JSON pointer can not be resolved
12005
*/
12006
BasicJsonType& get_unchecked(BasicJsonType* ptr) const
12007
{
12008
for (const auto& reference_token : reference_tokens)
12009
{
12010
// convert null values to arrays or objects before continuing
12011
if (ptr->is_null())
12012
{
12013
// check if reference token is a number
12014
const bool nums =
12015
std::all_of(reference_token.begin(), reference_token.end(),
12016
[](const unsigned char x)
12017
{
12018
return std::isdigit(x);
12019
});
12020
12021
// change value to array for numbers or "-" or to object otherwise
12022
*ptr = (nums || reference_token == "-")
12023
? detail::value_t::array
12024
: detail::value_t::object;
12025
}
12026
12027
switch (ptr->type())
12028
{
12029
case detail::value_t::object:
12030
{
12031
// use unchecked object access
12032
ptr = &ptr->operator[](reference_token);
12033
break;
12034
}
12035
12036
case detail::value_t::array:
12037
{
12038
if (reference_token == "-")
12039
{
12040
// explicitly treat "-" as index beyond the end
12041
ptr = &ptr->operator[](ptr->m_value.array->size());
12042
}
12043
else
12044
{
12045
// convert array index to number; unchecked access
12046
ptr = &ptr->operator[](array_index(reference_token));
12047
}
12048
break;
12049
}
12050
12051
default:
12052
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12053
}
12054
}
12055
12056
return *ptr;
12057
}
12058
12059
/*!
12060
@throw parse_error.106 if an array index begins with '0'
12061
@throw parse_error.109 if an array index was not a number
12062
@throw out_of_range.402 if the array index '-' is used
12063
@throw out_of_range.404 if the JSON pointer can not be resolved
12064
*/
12065
BasicJsonType& get_checked(BasicJsonType* ptr) const
12066
{
12067
for (const auto& reference_token : reference_tokens)
12068
{
12069
switch (ptr->type())
12070
{
12071
case detail::value_t::object:
12072
{
12073
// note: at performs range check
12074
ptr = &ptr->at(reference_token);
12075
break;
12076
}
12077
12078
case detail::value_t::array:
12079
{
12080
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12081
{
12082
// "-" always fails the range check
12083
JSON_THROW(detail::out_of_range::create(402,
12084
"array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12085
") is out of range"));
12086
}
12087
12088
// note: at performs range check
12089
ptr = &ptr->at(array_index(reference_token));
12090
break;
12091
}
12092
12093
default:
12094
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12095
}
12096
}
12097
12098
return *ptr;
12099
}
12100
12101
/*!
12102
@brief return a const reference to the pointed to value
12103
12104
@param[in] ptr a JSON value
12105
12106
@return const reference to the JSON value pointed to by the JSON
12107
pointer
12108
12109
@throw parse_error.106 if an array index begins with '0'
12110
@throw parse_error.109 if an array index was not a number
12111
@throw out_of_range.402 if the array index '-' is used
12112
@throw out_of_range.404 if the JSON pointer can not be resolved
12113
*/
12114
const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
12115
{
12116
for (const auto& reference_token : reference_tokens)
12117
{
12118
switch (ptr->type())
12119
{
12120
case detail::value_t::object:
12121
{
12122
// use unchecked object access
12123
ptr = &ptr->operator[](reference_token);
12124
break;
12125
}
12126
12127
case detail::value_t::array:
12128
{
12129
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12130
{
12131
// "-" cannot be used for const access
12132
JSON_THROW(detail::out_of_range::create(402,
12133
"array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12134
") is out of range"));
12135
}
12136
12137
// use unchecked array access
12138
ptr = &ptr->operator[](array_index(reference_token));
12139
break;
12140
}
12141
12142
default:
12143
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12144
}
12145
}
12146
12147
return *ptr;
12148
}
12149
12150
/*!
12151
@throw parse_error.106 if an array index begins with '0'
12152
@throw parse_error.109 if an array index was not a number
12153
@throw out_of_range.402 if the array index '-' is used
12154
@throw out_of_range.404 if the JSON pointer can not be resolved
12155
*/
12156
const BasicJsonType& get_checked(const BasicJsonType* ptr) const
12157
{
12158
for (const auto& reference_token : reference_tokens)
12159
{
12160
switch (ptr->type())
12161
{
12162
case detail::value_t::object:
12163
{
12164
// note: at performs range check
12165
ptr = &ptr->at(reference_token);
12166
break;
12167
}
12168
12169
case detail::value_t::array:
12170
{
12171
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12172
{
12173
// "-" always fails the range check
12174
JSON_THROW(detail::out_of_range::create(402,
12175
"array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12176
") is out of range"));
12177
}
12178
12179
// note: at performs range check
12180
ptr = &ptr->at(array_index(reference_token));
12181
break;
12182
}
12183
12184
default:
12185
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12186
}
12187
}
12188
12189
return *ptr;
12190
}
12191
12192
/*!
12193
@throw parse_error.106 if an array index begins with '0'
12194
@throw parse_error.109 if an array index was not a number
12195
*/
12196
bool contains(const BasicJsonType* ptr) const
12197
{
12198
for (const auto& reference_token : reference_tokens)
12199
{
12200
switch (ptr->type())
12201
{
12202
case detail::value_t::object:
12203
{
12204
if (!ptr->contains(reference_token))
12205
{
12206
// we did not find the key in the object
12207
return false;
12208
}
12209
12210
ptr = &ptr->operator[](reference_token);
12211
break;
12212
}
12213
12214
case detail::value_t::array:
12215
{
12216
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12217
{
12218
// "-" always fails the range check
12219
return false;
12220
}
12221
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
12222
{
12223
// invalid char
12224
return false;
12225
}
12226
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
12227
{
12228
if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
12229
{
12230
// first char should be between '1' and '9'
12231
return false;
12232
}
12233
for (std::size_t i = 1; i < reference_token.size(); i++)
12234
{
12235
if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
12236
{
12237
// other char should be between '0' and '9'
12238
return false;
12239
}
12240
}
12241
}
12242
12243
const auto idx = array_index(reference_token);
12244
if (idx >= ptr->size())
12245
{
12246
// index out of range
12247
return false;
12248
}
12249
12250
ptr = &ptr->operator[](idx);
12251
break;
12252
}
12253
12254
default:
12255
{
12256
// we do not expect primitive values if there is still a
12257
// reference token to process
12258
return false;
12259
}
12260
}
12261
}
12262
12263
// no reference token left means we found a primitive value
12264
return true;
12265
}
12266
12267
/*!
12268
@brief split the string input to reference tokens
12269
12270
@note This function is only called by the json_pointer constructor.
12271
All exceptions below are documented there.
12272
12273
@throw parse_error.107 if the pointer is not empty or begins with '/'
12274
@throw parse_error.108 if character '~' is not followed by '0' or '1'
12275
*/
12276
static std::vector<std::string> split(const std::string& reference_string)
12277
{
12278
std::vector<std::string> result;
12279
12280
// special case: empty reference string -> no reference tokens
12281
if (reference_string.empty())
12282
{
12283
return result;
12284
}
12285
12286
// check if nonempty reference string begins with slash
12287
if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
12288
{
12289
JSON_THROW(detail::parse_error::create(107, 1,
12290
"JSON pointer must be empty or begin with '/' - was: '" +
12291
reference_string + "'"));
12292
}
12293
12294
// extract the reference tokens:
12295
// - slash: position of the last read slash (or end of string)
12296
// - start: position after the previous slash
12297
for (
12298
// search for the first slash after the first character
12299
std::size_t slash = reference_string.find_first_of('/', 1),
12300
// set the beginning of the first reference token
12301
start = 1;
12302
// we can stop if start == 0 (if slash == std::string::npos)
12303
start != 0;
12304
// set the beginning of the next reference token
12305
// (will eventually be 0 if slash == std::string::npos)
12306
start = (slash == std::string::npos) ? 0 : slash + 1,
12307
// find next slash
12308
slash = reference_string.find_first_of('/', start))
12309
{
12310
// use the text between the beginning of the reference token
12311
// (start) and the last slash (slash).
12312
auto reference_token = reference_string.substr(start, slash - start);
12313
12314
// check reference tokens are properly escaped
12315
for (std::size_t pos = reference_token.find_first_of('~');
12316
pos != std::string::npos;
12317
pos = reference_token.find_first_of('~', pos + 1))
12318
{
12319
JSON_ASSERT(reference_token[pos] == '~');
12320
12321
// ~ must be followed by 0 or 1
12322
if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
12323
(reference_token[pos + 1] != '0' &&
12324
reference_token[pos + 1] != '1')))
12325
{
12326
JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
12327
}
12328
}
12329
12330
// finally, store the reference token
12331
unescape(reference_token);
12332
result.push_back(reference_token);
12333
}
12334
12335
return result;
12336
}
12337
12338
/*!
12339
@brief replace all occurrences of a substring by another string
12340
12341
@param[in,out] s the string to manipulate; changed so that all
12342
occurrences of @a f are replaced with @a t
12343
@param[in] f the substring to replace with @a t
12344
@param[in] t the string to replace @a f
12345
12346
@pre The search string @a f must not be empty. **This precondition is
12347
enforced with an assertion.**
12348
12349
@since version 2.0.0
12350
*/
12351
static void replace_substring(std::string& s, const std::string& f,
12352
const std::string& t)
12353
{
12354
JSON_ASSERT(!f.empty());
12355
for (auto pos = s.find(f); // find first occurrence of f
12356
pos != std::string::npos; // make sure f was found
12357
s.replace(pos, f.size(), t), // replace with t, and
12358
pos = s.find(f, pos + t.size())) // find next occurrence of f
12359
{}
12360
}
12361
12362
/// escape "~" to "~0" and "/" to "~1"
12363
static std::string escape(std::string s)
12364
{
12365
replace_substring(s, "~", "~0");
12366
replace_substring(s, "/", "~1");
12367
return s;
12368
}
12369
12370
/// unescape "~1" to tilde and "~0" to slash (order is important!)
12371
static void unescape(std::string& s)
12372
{
12373
replace_substring(s, "~1", "/");
12374
replace_substring(s, "~0", "~");
12375
}
12376
12377
/*!
12378
@param[in] reference_string the reference string to the current value
12379
@param[in] value the value to consider
12380
@param[in,out] result the result object to insert values to
12381
12382
@note Empty objects or arrays are flattened to `null`.
12383
*/
12384
static void flatten(const std::string& reference_string,
12385
const BasicJsonType& value,
12386
BasicJsonType& result)
12387
{
12388
switch (value.type())
12389
{
12390
case detail::value_t::array:
12391
{
12392
if (value.m_value.array->empty())
12393
{
12394
// flatten empty array as null
12395
result[reference_string] = nullptr;
12396
}
12397
else
12398
{
12399
// iterate array and use index as reference string
12400
for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
12401
{
12402
flatten(reference_string + "/" + std::to_string(i),
12403
value.m_value.array->operator[](i), result);
12404
}
12405
}
12406
break;
12407
}
12408
12409
case detail::value_t::object:
12410
{
12411
if (value.m_value.object->empty())
12412
{
12413
// flatten empty object as null
12414
result[reference_string] = nullptr;
12415
}
12416
else
12417
{
12418
// iterate object and use keys as reference string
12419
for (const auto& element : *value.m_value.object)
12420
{
12421
flatten(reference_string + "/" + escape(element.first), element.second, result);
12422
}
12423
}
12424
break;
12425
}
12426
12427
default:
12428
{
12429
// add primitive value with its reference string
12430
result[reference_string] = value;
12431
break;
12432
}
12433
}
12434
}
12435
12436
/*!
12437
@param[in] value flattened JSON
12438
12439
@return unflattened JSON
12440
12441
@throw parse_error.109 if array index is not a number
12442
@throw type_error.314 if value is not an object
12443
@throw type_error.315 if object values are not primitive
12444
@throw type_error.313 if value cannot be unflattened
12445
*/
12446
static BasicJsonType
12447
unflatten(const BasicJsonType& value)
12448
{
12449
if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
12450
{
12451
JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
12452
}
12453
12454
BasicJsonType result;
12455
12456
// iterate the JSON object values
12457
for (const auto& element : *value.m_value.object)
12458
{
12459
if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
12460
{
12461
JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
12462
}
12463
12464
// assign value to reference pointed to by JSON pointer; Note that if
12465
// the JSON pointer is "" (i.e., points to the whole value), function
12466
// get_and_create returns a reference to result itself. An assignment
12467
// will then create a primitive value.
12468
json_pointer(element.first).get_and_create(result) = element.second;
12469
}
12470
12471
return result;
12472
}
12473
12474
/*!
12475
@brief compares two JSON pointers for equality
12476
12477
@param[in] lhs JSON pointer to compare
12478
@param[in] rhs JSON pointer to compare
12479
@return whether @a lhs is equal to @a rhs
12480
12481
@complexity Linear in the length of the JSON pointer
12482
12483
@exceptionsafety No-throw guarantee: this function never throws exceptions.
12484
*/
12485
friend bool operator==(json_pointer const& lhs,
12486
json_pointer const& rhs) noexcept
12487
{
12488
return lhs.reference_tokens == rhs.reference_tokens;
12489
}
12490
12491
/*!
12492
@brief compares two JSON pointers for inequality
12493
12494
@param[in] lhs JSON pointer to compare
12495
@param[in] rhs JSON pointer to compare
12496
@return whether @a lhs is not equal @a rhs
12497
12498
@complexity Linear in the length of the JSON pointer
12499
12500
@exceptionsafety No-throw guarantee: this function never throws exceptions.
12501
*/
12502
friend bool operator!=(json_pointer const& lhs,
12503
json_pointer const& rhs) noexcept
12504
{
12505
return !(lhs == rhs);
12506
}
12507
12508
/// the reference tokens
12509
std::vector<std::string> reference_tokens;
12510
};
12511
} // namespace nlohmann
12512
12513
// #include <nlohmann/detail/json_ref.hpp>
12514
12515
12516
#include <initializer_list>
12517
#include <utility>
12518
12519
// #include <nlohmann/detail/meta/type_traits.hpp>
12520
12521
12522
namespace nlohmann
12523
{
12524
namespace detail
12525
{
12526
template<typename BasicJsonType>
12527
class json_ref
12528
{
12529
public:
12530
using value_type = BasicJsonType;
12531
12532
json_ref(value_type&& value)
12533
: owned_value(std::move(value))
12534
, value_ref(&owned_value)
12535
, is_rvalue(true)
12536
{}
12537
12538
json_ref(const value_type& value)
12539
: value_ref(const_cast<value_type*>(&value))
12540
, is_rvalue(false)
12541
{}
12542
12543
json_ref(std::initializer_list<json_ref> init)
12544
: owned_value(init)
12545
, value_ref(&owned_value)
12546
, is_rvalue(true)
12547
{}
12548
12549
template <
12550
class... Args,
12551
enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
12552
json_ref(Args && ... args)
12553
: owned_value(std::forward<Args>(args)...)
12554
, value_ref(&owned_value)
12555
, is_rvalue(true)
12556
{}
12557
12558
// class should be movable only
12559
json_ref(json_ref&&) = default;
12560
json_ref(const json_ref&) = delete;
12561
json_ref& operator=(const json_ref&) = delete;
12562
json_ref& operator=(json_ref&&) = delete;
12563
~json_ref() = default;
12564
12565
value_type moved_or_copied() const
12566
{
12567
if (is_rvalue)
12568
{
12569
return std::move(*value_ref);
12570
}
12571
return *value_ref;
12572
}
12573
12574
value_type const& operator*() const
12575
{
12576
return *static_cast<value_type const*>(value_ref);
12577
}
12578
12579
value_type const* operator->() const
12580
{
12581
return static_cast<value_type const*>(value_ref);
12582
}
12583
12584
private:
12585
mutable value_type owned_value = nullptr;
12586
value_type* value_ref = nullptr;
12587
const bool is_rvalue = true;
12588
};
12589
} // namespace detail
12590
} // namespace nlohmann
12591
12592
// #include <nlohmann/detail/macro_scope.hpp>
12593
12594
// #include <nlohmann/detail/meta/cpp_future.hpp>
12595
12596
// #include <nlohmann/detail/meta/type_traits.hpp>
12597
12598
// #include <nlohmann/detail/output/binary_writer.hpp>
12599
12600
12601
#include <algorithm> // reverse
12602
#include <array> // array
12603
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
12604
#include <cstring> // memcpy
12605
#include <limits> // numeric_limits
12606
#include <string> // string
12607
#include <cmath> // isnan, isinf
12608
12609
// #include <nlohmann/detail/input/binary_reader.hpp>
12610
12611
// #include <nlohmann/detail/macro_scope.hpp>
12612
12613
// #include <nlohmann/detail/output/output_adapters.hpp>
12614
12615
12616
#include <algorithm> // copy
12617
#include <cstddef> // size_t
12618
#include <ios> // streamsize
12619
#include <iterator> // back_inserter
12620
#include <memory> // shared_ptr, make_shared
12621
#include <ostream> // basic_ostream
12622
#include <string> // basic_string
12623
#include <vector> // vector
12624
// #include <nlohmann/detail/macro_scope.hpp>
12625
12626
12627
namespace nlohmann
12628
{
12629
namespace detail
12630
{
12631
/// abstract output adapter interface
12632
template<typename CharType> struct output_adapter_protocol
12633
{
12634
virtual void write_character(CharType c) = 0;
12635
virtual void write_characters(const CharType* s, std::size_t length) = 0;
12636
virtual ~output_adapter_protocol() = default;
12637
};
12638
12639
/// a type to simplify interfaces
12640
template<typename CharType>
12641
using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
12642
12643
/// output adapter for byte vectors
12644
template<typename CharType>
12645
class output_vector_adapter : public output_adapter_protocol<CharType>
12646
{
12647
public:
12648
explicit output_vector_adapter(std::vector<CharType>& vec) noexcept
12649
: v(vec)
12650
{}
12651
12652
void write_character(CharType c) override
12653
{
12654
v.push_back(c);
12655
}
12656
12657
JSON_HEDLEY_NON_NULL(2)
12658
void write_characters(const CharType* s, std::size_t length) override
12659
{
12660
std::copy(s, s + length, std::back_inserter(v));
12661
}
12662
12663
private:
12664
std::vector<CharType>& v;
12665
};
12666
12667
/// output adapter for output streams
12668
template<typename CharType>
12669
class output_stream_adapter : public output_adapter_protocol<CharType>
12670
{
12671
public:
12672
explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
12673
: stream(s)
12674
{}
12675
12676
void write_character(CharType c) override
12677
{
12678
stream.put(c);
12679
}
12680
12681
JSON_HEDLEY_NON_NULL(2)
12682
void write_characters(const CharType* s, std::size_t length) override
12683
{
12684
stream.write(s, static_cast<std::streamsize>(length));
12685
}
12686
12687
private:
12688
std::basic_ostream<CharType>& stream;
12689
};
12690
12691
/// output adapter for basic_string
12692
template<typename CharType, typename StringType = std::basic_string<CharType>>
12693
class output_string_adapter : public output_adapter_protocol<CharType>
12694
{
12695
public:
12696
explicit output_string_adapter(StringType& s) noexcept
12697
: str(s)
12698
{}
12699
12700
void write_character(CharType c) override
12701
{
12702
str.push_back(c);
12703
}
12704
12705
JSON_HEDLEY_NON_NULL(2)
12706
void write_characters(const CharType* s, std::size_t length) override
12707
{
12708
str.append(s, length);
12709
}
12710
12711
private:
12712
StringType& str;
12713
};
12714
12715
template<typename CharType, typename StringType = std::basic_string<CharType>>
12716
class output_adapter
12717
{
12718
public:
12719
output_adapter(std::vector<CharType>& vec)
12720
: oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
12721
12722
output_adapter(std::basic_ostream<CharType>& s)
12723
: oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
12724
12725
output_adapter(StringType& s)
12726
: oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
12727
12728
operator output_adapter_t<CharType>()
12729
{
12730
return oa;
12731
}
12732
12733
private:
12734
output_adapter_t<CharType> oa = nullptr;
12735
};
12736
} // namespace detail
12737
} // namespace nlohmann
12738
12739
12740
namespace nlohmann
12741
{
12742
namespace detail
12743
{
12744
///////////////////
12745
// binary writer //
12746
///////////////////
12747
12748
/*!
12749
@brief serialization to CBOR and MessagePack values
12750
*/
12751
template<typename BasicJsonType, typename CharType>
12752
class binary_writer
12753
{
12754
using string_t = typename BasicJsonType::string_t;
12755
using binary_t = typename BasicJsonType::binary_t;
12756
using number_float_t = typename BasicJsonType::number_float_t;
12757
12758
public:
12759
/*!
12760
@brief create a binary writer
12761
12762
@param[in] adapter output adapter to write to
12763
*/
12764
explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
12765
{
12766
JSON_ASSERT(oa);
12767
}
12768
12769
/*!
12770
@param[in] j JSON value to serialize
12771
@pre j.type() == value_t::object
12772
*/
12773
void write_bson(const BasicJsonType& j)
12774
{
12775
switch (j.type())
12776
{
12777
case value_t::object:
12778
{
12779
write_bson_object(*j.m_value.object);
12780
break;
12781
}
12782
12783
default:
12784
{
12785
JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name())));
12786
}
12787
}
12788
}
12789
12790
/*!
12791
@param[in] j JSON value to serialize
12792
*/
12793
void write_cbor(const BasicJsonType& j)
12794
{
12795
switch (j.type())
12796
{
12797
case value_t::null:
12798
{
12799
oa->write_character(to_char_type(0xF6));
12800
break;
12801
}
12802
12803
case value_t::boolean:
12804
{
12805
oa->write_character(j.m_value.boolean
12806
? to_char_type(0xF5)
12807
: to_char_type(0xF4));
12808
break;
12809
}
12810
12811
case value_t::number_integer:
12812
{
12813
if (j.m_value.number_integer >= 0)
12814
{
12815
// CBOR does not differentiate between positive signed
12816
// integers and unsigned integers. Therefore, we used the
12817
// code from the value_t::number_unsigned case here.
12818
if (j.m_value.number_integer <= 0x17)
12819
{
12820
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
12821
}
12822
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
12823
{
12824
oa->write_character(to_char_type(0x18));
12825
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
12826
}
12827
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
12828
{
12829
oa->write_character(to_char_type(0x19));
12830
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
12831
}
12832
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
12833
{
12834
oa->write_character(to_char_type(0x1A));
12835
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
12836
}
12837
else
12838
{
12839
oa->write_character(to_char_type(0x1B));
12840
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
12841
}
12842
}
12843
else
12844
{
12845
// The conversions below encode the sign in the first
12846
// byte, and the value is converted to a positive number.
12847
const auto positive_number = -1 - j.m_value.number_integer;
12848
if (j.m_value.number_integer >= -24)
12849
{
12850
write_number(static_cast<std::uint8_t>(0x20 + positive_number));
12851
}
12852
else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
12853
{
12854
oa->write_character(to_char_type(0x38));
12855
write_number(static_cast<std::uint8_t>(positive_number));
12856
}
12857
else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
12858
{
12859
oa->write_character(to_char_type(0x39));
12860
write_number(static_cast<std::uint16_t>(positive_number));
12861
}
12862
else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
12863
{
12864
oa->write_character(to_char_type(0x3A));
12865
write_number(static_cast<std::uint32_t>(positive_number));
12866
}
12867
else
12868
{
12869
oa->write_character(to_char_type(0x3B));
12870
write_number(static_cast<std::uint64_t>(positive_number));
12871
}
12872
}
12873
break;
12874
}
12875
12876
case value_t::number_unsigned:
12877
{
12878
if (j.m_value.number_unsigned <= 0x17)
12879
{
12880
write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
12881
}
12882
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
12883
{
12884
oa->write_character(to_char_type(0x18));
12885
write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
12886
}
12887
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
12888
{
12889
oa->write_character(to_char_type(0x19));
12890
write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
12891
}
12892
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
12893
{
12894
oa->write_character(to_char_type(0x1A));
12895
write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
12896
}
12897
else
12898
{
12899
oa->write_character(to_char_type(0x1B));
12900
write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
12901
}
12902
break;
12903
}
12904
12905
case value_t::number_float:
12906
{
12907
if (std::isnan(j.m_value.number_float))
12908
{
12909
// NaN is 0xf97e00 in CBOR
12910
oa->write_character(to_char_type(0xF9));
12911
oa->write_character(to_char_type(0x7E));
12912
oa->write_character(to_char_type(0x00));
12913
}
12914
else if (std::isinf(j.m_value.number_float))
12915
{
12916
// Infinity is 0xf97c00, -Infinity is 0xf9fc00
12917
oa->write_character(to_char_type(0xf9));
12918
oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
12919
oa->write_character(to_char_type(0x00));
12920
}
12921
else
12922
{
12923
write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
12924
}
12925
break;
12926
}
12927
12928
case value_t::string:
12929
{
12930
// step 1: write control byte and the string length
12931
const auto N = j.m_value.string->size();
12932
if (N <= 0x17)
12933
{
12934
write_number(static_cast<std::uint8_t>(0x60 + N));
12935
}
12936
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
12937
{
12938
oa->write_character(to_char_type(0x78));
12939
write_number(static_cast<std::uint8_t>(N));
12940
}
12941
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
12942
{
12943
oa->write_character(to_char_type(0x79));
12944
write_number(static_cast<std::uint16_t>(N));
12945
}
12946
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
12947
{
12948
oa->write_character(to_char_type(0x7A));
12949
write_number(static_cast<std::uint32_t>(N));
12950
}
12951
// LCOV_EXCL_START
12952
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
12953
{
12954
oa->write_character(to_char_type(0x7B));
12955
write_number(static_cast<std::uint64_t>(N));
12956
}
12957
// LCOV_EXCL_STOP
12958
12959
// step 2: write the string
12960
oa->write_characters(
12961
reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
12962
j.m_value.string->size());
12963
break;
12964
}
12965
12966
case value_t::array:
12967
{
12968
// step 1: write control byte and the array size
12969
const auto N = j.m_value.array->size();
12970
if (N <= 0x17)
12971
{
12972
write_number(static_cast<std::uint8_t>(0x80 + N));
12973
}
12974
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
12975
{
12976
oa->write_character(to_char_type(0x98));
12977
write_number(static_cast<std::uint8_t>(N));
12978
}
12979
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
12980
{
12981
oa->write_character(to_char_type(0x99));
12982
write_number(static_cast<std::uint16_t>(N));
12983
}
12984
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
12985
{
12986
oa->write_character(to_char_type(0x9A));
12987
write_number(static_cast<std::uint32_t>(N));
12988
}
12989
// LCOV_EXCL_START
12990
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
12991
{
12992
oa->write_character(to_char_type(0x9B));
12993
write_number(static_cast<std::uint64_t>(N));
12994
}
12995
// LCOV_EXCL_STOP
12996
12997
// step 2: write each element
12998
for (const auto& el : *j.m_value.array)
12999
{
13000
write_cbor(el);
13001
}
13002
break;
13003
}
13004
13005
case value_t::binary:
13006
{
13007
if (j.m_value.binary->has_subtype())
13008
{
13009
write_number(static_cast<std::uint8_t>(0xd8));
13010
write_number(j.m_value.binary->subtype());
13011
}
13012
13013
// step 1: write control byte and the binary array size
13014
const auto N = j.m_value.binary->size();
13015
if (N <= 0x17)
13016
{
13017
write_number(static_cast<std::uint8_t>(0x40 + N));
13018
}
13019
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13020
{
13021
oa->write_character(to_char_type(0x58));
13022
write_number(static_cast<std::uint8_t>(N));
13023
}
13024
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13025
{
13026
oa->write_character(to_char_type(0x59));
13027
write_number(static_cast<std::uint16_t>(N));
13028
}
13029
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13030
{
13031
oa->write_character(to_char_type(0x5A));
13032
write_number(static_cast<std::uint32_t>(N));
13033
}
13034
// LCOV_EXCL_START
13035
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13036
{
13037
oa->write_character(to_char_type(0x5B));
13038
write_number(static_cast<std::uint64_t>(N));
13039
}
13040
// LCOV_EXCL_STOP
13041
13042
// step 2: write each element
13043
oa->write_characters(
13044
reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13045
N);
13046
13047
break;
13048
}
13049
13050
case value_t::object:
13051
{
13052
// step 1: write control byte and the object size
13053
const auto N = j.m_value.object->size();
13054
if (N <= 0x17)
13055
{
13056
write_number(static_cast<std::uint8_t>(0xA0 + N));
13057
}
13058
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13059
{
13060
oa->write_character(to_char_type(0xB8));
13061
write_number(static_cast<std::uint8_t>(N));
13062
}
13063
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13064
{
13065
oa->write_character(to_char_type(0xB9));
13066
write_number(static_cast<std::uint16_t>(N));
13067
}
13068
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13069
{
13070
oa->write_character(to_char_type(0xBA));
13071
write_number(static_cast<std::uint32_t>(N));
13072
}
13073
// LCOV_EXCL_START
13074
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13075
{
13076
oa->write_character(to_char_type(0xBB));
13077
write_number(static_cast<std::uint64_t>(N));
13078
}
13079
// LCOV_EXCL_STOP
13080
13081
// step 2: write each element
13082
for (const auto& el : *j.m_value.object)
13083
{
13084
write_cbor(el.first);
13085
write_cbor(el.second);
13086
}
13087
break;
13088
}
13089
13090
default:
13091
break;
13092
}
13093
}
13094
13095
/*!
13096
@param[in] j JSON value to serialize
13097
*/
13098
void write_msgpack(const BasicJsonType& j)
13099
{
13100
switch (j.type())
13101
{
13102
case value_t::null: // nil
13103
{
13104
oa->write_character(to_char_type(0xC0));
13105
break;
13106
}
13107
13108
case value_t::boolean: // true and false
13109
{
13110
oa->write_character(j.m_value.boolean
13111
? to_char_type(0xC3)
13112
: to_char_type(0xC2));
13113
break;
13114
}
13115
13116
case value_t::number_integer:
13117
{
13118
if (j.m_value.number_integer >= 0)
13119
{
13120
// MessagePack does not differentiate between positive
13121
// signed integers and unsigned integers. Therefore, we used
13122
// the code from the value_t::number_unsigned case here.
13123
if (j.m_value.number_unsigned < 128)
13124
{
13125
// positive fixnum
13126
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13127
}
13128
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
13129
{
13130
// uint 8
13131
oa->write_character(to_char_type(0xCC));
13132
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13133
}
13134
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
13135
{
13136
// uint 16
13137
oa->write_character(to_char_type(0xCD));
13138
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13139
}
13140
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
13141
{
13142
// uint 32
13143
oa->write_character(to_char_type(0xCE));
13144
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13145
}
13146
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
13147
{
13148
// uint 64
13149
oa->write_character(to_char_type(0xCF));
13150
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13151
}
13152
}
13153
else
13154
{
13155
if (j.m_value.number_integer >= -32)
13156
{
13157
// negative fixnum
13158
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
13159
}
13160
else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
13161
j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
13162
{
13163
// int 8
13164
oa->write_character(to_char_type(0xD0));
13165
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
13166
}
13167
else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
13168
j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
13169
{
13170
// int 16
13171
oa->write_character(to_char_type(0xD1));
13172
write_number(static_cast<std::int16_t>(j.m_value.number_integer));
13173
}
13174
else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
13175
j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
13176
{
13177
// int 32
13178
oa->write_character(to_char_type(0xD2));
13179
write_number(static_cast<std::int32_t>(j.m_value.number_integer));
13180
}
13181
else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
13182
j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
13183
{
13184
// int 64
13185
oa->write_character(to_char_type(0xD3));
13186
write_number(static_cast<std::int64_t>(j.m_value.number_integer));
13187
}
13188
}
13189
break;
13190
}
13191
13192
case value_t::number_unsigned:
13193
{
13194
if (j.m_value.number_unsigned < 128)
13195
{
13196
// positive fixnum
13197
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13198
}
13199
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
13200
{
13201
// uint 8
13202
oa->write_character(to_char_type(0xCC));
13203
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13204
}
13205
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
13206
{
13207
// uint 16
13208
oa->write_character(to_char_type(0xCD));
13209
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13210
}
13211
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
13212
{
13213
// uint 32
13214
oa->write_character(to_char_type(0xCE));
13215
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13216
}
13217
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
13218
{
13219
// uint 64
13220
oa->write_character(to_char_type(0xCF));
13221
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13222
}
13223
break;
13224
}
13225
13226
case value_t::number_float:
13227
{
13228
write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
13229
break;
13230
}
13231
13232
case value_t::string:
13233
{
13234
// step 1: write control byte and the string length
13235
const auto N = j.m_value.string->size();
13236
if (N <= 31)
13237
{
13238
// fixstr
13239
write_number(static_cast<std::uint8_t>(0xA0 | N));
13240
}
13241
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13242
{
13243
// str 8
13244
oa->write_character(to_char_type(0xD9));
13245
write_number(static_cast<std::uint8_t>(N));
13246
}
13247
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13248
{
13249
// str 16
13250
oa->write_character(to_char_type(0xDA));
13251
write_number(static_cast<std::uint16_t>(N));
13252
}
13253
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13254
{
13255
// str 32
13256
oa->write_character(to_char_type(0xDB));
13257
write_number(static_cast<std::uint32_t>(N));
13258
}
13259
13260
// step 2: write the string
13261
oa->write_characters(
13262
reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
13263
j.m_value.string->size());
13264
break;
13265
}
13266
13267
case value_t::array:
13268
{
13269
// step 1: write control byte and the array size
13270
const auto N = j.m_value.array->size();
13271
if (N <= 15)
13272
{
13273
// fixarray
13274
write_number(static_cast<std::uint8_t>(0x90 | N));
13275
}
13276
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13277
{
13278
// array 16
13279
oa->write_character(to_char_type(0xDC));
13280
write_number(static_cast<std::uint16_t>(N));
13281
}
13282
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13283
{
13284
// array 32
13285
oa->write_character(to_char_type(0xDD));
13286
write_number(static_cast<std::uint32_t>(N));
13287
}
13288
13289
// step 2: write each element
13290
for (const auto& el : *j.m_value.array)
13291
{
13292
write_msgpack(el);
13293
}
13294
break;
13295
}
13296
13297
case value_t::binary:
13298
{
13299
// step 0: determine if the binary type has a set subtype to
13300
// determine whether or not to use the ext or fixext types
13301
const bool use_ext = j.m_value.binary->has_subtype();
13302
13303
// step 1: write control byte and the byte string length
13304
const auto N = j.m_value.binary->size();
13305
if (N <= (std::numeric_limits<std::uint8_t>::max)())
13306
{
13307
std::uint8_t output_type{};
13308
bool fixed = true;
13309
if (use_ext)
13310
{
13311
switch (N)
13312
{
13313
case 1:
13314
output_type = 0xD4; // fixext 1
13315
break;
13316
case 2:
13317
output_type = 0xD5; // fixext 2
13318
break;
13319
case 4:
13320
output_type = 0xD6; // fixext 4
13321
break;
13322
case 8:
13323
output_type = 0xD7; // fixext 8
13324
break;
13325
case 16:
13326
output_type = 0xD8; // fixext 16
13327
break;
13328
default:
13329
output_type = 0xC7; // ext 8
13330
fixed = false;
13331
break;
13332
}
13333
13334
}
13335
else
13336
{
13337
output_type = 0xC4; // bin 8
13338
fixed = false;
13339
}
13340
13341
oa->write_character(to_char_type(output_type));
13342
if (!fixed)
13343
{
13344
write_number(static_cast<std::uint8_t>(N));
13345
}
13346
}
13347
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13348
{
13349
std::uint8_t output_type = use_ext
13350
? 0xC8 // ext 16
13351
: 0xC5; // bin 16
13352
13353
oa->write_character(to_char_type(output_type));
13354
write_number(static_cast<std::uint16_t>(N));
13355
}
13356
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13357
{
13358
std::uint8_t output_type = use_ext
13359
? 0xC9 // ext 32
13360
: 0xC6; // bin 32
13361
13362
oa->write_character(to_char_type(output_type));
13363
write_number(static_cast<std::uint32_t>(N));
13364
}
13365
13366
// step 1.5: if this is an ext type, write the subtype
13367
if (use_ext)
13368
{
13369
write_number(static_cast<std::int8_t>(j.m_value.binary->subtype()));
13370
}
13371
13372
// step 2: write the byte string
13373
oa->write_characters(
13374
reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13375
N);
13376
13377
break;
13378
}
13379
13380
case value_t::object:
13381
{
13382
// step 1: write control byte and the object size
13383
const auto N = j.m_value.object->size();
13384
if (N <= 15)
13385
{
13386
// fixmap
13387
write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
13388
}
13389
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13390
{
13391
// map 16
13392
oa->write_character(to_char_type(0xDE));
13393
write_number(static_cast<std::uint16_t>(N));
13394
}
13395
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13396
{
13397
// map 32
13398
oa->write_character(to_char_type(0xDF));
13399
write_number(static_cast<std::uint32_t>(N));
13400
}
13401
13402
// step 2: write each element
13403
for (const auto& el : *j.m_value.object)
13404
{
13405
write_msgpack(el.first);
13406
write_msgpack(el.second);
13407
}
13408
break;
13409
}
13410
13411
default:
13412
break;
13413
}
13414
}
13415
13416
/*!
13417
@param[in] j JSON value to serialize
13418
@param[in] use_count whether to use '#' prefixes (optimized format)
13419
@param[in] use_type whether to use '$' prefixes (optimized format)
13420
@param[in] add_prefix whether prefixes need to be used for this value
13421
*/
13422
void write_ubjson(const BasicJsonType& j, const bool use_count,
13423
const bool use_type, const bool add_prefix = true)
13424
{
13425
switch (j.type())
13426
{
13427
case value_t::null:
13428
{
13429
if (add_prefix)
13430
{
13431
oa->write_character(to_char_type('Z'));
13432
}
13433
break;
13434
}
13435
13436
case value_t::boolean:
13437
{
13438
if (add_prefix)
13439
{
13440
oa->write_character(j.m_value.boolean
13441
? to_char_type('T')
13442
: to_char_type('F'));
13443
}
13444
break;
13445
}
13446
13447
case value_t::number_integer:
13448
{
13449
write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
13450
break;
13451
}
13452
13453
case value_t::number_unsigned:
13454
{
13455
write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
13456
break;
13457
}
13458
13459
case value_t::number_float:
13460
{
13461
write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
13462
break;
13463
}
13464
13465
case value_t::string:
13466
{
13467
if (add_prefix)
13468
{
13469
oa->write_character(to_char_type('S'));
13470
}
13471
write_number_with_ubjson_prefix(j.m_value.string->size(), true);
13472
oa->write_characters(
13473
reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
13474
j.m_value.string->size());
13475
break;
13476
}
13477
13478
case value_t::array:
13479
{
13480
if (add_prefix)
13481
{
13482
oa->write_character(to_char_type('['));
13483
}
13484
13485
bool prefix_required = true;
13486
if (use_type && !j.m_value.array->empty())
13487
{
13488
JSON_ASSERT(use_count);
13489
const CharType first_prefix = ubjson_prefix(j.front());
13490
const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
13491
[this, first_prefix](const BasicJsonType & v)
13492
{
13493
return ubjson_prefix(v) == first_prefix;
13494
});
13495
13496
if (same_prefix)
13497
{
13498
prefix_required = false;
13499
oa->write_character(to_char_type('$'));
13500
oa->write_character(first_prefix);
13501
}
13502
}
13503
13504
if (use_count)
13505
{
13506
oa->write_character(to_char_type('#'));
13507
write_number_with_ubjson_prefix(j.m_value.array->size(), true);
13508
}
13509
13510
for (const auto& el : *j.m_value.array)
13511
{
13512
write_ubjson(el, use_count, use_type, prefix_required);
13513
}
13514
13515
if (!use_count)
13516
{
13517
oa->write_character(to_char_type(']'));
13518
}
13519
13520
break;
13521
}
13522
13523
case value_t::binary:
13524
{
13525
if (add_prefix)
13526
{
13527
oa->write_character(to_char_type('['));
13528
}
13529
13530
if (use_type && !j.m_value.binary->empty())
13531
{
13532
JSON_ASSERT(use_count);
13533
oa->write_character(to_char_type('$'));
13534
oa->write_character('U');
13535
}
13536
13537
if (use_count)
13538
{
13539
oa->write_character(to_char_type('#'));
13540
write_number_with_ubjson_prefix(j.m_value.binary->size(), true);
13541
}
13542
13543
if (use_type)
13544
{
13545
oa->write_characters(
13546
reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13547
j.m_value.binary->size());
13548
}
13549
else
13550
{
13551
for (size_t i = 0; i < j.m_value.binary->size(); ++i)
13552
{
13553
oa->write_character(to_char_type('U'));
13554
oa->write_character(j.m_value.binary->data()[i]);
13555
}
13556
}
13557
13558
if (!use_count)
13559
{
13560
oa->write_character(to_char_type(']'));
13561
}
13562
13563
break;
13564
}
13565
13566
case value_t::object:
13567
{
13568
if (add_prefix)
13569
{
13570
oa->write_character(to_char_type('{'));
13571
}
13572
13573
bool prefix_required = true;
13574
if (use_type && !j.m_value.object->empty())
13575
{
13576
JSON_ASSERT(use_count);
13577
const CharType first_prefix = ubjson_prefix(j.front());
13578
const bool same_prefix = std::all_of(j.begin(), j.end(),
13579
[this, first_prefix](const BasicJsonType & v)
13580
{
13581
return ubjson_prefix(v) == first_prefix;
13582
});
13583
13584
if (same_prefix)
13585
{
13586
prefix_required = false;
13587
oa->write_character(to_char_type('$'));
13588
oa->write_character(first_prefix);
13589
}
13590
}
13591
13592
if (use_count)
13593
{
13594
oa->write_character(to_char_type('#'));
13595
write_number_with_ubjson_prefix(j.m_value.object->size(), true);
13596
}
13597
13598
for (const auto& el : *j.m_value.object)
13599
{
13600
write_number_with_ubjson_prefix(el.first.size(), true);
13601
oa->write_characters(
13602
reinterpret_cast<const CharType*>(el.first.c_str()),
13603
el.first.size());
13604
write_ubjson(el.second, use_count, use_type, prefix_required);
13605
}
13606
13607
if (!use_count)
13608
{
13609
oa->write_character(to_char_type('}'));
13610
}
13611
13612
break;
13613
}
13614
13615
default:
13616
break;
13617
}
13618
}
13619
13620
private:
13621
//////////
13622
// BSON //
13623
//////////
13624
13625
/*!
13626
@return The size of a BSON document entry header, including the id marker
13627
and the entry name size (and its null-terminator).
13628
*/
13629
static std::size_t calc_bson_entry_header_size(const string_t& name)
13630
{
13631
const auto it = name.find(static_cast<typename string_t::value_type>(0));
13632
if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
13633
{
13634
JSON_THROW(out_of_range::create(409,
13635
"BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")"));
13636
}
13637
13638
return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
13639
}
13640
13641
/*!
13642
@brief Writes the given @a element_type and @a name to the output adapter
13643
*/
13644
void write_bson_entry_header(const string_t& name,
13645
const std::uint8_t element_type)
13646
{
13647
oa->write_character(to_char_type(element_type)); // boolean
13648
oa->write_characters(
13649
reinterpret_cast<const CharType*>(name.c_str()),
13650
name.size() + 1u);
13651
}
13652
13653
/*!
13654
@brief Writes a BSON element with key @a name and boolean value @a value
13655
*/
13656
void write_bson_boolean(const string_t& name,
13657
const bool value)
13658
{
13659
write_bson_entry_header(name, 0x08);
13660
oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
13661
}
13662
13663
/*!
13664
@brief Writes a BSON element with key @a name and double value @a value
13665
*/
13666
void write_bson_double(const string_t& name,
13667
const double value)
13668
{
13669
write_bson_entry_header(name, 0x01);
13670
write_number<double, true>(value);
13671
}
13672
13673
/*!
13674
@return The size of the BSON-encoded string in @a value
13675
*/
13676
static std::size_t calc_bson_string_size(const string_t& value)
13677
{
13678
return sizeof(std::int32_t) + value.size() + 1ul;
13679
}
13680
13681
/*!
13682
@brief Writes a BSON element with key @a name and string value @a value
13683
*/
13684
void write_bson_string(const string_t& name,
13685
const string_t& value)
13686
{
13687
write_bson_entry_header(name, 0x02);
13688
13689
write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
13690
oa->write_characters(
13691
reinterpret_cast<const CharType*>(value.c_str()),
13692
value.size() + 1);
13693
}
13694
13695
/*!
13696
@brief Writes a BSON element with key @a name and null value
13697
*/
13698
void write_bson_null(const string_t& name)
13699
{
13700
write_bson_entry_header(name, 0x0A);
13701
}
13702
13703
/*!
13704
@return The size of the BSON-encoded integer @a value
13705
*/
13706
static std::size_t calc_bson_integer_size(const std::int64_t value)
13707
{
13708
return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
13709
? sizeof(std::int32_t)
13710
: sizeof(std::int64_t);
13711
}
13712
13713
/*!
13714
@brief Writes a BSON element with key @a name and integer @a value
13715
*/
13716
void write_bson_integer(const string_t& name,
13717
const std::int64_t value)
13718
{
13719
if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
13720
{
13721
write_bson_entry_header(name, 0x10); // int32
13722
write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
13723
}
13724
else
13725
{
13726
write_bson_entry_header(name, 0x12); // int64
13727
write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
13728
}
13729
}
13730
13731
/*!
13732
@return The size of the BSON-encoded unsigned integer in @a j
13733
*/
13734
static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
13735
{
13736
return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
13737
? sizeof(std::int32_t)
13738
: sizeof(std::int64_t);
13739
}
13740
13741
/*!
13742
@brief Writes a BSON element with key @a name and unsigned @a value
13743
*/
13744
void write_bson_unsigned(const string_t& name,
13745
const std::uint64_t value)
13746
{
13747
if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
13748
{
13749
write_bson_entry_header(name, 0x10 /* int32 */);
13750
write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
13751
}
13752
else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
13753
{
13754
write_bson_entry_header(name, 0x12 /* int64 */);
13755
write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
13756
}
13757
else
13758
{
13759
JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64"));
13760
}
13761
}
13762
13763
/*!
13764
@brief Writes a BSON element with key @a name and object @a value
13765
*/
13766
void write_bson_object_entry(const string_t& name,
13767
const typename BasicJsonType::object_t& value)
13768
{
13769
write_bson_entry_header(name, 0x03); // object
13770
write_bson_object(value);
13771
}
13772
13773
/*!
13774
@return The size of the BSON-encoded array @a value
13775
*/
13776
static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
13777
{
13778
std::size_t array_index = 0ul;
13779
13780
const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), std::size_t(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
13781
{
13782
return result + calc_bson_element_size(std::to_string(array_index++), el);
13783
});
13784
13785
return sizeof(std::int32_t) + embedded_document_size + 1ul;
13786
}
13787
13788
/*!
13789
@return The size of the BSON-encoded binary array @a value
13790
*/
13791
static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
13792
{
13793
return sizeof(std::int32_t) + value.size() + 1ul;
13794
}
13795
13796
/*!
13797
@brief Writes a BSON element with key @a name and array @a value
13798
*/
13799
void write_bson_array(const string_t& name,
13800
const typename BasicJsonType::array_t& value)
13801
{
13802
write_bson_entry_header(name, 0x04); // array
13803
write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
13804
13805
std::size_t array_index = 0ul;
13806
13807
for (const auto& el : value)
13808
{
13809
write_bson_element(std::to_string(array_index++), el);
13810
}
13811
13812
oa->write_character(to_char_type(0x00));
13813
}
13814
13815
/*!
13816
@brief Writes a BSON element with key @a name and binary value @a value
13817
*/
13818
void write_bson_binary(const string_t& name,
13819
const binary_t& value)
13820
{
13821
write_bson_entry_header(name, 0x05);
13822
13823
write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
13824
write_number(value.has_subtype() ? value.subtype() : std::uint8_t(0x00));
13825
13826
oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
13827
}
13828
13829
/*!
13830
@brief Calculates the size necessary to serialize the JSON value @a j with its @a name
13831
@return The calculated size for the BSON document entry for @a j with the given @a name.
13832
*/
13833
static std::size_t calc_bson_element_size(const string_t& name,
13834
const BasicJsonType& j)
13835
{
13836
const auto header_size = calc_bson_entry_header_size(name);
13837
switch (j.type())
13838
{
13839
case value_t::object:
13840
return header_size + calc_bson_object_size(*j.m_value.object);
13841
13842
case value_t::array:
13843
return header_size + calc_bson_array_size(*j.m_value.array);
13844
13845
case value_t::binary:
13846
return header_size + calc_bson_binary_size(*j.m_value.binary);
13847
13848
case value_t::boolean:
13849
return header_size + 1ul;
13850
13851
case value_t::number_float:
13852
return header_size + 8ul;
13853
13854
case value_t::number_integer:
13855
return header_size + calc_bson_integer_size(j.m_value.number_integer);
13856
13857
case value_t::number_unsigned:
13858
return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
13859
13860
case value_t::string:
13861
return header_size + calc_bson_string_size(*j.m_value.string);
13862
13863
case value_t::null:
13864
return header_size + 0ul;
13865
13866
// LCOV_EXCL_START
13867
default:
13868
JSON_ASSERT(false);
13869
return 0ul;
13870
// LCOV_EXCL_STOP
13871
}
13872
}
13873
13874
/*!
13875
@brief Serializes the JSON value @a j to BSON and associates it with the
13876
key @a name.
13877
@param name The name to associate with the JSON entity @a j within the
13878
current BSON document
13879
@return The size of the BSON entry
13880
*/
13881
void write_bson_element(const string_t& name,
13882
const BasicJsonType& j)
13883
{
13884
switch (j.type())
13885
{
13886
case value_t::object:
13887
return write_bson_object_entry(name, *j.m_value.object);
13888
13889
case value_t::array:
13890
return write_bson_array(name, *j.m_value.array);
13891
13892
case value_t::binary:
13893
return write_bson_binary(name, *j.m_value.binary);
13894
13895
case value_t::boolean:
13896
return write_bson_boolean(name, j.m_value.boolean);
13897
13898
case value_t::number_float:
13899
return write_bson_double(name, j.m_value.number_float);
13900
13901
case value_t::number_integer:
13902
return write_bson_integer(name, j.m_value.number_integer);
13903
13904
case value_t::number_unsigned:
13905
return write_bson_unsigned(name, j.m_value.number_unsigned);
13906
13907
case value_t::string:
13908
return write_bson_string(name, *j.m_value.string);
13909
13910
case value_t::null:
13911
return write_bson_null(name);
13912
13913
// LCOV_EXCL_START
13914
default:
13915
JSON_ASSERT(false);
13916
return;
13917
// LCOV_EXCL_STOP
13918
}
13919
}
13920
13921
/*!
13922
@brief Calculates the size of the BSON serialization of the given
13923
JSON-object @a j.
13924
@param[in] j JSON value to serialize
13925
@pre j.type() == value_t::object
13926
*/
13927
static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
13928
{
13929
std::size_t document_size = std::accumulate(value.begin(), value.end(), std::size_t(0),
13930
[](size_t result, const typename BasicJsonType::object_t::value_type & el)
13931
{
13932
return result += calc_bson_element_size(el.first, el.second);
13933
});
13934
13935
return sizeof(std::int32_t) + document_size + 1ul;
13936
}
13937
13938
/*!
13939
@param[in] j JSON value to serialize
13940
@pre j.type() == value_t::object
13941
*/
13942
void write_bson_object(const typename BasicJsonType::object_t& value)
13943
{
13944
write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
13945
13946
for (const auto& el : value)
13947
{
13948
write_bson_element(el.first, el.second);
13949
}
13950
13951
oa->write_character(to_char_type(0x00));
13952
}
13953
13954
//////////
13955
// CBOR //
13956
//////////
13957
13958
static constexpr CharType get_cbor_float_prefix(float /*unused*/)
13959
{
13960
return to_char_type(0xFA); // Single-Precision Float
13961
}
13962
13963
static constexpr CharType get_cbor_float_prefix(double /*unused*/)
13964
{
13965
return to_char_type(0xFB); // Double-Precision Float
13966
}
13967
13968
/////////////
13969
// MsgPack //
13970
/////////////
13971
13972
static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
13973
{
13974
return to_char_type(0xCA); // float 32
13975
}
13976
13977
static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
13978
{
13979
return to_char_type(0xCB); // float 64
13980
}
13981
13982
////////////
13983
// UBJSON //
13984
////////////
13985
13986
// UBJSON: write number (floating point)
13987
template<typename NumberType, typename std::enable_if<
13988
std::is_floating_point<NumberType>::value, int>::type = 0>
13989
void write_number_with_ubjson_prefix(const NumberType n,
13990
const bool add_prefix)
13991
{
13992
if (add_prefix)
13993
{
13994
oa->write_character(get_ubjson_float_prefix(n));
13995
}
13996
write_number(n);
13997
}
13998
13999
// UBJSON: write number (unsigned integer)
14000
template<typename NumberType, typename std::enable_if<
14001
std::is_unsigned<NumberType>::value, int>::type = 0>
14002
void write_number_with_ubjson_prefix(const NumberType n,
14003
const bool add_prefix)
14004
{
14005
if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
14006
{
14007
if (add_prefix)
14008
{
14009
oa->write_character(to_char_type('i')); // int8
14010
}
14011
write_number(static_cast<std::uint8_t>(n));
14012
}
14013
else if (n <= (std::numeric_limits<std::uint8_t>::max)())
14014
{
14015
if (add_prefix)
14016
{
14017
oa->write_character(to_char_type('U')); // uint8
14018
}
14019
write_number(static_cast<std::uint8_t>(n));
14020
}
14021
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
14022
{
14023
if (add_prefix)
14024
{
14025
oa->write_character(to_char_type('I')); // int16
14026
}
14027
write_number(static_cast<std::int16_t>(n));
14028
}
14029
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14030
{
14031
if (add_prefix)
14032
{
14033
oa->write_character(to_char_type('l')); // int32
14034
}
14035
write_number(static_cast<std::int32_t>(n));
14036
}
14037
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14038
{
14039
if (add_prefix)
14040
{
14041
oa->write_character(to_char_type('L')); // int64
14042
}
14043
write_number(static_cast<std::int64_t>(n));
14044
}
14045
else
14046
{
14047
if (add_prefix)
14048
{
14049
oa->write_character(to_char_type('H')); // high-precision number
14050
}
14051
14052
const auto number = BasicJsonType(n).dump();
14053
write_number_with_ubjson_prefix(number.size(), true);
14054
for (std::size_t i = 0; i < number.size(); ++i)
14055
{
14056
oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
14057
}
14058
}
14059
}
14060
14061
// UBJSON: write number (signed integer)
14062
template < typename NumberType, typename std::enable_if <
14063
std::is_signed<NumberType>::value&&
14064
!std::is_floating_point<NumberType>::value, int >::type = 0 >
14065
void write_number_with_ubjson_prefix(const NumberType n,
14066
const bool add_prefix)
14067
{
14068
if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
14069
{
14070
if (add_prefix)
14071
{
14072
oa->write_character(to_char_type('i')); // int8
14073
}
14074
write_number(static_cast<std::int8_t>(n));
14075
}
14076
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)()))
14077
{
14078
if (add_prefix)
14079
{
14080
oa->write_character(to_char_type('U')); // uint8
14081
}
14082
write_number(static_cast<std::uint8_t>(n));
14083
}
14084
else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
14085
{
14086
if (add_prefix)
14087
{
14088
oa->write_character(to_char_type('I')); // int16
14089
}
14090
write_number(static_cast<std::int16_t>(n));
14091
}
14092
else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
14093
{
14094
if (add_prefix)
14095
{
14096
oa->write_character(to_char_type('l')); // int32
14097
}
14098
write_number(static_cast<std::int32_t>(n));
14099
}
14100
else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
14101
{
14102
if (add_prefix)
14103
{
14104
oa->write_character(to_char_type('L')); // int64
14105
}
14106
write_number(static_cast<std::int64_t>(n));
14107
}
14108
// LCOV_EXCL_START
14109
else
14110
{
14111
if (add_prefix)
14112
{
14113
oa->write_character(to_char_type('H')); // high-precision number
14114
}
14115
14116
const auto number = BasicJsonType(n).dump();
14117
write_number_with_ubjson_prefix(number.size(), true);
14118
for (std::size_t i = 0; i < number.size(); ++i)
14119
{
14120
oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
14121
}
14122
}
14123
// LCOV_EXCL_STOP
14124
}
14125
14126
/*!
14127
@brief determine the type prefix of container values
14128
*/
14129
CharType ubjson_prefix(const BasicJsonType& j) const noexcept
14130
{
14131
switch (j.type())
14132
{
14133
case value_t::null:
14134
return 'Z';
14135
14136
case value_t::boolean:
14137
return j.m_value.boolean ? 'T' : 'F';
14138
14139
case value_t::number_integer:
14140
{
14141
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)())
14142
{
14143
return 'i';
14144
}
14145
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)())
14146
{
14147
return 'U';
14148
}
14149
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)())
14150
{
14151
return 'I';
14152
}
14153
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)())
14154
{
14155
return 'l';
14156
}
14157
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)())
14158
{
14159
return 'L';
14160
}
14161
// anything else is treated as high-precision number
14162
return 'H'; // LCOV_EXCL_LINE
14163
}
14164
14165
case value_t::number_unsigned:
14166
{
14167
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
14168
{
14169
return 'i';
14170
}
14171
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
14172
{
14173
return 'U';
14174
}
14175
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
14176
{
14177
return 'I';
14178
}
14179
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14180
{
14181
return 'l';
14182
}
14183
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14184
{
14185
return 'L';
14186
}
14187
// anything else is treated as high-precision number
14188
return 'H'; // LCOV_EXCL_LINE
14189
}
14190
14191
case value_t::number_float:
14192
return get_ubjson_float_prefix(j.m_value.number_float);
14193
14194
case value_t::string:
14195
return 'S';
14196
14197
case value_t::array: // fallthrough
14198
case value_t::binary:
14199
return '[';
14200
14201
case value_t::object:
14202
return '{';
14203
14204
default: // discarded values
14205
return 'N';
14206
}
14207
}
14208
14209
static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
14210
{
14211
return 'd'; // float 32
14212
}
14213
14214
static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
14215
{
14216
return 'D'; // float 64
14217
}
14218
14219
///////////////////////
14220
// Utility functions //
14221
///////////////////////
14222
14223
/*
14224
@brief write a number to output input
14225
@param[in] n number of type @a NumberType
14226
@tparam NumberType the type of the number
14227
@tparam OutputIsLittleEndian Set to true if output data is
14228
required to be little endian
14229
14230
@note This function needs to respect the system's endianess, because bytes
14231
in CBOR, MessagePack, and UBJSON are stored in network order (big
14232
endian) and therefore need reordering on little endian systems.
14233
*/
14234
template<typename NumberType, bool OutputIsLittleEndian = false>
14235
void write_number(const NumberType n)
14236
{
14237
// step 1: write number to array of length NumberType
14238
std::array<CharType, sizeof(NumberType)> vec;
14239
std::memcpy(vec.data(), &n, sizeof(NumberType));
14240
14241
// step 2: write array to output (with possible reordering)
14242
if (is_little_endian != OutputIsLittleEndian)
14243
{
14244
// reverse byte order prior to conversion if necessary
14245
std::reverse(vec.begin(), vec.end());
14246
}
14247
14248
oa->write_characters(vec.data(), sizeof(NumberType));
14249
}
14250
14251
void write_compact_float(const number_float_t n, detail::input_format_t format)
14252
{
14253
if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
14254
static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
14255
static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
14256
{
14257
oa->write_character(format == detail::input_format_t::cbor
14258
? get_cbor_float_prefix(static_cast<float>(n))
14259
: get_msgpack_float_prefix(static_cast<float>(n)));
14260
write_number(static_cast<float>(n));
14261
}
14262
else
14263
{
14264
oa->write_character(format == detail::input_format_t::cbor
14265
? get_cbor_float_prefix(n)
14266
: get_msgpack_float_prefix(n));
14267
write_number(n);
14268
}
14269
}
14270
14271
public:
14272
// The following to_char_type functions are implement the conversion
14273
// between uint8_t and CharType. In case CharType is not unsigned,
14274
// such a conversion is required to allow values greater than 128.
14275
// See <https://github.com/nlohmann/json/issues/1286> for a discussion.
14276
template < typename C = CharType,
14277
enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
14278
static constexpr CharType to_char_type(std::uint8_t x) noexcept
14279
{
14280
return *reinterpret_cast<char*>(&x);
14281
}
14282
14283
template < typename C = CharType,
14284
enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
14285
static CharType to_char_type(std::uint8_t x) noexcept
14286
{
14287
static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
14288
static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
14289
CharType result;
14290
std::memcpy(&result, &x, sizeof(x));
14291
return result;
14292
}
14293
14294
template<typename C = CharType,
14295
enable_if_t<std::is_unsigned<C>::value>* = nullptr>
14296
static constexpr CharType to_char_type(std::uint8_t x) noexcept
14297
{
14298
return x;
14299
}
14300
14301
template < typename InputCharType, typename C = CharType,
14302
enable_if_t <
14303
std::is_signed<C>::value &&
14304
std::is_signed<char>::value &&
14305
std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
14306
> * = nullptr >
14307
static constexpr CharType to_char_type(InputCharType x) noexcept
14308
{
14309
return x;
14310
}
14311
14312
private:
14313
/// whether we can assume little endianess
14314
const bool is_little_endian = little_endianess();
14315
14316
/// the output
14317
output_adapter_t<CharType> oa = nullptr;
14318
};
14319
} // namespace detail
14320
} // namespace nlohmann
14321
14322
// #include <nlohmann/detail/output/output_adapters.hpp>
14323
14324
// #include <nlohmann/detail/output/serializer.hpp>
14325
14326
14327
#include <algorithm> // reverse, remove, fill, find, none_of
14328
#include <array> // array
14329
#include <clocale> // localeconv, lconv
14330
#include <cmath> // labs, isfinite, isnan, signbit
14331
#include <cstddef> // size_t, ptrdiff_t
14332
#include <cstdint> // uint8_t
14333
#include <cstdio> // snprintf
14334
#include <limits> // numeric_limits
14335
#include <string> // string, char_traits
14336
#include <type_traits> // is_same
14337
#include <utility> // move
14338
14339
// #include <nlohmann/detail/conversions/to_chars.hpp>
14340
14341
14342
#include <array> // array
14343
#include <cmath> // signbit, isfinite
14344
#include <cstdint> // intN_t, uintN_t
14345
#include <cstring> // memcpy, memmove
14346
#include <limits> // numeric_limits
14347
#include <type_traits> // conditional
14348
14349
// #include <nlohmann/detail/macro_scope.hpp>
14350
14351
14352
namespace nlohmann
14353
{
14354
namespace detail
14355
{
14356
14357
/*!
14358
@brief implements the Grisu2 algorithm for binary to decimal floating-point
14359
conversion.
14360
14361
This implementation is a slightly modified version of the reference
14362
implementation which may be obtained from
14363
http://florian.loitsch.com/publications (bench.tar.gz).
14364
14365
The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
14366
14367
For a detailed description of the algorithm see:
14368
14369
[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
14370
Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
14371
Language Design and Implementation, PLDI 2010
14372
[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
14373
Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
14374
Design and Implementation, PLDI 1996
14375
*/
14376
namespace dtoa_impl
14377
{
14378
14379
template<typename Target, typename Source>
14380
Target reinterpret_bits(const Source source)
14381
{
14382
static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
14383
14384
Target target;
14385
std::memcpy(&target, &source, sizeof(Source));
14386
return target;
14387
}
14388
14389
struct diyfp // f * 2^e
14390
{
14391
static constexpr int kPrecision = 64; // = q
14392
14393
std::uint64_t f = 0;
14394
int e = 0;
14395
14396
constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
14397
14398
/*!
14399
@brief returns x - y
14400
@pre x.e == y.e and x.f >= y.f
14401
*/
14402
static diyfp sub(const diyfp& x, const diyfp& y) noexcept
14403
{
14404
JSON_ASSERT(x.e == y.e);
14405
JSON_ASSERT(x.f >= y.f);
14406
14407
return {x.f - y.f, x.e};
14408
}
14409
14410
/*!
14411
@brief returns x * y
14412
@note The result is rounded. (Only the upper q bits are returned.)
14413
*/
14414
static diyfp mul(const diyfp& x, const diyfp& y) noexcept
14415
{
14416
static_assert(kPrecision == 64, "internal error");
14417
14418
// Computes:
14419
// f = round((x.f * y.f) / 2^q)
14420
// e = x.e + y.e + q
14421
14422
// Emulate the 64-bit * 64-bit multiplication:
14423
//
14424
// p = u * v
14425
// = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
14426
// = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
14427
// = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
14428
// = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
14429
// = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
14430
// = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
14431
// = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
14432
//
14433
// (Since Q might be larger than 2^32 - 1)
14434
//
14435
// = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
14436
//
14437
// (Q_hi + H does not overflow a 64-bit int)
14438
//
14439
// = p_lo + 2^64 p_hi
14440
14441
const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
14442
const std::uint64_t u_hi = x.f >> 32u;
14443
const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
14444
const std::uint64_t v_hi = y.f >> 32u;
14445
14446
const std::uint64_t p0 = u_lo * v_lo;
14447
const std::uint64_t p1 = u_lo * v_hi;
14448
const std::uint64_t p2 = u_hi * v_lo;
14449
const std::uint64_t p3 = u_hi * v_hi;
14450
14451
const std::uint64_t p0_hi = p0 >> 32u;
14452
const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
14453
const std::uint64_t p1_hi = p1 >> 32u;
14454
const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
14455
const std::uint64_t p2_hi = p2 >> 32u;
14456
14457
std::uint64_t Q = p0_hi + p1_lo + p2_lo;
14458
14459
// The full product might now be computed as
14460
//
14461
// p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
14462
// p_lo = p0_lo + (Q << 32)
14463
//
14464
// But in this particular case here, the full p_lo is not required.
14465
// Effectively we only need to add the highest bit in p_lo to p_hi (and
14466
// Q_hi + 1 does not overflow).
14467
14468
Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
14469
14470
const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
14471
14472
return {h, x.e + y.e + 64};
14473
}
14474
14475
/*!
14476
@brief normalize x such that the significand is >= 2^(q-1)
14477
@pre x.f != 0
14478
*/
14479
static diyfp normalize(diyfp x) noexcept
14480
{
14481
JSON_ASSERT(x.f != 0);
14482
14483
while ((x.f >> 63u) == 0)
14484
{
14485
x.f <<= 1u;
14486
x.e--;
14487
}
14488
14489
return x;
14490
}
14491
14492
/*!
14493
@brief normalize x such that the result has the exponent E
14494
@pre e >= x.e and the upper e - x.e bits of x.f must be zero.
14495
*/
14496
static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
14497
{
14498
const int delta = x.e - target_exponent;
14499
14500
JSON_ASSERT(delta >= 0);
14501
JSON_ASSERT(((x.f << delta) >> delta) == x.f);
14502
14503
return {x.f << delta, target_exponent};
14504
}
14505
};
14506
14507
struct boundaries
14508
{
14509
diyfp w;
14510
diyfp minus;
14511
diyfp plus;
14512
};
14513
14514
/*!
14515
Compute the (normalized) diyfp representing the input number 'value' and its
14516
boundaries.
14517
14518
@pre value must be finite and positive
14519
*/
14520
template<typename FloatType>
14521
boundaries compute_boundaries(FloatType value)
14522
{
14523
JSON_ASSERT(std::isfinite(value));
14524
JSON_ASSERT(value > 0);
14525
14526
// Convert the IEEE representation into a diyfp.
14527
//
14528
// If v is denormal:
14529
// value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
14530
// If v is normalized:
14531
// value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
14532
14533
static_assert(std::numeric_limits<FloatType>::is_iec559,
14534
"internal error: dtoa_short requires an IEEE-754 floating-point implementation");
14535
14536
constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
14537
constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
14538
constexpr int kMinExp = 1 - kBias;
14539
constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
14540
14541
using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
14542
14543
const std::uint64_t bits = reinterpret_bits<bits_type>(value);
14544
const std::uint64_t E = bits >> (kPrecision - 1);
14545
const std::uint64_t F = bits & (kHiddenBit - 1);
14546
14547
const bool is_denormal = E == 0;
14548
const diyfp v = is_denormal
14549
? diyfp(F, kMinExp)
14550
: diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
14551
14552
// Compute the boundaries m- and m+ of the floating-point value
14553
// v = f * 2^e.
14554
//
14555
// Determine v- and v+, the floating-point predecessor and successor if v,
14556
// respectively.
14557
//
14558
// v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
14559
// = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
14560
//
14561
// v+ = v + 2^e
14562
//
14563
// Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
14564
// between m- and m+ round to v, regardless of how the input rounding
14565
// algorithm breaks ties.
14566
//
14567
// ---+-------------+-------------+-------------+-------------+--- (A)
14568
// v- m- v m+ v+
14569
//
14570
// -----------------+------+------+-------------+-------------+--- (B)
14571
// v- m- v m+ v+
14572
14573
const bool lower_boundary_is_closer = F == 0 && E > 1;
14574
const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
14575
const diyfp m_minus = lower_boundary_is_closer
14576
? diyfp(4 * v.f - 1, v.e - 2) // (B)
14577
: diyfp(2 * v.f - 1, v.e - 1); // (A)
14578
14579
// Determine the normalized w+ = m+.
14580
const diyfp w_plus = diyfp::normalize(m_plus);
14581
14582
// Determine w- = m- such that e_(w-) = e_(w+).
14583
const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
14584
14585
return {diyfp::normalize(v), w_minus, w_plus};
14586
}
14587
14588
// Given normalized diyfp w, Grisu needs to find a (normalized) cached
14589
// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
14590
// within a certain range [alpha, gamma] (Definition 3.2 from [1])
14591
//
14592
// alpha <= e = e_c + e_w + q <= gamma
14593
//
14594
// or
14595
//
14596
// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
14597
// <= f_c * f_w * 2^gamma
14598
//
14599
// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
14600
//
14601
// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
14602
//
14603
// or
14604
//
14605
// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
14606
//
14607
// The choice of (alpha,gamma) determines the size of the table and the form of
14608
// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
14609
// in practice:
14610
//
14611
// The idea is to cut the number c * w = f * 2^e into two parts, which can be
14612
// processed independently: An integral part p1, and a fractional part p2:
14613
//
14614
// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
14615
// = (f div 2^-e) + (f mod 2^-e) * 2^e
14616
// = p1 + p2 * 2^e
14617
//
14618
// The conversion of p1 into decimal form requires a series of divisions and
14619
// modulos by (a power of) 10. These operations are faster for 32-bit than for
14620
// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
14621
// achieved by choosing
14622
//
14623
// -e >= 32 or e <= -32 := gamma
14624
//
14625
// In order to convert the fractional part
14626
//
14627
// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
14628
//
14629
// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
14630
// d[-i] are extracted in order:
14631
//
14632
// (10 * p2) div 2^-e = d[-1]
14633
// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
14634
//
14635
// The multiplication by 10 must not overflow. It is sufficient to choose
14636
//
14637
// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
14638
//
14639
// Since p2 = f mod 2^-e < 2^-e,
14640
//
14641
// -e <= 60 or e >= -60 := alpha
14642
14643
constexpr int kAlpha = -60;
14644
constexpr int kGamma = -32;
14645
14646
struct cached_power // c = f * 2^e ~= 10^k
14647
{
14648
std::uint64_t f;
14649
int e;
14650
int k;
14651
};
14652
14653
/*!
14654
For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
14655
power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
14656
satisfies (Definition 3.2 from [1])
14657
14658
alpha <= e_c + e + q <= gamma.
14659
*/
14660
inline cached_power get_cached_power_for_binary_exponent(int e)
14661
{
14662
// Now
14663
//
14664
// alpha <= e_c + e + q <= gamma (1)
14665
// ==> f_c * 2^alpha <= c * 2^e * 2^q
14666
//
14667
// and since the c's are normalized, 2^(q-1) <= f_c,
14668
//
14669
// ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
14670
// ==> 2^(alpha - e - 1) <= c
14671
//
14672
// If c were an exact power of ten, i.e. c = 10^k, one may determine k as
14673
//
14674
// k = ceil( log_10( 2^(alpha - e - 1) ) )
14675
// = ceil( (alpha - e - 1) * log_10(2) )
14676
//
14677
// From the paper:
14678
// "In theory the result of the procedure could be wrong since c is rounded,
14679
// and the computation itself is approximated [...]. In practice, however,
14680
// this simple function is sufficient."
14681
//
14682
// For IEEE double precision floating-point numbers converted into
14683
// normalized diyfp's w = f * 2^e, with q = 64,
14684
//
14685
// e >= -1022 (min IEEE exponent)
14686
// -52 (p - 1)
14687
// -52 (p - 1, possibly normalize denormal IEEE numbers)
14688
// -11 (normalize the diyfp)
14689
// = -1137
14690
//
14691
// and
14692
//
14693
// e <= +1023 (max IEEE exponent)
14694
// -52 (p - 1)
14695
// -11 (normalize the diyfp)
14696
// = 960
14697
//
14698
// This binary exponent range [-1137,960] results in a decimal exponent
14699
// range [-307,324]. One does not need to store a cached power for each
14700
// k in this range. For each such k it suffices to find a cached power
14701
// such that the exponent of the product lies in [alpha,gamma].
14702
// This implies that the difference of the decimal exponents of adjacent
14703
// table entries must be less than or equal to
14704
//
14705
// floor( (gamma - alpha) * log_10(2) ) = 8.
14706
//
14707
// (A smaller distance gamma-alpha would require a larger table.)
14708
14709
// NB:
14710
// Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
14711
14712
constexpr int kCachedPowersMinDecExp = -300;
14713
constexpr int kCachedPowersDecStep = 8;
14714
14715
static constexpr std::array<cached_power, 79> kCachedPowers =
14716
{
14717
{
14718
{ 0xAB70FE17C79AC6CA, -1060, -300 },
14719
{ 0xFF77B1FCBEBCDC4F, -1034, -292 },
14720
{ 0xBE5691EF416BD60C, -1007, -284 },
14721
{ 0x8DD01FAD907FFC3C, -980, -276 },
14722
{ 0xD3515C2831559A83, -954, -268 },
14723
{ 0x9D71AC8FADA6C9B5, -927, -260 },
14724
{ 0xEA9C227723EE8BCB, -901, -252 },
14725
{ 0xAECC49914078536D, -874, -244 },
14726
{ 0x823C12795DB6CE57, -847, -236 },
14727
{ 0xC21094364DFB5637, -821, -228 },
14728
{ 0x9096EA6F3848984F, -794, -220 },
14729
{ 0xD77485CB25823AC7, -768, -212 },
14730
{ 0xA086CFCD97BF97F4, -741, -204 },
14731
{ 0xEF340A98172AACE5, -715, -196 },
14732
{ 0xB23867FB2A35B28E, -688, -188 },
14733
{ 0x84C8D4DFD2C63F3B, -661, -180 },
14734
{ 0xC5DD44271AD3CDBA, -635, -172 },
14735
{ 0x936B9FCEBB25C996, -608, -164 },
14736
{ 0xDBAC6C247D62A584, -582, -156 },
14737
{ 0xA3AB66580D5FDAF6, -555, -148 },
14738
{ 0xF3E2F893DEC3F126, -529, -140 },
14739
{ 0xB5B5ADA8AAFF80B8, -502, -132 },
14740
{ 0x87625F056C7C4A8B, -475, -124 },
14741
{ 0xC9BCFF6034C13053, -449, -116 },
14742
{ 0x964E858C91BA2655, -422, -108 },
14743
{ 0xDFF9772470297EBD, -396, -100 },
14744
{ 0xA6DFBD9FB8E5B88F, -369, -92 },
14745
{ 0xF8A95FCF88747D94, -343, -84 },
14746
{ 0xB94470938FA89BCF, -316, -76 },
14747
{ 0x8A08F0F8BF0F156B, -289, -68 },
14748
{ 0xCDB02555653131B6, -263, -60 },
14749
{ 0x993FE2C6D07B7FAC, -236, -52 },
14750
{ 0xE45C10C42A2B3B06, -210, -44 },
14751
{ 0xAA242499697392D3, -183, -36 },
14752
{ 0xFD87B5F28300CA0E, -157, -28 },
14753
{ 0xBCE5086492111AEB, -130, -20 },
14754
{ 0x8CBCCC096F5088CC, -103, -12 },
14755
{ 0xD1B71758E219652C, -77, -4 },
14756
{ 0x9C40000000000000, -50, 4 },
14757
{ 0xE8D4A51000000000, -24, 12 },
14758
{ 0xAD78EBC5AC620000, 3, 20 },
14759
{ 0x813F3978F8940984, 30, 28 },
14760
{ 0xC097CE7BC90715B3, 56, 36 },
14761
{ 0x8F7E32CE7BEA5C70, 83, 44 },
14762
{ 0xD5D238A4ABE98068, 109, 52 },
14763
{ 0x9F4F2726179A2245, 136, 60 },
14764
{ 0xED63A231D4C4FB27, 162, 68 },
14765
{ 0xB0DE65388CC8ADA8, 189, 76 },
14766
{ 0x83C7088E1AAB65DB, 216, 84 },
14767
{ 0xC45D1DF942711D9A, 242, 92 },
14768
{ 0x924D692CA61BE758, 269, 100 },
14769
{ 0xDA01EE641A708DEA, 295, 108 },
14770
{ 0xA26DA3999AEF774A, 322, 116 },
14771
{ 0xF209787BB47D6B85, 348, 124 },
14772
{ 0xB454E4A179DD1877, 375, 132 },
14773
{ 0x865B86925B9BC5C2, 402, 140 },
14774
{ 0xC83553C5C8965D3D, 428, 148 },
14775
{ 0x952AB45CFA97A0B3, 455, 156 },
14776
{ 0xDE469FBD99A05FE3, 481, 164 },
14777
{ 0xA59BC234DB398C25, 508, 172 },
14778
{ 0xF6C69A72A3989F5C, 534, 180 },
14779
{ 0xB7DCBF5354E9BECE, 561, 188 },
14780
{ 0x88FCF317F22241E2, 588, 196 },
14781
{ 0xCC20CE9BD35C78A5, 614, 204 },
14782
{ 0x98165AF37B2153DF, 641, 212 },
14783
{ 0xE2A0B5DC971F303A, 667, 220 },
14784
{ 0xA8D9D1535CE3B396, 694, 228 },
14785
{ 0xFB9B7CD9A4A7443C, 720, 236 },
14786
{ 0xBB764C4CA7A44410, 747, 244 },
14787
{ 0x8BAB8EEFB6409C1A, 774, 252 },
14788
{ 0xD01FEF10A657842C, 800, 260 },
14789
{ 0x9B10A4E5E9913129, 827, 268 },
14790
{ 0xE7109BFBA19C0C9D, 853, 276 },
14791
{ 0xAC2820D9623BF429, 880, 284 },
14792
{ 0x80444B5E7AA7CF85, 907, 292 },
14793
{ 0xBF21E44003ACDD2D, 933, 300 },
14794
{ 0x8E679C2F5E44FF8F, 960, 308 },
14795
{ 0xD433179D9C8CB841, 986, 316 },
14796
{ 0x9E19DB92B4E31BA9, 1013, 324 },
14797
}
14798
};
14799
14800
// This computation gives exactly the same results for k as
14801
// k = ceil((kAlpha - e - 1) * 0.30102999566398114)
14802
// for |e| <= 1500, but doesn't require floating-point operations.
14803
// NB: log_10(2) ~= 78913 / 2^18
14804
JSON_ASSERT(e >= -1500);
14805
JSON_ASSERT(e <= 1500);
14806
const int f = kAlpha - e - 1;
14807
const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
14808
14809
const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
14810
JSON_ASSERT(index >= 0);
14811
JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
14812
14813
const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
14814
JSON_ASSERT(kAlpha <= cached.e + e + 64);
14815
JSON_ASSERT(kGamma >= cached.e + e + 64);
14816
14817
return cached;
14818
}
14819
14820
/*!
14821
For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
14822
For n == 0, returns 1 and sets pow10 := 1.
14823
*/
14824
inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
14825
{
14826
// LCOV_EXCL_START
14827
if (n >= 1000000000)
14828
{
14829
pow10 = 1000000000;
14830
return 10;
14831
}
14832
// LCOV_EXCL_STOP
14833
else if (n >= 100000000)
14834
{
14835
pow10 = 100000000;
14836
return 9;
14837
}
14838
else if (n >= 10000000)
14839
{
14840
pow10 = 10000000;
14841
return 8;
14842
}
14843
else if (n >= 1000000)
14844
{
14845
pow10 = 1000000;
14846
return 7;
14847
}
14848
else if (n >= 100000)
14849
{
14850
pow10 = 100000;
14851
return 6;
14852
}
14853
else if (n >= 10000)
14854
{
14855
pow10 = 10000;
14856
return 5;
14857
}
14858
else if (n >= 1000)
14859
{
14860
pow10 = 1000;
14861
return 4;
14862
}
14863
else if (n >= 100)
14864
{
14865
pow10 = 100;
14866
return 3;
14867
}
14868
else if (n >= 10)
14869
{
14870
pow10 = 10;
14871
return 2;
14872
}
14873
else
14874
{
14875
pow10 = 1;
14876
return 1;
14877
}
14878
}
14879
14880
inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
14881
std::uint64_t rest, std::uint64_t ten_k)
14882
{
14883
JSON_ASSERT(len >= 1);
14884
JSON_ASSERT(dist <= delta);
14885
JSON_ASSERT(rest <= delta);
14886
JSON_ASSERT(ten_k > 0);
14887
14888
// <--------------------------- delta ---->
14889
// <---- dist --------->
14890
// --------------[------------------+-------------------]--------------
14891
// M- w M+
14892
//
14893
// ten_k
14894
// <------>
14895
// <---- rest ---->
14896
// --------------[------------------+----+--------------]--------------
14897
// w V
14898
// = buf * 10^k
14899
//
14900
// ten_k represents a unit-in-the-last-place in the decimal representation
14901
// stored in buf.
14902
// Decrement buf by ten_k while this takes buf closer to w.
14903
14904
// The tests are written in this order to avoid overflow in unsigned
14905
// integer arithmetic.
14906
14907
while (rest < dist
14908
&& delta - rest >= ten_k
14909
&& (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
14910
{
14911
JSON_ASSERT(buf[len - 1] != '0');
14912
buf[len - 1]--;
14913
rest += ten_k;
14914
}
14915
}
14916
14917
/*!
14918
Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
14919
M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
14920
*/
14921
inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
14922
diyfp M_minus, diyfp w, diyfp M_plus)
14923
{
14924
static_assert(kAlpha >= -60, "internal error");
14925
static_assert(kGamma <= -32, "internal error");
14926
14927
// Generates the digits (and the exponent) of a decimal floating-point
14928
// number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
14929
// w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
14930
//
14931
// <--------------------------- delta ---->
14932
// <---- dist --------->
14933
// --------------[------------------+-------------------]--------------
14934
// M- w M+
14935
//
14936
// Grisu2 generates the digits of M+ from left to right and stops as soon as
14937
// V is in [M-,M+].
14938
14939
JSON_ASSERT(M_plus.e >= kAlpha);
14940
JSON_ASSERT(M_plus.e <= kGamma);
14941
14942
std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
14943
std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
14944
14945
// Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
14946
//
14947
// M+ = f * 2^e
14948
// = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
14949
// = ((p1 ) * 2^-e + (p2 )) * 2^e
14950
// = p1 + p2 * 2^e
14951
14952
const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
14953
14954
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.)
14955
std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
14956
14957
// 1)
14958
//
14959
// Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
14960
14961
JSON_ASSERT(p1 > 0);
14962
14963
std::uint32_t pow10;
14964
const int k = find_largest_pow10(p1, pow10);
14965
14966
// 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
14967
//
14968
// p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
14969
// = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
14970
//
14971
// M+ = p1 + p2 * 2^e
14972
// = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
14973
// = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
14974
// = d[k-1] * 10^(k-1) + ( rest) * 2^e
14975
//
14976
// Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
14977
//
14978
// p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
14979
//
14980
// but stop as soon as
14981
//
14982
// rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
14983
14984
int n = k;
14985
while (n > 0)
14986
{
14987
// Invariants:
14988
// M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
14989
// pow10 = 10^(n-1) <= p1 < 10^n
14990
//
14991
const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
14992
const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
14993
//
14994
// M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
14995
// = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
14996
//
14997
JSON_ASSERT(d <= 9);
14998
buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
14999
//
15000
// M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
15001
//
15002
p1 = r;
15003
n--;
15004
//
15005
// M+ = buffer * 10^n + (p1 + p2 * 2^e)
15006
// pow10 = 10^n
15007
//
15008
15009
// Now check if enough digits have been generated.
15010
// Compute
15011
//
15012
// p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
15013
//
15014
// Note:
15015
// Since rest and delta share the same exponent e, it suffices to
15016
// compare the significands.
15017
const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
15018
if (rest <= delta)
15019
{
15020
// V = buffer * 10^n, with M- <= V <= M+.
15021
15022
decimal_exponent += n;
15023
15024
// We may now just stop. But instead look if the buffer could be
15025
// decremented to bring V closer to w.
15026
//
15027
// pow10 = 10^n is now 1 ulp in the decimal representation V.
15028
// The rounding procedure works with diyfp's with an implicit
15029
// exponent of e.
15030
//
15031
// 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
15032
//
15033
const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
15034
grisu2_round(buffer, length, dist, delta, rest, ten_n);
15035
15036
return;
15037
}
15038
15039
pow10 /= 10;
15040
//
15041
// pow10 = 10^(n-1) <= p1 < 10^n
15042
// Invariants restored.
15043
}
15044
15045
// 2)
15046
//
15047
// The digits of the integral part have been generated:
15048
//
15049
// M+ = d[k-1]...d[1]d[0] + p2 * 2^e
15050
// = buffer + p2 * 2^e
15051
//
15052
// Now generate the digits of the fractional part p2 * 2^e.
15053
//
15054
// Note:
15055
// No decimal point is generated: the exponent is adjusted instead.
15056
//
15057
// p2 actually represents the fraction
15058
//
15059
// p2 * 2^e
15060
// = p2 / 2^-e
15061
// = d[-1] / 10^1 + d[-2] / 10^2 + ...
15062
//
15063
// Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
15064
//
15065
// p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
15066
// + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
15067
//
15068
// using
15069
//
15070
// 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
15071
// = ( d) * 2^-e + ( r)
15072
//
15073
// or
15074
// 10^m * p2 * 2^e = d + r * 2^e
15075
//
15076
// i.e.
15077
//
15078
// M+ = buffer + p2 * 2^e
15079
// = buffer + 10^-m * (d + r * 2^e)
15080
// = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
15081
//
15082
// and stop as soon as 10^-m * r * 2^e <= delta * 2^e
15083
15084
JSON_ASSERT(p2 > delta);
15085
15086
int m = 0;
15087
for (;;)
15088
{
15089
// Invariant:
15090
// M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
15091
// = buffer * 10^-m + 10^-m * (p2 ) * 2^e
15092
// = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
15093
// = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
15094
//
15095
JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
15096
p2 *= 10;
15097
const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
15098
const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
15099
//
15100
// M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
15101
// = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
15102
// = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
15103
//
15104
JSON_ASSERT(d <= 9);
15105
buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
15106
//
15107
// M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
15108
//
15109
p2 = r;
15110
m++;
15111
//
15112
// M+ = buffer * 10^-m + 10^-m * p2 * 2^e
15113
// Invariant restored.
15114
15115
// Check if enough digits have been generated.
15116
//
15117
// 10^-m * p2 * 2^e <= delta * 2^e
15118
// p2 * 2^e <= 10^m * delta * 2^e
15119
// p2 <= 10^m * delta
15120
delta *= 10;
15121
dist *= 10;
15122
if (p2 <= delta)
15123
{
15124
break;
15125
}
15126
}
15127
15128
// V = buffer * 10^-m, with M- <= V <= M+.
15129
15130
decimal_exponent -= m;
15131
15132
// 1 ulp in the decimal representation is now 10^-m.
15133
// Since delta and dist are now scaled by 10^m, we need to do the
15134
// same with ulp in order to keep the units in sync.
15135
//
15136
// 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
15137
//
15138
const std::uint64_t ten_m = one.f;
15139
grisu2_round(buffer, length, dist, delta, p2, ten_m);
15140
15141
// By construction this algorithm generates the shortest possible decimal
15142
// number (Loitsch, Theorem 6.2) which rounds back to w.
15143
// For an input number of precision p, at least
15144
//
15145
// N = 1 + ceil(p * log_10(2))
15146
//
15147
// decimal digits are sufficient to identify all binary floating-point
15148
// numbers (Matula, "In-and-Out conversions").
15149
// This implies that the algorithm does not produce more than N decimal
15150
// digits.
15151
//
15152
// N = 17 for p = 53 (IEEE double precision)
15153
// N = 9 for p = 24 (IEEE single precision)
15154
}
15155
15156
/*!
15157
v = buf * 10^decimal_exponent
15158
len is the length of the buffer (number of decimal digits)
15159
The buffer must be large enough, i.e. >= max_digits10.
15160
*/
15161
JSON_HEDLEY_NON_NULL(1)
15162
inline void grisu2(char* buf, int& len, int& decimal_exponent,
15163
diyfp m_minus, diyfp v, diyfp m_plus)
15164
{
15165
JSON_ASSERT(m_plus.e == m_minus.e);
15166
JSON_ASSERT(m_plus.e == v.e);
15167
15168
// --------(-----------------------+-----------------------)-------- (A)
15169
// m- v m+
15170
//
15171
// --------------------(-----------+-----------------------)-------- (B)
15172
// m- v m+
15173
//
15174
// First scale v (and m- and m+) such that the exponent is in the range
15175
// [alpha, gamma].
15176
15177
const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
15178
15179
const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
15180
15181
// The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
15182
const diyfp w = diyfp::mul(v, c_minus_k);
15183
const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
15184
const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
15185
15186
// ----(---+---)---------------(---+---)---------------(---+---)----
15187
// w- w w+
15188
// = c*m- = c*v = c*m+
15189
//
15190
// diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
15191
// w+ are now off by a small amount.
15192
// In fact:
15193
//
15194
// w - v * 10^k < 1 ulp
15195
//
15196
// To account for this inaccuracy, add resp. subtract 1 ulp.
15197
//
15198
// --------+---[---------------(---+---)---------------]---+--------
15199
// w- M- w M+ w+
15200
//
15201
// Now any number in [M-, M+] (bounds included) will round to w when input,
15202
// regardless of how the input rounding algorithm breaks ties.
15203
//
15204
// And digit_gen generates the shortest possible such number in [M-, M+].
15205
// Note that this does not mean that Grisu2 always generates the shortest
15206
// possible number in the interval (m-, m+).
15207
const diyfp M_minus(w_minus.f + 1, w_minus.e);
15208
const diyfp M_plus (w_plus.f - 1, w_plus.e );
15209
15210
decimal_exponent = -cached.k; // = -(-k) = k
15211
15212
grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
15213
}
15214
15215
/*!
15216
v = buf * 10^decimal_exponent
15217
len is the length of the buffer (number of decimal digits)
15218
The buffer must be large enough, i.e. >= max_digits10.
15219
*/
15220
template<typename FloatType>
15221
JSON_HEDLEY_NON_NULL(1)
15222
void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
15223
{
15224
static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
15225
"internal error: not enough precision");
15226
15227
JSON_ASSERT(std::isfinite(value));
15228
JSON_ASSERT(value > 0);
15229
15230
// If the neighbors (and boundaries) of 'value' are always computed for double-precision
15231
// numbers, all float's can be recovered using strtod (and strtof). However, the resulting
15232
// decimal representations are not exactly "short".
15233
//
15234
// The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
15235
// says "value is converted to a string as if by std::sprintf in the default ("C") locale"
15236
// and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
15237
// does.
15238
// On the other hand, the documentation for 'std::to_chars' requires that "parsing the
15239
// representation using the corresponding std::from_chars function recovers value exactly". That
15240
// indicates that single precision floating-point numbers should be recovered using
15241
// 'std::strtof'.
15242
//
15243
// NB: If the neighbors are computed for single-precision numbers, there is a single float
15244
// (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
15245
// value is off by 1 ulp.
15246
#if 0
15247
const boundaries w = compute_boundaries(static_cast<double>(value));
15248
#else
15249
const boundaries w = compute_boundaries(value);
15250
#endif
15251
15252
grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
15253
}
15254
15255
/*!
15256
@brief appends a decimal representation of e to buf
15257
@return a pointer to the element following the exponent.
15258
@pre -1000 < e < 1000
15259
*/
15260
JSON_HEDLEY_NON_NULL(1)
15261
JSON_HEDLEY_RETURNS_NON_NULL
15262
inline char* append_exponent(char* buf, int e)
15263
{
15264
JSON_ASSERT(e > -1000);
15265
JSON_ASSERT(e < 1000);
15266
15267
if (e < 0)
15268
{
15269
e = -e;
15270
*buf++ = '-';
15271
}
15272
else
15273
{
15274
*buf++ = '+';
15275
}
15276
15277
auto k = static_cast<std::uint32_t>(e);
15278
if (k < 10)
15279
{
15280
// Always print at least two digits in the exponent.
15281
// This is for compatibility with printf("%g").
15282
*buf++ = '0';
15283
*buf++ = static_cast<char>('0' + k);
15284
}
15285
else if (k < 100)
15286
{
15287
*buf++ = static_cast<char>('0' + k / 10);
15288
k %= 10;
15289
*buf++ = static_cast<char>('0' + k);
15290
}
15291
else
15292
{
15293
*buf++ = static_cast<char>('0' + k / 100);
15294
k %= 100;
15295
*buf++ = static_cast<char>('0' + k / 10);
15296
k %= 10;
15297
*buf++ = static_cast<char>('0' + k);
15298
}
15299
15300
return buf;
15301
}
15302
15303
/*!
15304
@brief prettify v = buf * 10^decimal_exponent
15305
15306
If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
15307
notation. Otherwise it will be printed in exponential notation.
15308
15309
@pre min_exp < 0
15310
@pre max_exp > 0
15311
*/
15312
JSON_HEDLEY_NON_NULL(1)
15313
JSON_HEDLEY_RETURNS_NON_NULL
15314
inline char* format_buffer(char* buf, int len, int decimal_exponent,
15315
int min_exp, int max_exp)
15316
{
15317
JSON_ASSERT(min_exp < 0);
15318
JSON_ASSERT(max_exp > 0);
15319
15320
const int k = len;
15321
const int n = len + decimal_exponent;
15322
15323
// v = buf * 10^(n-k)
15324
// k is the length of the buffer (number of decimal digits)
15325
// n is the position of the decimal point relative to the start of the buffer.
15326
15327
if (k <= n && n <= max_exp)
15328
{
15329
// digits[000]
15330
// len <= max_exp + 2
15331
15332
std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
15333
// Make it look like a floating-point number (#362, #378)
15334
buf[n + 0] = '.';
15335
buf[n + 1] = '0';
15336
return buf + (static_cast<size_t>(n) + 2);
15337
}
15338
15339
if (0 < n && n <= max_exp)
15340
{
15341
// dig.its
15342
// len <= max_digits10 + 1
15343
15344
JSON_ASSERT(k > n);
15345
15346
std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
15347
buf[n] = '.';
15348
return buf + (static_cast<size_t>(k) + 1U);
15349
}
15350
15351
if (min_exp < n && n <= 0)
15352
{
15353
// 0.[000]digits
15354
// len <= 2 + (-min_exp - 1) + max_digits10
15355
15356
std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
15357
buf[0] = '0';
15358
buf[1] = '.';
15359
std::memset(buf + 2, '0', static_cast<size_t>(-n));
15360
return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
15361
}
15362
15363
if (k == 1)
15364
{
15365
// dE+123
15366
// len <= 1 + 5
15367
15368
buf += 1;
15369
}
15370
else
15371
{
15372
// d.igitsE+123
15373
// len <= max_digits10 + 1 + 5
15374
15375
std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
15376
buf[1] = '.';
15377
buf += 1 + static_cast<size_t>(k);
15378
}
15379
15380
*buf++ = 'e';
15381
return append_exponent(buf, n - 1);
15382
}
15383
15384
} // namespace dtoa_impl
15385
15386
/*!
15387
@brief generates a decimal representation of the floating-point number value in [first, last).
15388
15389
The format of the resulting decimal representation is similar to printf's %g
15390
format. Returns an iterator pointing past-the-end of the decimal representation.
15391
15392
@note The input number must be finite, i.e. NaN's and Inf's are not supported.
15393
@note The buffer must be large enough.
15394
@note The result is NOT null-terminated.
15395
*/
15396
template<typename FloatType>
15397
JSON_HEDLEY_NON_NULL(1, 2)
15398
JSON_HEDLEY_RETURNS_NON_NULL
15399
char* to_chars(char* first, const char* last, FloatType value)
15400
{
15401
static_cast<void>(last); // maybe unused - fix warning
15402
JSON_ASSERT(std::isfinite(value));
15403
15404
// Use signbit(value) instead of (value < 0) since signbit works for -0.
15405
if (std::signbit(value))
15406
{
15407
value = -value;
15408
*first++ = '-';
15409
}
15410
15411
if (value == 0) // +-0
15412
{
15413
*first++ = '0';
15414
// Make it look like a floating-point number (#362, #378)
15415
*first++ = '.';
15416
*first++ = '0';
15417
return first;
15418
}
15419
15420
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
15421
15422
// Compute v = buffer * 10^decimal_exponent.
15423
// The decimal digits are stored in the buffer, which needs to be interpreted
15424
// as an unsigned decimal integer.
15425
// len is the length of the buffer, i.e. the number of decimal digits.
15426
int len = 0;
15427
int decimal_exponent = 0;
15428
dtoa_impl::grisu2(first, len, decimal_exponent, value);
15429
15430
JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
15431
15432
// Format the buffer like printf("%.*g", prec, value)
15433
constexpr int kMinExp = -4;
15434
// Use digits10 here to increase compatibility with version 2.
15435
constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
15436
15437
JSON_ASSERT(last - first >= kMaxExp + 2);
15438
JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
15439
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
15440
15441
return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
15442
}
15443
15444
} // namespace detail
15445
} // namespace nlohmann
15446
15447
// #include <nlohmann/detail/exceptions.hpp>
15448
15449
// #include <nlohmann/detail/macro_scope.hpp>
15450
15451
// #include <nlohmann/detail/meta/cpp_future.hpp>
15452
15453
// #include <nlohmann/detail/output/binary_writer.hpp>
15454
15455
// #include <nlohmann/detail/output/output_adapters.hpp>
15456
15457
// #include <nlohmann/detail/value_t.hpp>
15458
15459
15460
namespace nlohmann
15461
{
15462
namespace detail
15463
{
15464
///////////////////
15465
// serialization //
15466
///////////////////
15467
15468
/// how to treat decoding errors
15469
enum class error_handler_t
15470
{
15471
strict, ///< throw a type_error exception in case of invalid UTF-8
15472
replace, ///< replace invalid UTF-8 sequences with U+FFFD
15473
ignore ///< ignore invalid UTF-8 sequences
15474
};
15475
15476
template<typename BasicJsonType>
15477
class serializer
15478
{
15479
using string_t = typename BasicJsonType::string_t;
15480
using number_float_t = typename BasicJsonType::number_float_t;
15481
using number_integer_t = typename BasicJsonType::number_integer_t;
15482
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
15483
using binary_char_t = typename BasicJsonType::binary_t::value_type;
15484
static constexpr std::uint8_t UTF8_ACCEPT = 0;
15485
static constexpr std::uint8_t UTF8_REJECT = 1;
15486
15487
public:
15488
/*!
15489
@param[in] s output stream to serialize to
15490
@param[in] ichar indentation character to use
15491
@param[in] error_handler_ how to react on decoding errors
15492
*/
15493
serializer(output_adapter_t<char> s, const char ichar,
15494
error_handler_t error_handler_ = error_handler_t::strict)
15495
: o(std::move(s))
15496
, loc(std::localeconv())
15497
, thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
15498
, decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
15499
, indent_char(ichar)
15500
, indent_string(512, indent_char)
15501
, error_handler(error_handler_)
15502
{}
15503
15504
// delete because of pointer members
15505
serializer(const serializer&) = delete;
15506
serializer& operator=(const serializer&) = delete;
15507
serializer(serializer&&) = delete;
15508
serializer& operator=(serializer&&) = delete;
15509
~serializer() = default;
15510
15511
/*!
15512
@brief internal implementation of the serialization function
15513
15514
This function is called by the public member function dump and organizes
15515
the serialization internally. The indentation level is propagated as
15516
additional parameter. In case of arrays and objects, the function is
15517
called recursively.
15518
15519
- strings and object keys are escaped using `escape_string()`
15520
- integer numbers are converted implicitly via `operator<<`
15521
- floating-point numbers are converted to a string using `"%g"` format
15522
- binary values are serialized as objects containing the subtype and the
15523
byte array
15524
15525
@param[in] val value to serialize
15526
@param[in] pretty_print whether the output shall be pretty-printed
15527
@param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
15528
in the output are escaped with `\uXXXX` sequences, and the result consists
15529
of ASCII characters only.
15530
@param[in] indent_step the indent level
15531
@param[in] current_indent the current indent level (only used internally)
15532
*/
15533
void dump(const BasicJsonType& val,
15534
const bool pretty_print,
15535
const bool ensure_ascii,
15536
const unsigned int indent_step,
15537
const unsigned int current_indent = 0)
15538
{
15539
switch (val.m_type)
15540
{
15541
case value_t::object:
15542
{
15543
if (val.m_value.object->empty())
15544
{
15545
o->write_characters("{}", 2);
15546
return;
15547
}
15548
15549
if (pretty_print)
15550
{
15551
o->write_characters("{\n", 2);
15552
15553
// variable to hold indentation for recursive calls
15554
const auto new_indent = current_indent + indent_step;
15555
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
15556
{
15557
indent_string.resize(indent_string.size() * 2, ' ');
15558
}
15559
15560
// first n-1 elements
15561
auto i = val.m_value.object->cbegin();
15562
for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
15563
{
15564
o->write_characters(indent_string.c_str(), new_indent);
15565
o->write_character('\"');
15566
dump_escaped(i->first, ensure_ascii);
15567
o->write_characters("\": ", 3);
15568
dump(i->second, true, ensure_ascii, indent_step, new_indent);
15569
o->write_characters(",\n", 2);
15570
}
15571
15572
// last element
15573
JSON_ASSERT(i != val.m_value.object->cend());
15574
JSON_ASSERT(std::next(i) == val.m_value.object->cend());
15575
o->write_characters(indent_string.c_str(), new_indent);
15576
o->write_character('\"');
15577
dump_escaped(i->first, ensure_ascii);
15578
o->write_characters("\": ", 3);
15579
dump(i->second, true, ensure_ascii, indent_step, new_indent);
15580
15581
o->write_character('\n');
15582
o->write_characters(indent_string.c_str(), current_indent);
15583
o->write_character('}');
15584
}
15585
else
15586
{
15587
o->write_character('{');
15588
15589
// first n-1 elements
15590
auto i = val.m_value.object->cbegin();
15591
for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
15592
{
15593
o->write_character('\"');
15594
dump_escaped(i->first, ensure_ascii);
15595
o->write_characters("\":", 2);
15596
dump(i->second, false, ensure_ascii, indent_step, current_indent);
15597
o->write_character(',');
15598
}
15599
15600
// last element
15601
JSON_ASSERT(i != val.m_value.object->cend());
15602
JSON_ASSERT(std::next(i) == val.m_value.object->cend());
15603
o->write_character('\"');
15604
dump_escaped(i->first, ensure_ascii);
15605
o->write_characters("\":", 2);
15606
dump(i->second, false, ensure_ascii, indent_step, current_indent);
15607
15608
o->write_character('}');
15609
}
15610
15611
return;
15612
}
15613
15614
case value_t::array:
15615
{
15616
if (val.m_value.array->empty())
15617
{
15618
o->write_characters("[]", 2);
15619
return;
15620
}
15621
15622
if (pretty_print)
15623
{
15624
o->write_characters("[\n", 2);
15625
15626
// variable to hold indentation for recursive calls
15627
const auto new_indent = current_indent + indent_step;
15628
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
15629
{
15630
indent_string.resize(indent_string.size() * 2, ' ');
15631
}
15632
15633
// first n-1 elements
15634
for (auto i = val.m_value.array->cbegin();
15635
i != val.m_value.array->cend() - 1; ++i)
15636
{
15637
o->write_characters(indent_string.c_str(), new_indent);
15638
dump(*i, true, ensure_ascii, indent_step, new_indent);
15639
o->write_characters(",\n", 2);
15640
}
15641
15642
// last element
15643
JSON_ASSERT(!val.m_value.array->empty());
15644
o->write_characters(indent_string.c_str(), new_indent);
15645
dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
15646
15647
o->write_character('\n');
15648
o->write_characters(indent_string.c_str(), current_indent);
15649
o->write_character(']');
15650
}
15651
else
15652
{
15653
o->write_character('[');
15654
15655
// first n-1 elements
15656
for (auto i = val.m_value.array->cbegin();
15657
i != val.m_value.array->cend() - 1; ++i)
15658
{
15659
dump(*i, false, ensure_ascii, indent_step, current_indent);
15660
o->write_character(',');
15661
}
15662
15663
// last element
15664
JSON_ASSERT(!val.m_value.array->empty());
15665
dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
15666
15667
o->write_character(']');
15668
}
15669
15670
return;
15671
}
15672
15673
case value_t::string:
15674
{
15675
o->write_character('\"');
15676
dump_escaped(*val.m_value.string, ensure_ascii);
15677
o->write_character('\"');
15678
return;
15679
}
15680
15681
case value_t::binary:
15682
{
15683
if (pretty_print)
15684
{
15685
o->write_characters("{\n", 2);
15686
15687
// variable to hold indentation for recursive calls
15688
const auto new_indent = current_indent + indent_step;
15689
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
15690
{
15691
indent_string.resize(indent_string.size() * 2, ' ');
15692
}
15693
15694
o->write_characters(indent_string.c_str(), new_indent);
15695
15696
o->write_characters("\"bytes\": [", 10);
15697
15698
if (!val.m_value.binary->empty())
15699
{
15700
for (auto i = val.m_value.binary->cbegin();
15701
i != val.m_value.binary->cend() - 1; ++i)
15702
{
15703
dump_integer(*i);
15704
o->write_characters(", ", 2);
15705
}
15706
dump_integer(val.m_value.binary->back());
15707
}
15708
15709
o->write_characters("],\n", 3);
15710
o->write_characters(indent_string.c_str(), new_indent);
15711
15712
o->write_characters("\"subtype\": ", 11);
15713
if (val.m_value.binary->has_subtype())
15714
{
15715
dump_integer(val.m_value.binary->subtype());
15716
}
15717
else
15718
{
15719
o->write_characters("null", 4);
15720
}
15721
o->write_character('\n');
15722
o->write_characters(indent_string.c_str(), current_indent);
15723
o->write_character('}');
15724
}
15725
else
15726
{
15727
o->write_characters("{\"bytes\":[", 10);
15728
15729
if (!val.m_value.binary->empty())
15730
{
15731
for (auto i = val.m_value.binary->cbegin();
15732
i != val.m_value.binary->cend() - 1; ++i)
15733
{
15734
dump_integer(*i);
15735
o->write_character(',');
15736
}
15737
dump_integer(val.m_value.binary->back());
15738
}
15739
15740
o->write_characters("],\"subtype\":", 12);
15741
if (val.m_value.binary->has_subtype())
15742
{
15743
dump_integer(val.m_value.binary->subtype());
15744
o->write_character('}');
15745
}
15746
else
15747
{
15748
o->write_characters("null}", 5);
15749
}
15750
}
15751
return;
15752
}
15753
15754
case value_t::boolean:
15755
{
15756
if (val.m_value.boolean)
15757
{
15758
o->write_characters("true", 4);
15759
}
15760
else
15761
{
15762
o->write_characters("false", 5);
15763
}
15764
return;
15765
}
15766
15767
case value_t::number_integer:
15768
{
15769
dump_integer(val.m_value.number_integer);
15770
return;
15771
}
15772
15773
case value_t::number_unsigned:
15774
{
15775
dump_integer(val.m_value.number_unsigned);
15776
return;
15777
}
15778
15779
case value_t::number_float:
15780
{
15781
dump_float(val.m_value.number_float);
15782
return;
15783
}
15784
15785
case value_t::discarded:
15786
{
15787
o->write_characters("<discarded>", 11);
15788
return;
15789
}
15790
15791
case value_t::null:
15792
{
15793
o->write_characters("null", 4);
15794
return;
15795
}
15796
15797
default: // LCOV_EXCL_LINE
15798
JSON_ASSERT(false); // LCOV_EXCL_LINE
15799
}
15800
}
15801
15802
private:
15803
/*!
15804
@brief dump escaped string
15805
15806
Escape a string by replacing certain special characters by a sequence of an
15807
escape character (backslash) and another character and other control
15808
characters by a sequence of "\u" followed by a four-digit hex
15809
representation. The escaped string is written to output stream @a o.
15810
15811
@param[in] s the string to escape
15812
@param[in] ensure_ascii whether to escape non-ASCII characters with
15813
\uXXXX sequences
15814
15815
@complexity Linear in the length of string @a s.
15816
*/
15817
void dump_escaped(const string_t& s, const bool ensure_ascii)
15818
{
15819
std::uint32_t codepoint;
15820
std::uint8_t state = UTF8_ACCEPT;
15821
std::size_t bytes = 0; // number of bytes written to string_buffer
15822
15823
// number of bytes written at the point of the last valid byte
15824
std::size_t bytes_after_last_accept = 0;
15825
std::size_t undumped_chars = 0;
15826
15827
for (std::size_t i = 0; i < s.size(); ++i)
15828
{
15829
const auto byte = static_cast<uint8_t>(s[i]);
15830
15831
switch (decode(state, codepoint, byte))
15832
{
15833
case UTF8_ACCEPT: // decode found a new code point
15834
{
15835
switch (codepoint)
15836
{
15837
case 0x08: // backspace
15838
{
15839
string_buffer[bytes++] = '\\';
15840
string_buffer[bytes++] = 'b';
15841
break;
15842
}
15843
15844
case 0x09: // horizontal tab
15845
{
15846
string_buffer[bytes++] = '\\';
15847
string_buffer[bytes++] = 't';
15848
break;
15849
}
15850
15851
case 0x0A: // newline
15852
{
15853
string_buffer[bytes++] = '\\';
15854
string_buffer[bytes++] = 'n';
15855
break;
15856
}
15857
15858
case 0x0C: // formfeed
15859
{
15860
string_buffer[bytes++] = '\\';
15861
string_buffer[bytes++] = 'f';
15862
break;
15863
}
15864
15865
case 0x0D: // carriage return
15866
{
15867
string_buffer[bytes++] = '\\';
15868
string_buffer[bytes++] = 'r';
15869
break;
15870
}
15871
15872
case 0x22: // quotation mark
15873
{
15874
string_buffer[bytes++] = '\\';
15875
string_buffer[bytes++] = '\"';
15876
break;
15877
}
15878
15879
case 0x5C: // reverse solidus
15880
{
15881
string_buffer[bytes++] = '\\';
15882
string_buffer[bytes++] = '\\';
15883
break;
15884
}
15885
15886
default:
15887
{
15888
// escape control characters (0x00..0x1F) or, if
15889
// ensure_ascii parameter is used, non-ASCII characters
15890
if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
15891
{
15892
if (codepoint <= 0xFFFF)
15893
{
15894
(std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
15895
static_cast<std::uint16_t>(codepoint));
15896
bytes += 6;
15897
}
15898
else
15899
{
15900
(std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
15901
static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
15902
static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)));
15903
bytes += 12;
15904
}
15905
}
15906
else
15907
{
15908
// copy byte to buffer (all previous bytes
15909
// been copied have in default case above)
15910
string_buffer[bytes++] = s[i];
15911
}
15912
break;
15913
}
15914
}
15915
15916
// write buffer and reset index; there must be 13 bytes
15917
// left, as this is the maximal number of bytes to be
15918
// written ("\uxxxx\uxxxx\0") for one code point
15919
if (string_buffer.size() - bytes < 13)
15920
{
15921
o->write_characters(string_buffer.data(), bytes);
15922
bytes = 0;
15923
}
15924
15925
// remember the byte position of this accept
15926
bytes_after_last_accept = bytes;
15927
undumped_chars = 0;
15928
break;
15929
}
15930
15931
case UTF8_REJECT: // decode found invalid UTF-8 byte
15932
{
15933
switch (error_handler)
15934
{
15935
case error_handler_t::strict:
15936
{
15937
std::string sn(3, '\0');
15938
(std::snprintf)(&sn[0], sn.size(), "%.2X", byte);
15939
JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn));
15940
}
15941
15942
case error_handler_t::ignore:
15943
case error_handler_t::replace:
15944
{
15945
// in case we saw this character the first time, we
15946
// would like to read it again, because the byte
15947
// may be OK for itself, but just not OK for the
15948
// previous sequence
15949
if (undumped_chars > 0)
15950
{
15951
--i;
15952
}
15953
15954
// reset length buffer to the last accepted index;
15955
// thus removing/ignoring the invalid characters
15956
bytes = bytes_after_last_accept;
15957
15958
if (error_handler == error_handler_t::replace)
15959
{
15960
// add a replacement character
15961
if (ensure_ascii)
15962
{
15963
string_buffer[bytes++] = '\\';
15964
string_buffer[bytes++] = 'u';
15965
string_buffer[bytes++] = 'f';
15966
string_buffer[bytes++] = 'f';
15967
string_buffer[bytes++] = 'f';
15968
string_buffer[bytes++] = 'd';
15969
}
15970
else
15971
{
15972
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
15973
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
15974
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
15975
}
15976
15977
// write buffer and reset index; there must be 13 bytes
15978
// left, as this is the maximal number of bytes to be
15979
// written ("\uxxxx\uxxxx\0") for one code point
15980
if (string_buffer.size() - bytes < 13)
15981
{
15982
o->write_characters(string_buffer.data(), bytes);
15983
bytes = 0;
15984
}
15985
15986
bytes_after_last_accept = bytes;
15987
}
15988
15989
undumped_chars = 0;
15990
15991
// continue processing the string
15992
state = UTF8_ACCEPT;
15993
break;
15994
}
15995
15996
default: // LCOV_EXCL_LINE
15997
JSON_ASSERT(false); // LCOV_EXCL_LINE
15998
}
15999
break;
16000
}
16001
16002
default: // decode found yet incomplete multi-byte code point
16003
{
16004
if (!ensure_ascii)
16005
{
16006
// code point will not be escaped - copy byte to buffer
16007
string_buffer[bytes++] = s[i];
16008
}
16009
++undumped_chars;
16010
break;
16011
}
16012
}
16013
}
16014
16015
// we finished processing the string
16016
if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
16017
{
16018
// write buffer
16019
if (bytes > 0)
16020
{
16021
o->write_characters(string_buffer.data(), bytes);
16022
}
16023
}
16024
else
16025
{
16026
// we finish reading, but do not accept: string was incomplete
16027
switch (error_handler)
16028
{
16029
case error_handler_t::strict:
16030
{
16031
std::string sn(3, '\0');
16032
(std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast<std::uint8_t>(s.back()));
16033
JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
16034
}
16035
16036
case error_handler_t::ignore:
16037
{
16038
// write all accepted bytes
16039
o->write_characters(string_buffer.data(), bytes_after_last_accept);
16040
break;
16041
}
16042
16043
case error_handler_t::replace:
16044
{
16045
// write all accepted bytes
16046
o->write_characters(string_buffer.data(), bytes_after_last_accept);
16047
// add a replacement character
16048
if (ensure_ascii)
16049
{
16050
o->write_characters("\\ufffd", 6);
16051
}
16052
else
16053
{
16054
o->write_characters("\xEF\xBF\xBD", 3);
16055
}
16056
break;
16057
}
16058
16059
default: // LCOV_EXCL_LINE
16060
JSON_ASSERT(false); // LCOV_EXCL_LINE
16061
}
16062
}
16063
}
16064
16065
/*!
16066
@brief count digits
16067
16068
Count the number of decimal (base 10) digits for an input unsigned integer.
16069
16070
@param[in] x unsigned integer number to count its digits
16071
@return number of decimal digits
16072
*/
16073
inline unsigned int count_digits(number_unsigned_t x) noexcept
16074
{
16075
unsigned int n_digits = 1;
16076
for (;;)
16077
{
16078
if (x < 10)
16079
{
16080
return n_digits;
16081
}
16082
if (x < 100)
16083
{
16084
return n_digits + 1;
16085
}
16086
if (x < 1000)
16087
{
16088
return n_digits + 2;
16089
}
16090
if (x < 10000)
16091
{
16092
return n_digits + 3;
16093
}
16094
x = x / 10000u;
16095
n_digits += 4;
16096
}
16097
}
16098
16099
/*!
16100
@brief dump an integer
16101
16102
Dump a given integer to output stream @a o. Works internally with
16103
@a number_buffer.
16104
16105
@param[in] x integer number (signed or unsigned) to dump
16106
@tparam NumberType either @a number_integer_t or @a number_unsigned_t
16107
*/
16108
template < typename NumberType, detail::enable_if_t <
16109
std::is_same<NumberType, number_unsigned_t>::value ||
16110
std::is_same<NumberType, number_integer_t>::value ||
16111
std::is_same<NumberType, binary_char_t>::value,
16112
int > = 0 >
16113
void dump_integer(NumberType x)
16114
{
16115
static constexpr std::array<std::array<char, 2>, 100> digits_to_99
16116
{
16117
{
16118
{{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
16119
{{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
16120
{{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
16121
{{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
16122
{{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
16123
{{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
16124
{{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
16125
{{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
16126
{{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
16127
{{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
16128
}
16129
};
16130
16131
// special case for "0"
16132
if (x == 0)
16133
{
16134
o->write_character('0');
16135
return;
16136
}
16137
16138
// use a pointer to fill the buffer
16139
auto buffer_ptr = number_buffer.begin();
16140
16141
const bool is_negative = std::is_same<NumberType, number_integer_t>::value && !(x >= 0); // see issue #755
16142
number_unsigned_t abs_value;
16143
16144
unsigned int n_chars;
16145
16146
if (is_negative)
16147
{
16148
*buffer_ptr = '-';
16149
abs_value = remove_sign(static_cast<number_integer_t>(x));
16150
16151
// account one more byte for the minus sign
16152
n_chars = 1 + count_digits(abs_value);
16153
}
16154
else
16155
{
16156
abs_value = static_cast<number_unsigned_t>(x);
16157
n_chars = count_digits(abs_value);
16158
}
16159
16160
// spare 1 byte for '\0'
16161
JSON_ASSERT(n_chars < number_buffer.size() - 1);
16162
16163
// jump to the end to generate the string from backward
16164
// so we later avoid reversing the result
16165
buffer_ptr += n_chars;
16166
16167
// Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
16168
// See: https://www.youtube.com/watch?v=o4-CwDo2zpg
16169
while (abs_value >= 100)
16170
{
16171
const auto digits_index = static_cast<unsigned>((abs_value % 100));
16172
abs_value /= 100;
16173
*(--buffer_ptr) = digits_to_99[digits_index][1];
16174
*(--buffer_ptr) = digits_to_99[digits_index][0];
16175
}
16176
16177
if (abs_value >= 10)
16178
{
16179
const auto digits_index = static_cast<unsigned>(abs_value);
16180
*(--buffer_ptr) = digits_to_99[digits_index][1];
16181
*(--buffer_ptr) = digits_to_99[digits_index][0];
16182
}
16183
else
16184
{
16185
*(--buffer_ptr) = static_cast<char>('0' + abs_value);
16186
}
16187
16188
o->write_characters(number_buffer.data(), n_chars);
16189
}
16190
16191
/*!
16192
@brief dump a floating-point number
16193
16194
Dump a given floating-point number to output stream @a o. Works internally
16195
with @a number_buffer.
16196
16197
@param[in] x floating-point number to dump
16198
*/
16199
void dump_float(number_float_t x)
16200
{
16201
// NaN / inf
16202
if (!std::isfinite(x))
16203
{
16204
o->write_characters("null", 4);
16205
return;
16206
}
16207
16208
// If number_float_t is an IEEE-754 single or double precision number,
16209
// use the Grisu2 algorithm to produce short numbers which are
16210
// guaranteed to round-trip, using strtof and strtod, resp.
16211
//
16212
// NB: The test below works if <long double> == <double>.
16213
static constexpr bool is_ieee_single_or_double
16214
= (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) ||
16215
(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);
16216
16217
dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
16218
}
16219
16220
void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
16221
{
16222
char* begin = number_buffer.data();
16223
char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
16224
16225
o->write_characters(begin, static_cast<size_t>(end - begin));
16226
}
16227
16228
void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
16229
{
16230
// get number of digits for a float -> text -> float round-trip
16231
static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
16232
16233
// the actual conversion
16234
std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
16235
16236
// negative value indicates an error
16237
JSON_ASSERT(len > 0);
16238
// check if buffer was large enough
16239
JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
16240
16241
// erase thousands separator
16242
if (thousands_sep != '\0')
16243
{
16244
const auto end = std::remove(number_buffer.begin(),
16245
number_buffer.begin() + len, thousands_sep);
16246
std::fill(end, number_buffer.end(), '\0');
16247
JSON_ASSERT((end - number_buffer.begin()) <= len);
16248
len = (end - number_buffer.begin());
16249
}
16250
16251
// convert decimal point to '.'
16252
if (decimal_point != '\0' && decimal_point != '.')
16253
{
16254
const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
16255
if (dec_pos != number_buffer.end())
16256
{
16257
*dec_pos = '.';
16258
}
16259
}
16260
16261
o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
16262
16263
// determine if need to append ".0"
16264
const bool value_is_int_like =
16265
std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
16266
[](char c)
16267
{
16268
return c == '.' || c == 'e';
16269
});
16270
16271
if (value_is_int_like)
16272
{
16273
o->write_characters(".0", 2);
16274
}
16275
}
16276
16277
/*!
16278
@brief check whether a string is UTF-8 encoded
16279
16280
The function checks each byte of a string whether it is UTF-8 encoded. The
16281
result of the check is stored in the @a state parameter. The function must
16282
be called initially with state 0 (accept). State 1 means the string must
16283
be rejected, because the current byte is not allowed. If the string is
16284
completely processed, but the state is non-zero, the string ended
16285
prematurely; that is, the last byte indicated more bytes should have
16286
followed.
16287
16288
@param[in,out] state the state of the decoding
16289
@param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
16290
@param[in] byte next byte to decode
16291
@return new state
16292
16293
@note The function has been edited: a std::array is used.
16294
16295
@copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <[email protected]>
16296
@sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
16297
*/
16298
static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
16299
{
16300
static const std::array<std::uint8_t, 400> utf8d =
16301
{
16302
{
16303
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
16304
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
16305
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
16306
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
16307
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
16308
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
16309
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
16310
0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
16311
0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
16312
0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
16313
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
16314
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
16315
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
16316
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
16317
}
16318
};
16319
16320
const std::uint8_t type = utf8d[byte];
16321
16322
codep = (state != UTF8_ACCEPT)
16323
? (byte & 0x3fu) | (codep << 6u)
16324
: (0xFFu >> type) & (byte);
16325
16326
std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
16327
JSON_ASSERT(index < 400);
16328
state = utf8d[index];
16329
return state;
16330
}
16331
16332
/*
16333
* Overload to make the compiler happy while it is instantiating
16334
* dump_integer for number_unsigned_t.
16335
* Must never be called.
16336
*/
16337
number_unsigned_t remove_sign(number_unsigned_t x)
16338
{
16339
JSON_ASSERT(false); // LCOV_EXCL_LINE
16340
return x; // LCOV_EXCL_LINE
16341
}
16342
16343
/*
16344
* Helper function for dump_integer
16345
*
16346
* This function takes a negative signed integer and returns its absolute
16347
* value as unsigned integer. The plus/minus shuffling is necessary as we can
16348
* not directly remove the sign of an arbitrary signed integer as the
16349
* absolute values of INT_MIN and INT_MAX are usually not the same. See
16350
* #1708 for details.
16351
*/
16352
inline number_unsigned_t remove_sign(number_integer_t x) noexcept
16353
{
16354
JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)());
16355
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
16356
}
16357
16358
private:
16359
/// the output of the serializer
16360
output_adapter_t<char> o = nullptr;
16361
16362
/// a (hopefully) large enough character buffer
16363
std::array<char, 64> number_buffer{{}};
16364
16365
/// the locale
16366
const std::lconv* loc = nullptr;
16367
/// the locale's thousand separator character
16368
const char thousands_sep = '\0';
16369
/// the locale's decimal point character
16370
const char decimal_point = '\0';
16371
16372
/// string buffer
16373
std::array<char, 512> string_buffer{{}};
16374
16375
/// the indentation character
16376
const char indent_char;
16377
/// the indentation string
16378
string_t indent_string;
16379
16380
/// error_handler how to react on decoding errors
16381
const error_handler_t error_handler;
16382
};
16383
} // namespace detail
16384
} // namespace nlohmann
16385
16386
// #include <nlohmann/detail/value_t.hpp>
16387
16388
// #include <nlohmann/json_fwd.hpp>
16389
16390
// #include <nlohmann/ordered_map.hpp>
16391
16392
16393
#include <functional> // less
16394
#include <memory> // allocator
16395
#include <utility> // pair
16396
#include <vector> // vector
16397
16398
namespace nlohmann
16399
{
16400
16401
/// ordered_map: a minimal map-like container that preserves insertion order
16402
/// for use within nlohmann::basic_json<ordered_map>
16403
template <class Key, class T, class IgnoredLess = std::less<Key>,
16404
class Allocator = std::allocator<std::pair<const Key, T>>>
16405
struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
16406
{
16407
using key_type = Key;
16408
using mapped_type = T;
16409
using Container = std::vector<std::pair<const Key, T>, Allocator>;
16410
using typename Container::iterator;
16411
using typename Container::const_iterator;
16412
using typename Container::size_type;
16413
using typename Container::value_type;
16414
16415
// Explicit constructors instead of `using Container::Container`
16416
// otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
16417
ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {}
16418
template <class It>
16419
ordered_map(It first, It last, const Allocator& alloc = Allocator())
16420
: Container{first, last, alloc} {}
16421
ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator() )
16422
: Container{init, alloc} {}
16423
16424
std::pair<iterator, bool> emplace(const key_type& key, T&& t)
16425
{
16426
for (auto it = this->begin(); it != this->end(); ++it)
16427
{
16428
if (it->first == key)
16429
{
16430
return {it, false};
16431
}
16432
}
16433
Container::emplace_back(key, t);
16434
return {--this->end(), true};
16435
}
16436
16437
T& operator[](const Key& key)
16438
{
16439
return emplace(key, T{}).first->second;
16440
}
16441
16442
const T& operator[](const Key& key) const
16443
{
16444
return at(key);
16445
}
16446
16447
T& at(const Key& key)
16448
{
16449
for (auto it = this->begin(); it != this->end(); ++it)
16450
{
16451
if (it->first == key)
16452
{
16453
return it->second;
16454
}
16455
}
16456
16457
throw std::out_of_range("key not found");
16458
}
16459
16460
const T& at(const Key& key) const
16461
{
16462
for (auto it = this->begin(); it != this->end(); ++it)
16463
{
16464
if (it->first == key)
16465
{
16466
return it->second;
16467
}
16468
}
16469
16470
throw std::out_of_range("key not found");
16471
}
16472
16473
size_type erase(const Key& key)
16474
{
16475
for (auto it = this->begin(); it != this->end(); ++it)
16476
{
16477
if (it->first == key)
16478
{
16479
// Since we cannot move const Keys, re-construct them in place
16480
for (auto next = it; ++next != this->end(); ++it)
16481
{
16482
it->~value_type(); // Destroy but keep allocation
16483
new (&*it) value_type{std::move(*next)};
16484
}
16485
Container::pop_back();
16486
return 1;
16487
}
16488
}
16489
return 0;
16490
}
16491
16492
iterator erase(iterator pos)
16493
{
16494
auto it = pos;
16495
16496
// Since we cannot move const Keys, re-construct them in place
16497
for (auto next = it; ++next != this->end(); ++it)
16498
{
16499
it->~value_type(); // Destroy but keep allocation
16500
new (&*it) value_type{std::move(*next)};
16501
}
16502
Container::pop_back();
16503
return pos;
16504
}
16505
16506
size_type count(const Key& key) const
16507
{
16508
for (auto it = this->begin(); it != this->end(); ++it)
16509
{
16510
if (it->first == key)
16511
{
16512
return 1;
16513
}
16514
}
16515
return 0;
16516
}
16517
16518
iterator find(const Key& key)
16519
{
16520
for (auto it = this->begin(); it != this->end(); ++it)
16521
{
16522
if (it->first == key)
16523
{
16524
return it;
16525
}
16526
}
16527
return Container::end();
16528
}
16529
16530
const_iterator find(const Key& key) const
16531
{
16532
for (auto it = this->begin(); it != this->end(); ++it)
16533
{
16534
if (it->first == key)
16535
{
16536
return it;
16537
}
16538
}
16539
return Container::end();
16540
}
16541
16542
std::pair<iterator, bool> insert( value_type&& value )
16543
{
16544
return emplace(value.first, std::move(value.second));
16545
}
16546
16547
std::pair<iterator, bool> insert( const value_type& value )
16548
{
16549
for (auto it = this->begin(); it != this->end(); ++it)
16550
{
16551
if (it->first == value.first)
16552
{
16553
return {it, false};
16554
}
16555
}
16556
Container::push_back(value);
16557
return {--this->end(), true};
16558
}
16559
};
16560
16561
} // namespace nlohmann
16562
16563
16564
/*!
16565
@brief namespace for Niels Lohmann
16566
@see https://github.com/nlohmann
16567
@since version 1.0.0
16568
*/
16569
namespace nlohmann
16570
{
16571
16572
/*!
16573
@brief a class to store JSON values
16574
16575
@tparam ObjectType type for JSON objects (`std::map` by default; will be used
16576
in @ref object_t)
16577
@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used
16578
in @ref array_t)
16579
@tparam StringType type for JSON strings and object keys (`std::string` by
16580
default; will be used in @ref string_t)
16581
@tparam BooleanType type for JSON booleans (`bool` by default; will be used
16582
in @ref boolean_t)
16583
@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by
16584
default; will be used in @ref number_integer_t)
16585
@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c
16586
`uint64_t` by default; will be used in @ref number_unsigned_t)
16587
@tparam NumberFloatType type for JSON floating-point numbers (`double` by
16588
default; will be used in @ref number_float_t)
16589
@tparam BinaryType type for packed binary data for compatibility with binary
16590
serialization formats (`std::vector<std::uint8_t>` by default; will be used in
16591
@ref binary_t)
16592
@tparam AllocatorType type of the allocator to use (`std::allocator` by
16593
default)
16594
@tparam JSONSerializer the serializer to resolve internal calls to `to_json()`
16595
and `from_json()` (@ref adl_serializer by default)
16596
16597
@requirement The class satisfies the following concept requirements:
16598
- Basic
16599
- [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible):
16600
JSON values can be default constructed. The result will be a JSON null
16601
value.
16602
- [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible):
16603
A JSON value can be constructed from an rvalue argument.
16604
- [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible):
16605
A JSON value can be copy-constructed from an lvalue expression.
16606
- [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable):
16607
A JSON value van be assigned from an rvalue argument.
16608
- [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable):
16609
A JSON value can be copy-assigned from an lvalue expression.
16610
- [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible):
16611
JSON values can be destructed.
16612
- Layout
16613
- [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType):
16614
JSON values have
16615
[standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
16616
All non-static data members are private and standard layout types, the
16617
class has no virtual functions or (virtual) base classes.
16618
- Library-wide
16619
- [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable):
16620
JSON values can be compared with `==`, see @ref
16621
operator==(const_reference,const_reference).
16622
- [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable):
16623
JSON values can be compared with `<`, see @ref
16624
operator<(const_reference,const_reference).
16625
- [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable):
16626
Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
16627
other compatible types, using unqualified function call @ref swap().
16628
- [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer):
16629
JSON values can be compared against `std::nullptr_t` objects which are used
16630
to model the `null` value.
16631
- Container
16632
- [Container](https://en.cppreference.com/w/cpp/named_req/Container):
16633
JSON values can be used like STL containers and provide iterator access.
16634
- [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer);
16635
JSON values can be used like STL containers and provide reverse iterator
16636
access.
16637
16638
@invariant The member variables @a m_value and @a m_type have the following
16639
relationship:
16640
- If `m_type == value_t::object`, then `m_value.object != nullptr`.
16641
- If `m_type == value_t::array`, then `m_value.array != nullptr`.
16642
- If `m_type == value_t::string`, then `m_value.string != nullptr`.
16643
The invariants are checked by member function assert_invariant().
16644
16645
@internal
16646
@note ObjectType trick from https://stackoverflow.com/a/9860911
16647
@endinternal
16648
16649
@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange
16650
Format](http://rfc7159.net/rfc7159)
16651
16652
@since version 1.0.0
16653
16654
@nosubgrouping
16655
*/
16656
NLOHMANN_BASIC_JSON_TPL_DECLARATION
16657
class basic_json
16658
{
16659
private:
16660
template<detail::value_t> friend struct detail::external_constructor;
16661
friend ::nlohmann::json_pointer<basic_json>;
16662
16663
template<typename BasicJsonType, typename InputType>
16664
friend class ::nlohmann::detail::parser;
16665
friend ::nlohmann::detail::serializer<basic_json>;
16666
template<typename BasicJsonType>
16667
friend class ::nlohmann::detail::iter_impl;
16668
template<typename BasicJsonType, typename CharType>
16669
friend class ::nlohmann::detail::binary_writer;
16670
template<typename BasicJsonType, typename InputType, typename SAX>
16671
friend class ::nlohmann::detail::binary_reader;
16672
template<typename BasicJsonType>
16673
friend class ::nlohmann::detail::json_sax_dom_parser;
16674
template<typename BasicJsonType>
16675
friend class ::nlohmann::detail::json_sax_dom_callback_parser;
16676
16677
/// workaround type for MSVC
16678
using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
16679
16680
// convenience aliases for types residing in namespace detail;
16681
using lexer = ::nlohmann::detail::lexer_base<basic_json>;
16682
16683
template<typename InputAdapterType>
16684
static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
16685
InputAdapterType adapter,
16686
detail::parser_callback_t<basic_json>cb = nullptr,
16687
const bool allow_exceptions = true,
16688
const bool ignore_comments = false
16689
)
16690
{
16691
return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
16692
std::move(cb), allow_exceptions, ignore_comments);
16693
}
16694
16695
using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
16696
template<typename BasicJsonType>
16697
using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
16698
template<typename BasicJsonType>
16699
using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
16700
template<typename Iterator>
16701
using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
16702
template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
16703
16704
template<typename CharType>
16705
using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
16706
16707
template<typename InputType>
16708
using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
16709
template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
16710
16711
using serializer = ::nlohmann::detail::serializer<basic_json>;
16712
16713
public:
16714
using value_t = detail::value_t;
16715
/// JSON Pointer, see @ref nlohmann::json_pointer
16716
using json_pointer = ::nlohmann::json_pointer<basic_json>;
16717
template<typename T, typename SFINAE>
16718
using json_serializer = JSONSerializer<T, SFINAE>;
16719
/// how to treat decoding errors
16720
using error_handler_t = detail::error_handler_t;
16721
/// how to treat CBOR tags
16722
using cbor_tag_handler_t = detail::cbor_tag_handler_t;
16723
/// helper type for initializer lists of basic_json values
16724
using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
16725
16726
using input_format_t = detail::input_format_t;
16727
/// SAX interface type, see @ref nlohmann::json_sax
16728
using json_sax_t = json_sax<basic_json>;
16729
16730
////////////////
16731
// exceptions //
16732
////////////////
16733
16734
/// @name exceptions
16735
/// Classes to implement user-defined exceptions.
16736
/// @{
16737
16738
/// @copydoc detail::exception
16739
using exception = detail::exception;
16740
/// @copydoc detail::parse_error
16741
using parse_error = detail::parse_error;
16742
/// @copydoc detail::invalid_iterator
16743
using invalid_iterator = detail::invalid_iterator;
16744
/// @copydoc detail::type_error
16745
using type_error = detail::type_error;
16746
/// @copydoc detail::out_of_range
16747
using out_of_range = detail::out_of_range;
16748
/// @copydoc detail::other_error
16749
using other_error = detail::other_error;
16750
16751
/// @}
16752
16753
16754
/////////////////////
16755
// container types //
16756
/////////////////////
16757
16758
/// @name container types
16759
/// The canonic container types to use @ref basic_json like any other STL
16760
/// container.
16761
/// @{
16762
16763
/// the type of elements in a basic_json container
16764
using value_type = basic_json;
16765
16766
/// the type of an element reference
16767
using reference = value_type&;
16768
/// the type of an element const reference
16769
using const_reference = const value_type&;
16770
16771
/// a type to represent differences between iterators
16772
using difference_type = std::ptrdiff_t;
16773
/// a type to represent container sizes
16774
using size_type = std::size_t;
16775
16776
/// the allocator type
16777
using allocator_type = AllocatorType<basic_json>;
16778
16779
/// the type of an element pointer
16780
using pointer = typename std::allocator_traits<allocator_type>::pointer;
16781
/// the type of an element const pointer
16782
using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
16783
16784
/// an iterator for a basic_json container
16785
using iterator = iter_impl<basic_json>;
16786
/// a const iterator for a basic_json container
16787
using const_iterator = iter_impl<const basic_json>;
16788
/// a reverse iterator for a basic_json container
16789
using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
16790
/// a const reverse iterator for a basic_json container
16791
using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
16792
16793
/// @}
16794
16795
16796
/*!
16797
@brief returns the allocator associated with the container
16798
*/
16799
static allocator_type get_allocator()
16800
{
16801
return allocator_type();
16802
}
16803
16804
/*!
16805
@brief returns version information on the library
16806
16807
This function returns a JSON object with information about the library,
16808
including the version number and information on the platform and compiler.
16809
16810
@return JSON object holding version information
16811
key | description
16812
----------- | ---------------
16813
`compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).
16814
`copyright` | The copyright line for the library as string.
16815
`name` | The name of the library as string.
16816
`platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`.
16817
`url` | The URL of the project as string.
16818
`version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string).
16819
16820
@liveexample{The following code shows an example output of the `meta()`
16821
function.,meta}
16822
16823
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
16824
changes to any JSON value.
16825
16826
@complexity Constant.
16827
16828
@since 2.1.0
16829
*/
16830
JSON_HEDLEY_WARN_UNUSED_RESULT
16831
static basic_json meta()
16832
{
16833
basic_json result;
16834
16835
result["copyright"] = "(C) 2013-2020 Niels Lohmann";
16836
result["name"] = "JSON for Modern C++";
16837
result["url"] = "https://github.com/nlohmann/json";
16838
result["version"]["string"] =
16839
std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
16840
std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
16841
std::to_string(NLOHMANN_JSON_VERSION_PATCH);
16842
result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
16843
result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
16844
result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
16845
16846
#ifdef _WIN32
16847
result["platform"] = "win32";
16848
#elif defined __linux__
16849
result["platform"] = "linux";
16850
#elif defined __APPLE__
16851
result["platform"] = "apple";
16852
#elif defined __unix__
16853
result["platform"] = "unix";
16854
#else
16855
result["platform"] = "unknown";
16856
#endif
16857
16858
#if defined(__ICC) || defined(__INTEL_COMPILER)
16859
result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
16860
#elif defined(__clang__)
16861
result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
16862
#elif defined(__GNUC__) || defined(__GNUG__)
16863
result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
16864
#elif defined(__HP_cc) || defined(__HP_aCC)
16865
result["compiler"] = "hp"
16866
#elif defined(__IBMCPP__)
16867
result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
16868
#elif defined(_MSC_VER)
16869
result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
16870
#elif defined(__PGI)
16871
result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
16872
#elif defined(__SUNPRO_CC)
16873
result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
16874
#else
16875
result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
16876
#endif
16877
16878
#ifdef __cplusplus
16879
result["compiler"]["c++"] = std::to_string(__cplusplus);
16880
#else
16881
result["compiler"]["c++"] = "unknown";
16882
#endif
16883
return result;
16884
}
16885
16886
16887
///////////////////////////
16888
// JSON value data types //
16889
///////////////////////////
16890
16891
/// @name JSON value data types
16892
/// The data types to store a JSON value. These types are derived from
16893
/// the template arguments passed to class @ref basic_json.
16894
/// @{
16895
16896
#if defined(JSON_HAS_CPP_14)
16897
// Use transparent comparator if possible, combined with perfect forwarding
16898
// on find() and count() calls prevents unnecessary string construction.
16899
using object_comparator_t = std::less<>;
16900
#else
16901
using object_comparator_t = std::less<StringType>;
16902
#endif
16903
16904
/*!
16905
@brief a type for an object
16906
16907
[RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:
16908
> An object is an unordered collection of zero or more name/value pairs,
16909
> where a name is a string and a value is a string, number, boolean, null,
16910
> object, or array.
16911
16912
To store objects in C++, a type is defined by the template parameters
16913
described below.
16914
16915
@tparam ObjectType the container to store objects (e.g., `std::map` or
16916
`std::unordered_map`)
16917
@tparam StringType the type of the keys or names (e.g., `std::string`).
16918
The comparison function `std::less<StringType>` is used to order elements
16919
inside the container.
16920
@tparam AllocatorType the allocator to use for objects (e.g.,
16921
`std::allocator`)
16922
16923
#### Default type
16924
16925
With the default values for @a ObjectType (`std::map`), @a StringType
16926
(`std::string`), and @a AllocatorType (`std::allocator`), the default
16927
value for @a object_t is:
16928
16929
@code {.cpp}
16930
std::map<
16931
std::string, // key_type
16932
basic_json, // value_type
16933
std::less<std::string>, // key_compare
16934
std::allocator<std::pair<const std::string, basic_json>> // allocator_type
16935
>
16936
@endcode
16937
16938
#### Behavior
16939
16940
The choice of @a object_t influences the behavior of the JSON class. With
16941
the default type, objects have the following behavior:
16942
16943
- When all names are unique, objects will be interoperable in the sense
16944
that all software implementations receiving that object will agree on
16945
the name-value mappings.
16946
- When the names within an object are not unique, it is unspecified which
16947
one of the values for a given key will be chosen. For instance,
16948
`{"key": 2, "key": 1}` could be equal to either `{"key": 1}` or
16949
`{"key": 2}`.
16950
- Internally, name/value pairs are stored in lexicographical order of the
16951
names. Objects will also be serialized (see @ref dump) in this order.
16952
For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored
16953
and serialized as `{"a": 2, "b": 1}`.
16954
- When comparing objects, the order of the name/value pairs is irrelevant.
16955
This makes objects interoperable in the sense that they will not be
16956
affected by these differences. For instance, `{"b": 1, "a": 2}` and
16957
`{"a": 2, "b": 1}` will be treated as equal.
16958
16959
#### Limits
16960
16961
[RFC 7159](http://rfc7159.net/rfc7159) specifies:
16962
> An implementation may set limits on the maximum depth of nesting.
16963
16964
In this class, the object's limit of nesting is not explicitly constrained.
16965
However, a maximum depth of nesting may be introduced by the compiler or
16966
runtime environment. A theoretical limit can be queried by calling the
16967
@ref max_size function of a JSON object.
16968
16969
#### Storage
16970
16971
Objects are stored as pointers in a @ref basic_json type. That is, for any
16972
access to object values, a pointer of type `object_t*` must be
16973
dereferenced.
16974
16975
@sa @ref array_t -- type for an array value
16976
16977
@since version 1.0.0
16978
16979
@note The order name/value pairs are added to the object is *not*
16980
preserved by the library. Therefore, iterating an object may return
16981
name/value pairs in a different order than they were originally stored. In
16982
fact, keys will be traversed in alphabetical order as `std::map` with
16983
`std::less` is used by default. Please note this behavior conforms to [RFC
16984
7159](http://rfc7159.net/rfc7159), because any order implements the
16985
specified "unordered" nature of JSON objects.
16986
*/
16987
using object_t = ObjectType<StringType,
16988
basic_json,
16989
object_comparator_t,
16990
AllocatorType<std::pair<const StringType,
16991
basic_json>>>;
16992
16993
/*!
16994
@brief a type for an array
16995
16996
[RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:
16997
> An array is an ordered sequence of zero or more values.
16998
16999
To store objects in C++, a type is defined by the template parameters
17000
explained below.
17001
17002
@tparam ArrayType container type to store arrays (e.g., `std::vector` or
17003
`std::list`)
17004
@tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)
17005
17006
#### Default type
17007
17008
With the default values for @a ArrayType (`std::vector`) and @a
17009
AllocatorType (`std::allocator`), the default value for @a array_t is:
17010
17011
@code {.cpp}
17012
std::vector<
17013
basic_json, // value_type
17014
std::allocator<basic_json> // allocator_type
17015
>
17016
@endcode
17017
17018
#### Limits
17019
17020
[RFC 7159](http://rfc7159.net/rfc7159) specifies:
17021
> An implementation may set limits on the maximum depth of nesting.
17022
17023
In this class, the array's limit of nesting is not explicitly constrained.
17024
However, a maximum depth of nesting may be introduced by the compiler or
17025
runtime environment. A theoretical limit can be queried by calling the
17026
@ref max_size function of a JSON array.
17027
17028
#### Storage
17029
17030
Arrays are stored as pointers in a @ref basic_json type. That is, for any
17031
access to array values, a pointer of type `array_t*` must be dereferenced.
17032
17033
@sa @ref object_t -- type for an object value
17034
17035
@since version 1.0.0
17036
*/
17037
using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
17038
17039
/*!
17040
@brief a type for a string
17041
17042
[RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:
17043
> A string is a sequence of zero or more Unicode characters.
17044
17045
To store objects in C++, a type is defined by the template parameter
17046
described below. Unicode values are split by the JSON class into
17047
byte-sized characters during deserialization.
17048
17049
@tparam StringType the container to store strings (e.g., `std::string`).
17050
Note this container is used for keys/names in objects, see @ref object_t.
17051
17052
#### Default type
17053
17054
With the default values for @a StringType (`std::string`), the default
17055
value for @a string_t is:
17056
17057
@code {.cpp}
17058
std::string
17059
@endcode
17060
17061
#### Encoding
17062
17063
Strings are stored in UTF-8 encoding. Therefore, functions like
17064
`std::string::size()` or `std::string::length()` return the number of
17065
bytes in the string rather than the number of characters or glyphs.
17066
17067
#### String comparison
17068
17069
[RFC 7159](http://rfc7159.net/rfc7159) states:
17070
> Software implementations are typically required to test names of object
17071
> members for equality. Implementations that transform the textual
17072
> representation into sequences of Unicode code units and then perform the
17073
> comparison numerically, code unit by code unit, are interoperable in the
17074
> sense that implementations will agree in all cases on equality or
17075
> inequality of two strings. For example, implementations that compare
17076
> strings with escaped characters unconverted may incorrectly find that
17077
> `"a\\b"` and `"a\u005Cb"` are not equal.
17078
17079
This implementation is interoperable as it does compare strings code unit
17080
by code unit.
17081
17082
#### Storage
17083
17084
String values are stored as pointers in a @ref basic_json type. That is,
17085
for any access to string values, a pointer of type `string_t*` must be
17086
dereferenced.
17087
17088
@since version 1.0.0
17089
*/
17090
using string_t = StringType;
17091
17092
/*!
17093
@brief a type for a boolean
17094
17095
[RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a
17096
type which differentiates the two literals `true` and `false`.
17097
17098
To store objects in C++, a type is defined by the template parameter @a
17099
BooleanType which chooses the type to use.
17100
17101
#### Default type
17102
17103
With the default values for @a BooleanType (`bool`), the default value for
17104
@a boolean_t is:
17105
17106
@code {.cpp}
17107
bool
17108
@endcode
17109
17110
#### Storage
17111
17112
Boolean values are stored directly inside a @ref basic_json type.
17113
17114
@since version 1.0.0
17115
*/
17116
using boolean_t = BooleanType;
17117
17118
/*!
17119
@brief a type for a number (integer)
17120
17121
[RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
17122
> The representation of numbers is similar to that used in most
17123
> programming languages. A number is represented in base 10 using decimal
17124
> digits. It contains an integer component that may be prefixed with an
17125
> optional minus sign, which may be followed by a fraction part and/or an
17126
> exponent part. Leading zeros are not allowed. (...) Numeric values that
17127
> cannot be represented in the grammar below (such as Infinity and NaN)
17128
> are not permitted.
17129
17130
This description includes both integer and floating-point numbers.
17131
However, C++ allows more precise storage if it is known whether the number
17132
is a signed integer, an unsigned integer or a floating-point number.
17133
Therefore, three different types, @ref number_integer_t, @ref
17134
number_unsigned_t and @ref number_float_t are used.
17135
17136
To store integer numbers in C++, a type is defined by the template
17137
parameter @a NumberIntegerType which chooses the type to use.
17138
17139
#### Default type
17140
17141
With the default values for @a NumberIntegerType (`int64_t`), the default
17142
value for @a number_integer_t is:
17143
17144
@code {.cpp}
17145
int64_t
17146
@endcode
17147
17148
#### Default behavior
17149
17150
- The restrictions about leading zeros is not enforced in C++. Instead,
17151
leading zeros in integer literals lead to an interpretation as octal
17152
number. Internally, the value will be stored as decimal number. For
17153
instance, the C++ integer literal `010` will be serialized to `8`.
17154
During deserialization, leading zeros yield an error.
17155
- Not-a-number (NaN) values will be serialized to `null`.
17156
17157
#### Limits
17158
17159
[RFC 7159](http://rfc7159.net/rfc7159) specifies:
17160
> An implementation may set limits on the range and precision of numbers.
17161
17162
When the default type is used, the maximal integer number that can be
17163
stored is `9223372036854775807` (INT64_MAX) and the minimal integer number
17164
that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
17165
that are out of range will yield over/underflow when used in a
17166
constructor. During deserialization, too large or small integer numbers
17167
will be automatically be stored as @ref number_unsigned_t or @ref
17168
number_float_t.
17169
17170
[RFC 7159](http://rfc7159.net/rfc7159) further states:
17171
> Note that when such software is used, numbers that are integers and are
17172
> in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
17173
> that implementations will agree exactly on their numeric values.
17174
17175
As this range is a subrange of the exactly supported range [INT64_MIN,
17176
INT64_MAX], this class's integer type is interoperable.
17177
17178
#### Storage
17179
17180
Integer number values are stored directly inside a @ref basic_json type.
17181
17182
@sa @ref number_float_t -- type for number values (floating-point)
17183
17184
@sa @ref number_unsigned_t -- type for number values (unsigned integer)
17185
17186
@since version 1.0.0
17187
*/
17188
using number_integer_t = NumberIntegerType;
17189
17190
/*!
17191
@brief a type for a number (unsigned)
17192
17193
[RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
17194
> The representation of numbers is similar to that used in most
17195
> programming languages. A number is represented in base 10 using decimal
17196
> digits. It contains an integer component that may be prefixed with an
17197
> optional minus sign, which may be followed by a fraction part and/or an
17198
> exponent part. Leading zeros are not allowed. (...) Numeric values that
17199
> cannot be represented in the grammar below (such as Infinity and NaN)
17200
> are not permitted.
17201
17202
This description includes both integer and floating-point numbers.
17203
However, C++ allows more precise storage if it is known whether the number
17204
is a signed integer, an unsigned integer or a floating-point number.
17205
Therefore, three different types, @ref number_integer_t, @ref
17206
number_unsigned_t and @ref number_float_t are used.
17207
17208
To store unsigned integer numbers in C++, a type is defined by the
17209
template parameter @a NumberUnsignedType which chooses the type to use.
17210
17211
#### Default type
17212
17213
With the default values for @a NumberUnsignedType (`uint64_t`), the
17214
default value for @a number_unsigned_t is:
17215
17216
@code {.cpp}
17217
uint64_t
17218
@endcode
17219
17220
#### Default behavior
17221
17222
- The restrictions about leading zeros is not enforced in C++. Instead,
17223
leading zeros in integer literals lead to an interpretation as octal
17224
number. Internally, the value will be stored as decimal number. For
17225
instance, the C++ integer literal `010` will be serialized to `8`.
17226
During deserialization, leading zeros yield an error.
17227
- Not-a-number (NaN) values will be serialized to `null`.
17228
17229
#### Limits
17230
17231
[RFC 7159](http://rfc7159.net/rfc7159) specifies:
17232
> An implementation may set limits on the range and precision of numbers.
17233
17234
When the default type is used, the maximal integer number that can be
17235
stored is `18446744073709551615` (UINT64_MAX) and the minimal integer
17236
number that can be stored is `0`. Integer numbers that are out of range
17237
will yield over/underflow when used in a constructor. During
17238
deserialization, too large or small integer numbers will be automatically
17239
be stored as @ref number_integer_t or @ref number_float_t.
17240
17241
[RFC 7159](http://rfc7159.net/rfc7159) further states:
17242
> Note that when such software is used, numbers that are integers and are
17243
> in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
17244
> that implementations will agree exactly on their numeric values.
17245
17246
As this range is a subrange (when considered in conjunction with the
17247
number_integer_t type) of the exactly supported range [0, UINT64_MAX],
17248
this class's integer type is interoperable.
17249
17250
#### Storage
17251
17252
Integer number values are stored directly inside a @ref basic_json type.
17253
17254
@sa @ref number_float_t -- type for number values (floating-point)
17255
@sa @ref number_integer_t -- type for number values (integer)
17256
17257
@since version 2.0.0
17258
*/
17259
using number_unsigned_t = NumberUnsignedType;
17260
17261
/*!
17262
@brief a type for a number (floating-point)
17263
17264
[RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
17265
> The representation of numbers is similar to that used in most
17266
> programming languages. A number is represented in base 10 using decimal
17267
> digits. It contains an integer component that may be prefixed with an
17268
> optional minus sign, which may be followed by a fraction part and/or an
17269
> exponent part. Leading zeros are not allowed. (...) Numeric values that
17270
> cannot be represented in the grammar below (such as Infinity and NaN)
17271
> are not permitted.
17272
17273
This description includes both integer and floating-point numbers.
17274
However, C++ allows more precise storage if it is known whether the number
17275
is a signed integer, an unsigned integer or a floating-point number.
17276
Therefore, three different types, @ref number_integer_t, @ref
17277
number_unsigned_t and @ref number_float_t are used.
17278
17279
To store floating-point numbers in C++, a type is defined by the template
17280
parameter @a NumberFloatType which chooses the type to use.
17281
17282
#### Default type
17283
17284
With the default values for @a NumberFloatType (`double`), the default
17285
value for @a number_float_t is:
17286
17287
@code {.cpp}
17288
double
17289
@endcode
17290
17291
#### Default behavior
17292
17293
- The restrictions about leading zeros is not enforced in C++. Instead,
17294
leading zeros in floating-point literals will be ignored. Internally,
17295
the value will be stored as decimal number. For instance, the C++
17296
floating-point literal `01.2` will be serialized to `1.2`. During
17297
deserialization, leading zeros yield an error.
17298
- Not-a-number (NaN) values will be serialized to `null`.
17299
17300
#### Limits
17301
17302
[RFC 7159](http://rfc7159.net/rfc7159) states:
17303
> This specification allows implementations to set limits on the range and
17304
> precision of numbers accepted. Since software that implements IEEE
17305
> 754-2008 binary64 (double precision) numbers is generally available and
17306
> widely used, good interoperability can be achieved by implementations
17307
> that expect no more precision or range than these provide, in the sense
17308
> that implementations will approximate JSON numbers within the expected
17309
> precision.
17310
17311
This implementation does exactly follow this approach, as it uses double
17312
precision floating-point numbers. Note values smaller than
17313
`-1.79769313486232e+308` and values greater than `1.79769313486232e+308`
17314
will be stored as NaN internally and be serialized to `null`.
17315
17316
#### Storage
17317
17318
Floating-point number values are stored directly inside a @ref basic_json
17319
type.
17320
17321
@sa @ref number_integer_t -- type for number values (integer)
17322
17323
@sa @ref number_unsigned_t -- type for number values (unsigned integer)
17324
17325
@since version 1.0.0
17326
*/
17327
using number_float_t = NumberFloatType;
17328
17329
/*!
17330
@brief a type for a packed binary type
17331
17332
This type is a type designed to carry binary data that appears in various
17333
serialized formats, such as CBOR's Major Type 2, MessagePack's bin, and
17334
BSON's generic binary subtype. This type is NOT a part of standard JSON and
17335
exists solely for compatibility with these binary types. As such, it is
17336
simply defined as an ordered sequence of zero or more byte values.
17337
17338
Additionally, as an implementation detail, the subtype of the binary data is
17339
carried around as a `std::uint8_t`, which is compatible with both of the
17340
binary data formats that use binary subtyping, (though the specific
17341
numbering is incompatible with each other, and it is up to the user to
17342
translate between them).
17343
17344
[CBOR's RFC 7049](https://tools.ietf.org/html/rfc7049) describes this type
17345
as:
17346
> Major type 2: a byte string. The string's length in bytes is represented
17347
> following the rules for positive integers (major type 0).
17348
17349
[MessagePack's documentation on the bin type
17350
family](https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family)
17351
describes this type as:
17352
> Bin format family stores an byte array in 2, 3, or 5 bytes of extra bytes
17353
> in addition to the size of the byte array.
17354
17355
[BSON's specifications](http://bsonspec.org/spec.html) describe several
17356
binary types; however, this type is intended to represent the generic binary
17357
type which has the description:
17358
> Generic binary subtype - This is the most commonly used binary subtype and
17359
> should be the 'default' for drivers and tools.
17360
17361
None of these impose any limitations on the internal representation other
17362
than the basic unit of storage be some type of array whose parts are
17363
decomposable into bytes.
17364
17365
The default representation of this binary format is a
17366
`std::vector<std::uint8_t>`, which is a very common way to represent a byte
17367
array in modern C++.
17368
17369
#### Default type
17370
17371
The default values for @a BinaryType is `std::vector<std::uint8_t>`
17372
17373
#### Storage
17374
17375
Binary Arrays are stored as pointers in a @ref basic_json type. That is,
17376
for any access to array values, a pointer of the type `binary_t*` must be
17377
dereferenced.
17378
17379
#### Notes on subtypes
17380
17381
- CBOR
17382
- Binary values are represented as byte strings. No subtypes are
17383
supported and will be ignored when CBOR is written.
17384
- MessagePack
17385
- If a subtype is given and the binary array contains exactly 1, 2, 4, 8,
17386
or 16 elements, the fixext family (fixext1, fixext2, fixext4, fixext8)
17387
is used. For other sizes, the ext family (ext8, ext16, ext32) is used.
17388
The subtype is then added as singed 8-bit integer.
17389
- If no subtype is given, the bin family (bin8, bin16, bin32) is used.
17390
- BSON
17391
- If a subtype is given, it is used and added as unsigned 8-bit integer.
17392
- If no subtype is given, the generic binary subtype 0x00 is used.
17393
17394
@sa @ref binary -- create a binary array
17395
17396
@since version 3.8.0
17397
*/
17398
using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
17399
/// @}
17400
17401
private:
17402
17403
/// helper for exception-safe object creation
17404
template<typename T, typename... Args>
17405
JSON_HEDLEY_RETURNS_NON_NULL
17406
static T* create(Args&& ... args)
17407
{
17408
AllocatorType<T> alloc;
17409
using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
17410
17411
auto deleter = [&](T * object)
17412
{
17413
AllocatorTraits::deallocate(alloc, object, 1);
17414
};
17415
std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
17416
AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
17417
JSON_ASSERT(object != nullptr);
17418
return object.release();
17419
}
17420
17421
////////////////////////
17422
// JSON value storage //
17423
////////////////////////
17424
17425
/*!
17426
@brief a JSON value
17427
17428
The actual storage for a JSON value of the @ref basic_json class. This
17429
union combines the different storage types for the JSON value types
17430
defined in @ref value_t.
17431
17432
JSON type | value_t type | used type
17433
--------- | --------------- | ------------------------
17434
object | object | pointer to @ref object_t
17435
array | array | pointer to @ref array_t
17436
string | string | pointer to @ref string_t
17437
boolean | boolean | @ref boolean_t
17438
number | number_integer | @ref number_integer_t
17439
number | number_unsigned | @ref number_unsigned_t
17440
number | number_float | @ref number_float_t
17441
binary | binary | pointer to @ref binary_t
17442
null | null | *no value is stored*
17443
17444
@note Variable-length types (objects, arrays, and strings) are stored as
17445
pointers. The size of the union should not exceed 64 bits if the default
17446
value types are used.
17447
17448
@since version 1.0.0
17449
*/
17450
union json_value
17451
{
17452
/// object (stored with pointer to save storage)
17453
object_t* object;
17454
/// array (stored with pointer to save storage)
17455
array_t* array;
17456
/// string (stored with pointer to save storage)
17457
string_t* string;
17458
/// binary (stored with pointer to save storage)
17459
binary_t* binary;
17460
/// boolean
17461
boolean_t boolean;
17462
/// number (integer)
17463
number_integer_t number_integer;
17464
/// number (unsigned integer)
17465
number_unsigned_t number_unsigned;
17466
/// number (floating-point)
17467
number_float_t number_float;
17468
17469
/// default constructor (for null values)
17470
json_value() = default;
17471
/// constructor for booleans
17472
json_value(boolean_t v) noexcept : boolean(v) {}
17473
/// constructor for numbers (integer)
17474
json_value(number_integer_t v) noexcept : number_integer(v) {}
17475
/// constructor for numbers (unsigned)
17476
json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
17477
/// constructor for numbers (floating-point)
17478
json_value(number_float_t v) noexcept : number_float(v) {}
17479
/// constructor for empty values of a given type
17480
json_value(value_t t)
17481
{
17482
switch (t)
17483
{
17484
case value_t::object:
17485
{
17486
object = create<object_t>();
17487
break;
17488
}
17489
17490
case value_t::array:
17491
{
17492
array = create<array_t>();
17493
break;
17494
}
17495
17496
case value_t::string:
17497
{
17498
string = create<string_t>("");
17499
break;
17500
}
17501
17502
case value_t::binary:
17503
{
17504
binary = create<binary_t>();
17505
break;
17506
}
17507
17508
case value_t::boolean:
17509
{
17510
boolean = boolean_t(false);
17511
break;
17512
}
17513
17514
case value_t::number_integer:
17515
{
17516
number_integer = number_integer_t(0);
17517
break;
17518
}
17519
17520
case value_t::number_unsigned:
17521
{
17522
number_unsigned = number_unsigned_t(0);
17523
break;
17524
}
17525
17526
case value_t::number_float:
17527
{
17528
number_float = number_float_t(0.0);
17529
break;
17530
}
17531
17532
case value_t::null:
17533
{
17534
object = nullptr; // silence warning, see #821
17535
break;
17536
}
17537
17538
default:
17539
{
17540
object = nullptr; // silence warning, see #821
17541
if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
17542
{
17543
JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.9.1")); // LCOV_EXCL_LINE
17544
}
17545
break;
17546
}
17547
}
17548
}
17549
17550
/// constructor for strings
17551
json_value(const string_t& value)
17552
{
17553
string = create<string_t>(value);
17554
}
17555
17556
/// constructor for rvalue strings
17557
json_value(string_t&& value)
17558
{
17559
string = create<string_t>(std::move(value));
17560
}
17561
17562
/// constructor for objects
17563
json_value(const object_t& value)
17564
{
17565
object = create<object_t>(value);
17566
}
17567
17568
/// constructor for rvalue objects
17569
json_value(object_t&& value)
17570
{
17571
object = create<object_t>(std::move(value));
17572
}
17573
17574
/// constructor for arrays
17575
json_value(const array_t& value)
17576
{
17577
array = create<array_t>(value);
17578
}
17579
17580
/// constructor for rvalue arrays
17581
json_value(array_t&& value)
17582
{
17583
array = create<array_t>(std::move(value));
17584
}
17585
17586
/// constructor for binary arrays
17587
json_value(const typename binary_t::container_type& value)
17588
{
17589
binary = create<binary_t>(value);
17590
}
17591
17592
/// constructor for rvalue binary arrays
17593
json_value(typename binary_t::container_type&& value)
17594
{
17595
binary = create<binary_t>(std::move(value));
17596
}
17597
17598
/// constructor for binary arrays (internal type)
17599
json_value(const binary_t& value)
17600
{
17601
binary = create<binary_t>(value);
17602
}
17603
17604
/// constructor for rvalue binary arrays (internal type)
17605
json_value(binary_t&& value)
17606
{
17607
binary = create<binary_t>(std::move(value));
17608
}
17609
17610
void destroy(value_t t) noexcept
17611
{
17612
// flatten the current json_value to a heap-allocated stack
17613
std::vector<basic_json> stack;
17614
17615
// move the top-level items to stack
17616
if (t == value_t::array)
17617
{
17618
stack.reserve(array->size());
17619
std::move(array->begin(), array->end(), std::back_inserter(stack));
17620
}
17621
else if (t == value_t::object)
17622
{
17623
stack.reserve(object->size());
17624
for (auto&& it : *object)
17625
{
17626
stack.push_back(std::move(it.second));
17627
}
17628
}
17629
17630
while (!stack.empty())
17631
{
17632
// move the last item to local variable to be processed
17633
basic_json current_item(std::move(stack.back()));
17634
stack.pop_back();
17635
17636
// if current_item is array/object, move
17637
// its children to the stack to be processed later
17638
if (current_item.is_array())
17639
{
17640
std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(),
17641
std::back_inserter(stack));
17642
17643
current_item.m_value.array->clear();
17644
}
17645
else if (current_item.is_object())
17646
{
17647
for (auto&& it : *current_item.m_value.object)
17648
{
17649
stack.push_back(std::move(it.second));
17650
}
17651
17652
current_item.m_value.object->clear();
17653
}
17654
17655
// it's now safe that current_item get destructed
17656
// since it doesn't have any children
17657
}
17658
17659
switch (t)
17660
{
17661
case value_t::object:
17662
{
17663
AllocatorType<object_t> alloc;
17664
std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
17665
std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
17666
break;
17667
}
17668
17669
case value_t::array:
17670
{
17671
AllocatorType<array_t> alloc;
17672
std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
17673
std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
17674
break;
17675
}
17676
17677
case value_t::string:
17678
{
17679
AllocatorType<string_t> alloc;
17680
std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
17681
std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
17682
break;
17683
}
17684
17685
case value_t::binary:
17686
{
17687
AllocatorType<binary_t> alloc;
17688
std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
17689
std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
17690
break;
17691
}
17692
17693
default:
17694
{
17695
break;
17696
}
17697
}
17698
}
17699
};
17700
17701
/*!
17702
@brief checks the class invariants
17703
17704
This function asserts the class invariants. It needs to be called at the
17705
end of every constructor to make sure that created objects respect the
17706
invariant. Furthermore, it has to be called each time the type of a JSON
17707
value is changed, because the invariant expresses a relationship between
17708
@a m_type and @a m_value.
17709
*/
17710
void assert_invariant() const noexcept
17711
{
17712
JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
17713
JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
17714
JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
17715
JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
17716
}
17717
17718
public:
17719
//////////////////////////
17720
// JSON parser callback //
17721
//////////////////////////
17722
17723
/*!
17724
@brief parser event types
17725
17726
The parser callback distinguishes the following events:
17727
- `object_start`: the parser read `{` and started to process a JSON object
17728
- `key`: the parser read a key of a value in an object
17729
- `object_end`: the parser read `}` and finished processing a JSON object
17730
- `array_start`: the parser read `[` and started to process a JSON array
17731
- `array_end`: the parser read `]` and finished processing a JSON array
17732
- `value`: the parser finished reading a JSON value
17733
17734
@image html callback_events.png "Example when certain parse events are triggered"
17735
17736
@sa @ref parser_callback_t for more information and examples
17737
*/
17738
using parse_event_t = detail::parse_event_t;
17739
17740
/*!
17741
@brief per-element parser callback type
17742
17743
With a parser callback function, the result of parsing a JSON text can be
17744
influenced. When passed to @ref parse, it is called on certain events
17745
(passed as @ref parse_event_t via parameter @a event) with a set recursion
17746
depth @a depth and context JSON value @a parsed. The return value of the
17747
callback function is a boolean indicating whether the element that emitted
17748
the callback shall be kept or not.
17749
17750
We distinguish six scenarios (determined by the event type) in which the
17751
callback function can be called. The following table describes the values
17752
of the parameters @a depth, @a event, and @a parsed.
17753
17754
parameter @a event | description | parameter @a depth | parameter @a parsed
17755
------------------ | ----------- | ------------------ | -------------------
17756
parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded
17757
parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key
17758
parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object
17759
parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded
17760
parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
17761
parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
17762
17763
@image html callback_events.png "Example when certain parse events are triggered"
17764
17765
Discarding a value (i.e., returning `false`) has different effects
17766
depending on the context in which function was called:
17767
17768
- Discarded values in structured types are skipped. That is, the parser
17769
will behave as if the discarded value was never read.
17770
- In case a value outside a structured type is skipped, it is replaced
17771
with `null`. This case happens if the top-level element is skipped.
17772
17773
@param[in] depth the depth of the recursion during parsing
17774
17775
@param[in] event an event of type parse_event_t indicating the context in
17776
the callback function has been called
17777
17778
@param[in,out] parsed the current intermediate parse result; note that
17779
writing to this value has no effect for parse_event_t::key events
17780
17781
@return Whether the JSON value which called the function during parsing
17782
should be kept (`true`) or not (`false`). In the latter case, it is either
17783
skipped completely or replaced by an empty discarded object.
17784
17785
@sa @ref parse for examples
17786
17787
@since version 1.0.0
17788
*/
17789
using parser_callback_t = detail::parser_callback_t<basic_json>;
17790
17791
//////////////////
17792
// constructors //
17793
//////////////////
17794
17795
/// @name constructors and destructors
17796
/// Constructors of class @ref basic_json, copy/move constructor, copy
17797
/// assignment, static functions creating objects, and the destructor.
17798
/// @{
17799
17800
/*!
17801
@brief create an empty value with a given type
17802
17803
Create an empty JSON value with a given type. The value will be default
17804
initialized with an empty value which depends on the type:
17805
17806
Value type | initial value
17807
----------- | -------------
17808
null | `null`
17809
boolean | `false`
17810
string | `""`
17811
number | `0`
17812
object | `{}`
17813
array | `[]`
17814
binary | empty array
17815
17816
@param[in] v the type of the value to create
17817
17818
@complexity Constant.
17819
17820
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
17821
changes to any JSON value.
17822
17823
@liveexample{The following code shows the constructor for different @ref
17824
value_t values,basic_json__value_t}
17825
17826
@sa @ref clear() -- restores the postcondition of this constructor
17827
17828
@since version 1.0.0
17829
*/
17830
basic_json(const value_t v)
17831
: m_type(v), m_value(v)
17832
{
17833
assert_invariant();
17834
}
17835
17836
/*!
17837
@brief create a null object
17838
17839
Create a `null` JSON value. It either takes a null pointer as parameter
17840
(explicitly creating `null`) or no parameter (implicitly creating `null`).
17841
The passed null pointer itself is not read -- it is only used to choose
17842
the right constructor.
17843
17844
@complexity Constant.
17845
17846
@exceptionsafety No-throw guarantee: this constructor never throws
17847
exceptions.
17848
17849
@liveexample{The following code shows the constructor with and without a
17850
null pointer parameter.,basic_json__nullptr_t}
17851
17852
@since version 1.0.0
17853
*/
17854
basic_json(std::nullptr_t = nullptr) noexcept
17855
: basic_json(value_t::null)
17856
{
17857
assert_invariant();
17858
}
17859
17860
/*!
17861
@brief create a JSON value
17862
17863
This is a "catch all" constructor for all compatible JSON types; that is,
17864
types for which a `to_json()` method exists. The constructor forwards the
17865
parameter @a val to that method (to `json_serializer<U>::to_json` method
17866
with `U = uncvref_t<CompatibleType>`, to be exact).
17867
17868
Template type @a CompatibleType includes, but is not limited to, the
17869
following types:
17870
- **arrays**: @ref array_t and all kinds of compatible containers such as
17871
`std::vector`, `std::deque`, `std::list`, `std::forward_list`,
17872
`std::array`, `std::valarray`, `std::set`, `std::unordered_set`,
17873
`std::multiset`, and `std::unordered_multiset` with a `value_type` from
17874
which a @ref basic_json value can be constructed.
17875
- **objects**: @ref object_t and all kinds of compatible associative
17876
containers such as `std::map`, `std::unordered_map`, `std::multimap`,
17877
and `std::unordered_multimap` with a `key_type` compatible to
17878
@ref string_t and a `value_type` from which a @ref basic_json value can
17879
be constructed.
17880
- **strings**: @ref string_t, string literals, and all compatible string
17881
containers can be used.
17882
- **numbers**: @ref number_integer_t, @ref number_unsigned_t,
17883
@ref number_float_t, and all convertible number types such as `int`,
17884
`size_t`, `int64_t`, `float` or `double` can be used.
17885
- **boolean**: @ref boolean_t / `bool` can be used.
17886
- **binary**: @ref binary_t / `std::vector<uint8_t>` may be used,
17887
unfortunately because string literals cannot be distinguished from binary
17888
character arrays by the C++ type system, all types compatible with `const
17889
char*` will be directed to the string constructor instead. This is both
17890
for backwards compatibility, and due to the fact that a binary type is not
17891
a standard JSON type.
17892
17893
See the examples below.
17894
17895
@tparam CompatibleType a type such that:
17896
- @a CompatibleType is not derived from `std::istream`,
17897
- @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move
17898
constructors),
17899
- @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments)
17900
- @a CompatibleType is not a @ref basic_json nested type (e.g.,
17901
@ref json_pointer, @ref iterator, etc ...)
17902
- @ref @ref json_serializer<U> has a
17903
`to_json(basic_json_t&, CompatibleType&&)` method
17904
17905
@tparam U = `uncvref_t<CompatibleType>`
17906
17907
@param[in] val the value to be forwarded to the respective constructor
17908
17909
@complexity Usually linear in the size of the passed @a val, also
17910
depending on the implementation of the called `to_json()`
17911
method.
17912
17913
@exceptionsafety Depends on the called constructor. For types directly
17914
supported by the library (i.e., all types for which no `to_json()` function
17915
was provided), strong guarantee holds: if an exception is thrown, there are
17916
no changes to any JSON value.
17917
17918
@liveexample{The following code shows the constructor with several
17919
compatible types.,basic_json__CompatibleType}
17920
17921
@since version 2.1.0
17922
*/
17923
template < typename CompatibleType,
17924
typename U = detail::uncvref_t<CompatibleType>,
17925
detail::enable_if_t <
17926
!detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
17927
basic_json(CompatibleType && val) noexcept(noexcept(
17928
JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
17929
std::forward<CompatibleType>(val))))
17930
{
17931
JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
17932
assert_invariant();
17933
}
17934
17935
/*!
17936
@brief create a JSON value from an existing one
17937
17938
This is a constructor for existing @ref basic_json types.
17939
It does not hijack copy/move constructors, since the parameter has different
17940
template arguments than the current ones.
17941
17942
The constructor tries to convert the internal @ref m_value of the parameter.
17943
17944
@tparam BasicJsonType a type such that:
17945
- @a BasicJsonType is a @ref basic_json type.
17946
- @a BasicJsonType has different template arguments than @ref basic_json_t.
17947
17948
@param[in] val the @ref basic_json value to be converted.
17949
17950
@complexity Usually linear in the size of the passed @a val, also
17951
depending on the implementation of the called `to_json()`
17952
method.
17953
17954
@exceptionsafety Depends on the called constructor. For types directly
17955
supported by the library (i.e., all types for which no `to_json()` function
17956
was provided), strong guarantee holds: if an exception is thrown, there are
17957
no changes to any JSON value.
17958
17959
@since version 3.2.0
17960
*/
17961
template < typename BasicJsonType,
17962
detail::enable_if_t <
17963
detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
17964
basic_json(const BasicJsonType& val)
17965
{
17966
using other_boolean_t = typename BasicJsonType::boolean_t;
17967
using other_number_float_t = typename BasicJsonType::number_float_t;
17968
using other_number_integer_t = typename BasicJsonType::number_integer_t;
17969
using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
17970
using other_string_t = typename BasicJsonType::string_t;
17971
using other_object_t = typename BasicJsonType::object_t;
17972
using other_array_t = typename BasicJsonType::array_t;
17973
using other_binary_t = typename BasicJsonType::binary_t;
17974
17975
switch (val.type())
17976
{
17977
case value_t::boolean:
17978
JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
17979
break;
17980
case value_t::number_float:
17981
JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
17982
break;
17983
case value_t::number_integer:
17984
JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
17985
break;
17986
case value_t::number_unsigned:
17987
JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
17988
break;
17989
case value_t::string:
17990
JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
17991
break;
17992
case value_t::object:
17993
JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
17994
break;
17995
case value_t::array:
17996
JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
17997
break;
17998
case value_t::binary:
17999
JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
18000
break;
18001
case value_t::null:
18002
*this = nullptr;
18003
break;
18004
case value_t::discarded:
18005
m_type = value_t::discarded;
18006
break;
18007
default: // LCOV_EXCL_LINE
18008
JSON_ASSERT(false); // LCOV_EXCL_LINE
18009
}
18010
assert_invariant();
18011
}
18012
18013
/*!
18014
@brief create a container (array or object) from an initializer list
18015
18016
Creates a JSON value of type array or object from the passed initializer
18017
list @a init. In case @a type_deduction is `true` (default), the type of
18018
the JSON value to be created is deducted from the initializer list @a init
18019
according to the following rules:
18020
18021
1. If the list is empty, an empty JSON object value `{}` is created.
18022
2. If the list consists of pairs whose first element is a string, a JSON
18023
object value is created where the first elements of the pairs are
18024
treated as keys and the second elements are as values.
18025
3. In all other cases, an array is created.
18026
18027
The rules aim to create the best fit between a C++ initializer list and
18028
JSON values. The rationale is as follows:
18029
18030
1. The empty initializer list is written as `{}` which is exactly an empty
18031
JSON object.
18032
2. C++ has no way of describing mapped types other than to list a list of
18033
pairs. As JSON requires that keys must be of type string, rule 2 is the
18034
weakest constraint one can pose on initializer lists to interpret them
18035
as an object.
18036
3. In all other cases, the initializer list could not be interpreted as
18037
JSON object type, so interpreting it as JSON array type is safe.
18038
18039
With the rules described above, the following JSON values cannot be
18040
expressed by an initializer list:
18041
18042
- the empty array (`[]`): use @ref array(initializer_list_t)
18043
with an empty initializer list in this case
18044
- arrays whose elements satisfy rule 2: use @ref
18045
array(initializer_list_t) with the same initializer list
18046
in this case
18047
18048
@note When used without parentheses around an empty initializer list, @ref
18049
basic_json() is called instead of this function, yielding the JSON null
18050
value.
18051
18052
@param[in] init initializer list with JSON values
18053
18054
@param[in] type_deduction internal parameter; when set to `true`, the type
18055
of the JSON value is deducted from the initializer list @a init; when set
18056
to `false`, the type provided via @a manual_type is forced. This mode is
18057
used by the functions @ref array(initializer_list_t) and
18058
@ref object(initializer_list_t).
18059
18060
@param[in] manual_type internal parameter; when @a type_deduction is set
18061
to `false`, the created JSON value will use the provided type (only @ref
18062
value_t::array and @ref value_t::object are valid); when @a type_deduction
18063
is set to `true`, this parameter has no effect
18064
18065
@throw type_error.301 if @a type_deduction is `false`, @a manual_type is
18066
`value_t::object`, but @a init contains an element which is not a pair
18067
whose first element is a string. In this case, the constructor could not
18068
create an object. If @a type_deduction would have be `true`, an array
18069
would have been created. See @ref object(initializer_list_t)
18070
for an example.
18071
18072
@complexity Linear in the size of the initializer list @a init.
18073
18074
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
18075
changes to any JSON value.
18076
18077
@liveexample{The example below shows how JSON values are created from
18078
initializer lists.,basic_json__list_init_t}
18079
18080
@sa @ref array(initializer_list_t) -- create a JSON array
18081
value from an initializer list
18082
@sa @ref object(initializer_list_t) -- create a JSON object
18083
value from an initializer list
18084
18085
@since version 1.0.0
18086
*/
18087
basic_json(initializer_list_t init,
18088
bool type_deduction = true,
18089
value_t manual_type = value_t::array)
18090
{
18091
// check if each element is an array with two elements whose first
18092
// element is a string
18093
bool is_an_object = std::all_of(init.begin(), init.end(),
18094
[](const detail::json_ref<basic_json>& element_ref)
18095
{
18096
return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
18097
});
18098
18099
// adjust type if type deduction is not wanted
18100
if (!type_deduction)
18101
{
18102
// if array is wanted, do not create an object though possible
18103
if (manual_type == value_t::array)
18104
{
18105
is_an_object = false;
18106
}
18107
18108
// if object is wanted but impossible, throw an exception
18109
if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
18110
{
18111
JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
18112
}
18113
}
18114
18115
if (is_an_object)
18116
{
18117
// the initializer list is a list of pairs -> create object
18118
m_type = value_t::object;
18119
m_value = value_t::object;
18120
18121
std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
18122
{
18123
auto element = element_ref.moved_or_copied();
18124
m_value.object->emplace(
18125
std::move(*((*element.m_value.array)[0].m_value.string)),
18126
std::move((*element.m_value.array)[1]));
18127
});
18128
}
18129
else
18130
{
18131
// the initializer list describes an array -> create array
18132
m_type = value_t::array;
18133
m_value.array = create<array_t>(init.begin(), init.end());
18134
}
18135
18136
assert_invariant();
18137
}
18138
18139
/*!
18140
@brief explicitly create a binary array (without subtype)
18141
18142
Creates a JSON binary array value from a given binary container. Binary
18143
values are part of various binary formats, such as CBOR, MessagePack, and
18144
BSON. This constructor is used to create a value for serialization to those
18145
formats.
18146
18147
@note Note, this function exists because of the difficulty in correctly
18148
specifying the correct template overload in the standard value ctor, as both
18149
JSON arrays and JSON binary arrays are backed with some form of a
18150
`std::vector`. Because JSON binary arrays are a non-standard extension it
18151
was decided that it would be best to prevent automatic initialization of a
18152
binary array type, for backwards compatibility and so it does not happen on
18153
accident.
18154
18155
@param[in] init container containing bytes to use as binary type
18156
18157
@return JSON binary array value
18158
18159
@complexity Linear in the size of @a init.
18160
18161
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
18162
changes to any JSON value.
18163
18164
@since version 3.8.0
18165
*/
18166
JSON_HEDLEY_WARN_UNUSED_RESULT
18167
static basic_json binary(const typename binary_t::container_type& init)
18168
{
18169
auto res = basic_json();
18170
res.m_type = value_t::binary;
18171
res.m_value = init;
18172
return res;
18173
}
18174
18175
/*!
18176
@brief explicitly create a binary array (with subtype)
18177
18178
Creates a JSON binary array value from a given binary container. Binary
18179
values are part of various binary formats, such as CBOR, MessagePack, and
18180
BSON. This constructor is used to create a value for serialization to those
18181
formats.
18182
18183
@note Note, this function exists because of the difficulty in correctly
18184
specifying the correct template overload in the standard value ctor, as both
18185
JSON arrays and JSON binary arrays are backed with some form of a
18186
`std::vector`. Because JSON binary arrays are a non-standard extension it
18187
was decided that it would be best to prevent automatic initialization of a
18188
binary array type, for backwards compatibility and so it does not happen on
18189
accident.
18190
18191
@param[in] init container containing bytes to use as binary type
18192
@param[in] subtype subtype to use in MessagePack and BSON
18193
18194
@return JSON binary array value
18195
18196
@complexity Linear in the size of @a init.
18197
18198
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
18199
changes to any JSON value.
18200
18201
@since version 3.8.0
18202
*/
18203
JSON_HEDLEY_WARN_UNUSED_RESULT
18204
static basic_json binary(const typename binary_t::container_type& init, std::uint8_t subtype)
18205
{
18206
auto res = basic_json();
18207
res.m_type = value_t::binary;
18208
res.m_value = binary_t(init, subtype);
18209
return res;
18210
}
18211
18212
/// @copydoc binary(const typename binary_t::container_type&)
18213
JSON_HEDLEY_WARN_UNUSED_RESULT
18214
static basic_json binary(typename binary_t::container_type&& init)
18215
{
18216
auto res = basic_json();
18217
res.m_type = value_t::binary;
18218
res.m_value = std::move(init);
18219
return res;
18220
}
18221
18222
/// @copydoc binary(const typename binary_t::container_type&, std::uint8_t)
18223
JSON_HEDLEY_WARN_UNUSED_RESULT
18224
static basic_json binary(typename binary_t::container_type&& init, std::uint8_t subtype)
18225
{
18226
auto res = basic_json();
18227
res.m_type = value_t::binary;
18228
res.m_value = binary_t(std::move(init), subtype);
18229
return res;
18230
}
18231
18232
/*!
18233
@brief explicitly create an array from an initializer list
18234
18235
Creates a JSON array value from a given initializer list. That is, given a
18236
list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the
18237
initializer list is empty, the empty array `[]` is created.
18238
18239
@note This function is only needed to express two edge cases that cannot
18240
be realized with the initializer list constructor (@ref
18241
basic_json(initializer_list_t, bool, value_t)). These cases
18242
are:
18243
1. creating an array whose elements are all pairs whose first element is a
18244
string -- in this case, the initializer list constructor would create an
18245
object, taking the first elements as keys
18246
2. creating an empty array -- passing the empty initializer list to the
18247
initializer list constructor yields an empty object
18248
18249
@param[in] init initializer list with JSON values to create an array from
18250
(optional)
18251
18252
@return JSON array value
18253
18254
@complexity Linear in the size of @a init.
18255
18256
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
18257
changes to any JSON value.
18258
18259
@liveexample{The following code shows an example for the `array`
18260
function.,array}
18261
18262
@sa @ref basic_json(initializer_list_t, bool, value_t) --
18263
create a JSON value from an initializer list
18264
@sa @ref object(initializer_list_t) -- create a JSON object
18265
value from an initializer list
18266
18267
@since version 1.0.0
18268
*/
18269
JSON_HEDLEY_WARN_UNUSED_RESULT
18270
static basic_json array(initializer_list_t init = {})
18271
{
18272
return basic_json(init, false, value_t::array);
18273
}
18274
18275
/*!
18276
@brief explicitly create an object from an initializer list
18277
18278
Creates a JSON object value from a given initializer list. The initializer
18279
lists elements must be pairs, and their first elements must be strings. If
18280
the initializer list is empty, the empty object `{}` is created.
18281
18282
@note This function is only added for symmetry reasons. In contrast to the
18283
related function @ref array(initializer_list_t), there are
18284
no cases which can only be expressed by this function. That is, any
18285
initializer list @a init can also be passed to the initializer list
18286
constructor @ref basic_json(initializer_list_t, bool, value_t).
18287
18288
@param[in] init initializer list to create an object from (optional)
18289
18290
@return JSON object value
18291
18292
@throw type_error.301 if @a init is not a list of pairs whose first
18293
elements are strings. In this case, no object can be created. When such a
18294
value is passed to @ref basic_json(initializer_list_t, bool, value_t),
18295
an array would have been created from the passed initializer list @a init.
18296
See example below.
18297
18298
@complexity Linear in the size of @a init.
18299
18300
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
18301
changes to any JSON value.
18302
18303
@liveexample{The following code shows an example for the `object`
18304
function.,object}
18305
18306
@sa @ref basic_json(initializer_list_t, bool, value_t) --
18307
create a JSON value from an initializer list
18308
@sa @ref array(initializer_list_t) -- create a JSON array
18309
value from an initializer list
18310
18311
@since version 1.0.0
18312
*/
18313
JSON_HEDLEY_WARN_UNUSED_RESULT
18314
static basic_json object(initializer_list_t init = {})
18315
{
18316
return basic_json(init, false, value_t::object);
18317
}
18318
18319
/*!
18320
@brief construct an array with count copies of given value
18321
18322
Constructs a JSON array value by creating @a cnt copies of a passed value.
18323
In case @a cnt is `0`, an empty array is created.
18324
18325
@param[in] cnt the number of JSON copies of @a val to create
18326
@param[in] val the JSON value to copy
18327
18328
@post `std::distance(begin(),end()) == cnt` holds.
18329
18330
@complexity Linear in @a cnt.
18331
18332
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
18333
changes to any JSON value.
18334
18335
@liveexample{The following code shows examples for the @ref
18336
basic_json(size_type\, const basic_json&)
18337
constructor.,basic_json__size_type_basic_json}
18338
18339
@since version 1.0.0
18340
*/
18341
basic_json(size_type cnt, const basic_json& val)
18342
: m_type(value_t::array)
18343
{
18344
m_value.array = create<array_t>(cnt, val);
18345
assert_invariant();
18346
}
18347
18348
/*!
18349
@brief construct a JSON container given an iterator range
18350
18351
Constructs the JSON value with the contents of the range `[first, last)`.
18352
The semantics depends on the different types a JSON value can have:
18353
- In case of a null type, invalid_iterator.206 is thrown.
18354
- In case of other primitive types (number, boolean, or string), @a first
18355
must be `begin()` and @a last must be `end()`. In this case, the value is
18356
copied. Otherwise, invalid_iterator.204 is thrown.
18357
- In case of structured types (array, object), the constructor behaves as
18358
similar versions for `std::vector` or `std::map`; that is, a JSON array
18359
or object is constructed from the values in the range.
18360
18361
@tparam InputIT an input iterator type (@ref iterator or @ref
18362
const_iterator)
18363
18364
@param[in] first begin of the range to copy from (included)
18365
@param[in] last end of the range to copy from (excluded)
18366
18367
@pre Iterators @a first and @a last must be initialized. **This
18368
precondition is enforced with an assertion (see warning).** If
18369
assertions are switched off, a violation of this precondition yields
18370
undefined behavior.
18371
18372
@pre Range `[first, last)` is valid. Usually, this precondition cannot be
18373
checked efficiently. Only certain edge cases are detected; see the
18374
description of the exceptions below. A violation of this precondition
18375
yields undefined behavior.
18376
18377
@warning A precondition is enforced with a runtime assertion that will
18378
result in calling `std::abort` if this precondition is not met.
18379
Assertions can be disabled by defining `NDEBUG` at compile time.
18380
See https://en.cppreference.com/w/cpp/error/assert for more
18381
information.
18382
18383
@throw invalid_iterator.201 if iterators @a first and @a last are not
18384
compatible (i.e., do not belong to the same JSON value). In this case,
18385
the range `[first, last)` is undefined.
18386
@throw invalid_iterator.204 if iterators @a first and @a last belong to a
18387
primitive type (number, boolean, or string), but @a first does not point
18388
to the first element any more. In this case, the range `[first, last)` is
18389
undefined. See example code below.
18390
@throw invalid_iterator.206 if iterators @a first and @a last belong to a
18391
null value. In this case, the range `[first, last)` is undefined.
18392
18393
@complexity Linear in distance between @a first and @a last.
18394
18395
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
18396
changes to any JSON value.
18397
18398
@liveexample{The example below shows several ways to create JSON values by
18399
specifying a subrange with iterators.,basic_json__InputIt_InputIt}
18400
18401
@since version 1.0.0
18402
*/
18403
template < class InputIT, typename std::enable_if <
18404
std::is_same<InputIT, typename basic_json_t::iterator>::value ||
18405
std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
18406
basic_json(InputIT first, InputIT last)
18407
{
18408
JSON_ASSERT(first.m_object != nullptr);
18409
JSON_ASSERT(last.m_object != nullptr);
18410
18411
// make sure iterator fits the current value
18412
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
18413
{
18414
JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
18415
}
18416
18417
// copy type from first iterator
18418
m_type = first.m_object->m_type;
18419
18420
// check if iterator range is complete for primitive values
18421
switch (m_type)
18422
{
18423
case value_t::boolean:
18424
case value_t::number_float:
18425
case value_t::number_integer:
18426
case value_t::number_unsigned:
18427
case value_t::string:
18428
{
18429
if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
18430
|| !last.m_it.primitive_iterator.is_end()))
18431
{
18432
JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
18433
}
18434
break;
18435
}
18436
18437
default:
18438
break;
18439
}
18440
18441
switch (m_type)
18442
{
18443
case value_t::number_integer:
18444
{
18445
m_value.number_integer = first.m_object->m_value.number_integer;
18446
break;
18447
}
18448
18449
case value_t::number_unsigned:
18450
{
18451
m_value.number_unsigned = first.m_object->m_value.number_unsigned;
18452
break;
18453
}
18454
18455
case value_t::number_float:
18456
{
18457
m_value.number_float = first.m_object->m_value.number_float;
18458
break;
18459
}
18460
18461
case value_t::boolean:
18462
{
18463
m_value.boolean = first.m_object->m_value.boolean;
18464
break;
18465
}
18466
18467
case value_t::string:
18468
{
18469
m_value = *first.m_object->m_value.string;
18470
break;
18471
}
18472
18473
case value_t::object:
18474
{
18475
m_value.object = create<object_t>(first.m_it.object_iterator,
18476
last.m_it.object_iterator);
18477
break;
18478
}
18479
18480
case value_t::array:
18481
{
18482
m_value.array = create<array_t>(first.m_it.array_iterator,
18483
last.m_it.array_iterator);
18484
break;
18485
}
18486
18487
case value_t::binary:
18488
{
18489
m_value = *first.m_object->m_value.binary;
18490
break;
18491
}
18492
18493
default:
18494
JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
18495
std::string(first.m_object->type_name())));
18496
}
18497
18498
assert_invariant();
18499
}
18500
18501
18502
///////////////////////////////////////
18503
// other constructors and destructor //
18504
///////////////////////////////////////
18505
18506
template<typename JsonRef,
18507
detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
18508
std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
18509
basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
18510
18511
/*!
18512
@brief copy constructor
18513
18514
Creates a copy of a given JSON value.
18515
18516
@param[in] other the JSON value to copy
18517
18518
@post `*this == other`
18519
18520
@complexity Linear in the size of @a other.
18521
18522
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
18523
changes to any JSON value.
18524
18525
@requirement This function helps `basic_json` satisfying the
18526
[Container](https://en.cppreference.com/w/cpp/named_req/Container)
18527
requirements:
18528
- The complexity is linear.
18529
- As postcondition, it holds: `other == basic_json(other)`.
18530
18531
@liveexample{The following code shows an example for the copy
18532
constructor.,basic_json__basic_json}
18533
18534
@since version 1.0.0
18535
*/
18536
basic_json(const basic_json& other)
18537
: m_type(other.m_type)
18538
{
18539
// check of passed value is valid
18540
other.assert_invariant();
18541
18542
switch (m_type)
18543
{
18544
case value_t::object:
18545
{
18546
m_value = *other.m_value.object;
18547
break;
18548
}
18549
18550
case value_t::array:
18551
{
18552
m_value = *other.m_value.array;
18553
break;
18554
}
18555
18556
case value_t::string:
18557
{
18558
m_value = *other.m_value.string;
18559
break;
18560
}
18561
18562
case value_t::boolean:
18563
{
18564
m_value = other.m_value.boolean;
18565
break;
18566
}
18567
18568
case value_t::number_integer:
18569
{
18570
m_value = other.m_value.number_integer;
18571
break;
18572
}
18573
18574
case value_t::number_unsigned:
18575
{
18576
m_value = other.m_value.number_unsigned;
18577
break;
18578
}
18579
18580
case value_t::number_float:
18581
{
18582
m_value = other.m_value.number_float;
18583
break;
18584
}
18585
18586
case value_t::binary:
18587
{
18588
m_value = *other.m_value.binary;
18589
break;
18590
}
18591
18592
default:
18593
break;
18594
}
18595
18596
assert_invariant();
18597
}
18598
18599
/*!
18600
@brief move constructor
18601
18602
Move constructor. Constructs a JSON value with the contents of the given
18603
value @a other using move semantics. It "steals" the resources from @a
18604
other and leaves it as JSON null value.
18605
18606
@param[in,out] other value to move to this object
18607
18608
@post `*this` has the same value as @a other before the call.
18609
@post @a other is a JSON null value.
18610
18611
@complexity Constant.
18612
18613
@exceptionsafety No-throw guarantee: this constructor never throws
18614
exceptions.
18615
18616
@requirement This function helps `basic_json` satisfying the
18617
[MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible)
18618
requirements.
18619
18620
@liveexample{The code below shows the move constructor explicitly called
18621
via std::move.,basic_json__moveconstructor}
18622
18623
@since version 1.0.0
18624
*/
18625
basic_json(basic_json&& other) noexcept
18626
: m_type(std::move(other.m_type)),
18627
m_value(std::move(other.m_value))
18628
{
18629
// check that passed value is valid
18630
other.assert_invariant();
18631
18632
// invalidate payload
18633
other.m_type = value_t::null;
18634
other.m_value = {};
18635
18636
assert_invariant();
18637
}
18638
18639
/*!
18640
@brief copy assignment
18641
18642
Copy assignment operator. Copies a JSON value via the "copy and swap"
18643
strategy: It is expressed in terms of the copy constructor, destructor,
18644
and the `swap()` member function.
18645
18646
@param[in] other value to copy from
18647
18648
@complexity Linear.
18649
18650
@requirement This function helps `basic_json` satisfying the
18651
[Container](https://en.cppreference.com/w/cpp/named_req/Container)
18652
requirements:
18653
- The complexity is linear.
18654
18655
@liveexample{The code below shows and example for the copy assignment. It
18656
creates a copy of value `a` which is then swapped with `b`. Finally\, the
18657
copy of `a` (which is the null value after the swap) is
18658
destroyed.,basic_json__copyassignment}
18659
18660
@since version 1.0.0
18661
*/
18662
basic_json& operator=(basic_json other) noexcept (
18663
std::is_nothrow_move_constructible<value_t>::value&&
18664
std::is_nothrow_move_assignable<value_t>::value&&
18665
std::is_nothrow_move_constructible<json_value>::value&&
18666
std::is_nothrow_move_assignable<json_value>::value
18667
)
18668
{
18669
// check that passed value is valid
18670
other.assert_invariant();
18671
18672
using std::swap;
18673
swap(m_type, other.m_type);
18674
swap(m_value, other.m_value);
18675
18676
assert_invariant();
18677
return *this;
18678
}
18679
18680
/*!
18681
@brief destructor
18682
18683
Destroys the JSON value and frees all allocated memory.
18684
18685
@complexity Linear.
18686
18687
@requirement This function helps `basic_json` satisfying the
18688
[Container](https://en.cppreference.com/w/cpp/named_req/Container)
18689
requirements:
18690
- The complexity is linear.
18691
- All stored elements are destroyed and all memory is freed.
18692
18693
@since version 1.0.0
18694
*/
18695
~basic_json() noexcept
18696
{
18697
assert_invariant();
18698
m_value.destroy(m_type);
18699
}
18700
18701
/// @}
18702
18703
public:
18704
///////////////////////
18705
// object inspection //
18706
///////////////////////
18707
18708
/// @name object inspection
18709
/// Functions to inspect the type of a JSON value.
18710
/// @{
18711
18712
/*!
18713
@brief serialization
18714
18715
Serialization function for JSON values. The function tries to mimic
18716
Python's `json.dumps()` function, and currently supports its @a indent
18717
and @a ensure_ascii parameters.
18718
18719
@param[in] indent If indent is nonnegative, then array elements and object
18720
members will be pretty-printed with that indent level. An indent level of
18721
`0` will only insert newlines. `-1` (the default) selects the most compact
18722
representation.
18723
@param[in] indent_char The character to use for indentation if @a indent is
18724
greater than `0`. The default is ` ` (space).
18725
@param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
18726
in the output are escaped with `\uXXXX` sequences, and the result consists
18727
of ASCII characters only.
18728
@param[in] error_handler how to react on decoding errors; there are three
18729
possible values: `strict` (throws and exception in case a decoding error
18730
occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD),
18731
and `ignore` (ignore invalid UTF-8 sequences during serialization; all
18732
bytes are copied to the output unchanged).
18733
18734
@return string containing the serialization of the JSON value
18735
18736
@throw type_error.316 if a string stored inside the JSON value is not
18737
UTF-8 encoded and @a error_handler is set to strict
18738
18739
@note Binary values are serialized as object containing two keys:
18740
- "bytes": an array of bytes as integers
18741
- "subtype": the subtype as integer or "null" if the binary has no subtype
18742
18743
@complexity Linear.
18744
18745
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
18746
changes in the JSON value.
18747
18748
@liveexample{The following example shows the effect of different @a indent\,
18749
@a indent_char\, and @a ensure_ascii parameters to the result of the
18750
serialization.,dump}
18751
18752
@see https://docs.python.org/2/library/json.html#json.dump
18753
18754
@since version 1.0.0; indentation character @a indent_char, option
18755
@a ensure_ascii and exceptions added in version 3.0.0; error
18756
handlers added in version 3.4.0; serialization of binary values added
18757
in version 3.8.0.
18758
*/
18759
string_t dump(const int indent = -1,
18760
const char indent_char = ' ',
18761
const bool ensure_ascii = false,
18762
const error_handler_t error_handler = error_handler_t::strict) const
18763
{
18764
string_t result;
18765
serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
18766
18767
if (indent >= 0)
18768
{
18769
s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
18770
}
18771
else
18772
{
18773
s.dump(*this, false, ensure_ascii, 0);
18774
}
18775
18776
return result;
18777
}
18778
18779
/*!
18780
@brief return the type of the JSON value (explicit)
18781
18782
Return the type of the JSON value as a value from the @ref value_t
18783
enumeration.
18784
18785
@return the type of the JSON value
18786
Value type | return value
18787
------------------------- | -------------------------
18788
null | value_t::null
18789
boolean | value_t::boolean
18790
string | value_t::string
18791
number (integer) | value_t::number_integer
18792
number (unsigned integer) | value_t::number_unsigned
18793
number (floating-point) | value_t::number_float
18794
object | value_t::object
18795
array | value_t::array
18796
binary | value_t::binary
18797
discarded | value_t::discarded
18798
18799
@complexity Constant.
18800
18801
@exceptionsafety No-throw guarantee: this member function never throws
18802
exceptions.
18803
18804
@liveexample{The following code exemplifies `type()` for all JSON
18805
types.,type}
18806
18807
@sa @ref operator value_t() -- return the type of the JSON value (implicit)
18808
@sa @ref type_name() -- return the type as string
18809
18810
@since version 1.0.0
18811
*/
18812
constexpr value_t type() const noexcept
18813
{
18814
return m_type;
18815
}
18816
18817
/*!
18818
@brief return whether type is primitive
18819
18820
This function returns true if and only if the JSON type is primitive
18821
(string, number, boolean, or null).
18822
18823
@return `true` if type is primitive (string, number, boolean, or null),
18824
`false` otherwise.
18825
18826
@complexity Constant.
18827
18828
@exceptionsafety No-throw guarantee: this member function never throws
18829
exceptions.
18830
18831
@liveexample{The following code exemplifies `is_primitive()` for all JSON
18832
types.,is_primitive}
18833
18834
@sa @ref is_structured() -- returns whether JSON value is structured
18835
@sa @ref is_null() -- returns whether JSON value is `null`
18836
@sa @ref is_string() -- returns whether JSON value is a string
18837
@sa @ref is_boolean() -- returns whether JSON value is a boolean
18838
@sa @ref is_number() -- returns whether JSON value is a number
18839
@sa @ref is_binary() -- returns whether JSON value is a binary array
18840
18841
@since version 1.0.0
18842
*/
18843
constexpr bool is_primitive() const noexcept
18844
{
18845
return is_null() || is_string() || is_boolean() || is_number() || is_binary();
18846
}
18847
18848
/*!
18849
@brief return whether type is structured
18850
18851
This function returns true if and only if the JSON type is structured
18852
(array or object).
18853
18854
@return `true` if type is structured (array or object), `false` otherwise.
18855
18856
@complexity Constant.
18857
18858
@exceptionsafety No-throw guarantee: this member function never throws
18859
exceptions.
18860
18861
@liveexample{The following code exemplifies `is_structured()` for all JSON
18862
types.,is_structured}
18863
18864
@sa @ref is_primitive() -- returns whether value is primitive
18865
@sa @ref is_array() -- returns whether value is an array
18866
@sa @ref is_object() -- returns whether value is an object
18867
18868
@since version 1.0.0
18869
*/
18870
constexpr bool is_structured() const noexcept
18871
{
18872
return is_array() || is_object();
18873
}
18874
18875
/*!
18876
@brief return whether value is null
18877
18878
This function returns true if and only if the JSON value is null.
18879
18880
@return `true` if type is null, `false` otherwise.
18881
18882
@complexity Constant.
18883
18884
@exceptionsafety No-throw guarantee: this member function never throws
18885
exceptions.
18886
18887
@liveexample{The following code exemplifies `is_null()` for all JSON
18888
types.,is_null}
18889
18890
@since version 1.0.0
18891
*/
18892
constexpr bool is_null() const noexcept
18893
{
18894
return m_type == value_t::null;
18895
}
18896
18897
/*!
18898
@brief return whether value is a boolean
18899
18900
This function returns true if and only if the JSON value is a boolean.
18901
18902
@return `true` if type is boolean, `false` otherwise.
18903
18904
@complexity Constant.
18905
18906
@exceptionsafety No-throw guarantee: this member function never throws
18907
exceptions.
18908
18909
@liveexample{The following code exemplifies `is_boolean()` for all JSON
18910
types.,is_boolean}
18911
18912
@since version 1.0.0
18913
*/
18914
constexpr bool is_boolean() const noexcept
18915
{
18916
return m_type == value_t::boolean;
18917
}
18918
18919
/*!
18920
@brief return whether value is a number
18921
18922
This function returns true if and only if the JSON value is a number. This
18923
includes both integer (signed and unsigned) and floating-point values.
18924
18925
@return `true` if type is number (regardless whether integer, unsigned
18926
integer or floating-type), `false` otherwise.
18927
18928
@complexity Constant.
18929
18930
@exceptionsafety No-throw guarantee: this member function never throws
18931
exceptions.
18932
18933
@liveexample{The following code exemplifies `is_number()` for all JSON
18934
types.,is_number}
18935
18936
@sa @ref is_number_integer() -- check if value is an integer or unsigned
18937
integer number
18938
@sa @ref is_number_unsigned() -- check if value is an unsigned integer
18939
number
18940
@sa @ref is_number_float() -- check if value is a floating-point number
18941
18942
@since version 1.0.0
18943
*/
18944
constexpr bool is_number() const noexcept
18945
{
18946
return is_number_integer() || is_number_float();
18947
}
18948
18949
/*!
18950
@brief return whether value is an integer number
18951
18952
This function returns true if and only if the JSON value is a signed or
18953
unsigned integer number. This excludes floating-point values.
18954
18955
@return `true` if type is an integer or unsigned integer number, `false`
18956
otherwise.
18957
18958
@complexity Constant.
18959
18960
@exceptionsafety No-throw guarantee: this member function never throws
18961
exceptions.
18962
18963
@liveexample{The following code exemplifies `is_number_integer()` for all
18964
JSON types.,is_number_integer}
18965
18966
@sa @ref is_number() -- check if value is a number
18967
@sa @ref is_number_unsigned() -- check if value is an unsigned integer
18968
number
18969
@sa @ref is_number_float() -- check if value is a floating-point number
18970
18971
@since version 1.0.0
18972
*/
18973
constexpr bool is_number_integer() const noexcept
18974
{
18975
return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
18976
}
18977
18978
/*!
18979
@brief return whether value is an unsigned integer number
18980
18981
This function returns true if and only if the JSON value is an unsigned
18982
integer number. This excludes floating-point and signed integer values.
18983
18984
@return `true` if type is an unsigned integer number, `false` otherwise.
18985
18986
@complexity Constant.
18987
18988
@exceptionsafety No-throw guarantee: this member function never throws
18989
exceptions.
18990
18991
@liveexample{The following code exemplifies `is_number_unsigned()` for all
18992
JSON types.,is_number_unsigned}
18993
18994
@sa @ref is_number() -- check if value is a number
18995
@sa @ref is_number_integer() -- check if value is an integer or unsigned
18996
integer number
18997
@sa @ref is_number_float() -- check if value is a floating-point number
18998
18999
@since version 2.0.0
19000
*/
19001
constexpr bool is_number_unsigned() const noexcept
19002
{
19003
return m_type == value_t::number_unsigned;
19004
}
19005
19006
/*!
19007
@brief return whether value is a floating-point number
19008
19009
This function returns true if and only if the JSON value is a
19010
floating-point number. This excludes signed and unsigned integer values.
19011
19012
@return `true` if type is a floating-point number, `false` otherwise.
19013
19014
@complexity Constant.
19015
19016
@exceptionsafety No-throw guarantee: this member function never throws
19017
exceptions.
19018
19019
@liveexample{The following code exemplifies `is_number_float()` for all
19020
JSON types.,is_number_float}
19021
19022
@sa @ref is_number() -- check if value is number
19023
@sa @ref is_number_integer() -- check if value is an integer number
19024
@sa @ref is_number_unsigned() -- check if value is an unsigned integer
19025
number
19026
19027
@since version 1.0.0
19028
*/
19029
constexpr bool is_number_float() const noexcept
19030
{
19031
return m_type == value_t::number_float;
19032
}
19033
19034
/*!
19035
@brief return whether value is an object
19036
19037
This function returns true if and only if the JSON value is an object.
19038
19039
@return `true` if type is object, `false` otherwise.
19040
19041
@complexity Constant.
19042
19043
@exceptionsafety No-throw guarantee: this member function never throws
19044
exceptions.
19045
19046
@liveexample{The following code exemplifies `is_object()` for all JSON
19047
types.,is_object}
19048
19049
@since version 1.0.0
19050
*/
19051
constexpr bool is_object() const noexcept
19052
{
19053
return m_type == value_t::object;
19054
}
19055
19056
/*!
19057
@brief return whether value is an array
19058
19059
This function returns true if and only if the JSON value is an array.
19060
19061
@return `true` if type is array, `false` otherwise.
19062
19063
@complexity Constant.
19064
19065
@exceptionsafety No-throw guarantee: this member function never throws
19066
exceptions.
19067
19068
@liveexample{The following code exemplifies `is_array()` for all JSON
19069
types.,is_array}
19070
19071
@since version 1.0.0
19072
*/
19073
constexpr bool is_array() const noexcept
19074
{
19075
return m_type == value_t::array;
19076
}
19077
19078
/*!
19079
@brief return whether value is a string
19080
19081
This function returns true if and only if the JSON value is a string.
19082
19083
@return `true` if type is string, `false` otherwise.
19084
19085
@complexity Constant.
19086
19087
@exceptionsafety No-throw guarantee: this member function never throws
19088
exceptions.
19089
19090
@liveexample{The following code exemplifies `is_string()` for all JSON
19091
types.,is_string}
19092
19093
@since version 1.0.0
19094
*/
19095
constexpr bool is_string() const noexcept
19096
{
19097
return m_type == value_t::string;
19098
}
19099
19100
/*!
19101
@brief return whether value is a binary array
19102
19103
This function returns true if and only if the JSON value is a binary array.
19104
19105
@return `true` if type is binary array, `false` otherwise.
19106
19107
@complexity Constant.
19108
19109
@exceptionsafety No-throw guarantee: this member function never throws
19110
exceptions.
19111
19112
@liveexample{The following code exemplifies `is_binary()` for all JSON
19113
types.,is_binary}
19114
19115
@since version 3.8.0
19116
*/
19117
constexpr bool is_binary() const noexcept
19118
{
19119
return m_type == value_t::binary;
19120
}
19121
19122
/*!
19123
@brief return whether value is discarded
19124
19125
This function returns true if and only if the JSON value was discarded
19126
during parsing with a callback function (see @ref parser_callback_t).
19127
19128
@note This function will always be `false` for JSON values after parsing.
19129
That is, discarded values can only occur during parsing, but will be
19130
removed when inside a structured value or replaced by null in other cases.
19131
19132
@return `true` if type is discarded, `false` otherwise.
19133
19134
@complexity Constant.
19135
19136
@exceptionsafety No-throw guarantee: this member function never throws
19137
exceptions.
19138
19139
@liveexample{The following code exemplifies `is_discarded()` for all JSON
19140
types.,is_discarded}
19141
19142
@since version 1.0.0
19143
*/
19144
constexpr bool is_discarded() const noexcept
19145
{
19146
return m_type == value_t::discarded;
19147
}
19148
19149
/*!
19150
@brief return the type of the JSON value (implicit)
19151
19152
Implicitly return the type of the JSON value as a value from the @ref
19153
value_t enumeration.
19154
19155
@return the type of the JSON value
19156
19157
@complexity Constant.
19158
19159
@exceptionsafety No-throw guarantee: this member function never throws
19160
exceptions.
19161
19162
@liveexample{The following code exemplifies the @ref value_t operator for
19163
all JSON types.,operator__value_t}
19164
19165
@sa @ref type() -- return the type of the JSON value (explicit)
19166
@sa @ref type_name() -- return the type as string
19167
19168
@since version 1.0.0
19169
*/
19170
constexpr operator value_t() const noexcept
19171
{
19172
return m_type;
19173
}
19174
19175
/// @}
19176
19177
private:
19178
//////////////////
19179
// value access //
19180
//////////////////
19181
19182
/// get a boolean (explicit)
19183
boolean_t get_impl(boolean_t* /*unused*/) const
19184
{
19185
if (JSON_HEDLEY_LIKELY(is_boolean()))
19186
{
19187
return m_value.boolean;
19188
}
19189
19190
JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name())));
19191
}
19192
19193
/// get a pointer to the value (object)
19194
object_t* get_impl_ptr(object_t* /*unused*/) noexcept
19195
{
19196
return is_object() ? m_value.object : nullptr;
19197
}
19198
19199
/// get a pointer to the value (object)
19200
constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
19201
{
19202
return is_object() ? m_value.object : nullptr;
19203
}
19204
19205
/// get a pointer to the value (array)
19206
array_t* get_impl_ptr(array_t* /*unused*/) noexcept
19207
{
19208
return is_array() ? m_value.array : nullptr;
19209
}
19210
19211
/// get a pointer to the value (array)
19212
constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
19213
{
19214
return is_array() ? m_value.array : nullptr;
19215
}
19216
19217
/// get a pointer to the value (string)
19218
string_t* get_impl_ptr(string_t* /*unused*/) noexcept
19219
{
19220
return is_string() ? m_value.string : nullptr;
19221
}
19222
19223
/// get a pointer to the value (string)
19224
constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
19225
{
19226
return is_string() ? m_value.string : nullptr;
19227
}
19228
19229
/// get a pointer to the value (boolean)
19230
boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
19231
{
19232
return is_boolean() ? &m_value.boolean : nullptr;
19233
}
19234
19235
/// get a pointer to the value (boolean)
19236
constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
19237
{
19238
return is_boolean() ? &m_value.boolean : nullptr;
19239
}
19240
19241
/// get a pointer to the value (integer number)
19242
number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
19243
{
19244
return is_number_integer() ? &m_value.number_integer : nullptr;
19245
}
19246
19247
/// get a pointer to the value (integer number)
19248
constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
19249
{
19250
return is_number_integer() ? &m_value.number_integer : nullptr;
19251
}
19252
19253
/// get a pointer to the value (unsigned number)
19254
number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
19255
{
19256
return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
19257
}
19258
19259
/// get a pointer to the value (unsigned number)
19260
constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
19261
{
19262
return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
19263
}
19264
19265
/// get a pointer to the value (floating-point number)
19266
number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
19267
{
19268
return is_number_float() ? &m_value.number_float : nullptr;
19269
}
19270
19271
/// get a pointer to the value (floating-point number)
19272
constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
19273
{
19274
return is_number_float() ? &m_value.number_float : nullptr;
19275
}
19276
19277
/// get a pointer to the value (binary)
19278
binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
19279
{
19280
return is_binary() ? m_value.binary : nullptr;
19281
}
19282
19283
/// get a pointer to the value (binary)
19284
constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
19285
{
19286
return is_binary() ? m_value.binary : nullptr;
19287
}
19288
19289
/*!
19290
@brief helper function to implement get_ref()
19291
19292
This function helps to implement get_ref() without code duplication for
19293
const and non-const overloads
19294
19295
@tparam ThisType will be deduced as `basic_json` or `const basic_json`
19296
19297
@throw type_error.303 if ReferenceType does not match underlying value
19298
type of the current JSON
19299
*/
19300
template<typename ReferenceType, typename ThisType>
19301
static ReferenceType get_ref_impl(ThisType& obj)
19302
{
19303
// delegate the call to get_ptr<>()
19304
auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
19305
19306
if (JSON_HEDLEY_LIKELY(ptr != nullptr))
19307
{
19308
return *ptr;
19309
}
19310
19311
JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
19312
}
19313
19314
public:
19315
/// @name value access
19316
/// Direct access to the stored value of a JSON value.
19317
/// @{
19318
19319
/*!
19320
@brief get special-case overload
19321
19322
This overloads avoids a lot of template boilerplate, it can be seen as the
19323
identity method
19324
19325
@tparam BasicJsonType == @ref basic_json
19326
19327
@return a copy of *this
19328
19329
@complexity Constant.
19330
19331
@since version 2.1.0
19332
*/
19333
template<typename BasicJsonType, detail::enable_if_t<
19334
std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,
19335
int> = 0>
19336
basic_json get() const
19337
{
19338
return *this;
19339
}
19340
19341
/*!
19342
@brief get special-case overload
19343
19344
This overloads converts the current @ref basic_json in a different
19345
@ref basic_json type
19346
19347
@tparam BasicJsonType == @ref basic_json
19348
19349
@return a copy of *this, converted into @tparam BasicJsonType
19350
19351
@complexity Depending on the implementation of the called `from_json()`
19352
method.
19353
19354
@since version 3.2.0
19355
*/
19356
template < typename BasicJsonType, detail::enable_if_t <
19357
!std::is_same<BasicJsonType, basic_json>::value&&
19358
detail::is_basic_json<BasicJsonType>::value, int > = 0 >
19359
BasicJsonType get() const
19360
{
19361
return *this;
19362
}
19363
19364
/*!
19365
@brief get a value (explicit)
19366
19367
Explicit type conversion between the JSON value and a compatible value
19368
which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
19369
and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
19370
The value is converted by calling the @ref json_serializer<ValueType>
19371
`from_json()` method.
19372
19373
The function is equivalent to executing
19374
@code {.cpp}
19375
ValueType ret;
19376
JSONSerializer<ValueType>::from_json(*this, ret);
19377
return ret;
19378
@endcode
19379
19380
This overloads is chosen if:
19381
- @a ValueType is not @ref basic_json,
19382
- @ref json_serializer<ValueType> has a `from_json()` method of the form
19383
`void from_json(const basic_json&, ValueType&)`, and
19384
- @ref json_serializer<ValueType> does not have a `from_json()` method of
19385
the form `ValueType from_json(const basic_json&)`
19386
19387
@tparam ValueTypeCV the provided value type
19388
@tparam ValueType the returned value type
19389
19390
@return copy of the JSON value, converted to @a ValueType
19391
19392
@throw what @ref json_serializer<ValueType> `from_json()` method throws
19393
19394
@liveexample{The example below shows several conversions from JSON values
19395
to other types. There a few things to note: (1) Floating-point numbers can
19396
be converted to integers\, (2) A JSON array can be converted to a standard
19397
`std::vector<short>`\, (3) A JSON object can be converted to C++
19398
associative containers such as `std::unordered_map<std::string\,
19399
json>`.,get__ValueType_const}
19400
19401
@since version 2.1.0
19402
*/
19403
template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
19404
detail::enable_if_t <
19405
!detail::is_basic_json<ValueType>::value &&
19406
detail::has_from_json<basic_json_t, ValueType>::value &&
19407
!detail::has_non_default_from_json<basic_json_t, ValueType>::value,
19408
int > = 0 >
19409
ValueType get() const noexcept(noexcept(
19410
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
19411
{
19412
// we cannot static_assert on ValueTypeCV being non-const, because
19413
// there is support for get<const basic_json_t>(), which is why we
19414
// still need the uncvref
19415
static_assert(!std::is_reference<ValueTypeCV>::value,
19416
"get() cannot be used with reference types, you might want to use get_ref()");
19417
static_assert(std::is_default_constructible<ValueType>::value,
19418
"types must be DefaultConstructible when used with get()");
19419
19420
ValueType ret;
19421
JSONSerializer<ValueType>::from_json(*this, ret);
19422
return ret;
19423
}
19424
19425
/*!
19426
@brief get a value (explicit); special case
19427
19428
Explicit type conversion between the JSON value and a compatible value
19429
which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
19430
and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
19431
The value is converted by calling the @ref json_serializer<ValueType>
19432
`from_json()` method.
19433
19434
The function is equivalent to executing
19435
@code {.cpp}
19436
return JSONSerializer<ValueTypeCV>::from_json(*this);
19437
@endcode
19438
19439
This overloads is chosen if:
19440
- @a ValueType is not @ref basic_json and
19441
- @ref json_serializer<ValueType> has a `from_json()` method of the form
19442
`ValueType from_json(const basic_json&)`
19443
19444
@note If @ref json_serializer<ValueType> has both overloads of
19445
`from_json()`, this one is chosen.
19446
19447
@tparam ValueTypeCV the provided value type
19448
@tparam ValueType the returned value type
19449
19450
@return copy of the JSON value, converted to @a ValueType
19451
19452
@throw what @ref json_serializer<ValueType> `from_json()` method throws
19453
19454
@since version 2.1.0
19455
*/
19456
template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
19457
detail::enable_if_t < !std::is_same<basic_json_t, ValueType>::value &&
19458
detail::has_non_default_from_json<basic_json_t, ValueType>::value,
19459
int > = 0 >
19460
ValueType get() const noexcept(noexcept(
19461
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
19462
{
19463
static_assert(!std::is_reference<ValueTypeCV>::value,
19464
"get() cannot be used with reference types, you might want to use get_ref()");
19465
return JSONSerializer<ValueType>::from_json(*this);
19466
}
19467
19468
/*!
19469
@brief get a value (explicit)
19470
19471
Explicit type conversion between the JSON value and a compatible value.
19472
The value is filled into the input parameter by calling the @ref json_serializer<ValueType>
19473
`from_json()` method.
19474
19475
The function is equivalent to executing
19476
@code {.cpp}
19477
ValueType v;
19478
JSONSerializer<ValueType>::from_json(*this, v);
19479
@endcode
19480
19481
This overloads is chosen if:
19482
- @a ValueType is not @ref basic_json,
19483
- @ref json_serializer<ValueType> has a `from_json()` method of the form
19484
`void from_json(const basic_json&, ValueType&)`, and
19485
19486
@tparam ValueType the input parameter type.
19487
19488
@return the input parameter, allowing chaining calls.
19489
19490
@throw what @ref json_serializer<ValueType> `from_json()` method throws
19491
19492
@liveexample{The example below shows several conversions from JSON values
19493
to other types. There a few things to note: (1) Floating-point numbers can
19494
be converted to integers\, (2) A JSON array can be converted to a standard
19495
`std::vector<short>`\, (3) A JSON object can be converted to C++
19496
associative containers such as `std::unordered_map<std::string\,
19497
json>`.,get_to}
19498
19499
@since version 3.3.0
19500
*/
19501
template < typename ValueType,
19502
detail::enable_if_t <
19503
!detail::is_basic_json<ValueType>::value&&
19504
detail::has_from_json<basic_json_t, ValueType>::value,
19505
int > = 0 >
19506
ValueType & get_to(ValueType& v) const noexcept(noexcept(
19507
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
19508
{
19509
JSONSerializer<ValueType>::from_json(*this, v);
19510
return v;
19511
}
19512
19513
// specialization to allow to call get_to with a basic_json value
19514
// see https://github.com/nlohmann/json/issues/2175
19515
template<typename ValueType,
19516
detail::enable_if_t <
19517
detail::is_basic_json<ValueType>::value,
19518
int> = 0>
19519
ValueType & get_to(ValueType& v) const
19520
{
19521
v = *this;
19522
return v;
19523
}
19524
19525
template <
19526
typename T, std::size_t N,
19527
typename Array = T (&)[N],
19528
detail::enable_if_t <
19529
detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
19530
Array get_to(T (&v)[N]) const
19531
noexcept(noexcept(JSONSerializer<Array>::from_json(
19532
std::declval<const basic_json_t&>(), v)))
19533
{
19534
JSONSerializer<Array>::from_json(*this, v);
19535
return v;
19536
}
19537
19538
19539
/*!
19540
@brief get a pointer value (implicit)
19541
19542
Implicit pointer access to the internally stored JSON value. No copies are
19543
made.
19544
19545
@warning Writing data to the pointee of the result yields an undefined
19546
state.
19547
19548
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
19549
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
19550
@ref number_unsigned_t, or @ref number_float_t. Enforced by a static
19551
assertion.
19552
19553
@return pointer to the internally stored JSON value if the requested
19554
pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
19555
19556
@complexity Constant.
19557
19558
@liveexample{The example below shows how pointers to internal values of a
19559
JSON value can be requested. Note that no type conversions are made and a
19560
`nullptr` is returned if the value and the requested pointer type does not
19561
match.,get_ptr}
19562
19563
@since version 1.0.0
19564
*/
19565
template<typename PointerType, typename std::enable_if<
19566
std::is_pointer<PointerType>::value, int>::type = 0>
19567
auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
19568
{
19569
// delegate the call to get_impl_ptr<>()
19570
return get_impl_ptr(static_cast<PointerType>(nullptr));
19571
}
19572
19573
/*!
19574
@brief get a pointer value (implicit)
19575
@copydoc get_ptr()
19576
*/
19577
template < typename PointerType, typename std::enable_if <
19578
std::is_pointer<PointerType>::value&&
19579
std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
19580
constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
19581
{
19582
// delegate the call to get_impl_ptr<>() const
19583
return get_impl_ptr(static_cast<PointerType>(nullptr));
19584
}
19585
19586
/*!
19587
@brief get a pointer value (explicit)
19588
19589
Explicit pointer access to the internally stored JSON value. No copies are
19590
made.
19591
19592
@warning The pointer becomes invalid if the underlying JSON object
19593
changes.
19594
19595
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
19596
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
19597
@ref number_unsigned_t, or @ref number_float_t.
19598
19599
@return pointer to the internally stored JSON value if the requested
19600
pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
19601
19602
@complexity Constant.
19603
19604
@liveexample{The example below shows how pointers to internal values of a
19605
JSON value can be requested. Note that no type conversions are made and a
19606
`nullptr` is returned if the value and the requested pointer type does not
19607
match.,get__PointerType}
19608
19609
@sa @ref get_ptr() for explicit pointer-member access
19610
19611
@since version 1.0.0
19612
*/
19613
template<typename PointerType, typename std::enable_if<
19614
std::is_pointer<PointerType>::value, int>::type = 0>
19615
auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
19616
{
19617
// delegate the call to get_ptr
19618
return get_ptr<PointerType>();
19619
}
19620
19621
/*!
19622
@brief get a pointer value (explicit)
19623
@copydoc get()
19624
*/
19625
template<typename PointerType, typename std::enable_if<
19626
std::is_pointer<PointerType>::value, int>::type = 0>
19627
constexpr auto get() const noexcept -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
19628
{
19629
// delegate the call to get_ptr
19630
return get_ptr<PointerType>();
19631
}
19632
19633
/*!
19634
@brief get a reference value (implicit)
19635
19636
Implicit reference access to the internally stored JSON value. No copies
19637
are made.
19638
19639
@warning Writing data to the referee of the result yields an undefined
19640
state.
19641
19642
@tparam ReferenceType reference type; must be a reference to @ref array_t,
19643
@ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or
19644
@ref number_float_t. Enforced by static assertion.
19645
19646
@return reference to the internally stored JSON value if the requested
19647
reference type @a ReferenceType fits to the JSON value; throws
19648
type_error.303 otherwise
19649
19650
@throw type_error.303 in case passed type @a ReferenceType is incompatible
19651
with the stored JSON value; see example below
19652
19653
@complexity Constant.
19654
19655
@liveexample{The example shows several calls to `get_ref()`.,get_ref}
19656
19657
@since version 1.1.0
19658
*/
19659
template<typename ReferenceType, typename std::enable_if<
19660
std::is_reference<ReferenceType>::value, int>::type = 0>
19661
ReferenceType get_ref()
19662
{
19663
// delegate call to get_ref_impl
19664
return get_ref_impl<ReferenceType>(*this);
19665
}
19666
19667
/*!
19668
@brief get a reference value (implicit)
19669
@copydoc get_ref()
19670
*/
19671
template < typename ReferenceType, typename std::enable_if <
19672
std::is_reference<ReferenceType>::value&&
19673
std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
19674
ReferenceType get_ref() const
19675
{
19676
// delegate call to get_ref_impl
19677
return get_ref_impl<ReferenceType>(*this);
19678
}
19679
19680
/*!
19681
@brief get a value (implicit)
19682
19683
Implicit type conversion between the JSON value and a compatible value.
19684
The call is realized by calling @ref get() const.
19685
19686
@tparam ValueType non-pointer type compatible to the JSON value, for
19687
instance `int` for JSON integer numbers, `bool` for JSON booleans, or
19688
`std::vector` types for JSON arrays. The character type of @ref string_t
19689
as well as an initializer list of this type is excluded to avoid
19690
ambiguities as these types implicitly convert to `std::string`.
19691
19692
@return copy of the JSON value, converted to type @a ValueType
19693
19694
@throw type_error.302 in case passed type @a ValueType is incompatible
19695
to the JSON value type (e.g., the JSON value is of type boolean, but a
19696
string is requested); see example below
19697
19698
@complexity Linear in the size of the JSON value.
19699
19700
@liveexample{The example below shows several conversions from JSON values
19701
to other types. There a few things to note: (1) Floating-point numbers can
19702
be converted to integers\, (2) A JSON array can be converted to a standard
19703
`std::vector<short>`\, (3) A JSON object can be converted to C++
19704
associative containers such as `std::unordered_map<std::string\,
19705
json>`.,operator__ValueType}
19706
19707
@since version 1.0.0
19708
*/
19709
template < typename ValueType, typename std::enable_if <
19710
!std::is_pointer<ValueType>::value&&
19711
!std::is_same<ValueType, detail::json_ref<basic_json>>::value&&
19712
!std::is_same<ValueType, typename string_t::value_type>::value&&
19713
!detail::is_basic_json<ValueType>::value
19714
&& !std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
19715
#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
19716
&& !std::is_same<ValueType, typename std::string_view>::value
19717
#endif
19718
&& detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value
19719
, int >::type = 0 >
19720
JSON_EXPLICIT operator ValueType() const
19721
{
19722
// delegate the call to get<>() const
19723
return get<ValueType>();
19724
}
19725
19726
/*!
19727
@return reference to the binary value
19728
19729
@throw type_error.302 if the value is not binary
19730
19731
@sa @ref is_binary() to check if the value is binary
19732
19733
@since version 3.8.0
19734
*/
19735
binary_t& get_binary()
19736
{
19737
if (!is_binary())
19738
{
19739
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name())));
19740
}
19741
19742
return *get_ptr<binary_t*>();
19743
}
19744
19745
/// @copydoc get_binary()
19746
const binary_t& get_binary() const
19747
{
19748
if (!is_binary())
19749
{
19750
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name())));
19751
}
19752
19753
return *get_ptr<const binary_t*>();
19754
}
19755
19756
/// @}
19757
19758
19759
////////////////////
19760
// element access //
19761
////////////////////
19762
19763
/// @name element access
19764
/// Access to the JSON value.
19765
/// @{
19766
19767
/*!
19768
@brief access specified array element with bounds checking
19769
19770
Returns a reference to the element at specified location @a idx, with
19771
bounds checking.
19772
19773
@param[in] idx index of the element to access
19774
19775
@return reference to the element at index @a idx
19776
19777
@throw type_error.304 if the JSON value is not an array; in this case,
19778
calling `at` with an index makes no sense. See example below.
19779
@throw out_of_range.401 if the index @a idx is out of range of the array;
19780
that is, `idx >= size()`. See example below.
19781
19782
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
19783
changes in the JSON value.
19784
19785
@complexity Constant.
19786
19787
@since version 1.0.0
19788
19789
@liveexample{The example below shows how array elements can be read and
19790
written using `at()`. It also demonstrates the different exceptions that
19791
can be thrown.,at__size_type}
19792
*/
19793
reference at(size_type idx)
19794
{
19795
// at only works for arrays
19796
if (JSON_HEDLEY_LIKELY(is_array()))
19797
{
19798
JSON_TRY
19799
{
19800
return m_value.array->at(idx);
19801
}
19802
JSON_CATCH (std::out_of_range&)
19803
{
19804
// create better exception explanation
19805
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
19806
}
19807
}
19808
else
19809
{
19810
JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
19811
}
19812
}
19813
19814
/*!
19815
@brief access specified array element with bounds checking
19816
19817
Returns a const reference to the element at specified location @a idx,
19818
with bounds checking.
19819
19820
@param[in] idx index of the element to access
19821
19822
@return const reference to the element at index @a idx
19823
19824
@throw type_error.304 if the JSON value is not an array; in this case,
19825
calling `at` with an index makes no sense. See example below.
19826
@throw out_of_range.401 if the index @a idx is out of range of the array;
19827
that is, `idx >= size()`. See example below.
19828
19829
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
19830
changes in the JSON value.
19831
19832
@complexity Constant.
19833
19834
@since version 1.0.0
19835
19836
@liveexample{The example below shows how array elements can be read using
19837
`at()`. It also demonstrates the different exceptions that can be thrown.,
19838
at__size_type_const}
19839
*/
19840
const_reference at(size_type idx) const
19841
{
19842
// at only works for arrays
19843
if (JSON_HEDLEY_LIKELY(is_array()))
19844
{
19845
JSON_TRY
19846
{
19847
return m_value.array->at(idx);
19848
}
19849
JSON_CATCH (std::out_of_range&)
19850
{
19851
// create better exception explanation
19852
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
19853
}
19854
}
19855
else
19856
{
19857
JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
19858
}
19859
}
19860
19861
/*!
19862
@brief access specified object element with bounds checking
19863
19864
Returns a reference to the element at with specified key @a key, with
19865
bounds checking.
19866
19867
@param[in] key key of the element to access
19868
19869
@return reference to the element at key @a key
19870
19871
@throw type_error.304 if the JSON value is not an object; in this case,
19872
calling `at` with a key makes no sense. See example below.
19873
@throw out_of_range.403 if the key @a key is is not stored in the object;
19874
that is, `find(key) == end()`. See example below.
19875
19876
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
19877
changes in the JSON value.
19878
19879
@complexity Logarithmic in the size of the container.
19880
19881
@sa @ref operator[](const typename object_t::key_type&) for unchecked
19882
access by reference
19883
@sa @ref value() for access by value with a default value
19884
19885
@since version 1.0.0
19886
19887
@liveexample{The example below shows how object elements can be read and
19888
written using `at()`. It also demonstrates the different exceptions that
19889
can be thrown.,at__object_t_key_type}
19890
*/
19891
reference at(const typename object_t::key_type& key)
19892
{
19893
// at only works for objects
19894
if (JSON_HEDLEY_LIKELY(is_object()))
19895
{
19896
JSON_TRY
19897
{
19898
return m_value.object->at(key);
19899
}
19900
JSON_CATCH (std::out_of_range&)
19901
{
19902
// create better exception explanation
19903
JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
19904
}
19905
}
19906
else
19907
{
19908
JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
19909
}
19910
}
19911
19912
/*!
19913
@brief access specified object element with bounds checking
19914
19915
Returns a const reference to the element at with specified key @a key,
19916
with bounds checking.
19917
19918
@param[in] key key of the element to access
19919
19920
@return const reference to the element at key @a key
19921
19922
@throw type_error.304 if the JSON value is not an object; in this case,
19923
calling `at` with a key makes no sense. See example below.
19924
@throw out_of_range.403 if the key @a key is is not stored in the object;
19925
that is, `find(key) == end()`. See example below.
19926
19927
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
19928
changes in the JSON value.
19929
19930
@complexity Logarithmic in the size of the container.
19931
19932
@sa @ref operator[](const typename object_t::key_type&) for unchecked
19933
access by reference
19934
@sa @ref value() for access by value with a default value
19935
19936
@since version 1.0.0
19937
19938
@liveexample{The example below shows how object elements can be read using
19939
`at()`. It also demonstrates the different exceptions that can be thrown.,
19940
at__object_t_key_type_const}
19941
*/
19942
const_reference at(const typename object_t::key_type& key) const
19943
{
19944
// at only works for objects
19945
if (JSON_HEDLEY_LIKELY(is_object()))
19946
{
19947
JSON_TRY
19948
{
19949
return m_value.object->at(key);
19950
}
19951
JSON_CATCH (std::out_of_range&)
19952
{
19953
// create better exception explanation
19954
JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
19955
}
19956
}
19957
else
19958
{
19959
JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
19960
}
19961
}
19962
19963
/*!
19964
@brief access specified array element
19965
19966
Returns a reference to the element at specified location @a idx.
19967
19968
@note If @a idx is beyond the range of the array (i.e., `idx >= size()`),
19969
then the array is silently filled up with `null` values to make `idx` a
19970
valid reference to the last stored element.
19971
19972
@param[in] idx index of the element to access
19973
19974
@return reference to the element at index @a idx
19975
19976
@throw type_error.305 if the JSON value is not an array or null; in that
19977
cases, using the [] operator with an index makes no sense.
19978
19979
@complexity Constant if @a idx is in the range of the array. Otherwise
19980
linear in `idx - size()`.
19981
19982
@liveexample{The example below shows how array elements can be read and
19983
written using `[]` operator. Note the addition of `null`
19984
values.,operatorarray__size_type}
19985
19986
@since version 1.0.0
19987
*/
19988
reference operator[](size_type idx)
19989
{
19990
// implicitly convert null value to an empty array
19991
if (is_null())
19992
{
19993
m_type = value_t::array;
19994
m_value.array = create<array_t>();
19995
assert_invariant();
19996
}
19997
19998
// operator[] only works for arrays
19999
if (JSON_HEDLEY_LIKELY(is_array()))
20000
{
20001
// fill up array with null values if given idx is outside range
20002
if (idx >= m_value.array->size())
20003
{
20004
m_value.array->insert(m_value.array->end(),
20005
idx - m_value.array->size() + 1,
20006
basic_json());
20007
}
20008
20009
return m_value.array->operator[](idx);
20010
}
20011
20012
JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
20013
}
20014
20015
/*!
20016
@brief access specified array element
20017
20018
Returns a const reference to the element at specified location @a idx.
20019
20020
@param[in] idx index of the element to access
20021
20022
@return const reference to the element at index @a idx
20023
20024
@throw type_error.305 if the JSON value is not an array; in that case,
20025
using the [] operator with an index makes no sense.
20026
20027
@complexity Constant.
20028
20029
@liveexample{The example below shows how array elements can be read using
20030
the `[]` operator.,operatorarray__size_type_const}
20031
20032
@since version 1.0.0
20033
*/
20034
const_reference operator[](size_type idx) const
20035
{
20036
// const operator[] only works for arrays
20037
if (JSON_HEDLEY_LIKELY(is_array()))
20038
{
20039
return m_value.array->operator[](idx);
20040
}
20041
20042
JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
20043
}
20044
20045
/*!
20046
@brief access specified object element
20047
20048
Returns a reference to the element at with specified key @a key.
20049
20050
@note If @a key is not found in the object, then it is silently added to
20051
the object and filled with a `null` value to make `key` a valid reference.
20052
In case the value was `null` before, it is converted to an object.
20053
20054
@param[in] key key of the element to access
20055
20056
@return reference to the element at key @a key
20057
20058
@throw type_error.305 if the JSON value is not an object or null; in that
20059
cases, using the [] operator with a key makes no sense.
20060
20061
@complexity Logarithmic in the size of the container.
20062
20063
@liveexample{The example below shows how object elements can be read and
20064
written using the `[]` operator.,operatorarray__key_type}
20065
20066
@sa @ref at(const typename object_t::key_type&) for access by reference
20067
with range checking
20068
@sa @ref value() for access by value with a default value
20069
20070
@since version 1.0.0
20071
*/
20072
reference operator[](const typename object_t::key_type& key)
20073
{
20074
// implicitly convert null value to an empty object
20075
if (is_null())
20076
{
20077
m_type = value_t::object;
20078
m_value.object = create<object_t>();
20079
assert_invariant();
20080
}
20081
20082
// operator[] only works for objects
20083
if (JSON_HEDLEY_LIKELY(is_object()))
20084
{
20085
return m_value.object->operator[](key);
20086
}
20087
20088
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
20089
}
20090
20091
/*!
20092
@brief read-only access specified object element
20093
20094
Returns a const reference to the element at with specified key @a key. No
20095
bounds checking is performed.
20096
20097
@warning If the element with key @a key does not exist, the behavior is
20098
undefined.
20099
20100
@param[in] key key of the element to access
20101
20102
@return const reference to the element at key @a key
20103
20104
@pre The element with key @a key must exist. **This precondition is
20105
enforced with an assertion.**
20106
20107
@throw type_error.305 if the JSON value is not an object; in that case,
20108
using the [] operator with a key makes no sense.
20109
20110
@complexity Logarithmic in the size of the container.
20111
20112
@liveexample{The example below shows how object elements can be read using
20113
the `[]` operator.,operatorarray__key_type_const}
20114
20115
@sa @ref at(const typename object_t::key_type&) for access by reference
20116
with range checking
20117
@sa @ref value() for access by value with a default value
20118
20119
@since version 1.0.0
20120
*/
20121
const_reference operator[](const typename object_t::key_type& key) const
20122
{
20123
// const operator[] only works for objects
20124
if (JSON_HEDLEY_LIKELY(is_object()))
20125
{
20126
JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
20127
return m_value.object->find(key)->second;
20128
}
20129
20130
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
20131
}
20132
20133
/*!
20134
@brief access specified object element
20135
20136
Returns a reference to the element at with specified key @a key.
20137
20138
@note If @a key is not found in the object, then it is silently added to
20139
the object and filled with a `null` value to make `key` a valid reference.
20140
In case the value was `null` before, it is converted to an object.
20141
20142
@param[in] key key of the element to access
20143
20144
@return reference to the element at key @a key
20145
20146
@throw type_error.305 if the JSON value is not an object or null; in that
20147
cases, using the [] operator with a key makes no sense.
20148
20149
@complexity Logarithmic in the size of the container.
20150
20151
@liveexample{The example below shows how object elements can be read and
20152
written using the `[]` operator.,operatorarray__key_type}
20153
20154
@sa @ref at(const typename object_t::key_type&) for access by reference
20155
with range checking
20156
@sa @ref value() for access by value with a default value
20157
20158
@since version 1.1.0
20159
*/
20160
template<typename T>
20161
JSON_HEDLEY_NON_NULL(2)
20162
reference operator[](T* key)
20163
{
20164
// implicitly convert null to object
20165
if (is_null())
20166
{
20167
m_type = value_t::object;
20168
m_value = value_t::object;
20169
assert_invariant();
20170
}
20171
20172
// at only works for objects
20173
if (JSON_HEDLEY_LIKELY(is_object()))
20174
{
20175
return m_value.object->operator[](key);
20176
}
20177
20178
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
20179
}
20180
20181
/*!
20182
@brief read-only access specified object element
20183
20184
Returns a const reference to the element at with specified key @a key. No
20185
bounds checking is performed.
20186
20187
@warning If the element with key @a key does not exist, the behavior is
20188
undefined.
20189
20190
@param[in] key key of the element to access
20191
20192
@return const reference to the element at key @a key
20193
20194
@pre The element with key @a key must exist. **This precondition is
20195
enforced with an assertion.**
20196
20197
@throw type_error.305 if the JSON value is not an object; in that case,
20198
using the [] operator with a key makes no sense.
20199
20200
@complexity Logarithmic in the size of the container.
20201
20202
@liveexample{The example below shows how object elements can be read using
20203
the `[]` operator.,operatorarray__key_type_const}
20204
20205
@sa @ref at(const typename object_t::key_type&) for access by reference
20206
with range checking
20207
@sa @ref value() for access by value with a default value
20208
20209
@since version 1.1.0
20210
*/
20211
template<typename T>
20212
JSON_HEDLEY_NON_NULL(2)
20213
const_reference operator[](T* key) const
20214
{
20215
// at only works for objects
20216
if (JSON_HEDLEY_LIKELY(is_object()))
20217
{
20218
JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
20219
return m_value.object->find(key)->second;
20220
}
20221
20222
JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
20223
}
20224
20225
/*!
20226
@brief access specified object element with default value
20227
20228
Returns either a copy of an object's element at the specified key @a key
20229
or a given default value if no element with key @a key exists.
20230
20231
The function is basically equivalent to executing
20232
@code {.cpp}
20233
try {
20234
return at(key);
20235
} catch(out_of_range) {
20236
return default_value;
20237
}
20238
@endcode
20239
20240
@note Unlike @ref at(const typename object_t::key_type&), this function
20241
does not throw if the given key @a key was not found.
20242
20243
@note Unlike @ref operator[](const typename object_t::key_type& key), this
20244
function does not implicitly add an element to the position defined by @a
20245
key. This function is furthermore also applicable to const objects.
20246
20247
@param[in] key key of the element to access
20248
@param[in] default_value the value to return if @a key is not found
20249
20250
@tparam ValueType type compatible to JSON values, for instance `int` for
20251
JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
20252
JSON arrays. Note the type of the expected value at @a key and the default
20253
value @a default_value must be compatible.
20254
20255
@return copy of the element at key @a key or @a default_value if @a key
20256
is not found
20257
20258
@throw type_error.302 if @a default_value does not match the type of the
20259
value at @a key
20260
@throw type_error.306 if the JSON value is not an object; in that case,
20261
using `value()` with a key makes no sense.
20262
20263
@complexity Logarithmic in the size of the container.
20264
20265
@liveexample{The example below shows how object elements can be queried
20266
with a default value.,basic_json__value}
20267
20268
@sa @ref at(const typename object_t::key_type&) for access by reference
20269
with range checking
20270
@sa @ref operator[](const typename object_t::key_type&) for unchecked
20271
access by reference
20272
20273
@since version 1.0.0
20274
*/
20275
// using std::is_convertible in a std::enable_if will fail when using explicit conversions
20276
template < class ValueType, typename std::enable_if <
20277
detail::is_getable<basic_json_t, ValueType>::value
20278
&& !std::is_same<value_t, ValueType>::value, int >::type = 0 >
20279
ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
20280
{
20281
// at only works for objects
20282
if (JSON_HEDLEY_LIKELY(is_object()))
20283
{
20284
// if key is found, return value and given default value otherwise
20285
const auto it = find(key);
20286
if (it != end())
20287
{
20288
return it->template get<ValueType>();
20289
}
20290
20291
return default_value;
20292
}
20293
20294
JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
20295
}
20296
20297
/*!
20298
@brief overload for a default value of type const char*
20299
@copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const
20300
*/
20301
string_t value(const typename object_t::key_type& key, const char* default_value) const
20302
{
20303
return value(key, string_t(default_value));
20304
}
20305
20306
/*!
20307
@brief access specified object element via JSON Pointer with default value
20308
20309
Returns either a copy of an object's element at the specified key @a key
20310
or a given default value if no element with key @a key exists.
20311
20312
The function is basically equivalent to executing
20313
@code {.cpp}
20314
try {
20315
return at(ptr);
20316
} catch(out_of_range) {
20317
return default_value;
20318
}
20319
@endcode
20320
20321
@note Unlike @ref at(const json_pointer&), this function does not throw
20322
if the given key @a key was not found.
20323
20324
@param[in] ptr a JSON pointer to the element to access
20325
@param[in] default_value the value to return if @a ptr found no value
20326
20327
@tparam ValueType type compatible to JSON values, for instance `int` for
20328
JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
20329
JSON arrays. Note the type of the expected value at @a key and the default
20330
value @a default_value must be compatible.
20331
20332
@return copy of the element at key @a key or @a default_value if @a key
20333
is not found
20334
20335
@throw type_error.302 if @a default_value does not match the type of the
20336
value at @a ptr
20337
@throw type_error.306 if the JSON value is not an object; in that case,
20338
using `value()` with a key makes no sense.
20339
20340
@complexity Logarithmic in the size of the container.
20341
20342
@liveexample{The example below shows how object elements can be queried
20343
with a default value.,basic_json__value_ptr}
20344
20345
@sa @ref operator[](const json_pointer&) for unchecked access by reference
20346
20347
@since version 2.0.2
20348
*/
20349
template<class ValueType, typename std::enable_if<
20350
detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
20351
ValueType value(const json_pointer& ptr, const ValueType& default_value) const
20352
{
20353
// at only works for objects
20354
if (JSON_HEDLEY_LIKELY(is_object()))
20355
{
20356
// if pointer resolves a value, return it or use default value
20357
JSON_TRY
20358
{
20359
return ptr.get_checked(this).template get<ValueType>();
20360
}
20361
JSON_INTERNAL_CATCH (out_of_range&)
20362
{
20363
return default_value;
20364
}
20365
}
20366
20367
JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
20368
}
20369
20370
/*!
20371
@brief overload for a default value of type const char*
20372
@copydoc basic_json::value(const json_pointer&, ValueType) const
20373
*/
20374
JSON_HEDLEY_NON_NULL(3)
20375
string_t value(const json_pointer& ptr, const char* default_value) const
20376
{
20377
return value(ptr, string_t(default_value));
20378
}
20379
20380
/*!
20381
@brief access the first element
20382
20383
Returns a reference to the first element in the container. For a JSON
20384
container `c`, the expression `c.front()` is equivalent to `*c.begin()`.
20385
20386
@return In case of a structured type (array or object), a reference to the
20387
first element is returned. In case of number, string, boolean, or binary
20388
values, a reference to the value is returned.
20389
20390
@complexity Constant.
20391
20392
@pre The JSON value must not be `null` (would throw `std::out_of_range`)
20393
or an empty array or object (undefined behavior, **guarded by
20394
assertions**).
20395
@post The JSON value remains unchanged.
20396
20397
@throw invalid_iterator.214 when called on `null` value
20398
20399
@liveexample{The following code shows an example for `front()`.,front}
20400
20401
@sa @ref back() -- access the last element
20402
20403
@since version 1.0.0
20404
*/
20405
reference front()
20406
{
20407
return *begin();
20408
}
20409
20410
/*!
20411
@copydoc basic_json::front()
20412
*/
20413
const_reference front() const
20414
{
20415
return *cbegin();
20416
}
20417
20418
/*!
20419
@brief access the last element
20420
20421
Returns a reference to the last element in the container. For a JSON
20422
container `c`, the expression `c.back()` is equivalent to
20423
@code {.cpp}
20424
auto tmp = c.end();
20425
--tmp;
20426
return *tmp;
20427
@endcode
20428
20429
@return In case of a structured type (array or object), a reference to the
20430
last element is returned. In case of number, string, boolean, or binary
20431
values, a reference to the value is returned.
20432
20433
@complexity Constant.
20434
20435
@pre The JSON value must not be `null` (would throw `std::out_of_range`)
20436
or an empty array or object (undefined behavior, **guarded by
20437
assertions**).
20438
@post The JSON value remains unchanged.
20439
20440
@throw invalid_iterator.214 when called on a `null` value. See example
20441
below.
20442
20443
@liveexample{The following code shows an example for `back()`.,back}
20444
20445
@sa @ref front() -- access the first element
20446
20447
@since version 1.0.0
20448
*/
20449
reference back()
20450
{
20451
auto tmp = end();
20452
--tmp;
20453
return *tmp;
20454
}
20455
20456
/*!
20457
@copydoc basic_json::back()
20458
*/
20459
const_reference back() const
20460
{
20461
auto tmp = cend();
20462
--tmp;
20463
return *tmp;
20464
}
20465
20466
/*!
20467
@brief remove element given an iterator
20468
20469
Removes the element specified by iterator @a pos. The iterator @a pos must
20470
be valid and dereferenceable. Thus the `end()` iterator (which is valid,
20471
but is not dereferenceable) cannot be used as a value for @a pos.
20472
20473
If called on a primitive type other than `null`, the resulting JSON value
20474
will be `null`.
20475
20476
@param[in] pos iterator to the element to remove
20477
@return Iterator following the last removed element. If the iterator @a
20478
pos refers to the last element, the `end()` iterator is returned.
20479
20480
@tparam IteratorType an @ref iterator or @ref const_iterator
20481
20482
@post Invalidates iterators and references at or after the point of the
20483
erase, including the `end()` iterator.
20484
20485
@throw type_error.307 if called on a `null` value; example: `"cannot use
20486
erase() with null"`
20487
@throw invalid_iterator.202 if called on an iterator which does not belong
20488
to the current JSON value; example: `"iterator does not fit current
20489
value"`
20490
@throw invalid_iterator.205 if called on a primitive type with invalid
20491
iterator (i.e., any iterator which is not `begin()`); example: `"iterator
20492
out of range"`
20493
20494
@complexity The complexity depends on the type:
20495
- objects: amortized constant
20496
- arrays: linear in distance between @a pos and the end of the container
20497
- strings and binary: linear in the length of the member
20498
- other types: constant
20499
20500
@liveexample{The example shows the result of `erase()` for different JSON
20501
types.,erase__IteratorType}
20502
20503
@sa @ref erase(IteratorType, IteratorType) -- removes the elements in
20504
the given range
20505
@sa @ref erase(const typename object_t::key_type&) -- removes the element
20506
from an object at the given key
20507
@sa @ref erase(const size_type) -- removes the element from an array at
20508
the given index
20509
20510
@since version 1.0.0
20511
*/
20512
template < class IteratorType, typename std::enable_if <
20513
std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
20514
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
20515
= 0 >
20516
IteratorType erase(IteratorType pos)
20517
{
20518
// make sure iterator fits the current value
20519
if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
20520
{
20521
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
20522
}
20523
20524
IteratorType result = end();
20525
20526
switch (m_type)
20527
{
20528
case value_t::boolean:
20529
case value_t::number_float:
20530
case value_t::number_integer:
20531
case value_t::number_unsigned:
20532
case value_t::string:
20533
case value_t::binary:
20534
{
20535
if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
20536
{
20537
JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
20538
}
20539
20540
if (is_string())
20541
{
20542
AllocatorType<string_t> alloc;
20543
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
20544
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
20545
m_value.string = nullptr;
20546
}
20547
else if (is_binary())
20548
{
20549
AllocatorType<binary_t> alloc;
20550
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
20551
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
20552
m_value.binary = nullptr;
20553
}
20554
20555
m_type = value_t::null;
20556
assert_invariant();
20557
break;
20558
}
20559
20560
case value_t::object:
20561
{
20562
result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
20563
break;
20564
}
20565
20566
case value_t::array:
20567
{
20568
result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
20569
break;
20570
}
20571
20572
default:
20573
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
20574
}
20575
20576
return result;
20577
}
20578
20579
/*!
20580
@brief remove elements given an iterator range
20581
20582
Removes the element specified by the range `[first; last)`. The iterator
20583
@a first does not need to be dereferenceable if `first == last`: erasing
20584
an empty range is a no-op.
20585
20586
If called on a primitive type other than `null`, the resulting JSON value
20587
will be `null`.
20588
20589
@param[in] first iterator to the beginning of the range to remove
20590
@param[in] last iterator past the end of the range to remove
20591
@return Iterator following the last removed element. If the iterator @a
20592
second refers to the last element, the `end()` iterator is returned.
20593
20594
@tparam IteratorType an @ref iterator or @ref const_iterator
20595
20596
@post Invalidates iterators and references at or after the point of the
20597
erase, including the `end()` iterator.
20598
20599
@throw type_error.307 if called on a `null` value; example: `"cannot use
20600
erase() with null"`
20601
@throw invalid_iterator.203 if called on iterators which does not belong
20602
to the current JSON value; example: `"iterators do not fit current value"`
20603
@throw invalid_iterator.204 if called on a primitive type with invalid
20604
iterators (i.e., if `first != begin()` and `last != end()`); example:
20605
`"iterators out of range"`
20606
20607
@complexity The complexity depends on the type:
20608
- objects: `log(size()) + std::distance(first, last)`
20609
- arrays: linear in the distance between @a first and @a last, plus linear
20610
in the distance between @a last and end of the container
20611
- strings and binary: linear in the length of the member
20612
- other types: constant
20613
20614
@liveexample{The example shows the result of `erase()` for different JSON
20615
types.,erase__IteratorType_IteratorType}
20616
20617
@sa @ref erase(IteratorType) -- removes the element at a given position
20618
@sa @ref erase(const typename object_t::key_type&) -- removes the element
20619
from an object at the given key
20620
@sa @ref erase(const size_type) -- removes the element from an array at
20621
the given index
20622
20623
@since version 1.0.0
20624
*/
20625
template < class IteratorType, typename std::enable_if <
20626
std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
20627
std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
20628
= 0 >
20629
IteratorType erase(IteratorType first, IteratorType last)
20630
{
20631
// make sure iterator fits the current value
20632
if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
20633
{
20634
JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
20635
}
20636
20637
IteratorType result = end();
20638
20639
switch (m_type)
20640
{
20641
case value_t::boolean:
20642
case value_t::number_float:
20643
case value_t::number_integer:
20644
case value_t::number_unsigned:
20645
case value_t::string:
20646
case value_t::binary:
20647
{
20648
if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
20649
|| !last.m_it.primitive_iterator.is_end()))
20650
{
20651
JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
20652
}
20653
20654
if (is_string())
20655
{
20656
AllocatorType<string_t> alloc;
20657
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
20658
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
20659
m_value.string = nullptr;
20660
}
20661
else if (is_binary())
20662
{
20663
AllocatorType<binary_t> alloc;
20664
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
20665
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
20666
m_value.binary = nullptr;
20667
}
20668
20669
m_type = value_t::null;
20670
assert_invariant();
20671
break;
20672
}
20673
20674
case value_t::object:
20675
{
20676
result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
20677
last.m_it.object_iterator);
20678
break;
20679
}
20680
20681
case value_t::array:
20682
{
20683
result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
20684
last.m_it.array_iterator);
20685
break;
20686
}
20687
20688
default:
20689
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
20690
}
20691
20692
return result;
20693
}
20694
20695
/*!
20696
@brief remove element from a JSON object given a key
20697
20698
Removes elements from a JSON object with the key value @a key.
20699
20700
@param[in] key value of the elements to remove
20701
20702
@return Number of elements removed. If @a ObjectType is the default
20703
`std::map` type, the return value will always be `0` (@a key was not
20704
found) or `1` (@a key was found).
20705
20706
@post References and iterators to the erased elements are invalidated.
20707
Other references and iterators are not affected.
20708
20709
@throw type_error.307 when called on a type other than JSON object;
20710
example: `"cannot use erase() with null"`
20711
20712
@complexity `log(size()) + count(key)`
20713
20714
@liveexample{The example shows the effect of `erase()`.,erase__key_type}
20715
20716
@sa @ref erase(IteratorType) -- removes the element at a given position
20717
@sa @ref erase(IteratorType, IteratorType) -- removes the elements in
20718
the given range
20719
@sa @ref erase(const size_type) -- removes the element from an array at
20720
the given index
20721
20722
@since version 1.0.0
20723
*/
20724
size_type erase(const typename object_t::key_type& key)
20725
{
20726
// this erase only works for objects
20727
if (JSON_HEDLEY_LIKELY(is_object()))
20728
{
20729
return m_value.object->erase(key);
20730
}
20731
20732
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
20733
}
20734
20735
/*!
20736
@brief remove element from a JSON array given an index
20737
20738
Removes element from a JSON array at the index @a idx.
20739
20740
@param[in] idx index of the element to remove
20741
20742
@throw type_error.307 when called on a type other than JSON object;
20743
example: `"cannot use erase() with null"`
20744
@throw out_of_range.401 when `idx >= size()`; example: `"array index 17
20745
is out of range"`
20746
20747
@complexity Linear in distance between @a idx and the end of the container.
20748
20749
@liveexample{The example shows the effect of `erase()`.,erase__size_type}
20750
20751
@sa @ref erase(IteratorType) -- removes the element at a given position
20752
@sa @ref erase(IteratorType, IteratorType) -- removes the elements in
20753
the given range
20754
@sa @ref erase(const typename object_t::key_type&) -- removes the element
20755
from an object at the given key
20756
20757
@since version 1.0.0
20758
*/
20759
void erase(const size_type idx)
20760
{
20761
// this erase only works for arrays
20762
if (JSON_HEDLEY_LIKELY(is_array()))
20763
{
20764
if (JSON_HEDLEY_UNLIKELY(idx >= size()))
20765
{
20766
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
20767
}
20768
20769
m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
20770
}
20771
else
20772
{
20773
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
20774
}
20775
}
20776
20777
/// @}
20778
20779
20780
////////////
20781
// lookup //
20782
////////////
20783
20784
/// @name lookup
20785
/// @{
20786
20787
/*!
20788
@brief find an element in a JSON object
20789
20790
Finds an element in a JSON object with key equivalent to @a key. If the
20791
element is not found or the JSON value is not an object, end() is
20792
returned.
20793
20794
@note This method always returns @ref end() when executed on a JSON type
20795
that is not an object.
20796
20797
@param[in] key key value of the element to search for.
20798
20799
@return Iterator to an element with key equivalent to @a key. If no such
20800
element is found or the JSON value is not an object, past-the-end (see
20801
@ref end()) iterator is returned.
20802
20803
@complexity Logarithmic in the size of the JSON object.
20804
20805
@liveexample{The example shows how `find()` is used.,find__key_type}
20806
20807
@sa @ref contains(KeyT&&) const -- checks whether a key exists
20808
20809
@since version 1.0.0
20810
*/
20811
template<typename KeyT>
20812
iterator find(KeyT&& key)
20813
{
20814
auto result = end();
20815
20816
if (is_object())
20817
{
20818
result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
20819
}
20820
20821
return result;
20822
}
20823
20824
/*!
20825
@brief find an element in a JSON object
20826
@copydoc find(KeyT&&)
20827
*/
20828
template<typename KeyT>
20829
const_iterator find(KeyT&& key) const
20830
{
20831
auto result = cend();
20832
20833
if (is_object())
20834
{
20835
result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
20836
}
20837
20838
return result;
20839
}
20840
20841
/*!
20842
@brief returns the number of occurrences of a key in a JSON object
20843
20844
Returns the number of elements with key @a key. If ObjectType is the
20845
default `std::map` type, the return value will always be `0` (@a key was
20846
not found) or `1` (@a key was found).
20847
20848
@note This method always returns `0` when executed on a JSON type that is
20849
not an object.
20850
20851
@param[in] key key value of the element to count
20852
20853
@return Number of elements with key @a key. If the JSON value is not an
20854
object, the return value will be `0`.
20855
20856
@complexity Logarithmic in the size of the JSON object.
20857
20858
@liveexample{The example shows how `count()` is used.,count}
20859
20860
@since version 1.0.0
20861
*/
20862
template<typename KeyT>
20863
size_type count(KeyT&& key) const
20864
{
20865
// return 0 for all nonobject types
20866
return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
20867
}
20868
20869
/*!
20870
@brief check the existence of an element in a JSON object
20871
20872
Check whether an element exists in a JSON object with key equivalent to
20873
@a key. If the element is not found or the JSON value is not an object,
20874
false is returned.
20875
20876
@note This method always returns false when executed on a JSON type
20877
that is not an object.
20878
20879
@param[in] key key value to check its existence.
20880
20881
@return true if an element with specified @a key exists. If no such
20882
element with such key is found or the JSON value is not an object,
20883
false is returned.
20884
20885
@complexity Logarithmic in the size of the JSON object.
20886
20887
@liveexample{The following code shows an example for `contains()`.,contains}
20888
20889
@sa @ref find(KeyT&&) -- returns an iterator to an object element
20890
@sa @ref contains(const json_pointer&) const -- checks the existence for a JSON pointer
20891
20892
@since version 3.6.0
20893
*/
20894
template < typename KeyT, typename std::enable_if <
20895
!std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int >::type = 0 >
20896
bool contains(KeyT && key) const
20897
{
20898
return is_object() && m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
20899
}
20900
20901
/*!
20902
@brief check the existence of an element in a JSON object given a JSON pointer
20903
20904
Check whether the given JSON pointer @a ptr can be resolved in the current
20905
JSON value.
20906
20907
@note This method can be executed on any JSON value type.
20908
20909
@param[in] ptr JSON pointer to check its existence.
20910
20911
@return true if the JSON pointer can be resolved to a stored value, false
20912
otherwise.
20913
20914
@post If `j.contains(ptr)` returns true, it is safe to call `j[ptr]`.
20915
20916
@throw parse_error.106 if an array index begins with '0'
20917
@throw parse_error.109 if an array index was not a number
20918
20919
@complexity Logarithmic in the size of the JSON object.
20920
20921
@liveexample{The following code shows an example for `contains()`.,contains_json_pointer}
20922
20923
@sa @ref contains(KeyT &&) const -- checks the existence of a key
20924
20925
@since version 3.7.0
20926
*/
20927
bool contains(const json_pointer& ptr) const
20928
{
20929
return ptr.contains(this);
20930
}
20931
20932
/// @}
20933
20934
20935
///////////////
20936
// iterators //
20937
///////////////
20938
20939
/// @name iterators
20940
/// @{
20941
20942
/*!
20943
@brief returns an iterator to the first element
20944
20945
Returns an iterator to the first element.
20946
20947
@image html range-begin-end.svg "Illustration from cppreference.com"
20948
20949
@return iterator to the first element
20950
20951
@complexity Constant.
20952
20953
@requirement This function helps `basic_json` satisfying the
20954
[Container](https://en.cppreference.com/w/cpp/named_req/Container)
20955
requirements:
20956
- The complexity is constant.
20957
20958
@liveexample{The following code shows an example for `begin()`.,begin}
20959
20960
@sa @ref cbegin() -- returns a const iterator to the beginning
20961
@sa @ref end() -- returns an iterator to the end
20962
@sa @ref cend() -- returns a const iterator to the end
20963
20964
@since version 1.0.0
20965
*/
20966
iterator begin() noexcept
20967
{
20968
iterator result(this);
20969
result.set_begin();
20970
return result;
20971
}
20972
20973
/*!
20974
@copydoc basic_json::cbegin()
20975
*/
20976
const_iterator begin() const noexcept
20977
{
20978
return cbegin();
20979
}
20980
20981
/*!
20982
@brief returns a const iterator to the first element
20983
20984
Returns a const iterator to the first element.
20985
20986
@image html range-begin-end.svg "Illustration from cppreference.com"
20987
20988
@return const iterator to the first element
20989
20990
@complexity Constant.
20991
20992
@requirement This function helps `basic_json` satisfying the
20993
[Container](https://en.cppreference.com/w/cpp/named_req/Container)
20994
requirements:
20995
- The complexity is constant.
20996
- Has the semantics of `const_cast<const basic_json&>(*this).begin()`.
20997
20998
@liveexample{The following code shows an example for `cbegin()`.,cbegin}
20999
21000
@sa @ref begin() -- returns an iterator to the beginning
21001
@sa @ref end() -- returns an iterator to the end
21002
@sa @ref cend() -- returns a const iterator to the end
21003
21004
@since version 1.0.0
21005
*/
21006
const_iterator cbegin() const noexcept
21007
{
21008
const_iterator result(this);
21009
result.set_begin();
21010
return result;
21011
}
21012
21013
/*!
21014
@brief returns an iterator to one past the last element
21015
21016
Returns an iterator to one past the last element.
21017
21018
@image html range-begin-end.svg "Illustration from cppreference.com"
21019
21020
@return iterator one past the last element
21021
21022
@complexity Constant.
21023
21024
@requirement This function helps `basic_json` satisfying the
21025
[Container](https://en.cppreference.com/w/cpp/named_req/Container)
21026
requirements:
21027
- The complexity is constant.
21028
21029
@liveexample{The following code shows an example for `end()`.,end}
21030
21031
@sa @ref cend() -- returns a const iterator to the end
21032
@sa @ref begin() -- returns an iterator to the beginning
21033
@sa @ref cbegin() -- returns a const iterator to the beginning
21034
21035
@since version 1.0.0
21036
*/
21037
iterator end() noexcept
21038
{
21039
iterator result(this);
21040
result.set_end();
21041
return result;
21042
}
21043
21044
/*!
21045
@copydoc basic_json::cend()
21046
*/
21047
const_iterator end() const noexcept
21048
{
21049
return cend();
21050
}
21051
21052
/*!
21053
@brief returns a const iterator to one past the last element
21054
21055
Returns a const iterator to one past the last element.
21056
21057
@image html range-begin-end.svg "Illustration from cppreference.com"
21058
21059
@return const iterator one past the last element
21060
21061
@complexity Constant.
21062
21063
@requirement This function helps `basic_json` satisfying the
21064
[Container](https://en.cppreference.com/w/cpp/named_req/Container)
21065
requirements:
21066
- The complexity is constant.
21067
- Has the semantics of `const_cast<const basic_json&>(*this).end()`.
21068
21069
@liveexample{The following code shows an example for `cend()`.,cend}
21070
21071
@sa @ref end() -- returns an iterator to the end
21072
@sa @ref begin() -- returns an iterator to the beginning
21073
@sa @ref cbegin() -- returns a const iterator to the beginning
21074
21075
@since version 1.0.0
21076
*/
21077
const_iterator cend() const noexcept
21078
{
21079
const_iterator result(this);
21080
result.set_end();
21081
return result;
21082
}
21083
21084
/*!
21085
@brief returns an iterator to the reverse-beginning
21086
21087
Returns an iterator to the reverse-beginning; that is, the last element.
21088
21089
@image html range-rbegin-rend.svg "Illustration from cppreference.com"
21090
21091
@complexity Constant.
21092
21093
@requirement This function helps `basic_json` satisfying the
21094
[ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
21095
requirements:
21096
- The complexity is constant.
21097
- Has the semantics of `reverse_iterator(end())`.
21098
21099
@liveexample{The following code shows an example for `rbegin()`.,rbegin}
21100
21101
@sa @ref crbegin() -- returns a const reverse iterator to the beginning
21102
@sa @ref rend() -- returns a reverse iterator to the end
21103
@sa @ref crend() -- returns a const reverse iterator to the end
21104
21105
@since version 1.0.0
21106
*/
21107
reverse_iterator rbegin() noexcept
21108
{
21109
return reverse_iterator(end());
21110
}
21111
21112
/*!
21113
@copydoc basic_json::crbegin()
21114
*/
21115
const_reverse_iterator rbegin() const noexcept
21116
{
21117
return crbegin();
21118
}
21119
21120
/*!
21121
@brief returns an iterator to the reverse-end
21122
21123
Returns an iterator to the reverse-end; that is, one before the first
21124
element.
21125
21126
@image html range-rbegin-rend.svg "Illustration from cppreference.com"
21127
21128
@complexity Constant.
21129
21130
@requirement This function helps `basic_json` satisfying the
21131
[ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
21132
requirements:
21133
- The complexity is constant.
21134
- Has the semantics of `reverse_iterator(begin())`.
21135
21136
@liveexample{The following code shows an example for `rend()`.,rend}
21137
21138
@sa @ref crend() -- returns a const reverse iterator to the end
21139
@sa @ref rbegin() -- returns a reverse iterator to the beginning
21140
@sa @ref crbegin() -- returns a const reverse iterator to the beginning
21141
21142
@since version 1.0.0
21143
*/
21144
reverse_iterator rend() noexcept
21145
{
21146
return reverse_iterator(begin());
21147
}
21148
21149
/*!
21150
@copydoc basic_json::crend()
21151
*/
21152
const_reverse_iterator rend() const noexcept
21153
{
21154
return crend();
21155
}
21156
21157
/*!
21158
@brief returns a const reverse iterator to the last element
21159
21160
Returns a const iterator to the reverse-beginning; that is, the last
21161
element.
21162
21163
@image html range-rbegin-rend.svg "Illustration from cppreference.com"
21164
21165
@complexity Constant.
21166
21167
@requirement This function helps `basic_json` satisfying the
21168
[ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
21169
requirements:
21170
- The complexity is constant.
21171
- Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.
21172
21173
@liveexample{The following code shows an example for `crbegin()`.,crbegin}
21174
21175
@sa @ref rbegin() -- returns a reverse iterator to the beginning
21176
@sa @ref rend() -- returns a reverse iterator to the end
21177
@sa @ref crend() -- returns a const reverse iterator to the end
21178
21179
@since version 1.0.0
21180
*/
21181
const_reverse_iterator crbegin() const noexcept
21182
{
21183
return const_reverse_iterator(cend());
21184
}
21185
21186
/*!
21187
@brief returns a const reverse iterator to one before the first
21188
21189
Returns a const reverse iterator to the reverse-end; that is, one before
21190
the first element.
21191
21192
@image html range-rbegin-rend.svg "Illustration from cppreference.com"
21193
21194
@complexity Constant.
21195
21196
@requirement This function helps `basic_json` satisfying the
21197
[ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
21198
requirements:
21199
- The complexity is constant.
21200
- Has the semantics of `const_cast<const basic_json&>(*this).rend()`.
21201
21202
@liveexample{The following code shows an example for `crend()`.,crend}
21203
21204
@sa @ref rend() -- returns a reverse iterator to the end
21205
@sa @ref rbegin() -- returns a reverse iterator to the beginning
21206
@sa @ref crbegin() -- returns a const reverse iterator to the beginning
21207
21208
@since version 1.0.0
21209
*/
21210
const_reverse_iterator crend() const noexcept
21211
{
21212
return const_reverse_iterator(cbegin());
21213
}
21214
21215
public:
21216
/*!
21217
@brief wrapper to access iterator member functions in range-based for
21218
21219
This function allows to access @ref iterator::key() and @ref
21220
iterator::value() during range-based for loops. In these loops, a
21221
reference to the JSON values is returned, so there is no access to the
21222
underlying iterator.
21223
21224
For loop without iterator_wrapper:
21225
21226
@code{cpp}
21227
for (auto it = j_object.begin(); it != j_object.end(); ++it)
21228
{
21229
std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
21230
}
21231
@endcode
21232
21233
Range-based for loop without iterator proxy:
21234
21235
@code{cpp}
21236
for (auto it : j_object)
21237
{
21238
// "it" is of type json::reference and has no key() member
21239
std::cout << "value: " << it << '\n';
21240
}
21241
@endcode
21242
21243
Range-based for loop with iterator proxy:
21244
21245
@code{cpp}
21246
for (auto it : json::iterator_wrapper(j_object))
21247
{
21248
std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
21249
}
21250
@endcode
21251
21252
@note When iterating over an array, `key()` will return the index of the
21253
element as string (see example).
21254
21255
@param[in] ref reference to a JSON value
21256
@return iteration proxy object wrapping @a ref with an interface to use in
21257
range-based for loops
21258
21259
@liveexample{The following code shows how the wrapper is used,iterator_wrapper}
21260
21261
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
21262
changes in the JSON value.
21263
21264
@complexity Constant.
21265
21266
@note The name of this function is not yet final and may change in the
21267
future.
21268
21269
@deprecated This stream operator is deprecated and will be removed in
21270
future 4.0.0 of the library. Please use @ref items() instead;
21271
that is, replace `json::iterator_wrapper(j)` with `j.items()`.
21272
*/
21273
JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
21274
static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
21275
{
21276
return ref.items();
21277
}
21278
21279
/*!
21280
@copydoc iterator_wrapper(reference)
21281
*/
21282
JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
21283
static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
21284
{
21285
return ref.items();
21286
}
21287
21288
/*!
21289
@brief helper to access iterator member functions in range-based for
21290
21291
This function allows to access @ref iterator::key() and @ref
21292
iterator::value() during range-based for loops. In these loops, a
21293
reference to the JSON values is returned, so there is no access to the
21294
underlying iterator.
21295
21296
For loop without `items()` function:
21297
21298
@code{cpp}
21299
for (auto it = j_object.begin(); it != j_object.end(); ++it)
21300
{
21301
std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
21302
}
21303
@endcode
21304
21305
Range-based for loop without `items()` function:
21306
21307
@code{cpp}
21308
for (auto it : j_object)
21309
{
21310
// "it" is of type json::reference and has no key() member
21311
std::cout << "value: " << it << '\n';
21312
}
21313
@endcode
21314
21315
Range-based for loop with `items()` function:
21316
21317
@code{cpp}
21318
for (auto& el : j_object.items())
21319
{
21320
std::cout << "key: " << el.key() << ", value:" << el.value() << '\n';
21321
}
21322
@endcode
21323
21324
The `items()` function also allows to use
21325
[structured bindings](https://en.cppreference.com/w/cpp/language/structured_binding)
21326
(C++17):
21327
21328
@code{cpp}
21329
for (auto& [key, val] : j_object.items())
21330
{
21331
std::cout << "key: " << key << ", value:" << val << '\n';
21332
}
21333
@endcode
21334
21335
@note When iterating over an array, `key()` will return the index of the
21336
element as string (see example). For primitive types (e.g., numbers),
21337
`key()` returns an empty string.
21338
21339
@warning Using `items()` on temporary objects is dangerous. Make sure the
21340
object's lifetime exeeds the iteration. See
21341
<https://github.com/nlohmann/json/issues/2040> for more
21342
information.
21343
21344
@return iteration proxy object wrapping @a ref with an interface to use in
21345
range-based for loops
21346
21347
@liveexample{The following code shows how the function is used.,items}
21348
21349
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
21350
changes in the JSON value.
21351
21352
@complexity Constant.
21353
21354
@since version 3.1.0, structured bindings support since 3.5.0.
21355
*/
21356
iteration_proxy<iterator> items() noexcept
21357
{
21358
return iteration_proxy<iterator>(*this);
21359
}
21360
21361
/*!
21362
@copydoc items()
21363
*/
21364
iteration_proxy<const_iterator> items() const noexcept
21365
{
21366
return iteration_proxy<const_iterator>(*this);
21367
}
21368
21369
/// @}
21370
21371
21372
//////////////
21373
// capacity //
21374
//////////////
21375
21376
/// @name capacity
21377
/// @{
21378
21379
/*!
21380
@brief checks whether the container is empty.
21381
21382
Checks if a JSON value has no elements (i.e. whether its @ref size is `0`).
21383
21384
@return The return value depends on the different types and is
21385
defined as follows:
21386
Value type | return value
21387
----------- | -------------
21388
null | `true`
21389
boolean | `false`
21390
string | `false`
21391
number | `false`
21392
binary | `false`
21393
object | result of function `object_t::empty()`
21394
array | result of function `array_t::empty()`
21395
21396
@liveexample{The following code uses `empty()` to check if a JSON
21397
object contains any elements.,empty}
21398
21399
@complexity Constant, as long as @ref array_t and @ref object_t satisfy
21400
the Container concept; that is, their `empty()` functions have constant
21401
complexity.
21402
21403
@iterators No changes.
21404
21405
@exceptionsafety No-throw guarantee: this function never throws exceptions.
21406
21407
@note This function does not return whether a string stored as JSON value
21408
is empty - it returns whether the JSON container itself is empty which is
21409
false in the case of a string.
21410
21411
@requirement This function helps `basic_json` satisfying the
21412
[Container](https://en.cppreference.com/w/cpp/named_req/Container)
21413
requirements:
21414
- The complexity is constant.
21415
- Has the semantics of `begin() == end()`.
21416
21417
@sa @ref size() -- returns the number of elements
21418
21419
@since version 1.0.0
21420
*/
21421
bool empty() const noexcept
21422
{
21423
switch (m_type)
21424
{
21425
case value_t::null:
21426
{
21427
// null values are empty
21428
return true;
21429
}
21430
21431
case value_t::array:
21432
{
21433
// delegate call to array_t::empty()
21434
return m_value.array->empty();
21435
}
21436
21437
case value_t::object:
21438
{
21439
// delegate call to object_t::empty()
21440
return m_value.object->empty();
21441
}
21442
21443
default:
21444
{
21445
// all other types are nonempty
21446
return false;
21447
}
21448
}
21449
}
21450
21451
/*!
21452
@brief returns the number of elements
21453
21454
Returns the number of elements in a JSON value.
21455
21456
@return The return value depends on the different types and is
21457
defined as follows:
21458
Value type | return value
21459
----------- | -------------
21460
null | `0`
21461
boolean | `1`
21462
string | `1`
21463
number | `1`
21464
binary | `1`
21465
object | result of function object_t::size()
21466
array | result of function array_t::size()
21467
21468
@liveexample{The following code calls `size()` on the different value
21469
types.,size}
21470
21471
@complexity Constant, as long as @ref array_t and @ref object_t satisfy
21472
the Container concept; that is, their size() functions have constant
21473
complexity.
21474
21475
@iterators No changes.
21476
21477
@exceptionsafety No-throw guarantee: this function never throws exceptions.
21478
21479
@note This function does not return the length of a string stored as JSON
21480
value - it returns the number of elements in the JSON value which is 1 in
21481
the case of a string.
21482
21483
@requirement This function helps `basic_json` satisfying the
21484
[Container](https://en.cppreference.com/w/cpp/named_req/Container)
21485
requirements:
21486
- The complexity is constant.
21487
- Has the semantics of `std::distance(begin(), end())`.
21488
21489
@sa @ref empty() -- checks whether the container is empty
21490
@sa @ref max_size() -- returns the maximal number of elements
21491
21492
@since version 1.0.0
21493
*/
21494
size_type size() const noexcept
21495
{
21496
switch (m_type)
21497
{
21498
case value_t::null:
21499
{
21500
// null values are empty
21501
return 0;
21502
}
21503
21504
case value_t::array:
21505
{
21506
// delegate call to array_t::size()
21507
return m_value.array->size();
21508
}
21509
21510
case value_t::object:
21511
{
21512
// delegate call to object_t::size()
21513
return m_value.object->size();
21514
}
21515
21516
default:
21517
{
21518
// all other types have size 1
21519
return 1;
21520
}
21521
}
21522
}
21523
21524
/*!
21525
@brief returns the maximum possible number of elements
21526
21527
Returns the maximum number of elements a JSON value is able to hold due to
21528
system or library implementation limitations, i.e. `std::distance(begin(),
21529
end())` for the JSON value.
21530
21531
@return The return value depends on the different types and is
21532
defined as follows:
21533
Value type | return value
21534
----------- | -------------
21535
null | `0` (same as `size()`)
21536
boolean | `1` (same as `size()`)
21537
string | `1` (same as `size()`)
21538
number | `1` (same as `size()`)
21539
binary | `1` (same as `size()`)
21540
object | result of function `object_t::max_size()`
21541
array | result of function `array_t::max_size()`
21542
21543
@liveexample{The following code calls `max_size()` on the different value
21544
types. Note the output is implementation specific.,max_size}
21545
21546
@complexity Constant, as long as @ref array_t and @ref object_t satisfy
21547
the Container concept; that is, their `max_size()` functions have constant
21548
complexity.
21549
21550
@iterators No changes.
21551
21552
@exceptionsafety No-throw guarantee: this function never throws exceptions.
21553
21554
@requirement This function helps `basic_json` satisfying the
21555
[Container](https://en.cppreference.com/w/cpp/named_req/Container)
21556
requirements:
21557
- The complexity is constant.
21558
- Has the semantics of returning `b.size()` where `b` is the largest
21559
possible JSON value.
21560
21561
@sa @ref size() -- returns the number of elements
21562
21563
@since version 1.0.0
21564
*/
21565
size_type max_size() const noexcept
21566
{
21567
switch (m_type)
21568
{
21569
case value_t::array:
21570
{
21571
// delegate call to array_t::max_size()
21572
return m_value.array->max_size();
21573
}
21574
21575
case value_t::object:
21576
{
21577
// delegate call to object_t::max_size()
21578
return m_value.object->max_size();
21579
}
21580
21581
default:
21582
{
21583
// all other types have max_size() == size()
21584
return size();
21585
}
21586
}
21587
}
21588
21589
/// @}
21590
21591
21592
///////////////
21593
// modifiers //
21594
///////////////
21595
21596
/// @name modifiers
21597
/// @{
21598
21599
/*!
21600
@brief clears the contents
21601
21602
Clears the content of a JSON value and resets it to the default value as
21603
if @ref basic_json(value_t) would have been called with the current value
21604
type from @ref type():
21605
21606
Value type | initial value
21607
----------- | -------------
21608
null | `null`
21609
boolean | `false`
21610
string | `""`
21611
number | `0`
21612
binary | An empty byte vector
21613
object | `{}`
21614
array | `[]`
21615
21616
@post Has the same effect as calling
21617
@code {.cpp}
21618
*this = basic_json(type());
21619
@endcode
21620
21621
@liveexample{The example below shows the effect of `clear()` to different
21622
JSON types.,clear}
21623
21624
@complexity Linear in the size of the JSON value.
21625
21626
@iterators All iterators, pointers and references related to this container
21627
are invalidated.
21628
21629
@exceptionsafety No-throw guarantee: this function never throws exceptions.
21630
21631
@sa @ref basic_json(value_t) -- constructor that creates an object with the
21632
same value than calling `clear()`
21633
21634
@since version 1.0.0
21635
*/
21636
void clear() noexcept
21637
{
21638
switch (m_type)
21639
{
21640
case value_t::number_integer:
21641
{
21642
m_value.number_integer = 0;
21643
break;
21644
}
21645
21646
case value_t::number_unsigned:
21647
{
21648
m_value.number_unsigned = 0;
21649
break;
21650
}
21651
21652
case value_t::number_float:
21653
{
21654
m_value.number_float = 0.0;
21655
break;
21656
}
21657
21658
case value_t::boolean:
21659
{
21660
m_value.boolean = false;
21661
break;
21662
}
21663
21664
case value_t::string:
21665
{
21666
m_value.string->clear();
21667
break;
21668
}
21669
21670
case value_t::binary:
21671
{
21672
m_value.binary->clear();
21673
break;
21674
}
21675
21676
case value_t::array:
21677
{
21678
m_value.array->clear();
21679
break;
21680
}
21681
21682
case value_t::object:
21683
{
21684
m_value.object->clear();
21685
break;
21686
}
21687
21688
default:
21689
break;
21690
}
21691
}
21692
21693
/*!
21694
@brief add an object to an array
21695
21696
Appends the given element @a val to the end of the JSON value. If the
21697
function is called on a JSON null value, an empty array is created before
21698
appending @a val.
21699
21700
@param[in] val the value to add to the JSON array
21701
21702
@throw type_error.308 when called on a type other than JSON array or
21703
null; example: `"cannot use push_back() with number"`
21704
21705
@complexity Amortized constant.
21706
21707
@liveexample{The example shows how `push_back()` and `+=` can be used to
21708
add elements to a JSON array. Note how the `null` value was silently
21709
converted to a JSON array.,push_back}
21710
21711
@since version 1.0.0
21712
*/
21713
void push_back(basic_json&& val)
21714
{
21715
// push_back only works for null objects or arrays
21716
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
21717
{
21718
JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
21719
}
21720
21721
// transform null object into an array
21722
if (is_null())
21723
{
21724
m_type = value_t::array;
21725
m_value = value_t::array;
21726
assert_invariant();
21727
}
21728
21729
// add element to array (move semantics)
21730
m_value.array->push_back(std::move(val));
21731
// if val is moved from, basic_json move constructor marks it null so we do not call the destructor
21732
}
21733
21734
/*!
21735
@brief add an object to an array
21736
@copydoc push_back(basic_json&&)
21737
*/
21738
reference operator+=(basic_json&& val)
21739
{
21740
push_back(std::move(val));
21741
return *this;
21742
}
21743
21744
/*!
21745
@brief add an object to an array
21746
@copydoc push_back(basic_json&&)
21747
*/
21748
void push_back(const basic_json& val)
21749
{
21750
// push_back only works for null objects or arrays
21751
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
21752
{
21753
JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
21754
}
21755
21756
// transform null object into an array
21757
if (is_null())
21758
{
21759
m_type = value_t::array;
21760
m_value = value_t::array;
21761
assert_invariant();
21762
}
21763
21764
// add element to array
21765
m_value.array->push_back(val);
21766
}
21767
21768
/*!
21769
@brief add an object to an array
21770
@copydoc push_back(basic_json&&)
21771
*/
21772
reference operator+=(const basic_json& val)
21773
{
21774
push_back(val);
21775
return *this;
21776
}
21777
21778
/*!
21779
@brief add an object to an object
21780
21781
Inserts the given element @a val to the JSON object. If the function is
21782
called on a JSON null value, an empty object is created before inserting
21783
@a val.
21784
21785
@param[in] val the value to add to the JSON object
21786
21787
@throw type_error.308 when called on a type other than JSON object or
21788
null; example: `"cannot use push_back() with number"`
21789
21790
@complexity Logarithmic in the size of the container, O(log(`size()`)).
21791
21792
@liveexample{The example shows how `push_back()` and `+=` can be used to
21793
add elements to a JSON object. Note how the `null` value was silently
21794
converted to a JSON object.,push_back__object_t__value}
21795
21796
@since version 1.0.0
21797
*/
21798
void push_back(const typename object_t::value_type& val)
21799
{
21800
// push_back only works for null objects or objects
21801
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
21802
{
21803
JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
21804
}
21805
21806
// transform null object into an object
21807
if (is_null())
21808
{
21809
m_type = value_t::object;
21810
m_value = value_t::object;
21811
assert_invariant();
21812
}
21813
21814
// add element to array
21815
m_value.object->insert(val);
21816
}
21817
21818
/*!
21819
@brief add an object to an object
21820
@copydoc push_back(const typename object_t::value_type&)
21821
*/
21822
reference operator+=(const typename object_t::value_type& val)
21823
{
21824
push_back(val);
21825
return *this;
21826
}
21827
21828
/*!
21829
@brief add an object to an object
21830
21831
This function allows to use `push_back` with an initializer list. In case
21832
21833
1. the current value is an object,
21834
2. the initializer list @a init contains only two elements, and
21835
3. the first element of @a init is a string,
21836
21837
@a init is converted into an object element and added using
21838
@ref push_back(const typename object_t::value_type&). Otherwise, @a init
21839
is converted to a JSON value and added using @ref push_back(basic_json&&).
21840
21841
@param[in] init an initializer list
21842
21843
@complexity Linear in the size of the initializer list @a init.
21844
21845
@note This function is required to resolve an ambiguous overload error,
21846
because pairs like `{"key", "value"}` can be both interpreted as
21847
`object_t::value_type` or `std::initializer_list<basic_json>`, see
21848
https://github.com/nlohmann/json/issues/235 for more information.
21849
21850
@liveexample{The example shows how initializer lists are treated as
21851
objects when possible.,push_back__initializer_list}
21852
*/
21853
void push_back(initializer_list_t init)
21854
{
21855
if (is_object() && init.size() == 2 && (*init.begin())->is_string())
21856
{
21857
basic_json&& key = init.begin()->moved_or_copied();
21858
push_back(typename object_t::value_type(
21859
std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
21860
}
21861
else
21862
{
21863
push_back(basic_json(init));
21864
}
21865
}
21866
21867
/*!
21868
@brief add an object to an object
21869
@copydoc push_back(initializer_list_t)
21870
*/
21871
reference operator+=(initializer_list_t init)
21872
{
21873
push_back(init);
21874
return *this;
21875
}
21876
21877
/*!
21878
@brief add an object to an array
21879
21880
Creates a JSON value from the passed parameters @a args to the end of the
21881
JSON value. If the function is called on a JSON null value, an empty array
21882
is created before appending the value created from @a args.
21883
21884
@param[in] args arguments to forward to a constructor of @ref basic_json
21885
@tparam Args compatible types to create a @ref basic_json object
21886
21887
@return reference to the inserted element
21888
21889
@throw type_error.311 when called on a type other than JSON array or
21890
null; example: `"cannot use emplace_back() with number"`
21891
21892
@complexity Amortized constant.
21893
21894
@liveexample{The example shows how `push_back()` can be used to add
21895
elements to a JSON array. Note how the `null` value was silently converted
21896
to a JSON array.,emplace_back}
21897
21898
@since version 2.0.8, returns reference since 3.7.0
21899
*/
21900
template<class... Args>
21901
reference emplace_back(Args&& ... args)
21902
{
21903
// emplace_back only works for null objects or arrays
21904
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
21905
{
21906
JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
21907
}
21908
21909
// transform null object into an array
21910
if (is_null())
21911
{
21912
m_type = value_t::array;
21913
m_value = value_t::array;
21914
assert_invariant();
21915
}
21916
21917
// add element to array (perfect forwarding)
21918
#ifdef JSON_HAS_CPP_17
21919
return m_value.array->emplace_back(std::forward<Args>(args)...);
21920
#else
21921
m_value.array->emplace_back(std::forward<Args>(args)...);
21922
return m_value.array->back();
21923
#endif
21924
}
21925
21926
/*!
21927
@brief add an object to an object if key does not exist
21928
21929
Inserts a new element into a JSON object constructed in-place with the
21930
given @a args if there is no element with the key in the container. If the
21931
function is called on a JSON null value, an empty object is created before
21932
appending the value created from @a args.
21933
21934
@param[in] args arguments to forward to a constructor of @ref basic_json
21935
@tparam Args compatible types to create a @ref basic_json object
21936
21937
@return a pair consisting of an iterator to the inserted element, or the
21938
already-existing element if no insertion happened, and a bool
21939
denoting whether the insertion took place.
21940
21941
@throw type_error.311 when called on a type other than JSON object or
21942
null; example: `"cannot use emplace() with number"`
21943
21944
@complexity Logarithmic in the size of the container, O(log(`size()`)).
21945
21946
@liveexample{The example shows how `emplace()` can be used to add elements
21947
to a JSON object. Note how the `null` value was silently converted to a
21948
JSON object. Further note how no value is added if there was already one
21949
value stored with the same key.,emplace}
21950
21951
@since version 2.0.8
21952
*/
21953
template<class... Args>
21954
std::pair<iterator, bool> emplace(Args&& ... args)
21955
{
21956
// emplace only works for null objects or arrays
21957
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
21958
{
21959
JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
21960
}
21961
21962
// transform null object into an object
21963
if (is_null())
21964
{
21965
m_type = value_t::object;
21966
m_value = value_t::object;
21967
assert_invariant();
21968
}
21969
21970
// add element to array (perfect forwarding)
21971
auto res = m_value.object->emplace(std::forward<Args>(args)...);
21972
// create result iterator and set iterator to the result of emplace
21973
auto it = begin();
21974
it.m_it.object_iterator = res.first;
21975
21976
// return pair of iterator and boolean
21977
return {it, res.second};
21978
}
21979
21980
/// Helper for insertion of an iterator
21981
/// @note: This uses std::distance to support GCC 4.8,
21982
/// see https://github.com/nlohmann/json/pull/1257
21983
template<typename... Args>
21984
iterator insert_iterator(const_iterator pos, Args&& ... args)
21985
{
21986
iterator result(this);
21987
JSON_ASSERT(m_value.array != nullptr);
21988
21989
auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
21990
m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
21991
result.m_it.array_iterator = m_value.array->begin() + insert_pos;
21992
21993
// This could have been written as:
21994
// result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
21995
// but the return value of insert is missing in GCC 4.8, so it is written this way instead.
21996
21997
return result;
21998
}
21999
22000
/*!
22001
@brief inserts element
22002
22003
Inserts element @a val before iterator @a pos.
22004
22005
@param[in] pos iterator before which the content will be inserted; may be
22006
the end() iterator
22007
@param[in] val element to insert
22008
@return iterator pointing to the inserted @a val.
22009
22010
@throw type_error.309 if called on JSON values other than arrays;
22011
example: `"cannot use insert() with string"`
22012
@throw invalid_iterator.202 if @a pos is not an iterator of *this;
22013
example: `"iterator does not fit current value"`
22014
22015
@complexity Constant plus linear in the distance between @a pos and end of
22016
the container.
22017
22018
@liveexample{The example shows how `insert()` is used.,insert}
22019
22020
@since version 1.0.0
22021
*/
22022
iterator insert(const_iterator pos, const basic_json& val)
22023
{
22024
// insert only works for arrays
22025
if (JSON_HEDLEY_LIKELY(is_array()))
22026
{
22027
// check if iterator pos fits to this JSON value
22028
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22029
{
22030
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
22031
}
22032
22033
// insert to array and return iterator
22034
return insert_iterator(pos, val);
22035
}
22036
22037
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
22038
}
22039
22040
/*!
22041
@brief inserts element
22042
@copydoc insert(const_iterator, const basic_json&)
22043
*/
22044
iterator insert(const_iterator pos, basic_json&& val)
22045
{
22046
return insert(pos, val);
22047
}
22048
22049
/*!
22050
@brief inserts elements
22051
22052
Inserts @a cnt copies of @a val before iterator @a pos.
22053
22054
@param[in] pos iterator before which the content will be inserted; may be
22055
the end() iterator
22056
@param[in] cnt number of copies of @a val to insert
22057
@param[in] val element to insert
22058
@return iterator pointing to the first element inserted, or @a pos if
22059
`cnt==0`
22060
22061
@throw type_error.309 if called on JSON values other than arrays; example:
22062
`"cannot use insert() with string"`
22063
@throw invalid_iterator.202 if @a pos is not an iterator of *this;
22064
example: `"iterator does not fit current value"`
22065
22066
@complexity Linear in @a cnt plus linear in the distance between @a pos
22067
and end of the container.
22068
22069
@liveexample{The example shows how `insert()` is used.,insert__count}
22070
22071
@since version 1.0.0
22072
*/
22073
iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
22074
{
22075
// insert only works for arrays
22076
if (JSON_HEDLEY_LIKELY(is_array()))
22077
{
22078
// check if iterator pos fits to this JSON value
22079
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22080
{
22081
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
22082
}
22083
22084
// insert to array and return iterator
22085
return insert_iterator(pos, cnt, val);
22086
}
22087
22088
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
22089
}
22090
22091
/*!
22092
@brief inserts elements
22093
22094
Inserts elements from range `[first, last)` before iterator @a pos.
22095
22096
@param[in] pos iterator before which the content will be inserted; may be
22097
the end() iterator
22098
@param[in] first begin of the range of elements to insert
22099
@param[in] last end of the range of elements to insert
22100
22101
@throw type_error.309 if called on JSON values other than arrays; example:
22102
`"cannot use insert() with string"`
22103
@throw invalid_iterator.202 if @a pos is not an iterator of *this;
22104
example: `"iterator does not fit current value"`
22105
@throw invalid_iterator.210 if @a first and @a last do not belong to the
22106
same JSON value; example: `"iterators do not fit"`
22107
@throw invalid_iterator.211 if @a first or @a last are iterators into
22108
container for which insert is called; example: `"passed iterators may not
22109
belong to container"`
22110
22111
@return iterator pointing to the first element inserted, or @a pos if
22112
`first==last`
22113
22114
@complexity Linear in `std::distance(first, last)` plus linear in the
22115
distance between @a pos and end of the container.
22116
22117
@liveexample{The example shows how `insert()` is used.,insert__range}
22118
22119
@since version 1.0.0
22120
*/
22121
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
22122
{
22123
// insert only works for arrays
22124
if (JSON_HEDLEY_UNLIKELY(!is_array()))
22125
{
22126
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
22127
}
22128
22129
// check if iterator pos fits to this JSON value
22130
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22131
{
22132
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
22133
}
22134
22135
// check if range iterators belong to the same JSON object
22136
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22137
{
22138
JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
22139
}
22140
22141
if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
22142
{
22143
JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
22144
}
22145
22146
// insert to array and return iterator
22147
return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
22148
}
22149
22150
/*!
22151
@brief inserts elements
22152
22153
Inserts elements from initializer list @a ilist before iterator @a pos.
22154
22155
@param[in] pos iterator before which the content will be inserted; may be
22156
the end() iterator
22157
@param[in] ilist initializer list to insert the values from
22158
22159
@throw type_error.309 if called on JSON values other than arrays; example:
22160
`"cannot use insert() with string"`
22161
@throw invalid_iterator.202 if @a pos is not an iterator of *this;
22162
example: `"iterator does not fit current value"`
22163
22164
@return iterator pointing to the first element inserted, or @a pos if
22165
`ilist` is empty
22166
22167
@complexity Linear in `ilist.size()` plus linear in the distance between
22168
@a pos and end of the container.
22169
22170
@liveexample{The example shows how `insert()` is used.,insert__ilist}
22171
22172
@since version 1.0.0
22173
*/
22174
iterator insert(const_iterator pos, initializer_list_t ilist)
22175
{
22176
// insert only works for arrays
22177
if (JSON_HEDLEY_UNLIKELY(!is_array()))
22178
{
22179
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
22180
}
22181
22182
// check if iterator pos fits to this JSON value
22183
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22184
{
22185
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
22186
}
22187
22188
// insert to array and return iterator
22189
return insert_iterator(pos, ilist.begin(), ilist.end());
22190
}
22191
22192
/*!
22193
@brief inserts elements
22194
22195
Inserts elements from range `[first, last)`.
22196
22197
@param[in] first begin of the range of elements to insert
22198
@param[in] last end of the range of elements to insert
22199
22200
@throw type_error.309 if called on JSON values other than objects; example:
22201
`"cannot use insert() with string"`
22202
@throw invalid_iterator.202 if iterator @a first or @a last does does not
22203
point to an object; example: `"iterators first and last must point to
22204
objects"`
22205
@throw invalid_iterator.210 if @a first and @a last do not belong to the
22206
same JSON value; example: `"iterators do not fit"`
22207
22208
@complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number
22209
of elements to insert.
22210
22211
@liveexample{The example shows how `insert()` is used.,insert__range_object}
22212
22213
@since version 3.0.0
22214
*/
22215
void insert(const_iterator first, const_iterator last)
22216
{
22217
// insert only works for objects
22218
if (JSON_HEDLEY_UNLIKELY(!is_object()))
22219
{
22220
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
22221
}
22222
22223
// check if range iterators belong to the same JSON object
22224
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22225
{
22226
JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
22227
}
22228
22229
// passed iterators must belong to objects
22230
if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22231
{
22232
JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
22233
}
22234
22235
m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
22236
}
22237
22238
/*!
22239
@brief updates a JSON object from another object, overwriting existing keys
22240
22241
Inserts all values from JSON object @a j and overwrites existing keys.
22242
22243
@param[in] j JSON object to read values from
22244
22245
@throw type_error.312 if called on JSON values other than objects; example:
22246
`"cannot use update() with string"`
22247
22248
@complexity O(N*log(size() + N)), where N is the number of elements to
22249
insert.
22250
22251
@liveexample{The example shows how `update()` is used.,update}
22252
22253
@sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
22254
22255
@since version 3.0.0
22256
*/
22257
void update(const_reference j)
22258
{
22259
// implicitly convert null value to an empty object
22260
if (is_null())
22261
{
22262
m_type = value_t::object;
22263
m_value.object = create<object_t>();
22264
assert_invariant();
22265
}
22266
22267
if (JSON_HEDLEY_UNLIKELY(!is_object()))
22268
{
22269
JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
22270
}
22271
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
22272
{
22273
JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name())));
22274
}
22275
22276
for (auto it = j.cbegin(); it != j.cend(); ++it)
22277
{
22278
m_value.object->operator[](it.key()) = it.value();
22279
}
22280
}
22281
22282
/*!
22283
@brief updates a JSON object from another object, overwriting existing keys
22284
22285
Inserts all values from from range `[first, last)` and overwrites existing
22286
keys.
22287
22288
@param[in] first begin of the range of elements to insert
22289
@param[in] last end of the range of elements to insert
22290
22291
@throw type_error.312 if called on JSON values other than objects; example:
22292
`"cannot use update() with string"`
22293
@throw invalid_iterator.202 if iterator @a first or @a last does does not
22294
point to an object; example: `"iterators first and last must point to
22295
objects"`
22296
@throw invalid_iterator.210 if @a first and @a last do not belong to the
22297
same JSON value; example: `"iterators do not fit"`
22298
22299
@complexity O(N*log(size() + N)), where N is the number of elements to
22300
insert.
22301
22302
@liveexample{The example shows how `update()` is used__range.,update}
22303
22304
@sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
22305
22306
@since version 3.0.0
22307
*/
22308
void update(const_iterator first, const_iterator last)
22309
{
22310
// implicitly convert null value to an empty object
22311
if (is_null())
22312
{
22313
m_type = value_t::object;
22314
m_value.object = create<object_t>();
22315
assert_invariant();
22316
}
22317
22318
if (JSON_HEDLEY_UNLIKELY(!is_object()))
22319
{
22320
JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
22321
}
22322
22323
// check if range iterators belong to the same JSON object
22324
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22325
{
22326
JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
22327
}
22328
22329
// passed iterators must belong to objects
22330
if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()
22331
|| !last.m_object->is_object()))
22332
{
22333
JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
22334
}
22335
22336
for (auto it = first; it != last; ++it)
22337
{
22338
m_value.object->operator[](it.key()) = it.value();
22339
}
22340
}
22341
22342
/*!
22343
@brief exchanges the values
22344
22345
Exchanges the contents of the JSON value with those of @a other. Does not
22346
invoke any move, copy, or swap operations on individual elements. All
22347
iterators and references remain valid. The past-the-end iterator is
22348
invalidated.
22349
22350
@param[in,out] other JSON value to exchange the contents with
22351
22352
@complexity Constant.
22353
22354
@liveexample{The example below shows how JSON values can be swapped with
22355
`swap()`.,swap__reference}
22356
22357
@since version 1.0.0
22358
*/
22359
void swap(reference other) noexcept (
22360
std::is_nothrow_move_constructible<value_t>::value&&
22361
std::is_nothrow_move_assignable<value_t>::value&&
22362
std::is_nothrow_move_constructible<json_value>::value&&
22363
std::is_nothrow_move_assignable<json_value>::value
22364
)
22365
{
22366
std::swap(m_type, other.m_type);
22367
std::swap(m_value, other.m_value);
22368
assert_invariant();
22369
}
22370
22371
/*!
22372
@brief exchanges the values
22373
22374
Exchanges the contents of the JSON value from @a left with those of @a right. Does not
22375
invoke any move, copy, or swap operations on individual elements. All
22376
iterators and references remain valid. The past-the-end iterator is
22377
invalidated. implemented as a friend function callable via ADL.
22378
22379
@param[in,out] left JSON value to exchange the contents with
22380
@param[in,out] right JSON value to exchange the contents with
22381
22382
@complexity Constant.
22383
22384
@liveexample{The example below shows how JSON values can be swapped with
22385
`swap()`.,swap__reference}
22386
22387
@since version 1.0.0
22388
*/
22389
friend void swap(reference left, reference right) noexcept (
22390
std::is_nothrow_move_constructible<value_t>::value&&
22391
std::is_nothrow_move_assignable<value_t>::value&&
22392
std::is_nothrow_move_constructible<json_value>::value&&
22393
std::is_nothrow_move_assignable<json_value>::value
22394
)
22395
{
22396
left.swap(right);
22397
}
22398
22399
/*!
22400
@brief exchanges the values
22401
22402
Exchanges the contents of a JSON array with those of @a other. Does not
22403
invoke any move, copy, or swap operations on individual elements. All
22404
iterators and references remain valid. The past-the-end iterator is
22405
invalidated.
22406
22407
@param[in,out] other array to exchange the contents with
22408
22409
@throw type_error.310 when JSON value is not an array; example: `"cannot
22410
use swap() with string"`
22411
22412
@complexity Constant.
22413
22414
@liveexample{The example below shows how arrays can be swapped with
22415
`swap()`.,swap__array_t}
22416
22417
@since version 1.0.0
22418
*/
22419
void swap(array_t& other)
22420
{
22421
// swap only works for arrays
22422
if (JSON_HEDLEY_LIKELY(is_array()))
22423
{
22424
std::swap(*(m_value.array), other);
22425
}
22426
else
22427
{
22428
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
22429
}
22430
}
22431
22432
/*!
22433
@brief exchanges the values
22434
22435
Exchanges the contents of a JSON object with those of @a other. Does not
22436
invoke any move, copy, or swap operations on individual elements. All
22437
iterators and references remain valid. The past-the-end iterator is
22438
invalidated.
22439
22440
@param[in,out] other object to exchange the contents with
22441
22442
@throw type_error.310 when JSON value is not an object; example:
22443
`"cannot use swap() with string"`
22444
22445
@complexity Constant.
22446
22447
@liveexample{The example below shows how objects can be swapped with
22448
`swap()`.,swap__object_t}
22449
22450
@since version 1.0.0
22451
*/
22452
void swap(object_t& other)
22453
{
22454
// swap only works for objects
22455
if (JSON_HEDLEY_LIKELY(is_object()))
22456
{
22457
std::swap(*(m_value.object), other);
22458
}
22459
else
22460
{
22461
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
22462
}
22463
}
22464
22465
/*!
22466
@brief exchanges the values
22467
22468
Exchanges the contents of a JSON string with those of @a other. Does not
22469
invoke any move, copy, or swap operations on individual elements. All
22470
iterators and references remain valid. The past-the-end iterator is
22471
invalidated.
22472
22473
@param[in,out] other string to exchange the contents with
22474
22475
@throw type_error.310 when JSON value is not a string; example: `"cannot
22476
use swap() with boolean"`
22477
22478
@complexity Constant.
22479
22480
@liveexample{The example below shows how strings can be swapped with
22481
`swap()`.,swap__string_t}
22482
22483
@since version 1.0.0
22484
*/
22485
void swap(string_t& other)
22486
{
22487
// swap only works for strings
22488
if (JSON_HEDLEY_LIKELY(is_string()))
22489
{
22490
std::swap(*(m_value.string), other);
22491
}
22492
else
22493
{
22494
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
22495
}
22496
}
22497
22498
/*!
22499
@brief exchanges the values
22500
22501
Exchanges the contents of a JSON string with those of @a other. Does not
22502
invoke any move, copy, or swap operations on individual elements. All
22503
iterators and references remain valid. The past-the-end iterator is
22504
invalidated.
22505
22506
@param[in,out] other binary to exchange the contents with
22507
22508
@throw type_error.310 when JSON value is not a string; example: `"cannot
22509
use swap() with boolean"`
22510
22511
@complexity Constant.
22512
22513
@liveexample{The example below shows how strings can be swapped with
22514
`swap()`.,swap__binary_t}
22515
22516
@since version 3.8.0
22517
*/
22518
void swap(binary_t& other)
22519
{
22520
// swap only works for strings
22521
if (JSON_HEDLEY_LIKELY(is_binary()))
22522
{
22523
std::swap(*(m_value.binary), other);
22524
}
22525
else
22526
{
22527
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
22528
}
22529
}
22530
22531
/// @copydoc swap(binary_t)
22532
void swap(typename binary_t::container_type& other)
22533
{
22534
// swap only works for strings
22535
if (JSON_HEDLEY_LIKELY(is_binary()))
22536
{
22537
std::swap(*(m_value.binary), other);
22538
}
22539
else
22540
{
22541
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
22542
}
22543
}
22544
22545
/// @}
22546
22547
public:
22548
//////////////////////////////////////////
22549
// lexicographical comparison operators //
22550
//////////////////////////////////////////
22551
22552
/// @name lexicographical comparison operators
22553
/// @{
22554
22555
/*!
22556
@brief comparison: equal
22557
22558
Compares two JSON values for equality according to the following rules:
22559
- Two JSON values are equal if (1) they are from the same type and (2)
22560
their stored values are the same according to their respective
22561
`operator==`.
22562
- Integer and floating-point numbers are automatically converted before
22563
comparison. Note that two NaN values are always treated as unequal.
22564
- Two JSON null values are equal.
22565
22566
@note Floating-point inside JSON values numbers are compared with
22567
`json::number_float_t::operator==` which is `double::operator==` by
22568
default. To compare floating-point while respecting an epsilon, an alternative
22569
[comparison function](https://github.com/mariokonrad/marnav/blob/master/include/marnav/math/floatingpoint.hpp#L34-#L39)
22570
could be used, for instance
22571
@code {.cpp}
22572
template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>
22573
inline bool is_same(T a, T b, T epsilon = std::numeric_limits<T>::epsilon()) noexcept
22574
{
22575
return std::abs(a - b) <= epsilon;
22576
}
22577
@endcode
22578
Or you can self-defined operator equal function like this:
22579
@code {.cpp}
22580
bool my_equal(const_reference lhs, const_reference rhs) {
22581
const auto lhs_type lhs.type();
22582
const auto rhs_type rhs.type();
22583
if (lhs_type == rhs_type) {
22584
switch(lhs_type)
22585
// self_defined case
22586
case value_t::number_float:
22587
return std::abs(lhs - rhs) <= std::numeric_limits<float>::epsilon();
22588
// other cases remain the same with the original
22589
...
22590
}
22591
...
22592
}
22593
@endcode
22594
22595
@note NaN values never compare equal to themselves or to other NaN values.
22596
22597
@param[in] lhs first JSON value to consider
22598
@param[in] rhs second JSON value to consider
22599
@return whether the values @a lhs and @a rhs are equal
22600
22601
@exceptionsafety No-throw guarantee: this function never throws exceptions.
22602
22603
@complexity Linear.
22604
22605
@liveexample{The example demonstrates comparing several JSON
22606
types.,operator__equal}
22607
22608
@since version 1.0.0
22609
*/
22610
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
22611
{
22612
const auto lhs_type = lhs.type();
22613
const auto rhs_type = rhs.type();
22614
22615
if (lhs_type == rhs_type)
22616
{
22617
switch (lhs_type)
22618
{
22619
case value_t::array:
22620
return *lhs.m_value.array == *rhs.m_value.array;
22621
22622
case value_t::object:
22623
return *lhs.m_value.object == *rhs.m_value.object;
22624
22625
case value_t::null:
22626
return true;
22627
22628
case value_t::string:
22629
return *lhs.m_value.string == *rhs.m_value.string;
22630
22631
case value_t::boolean:
22632
return lhs.m_value.boolean == rhs.m_value.boolean;
22633
22634
case value_t::number_integer:
22635
return lhs.m_value.number_integer == rhs.m_value.number_integer;
22636
22637
case value_t::number_unsigned:
22638
return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
22639
22640
case value_t::number_float:
22641
return lhs.m_value.number_float == rhs.m_value.number_float;
22642
22643
case value_t::binary:
22644
return *lhs.m_value.binary == *rhs.m_value.binary;
22645
22646
default:
22647
return false;
22648
}
22649
}
22650
else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
22651
{
22652
return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
22653
}
22654
else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
22655
{
22656
return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
22657
}
22658
else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
22659
{
22660
return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
22661
}
22662
else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
22663
{
22664
return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
22665
}
22666
else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
22667
{
22668
return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
22669
}
22670
else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
22671
{
22672
return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
22673
}
22674
22675
return false;
22676
}
22677
22678
/*!
22679
@brief comparison: equal
22680
@copydoc operator==(const_reference, const_reference)
22681
*/
22682
template<typename ScalarType, typename std::enable_if<
22683
std::is_scalar<ScalarType>::value, int>::type = 0>
22684
friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
22685
{
22686
return lhs == basic_json(rhs);
22687
}
22688
22689
/*!
22690
@brief comparison: equal
22691
@copydoc operator==(const_reference, const_reference)
22692
*/
22693
template<typename ScalarType, typename std::enable_if<
22694
std::is_scalar<ScalarType>::value, int>::type = 0>
22695
friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
22696
{
22697
return basic_json(lhs) == rhs;
22698
}
22699
22700
/*!
22701
@brief comparison: not equal
22702
22703
Compares two JSON values for inequality by calculating `not (lhs == rhs)`.
22704
22705
@param[in] lhs first JSON value to consider
22706
@param[in] rhs second JSON value to consider
22707
@return whether the values @a lhs and @a rhs are not equal
22708
22709
@complexity Linear.
22710
22711
@exceptionsafety No-throw guarantee: this function never throws exceptions.
22712
22713
@liveexample{The example demonstrates comparing several JSON
22714
types.,operator__notequal}
22715
22716
@since version 1.0.0
22717
*/
22718
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
22719
{
22720
return !(lhs == rhs);
22721
}
22722
22723
/*!
22724
@brief comparison: not equal
22725
@copydoc operator!=(const_reference, const_reference)
22726
*/
22727
template<typename ScalarType, typename std::enable_if<
22728
std::is_scalar<ScalarType>::value, int>::type = 0>
22729
friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
22730
{
22731
return lhs != basic_json(rhs);
22732
}
22733
22734
/*!
22735
@brief comparison: not equal
22736
@copydoc operator!=(const_reference, const_reference)
22737
*/
22738
template<typename ScalarType, typename std::enable_if<
22739
std::is_scalar<ScalarType>::value, int>::type = 0>
22740
friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
22741
{
22742
return basic_json(lhs) != rhs;
22743
}
22744
22745
/*!
22746
@brief comparison: less than
22747
22748
Compares whether one JSON value @a lhs is less than another JSON value @a
22749
rhs according to the following rules:
22750
- If @a lhs and @a rhs have the same type, the values are compared using
22751
the default `<` operator.
22752
- Integer and floating-point numbers are automatically converted before
22753
comparison
22754
- In case @a lhs and @a rhs have different types, the values are ignored
22755
and the order of the types is considered, see
22756
@ref operator<(const value_t, const value_t).
22757
22758
@param[in] lhs first JSON value to consider
22759
@param[in] rhs second JSON value to consider
22760
@return whether @a lhs is less than @a rhs
22761
22762
@complexity Linear.
22763
22764
@exceptionsafety No-throw guarantee: this function never throws exceptions.
22765
22766
@liveexample{The example demonstrates comparing several JSON
22767
types.,operator__less}
22768
22769
@since version 1.0.0
22770
*/
22771
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
22772
{
22773
const auto lhs_type = lhs.type();
22774
const auto rhs_type = rhs.type();
22775
22776
if (lhs_type == rhs_type)
22777
{
22778
switch (lhs_type)
22779
{
22780
case value_t::array:
22781
// note parentheses are necessary, see
22782
// https://github.com/nlohmann/json/issues/1530
22783
return (*lhs.m_value.array) < (*rhs.m_value.array);
22784
22785
case value_t::object:
22786
return (*lhs.m_value.object) < (*rhs.m_value.object);
22787
22788
case value_t::null:
22789
return false;
22790
22791
case value_t::string:
22792
return (*lhs.m_value.string) < (*rhs.m_value.string);
22793
22794
case value_t::boolean:
22795
return (lhs.m_value.boolean) < (rhs.m_value.boolean);
22796
22797
case value_t::number_integer:
22798
return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
22799
22800
case value_t::number_unsigned:
22801
return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned);
22802
22803
case value_t::number_float:
22804
return (lhs.m_value.number_float) < (rhs.m_value.number_float);
22805
22806
case value_t::binary:
22807
return (*lhs.m_value.binary) < (*rhs.m_value.binary);
22808
22809
default:
22810
return false;
22811
}
22812
}
22813
else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
22814
{
22815
return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
22816
}
22817
else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
22818
{
22819
return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
22820
}
22821
else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
22822
{
22823
return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
22824
}
22825
else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
22826
{
22827
return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
22828
}
22829
else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
22830
{
22831
return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
22832
}
22833
else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
22834
{
22835
return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
22836
}
22837
22838
// We only reach this line if we cannot compare values. In that case,
22839
// we compare types. Note we have to call the operator explicitly,
22840
// because MSVC has problems otherwise.
22841
return operator<(lhs_type, rhs_type);
22842
}
22843
22844
/*!
22845
@brief comparison: less than
22846
@copydoc operator<(const_reference, const_reference)
22847
*/
22848
template<typename ScalarType, typename std::enable_if<
22849
std::is_scalar<ScalarType>::value, int>::type = 0>
22850
friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
22851
{
22852
return lhs < basic_json(rhs);
22853
}
22854
22855
/*!
22856
@brief comparison: less than
22857
@copydoc operator<(const_reference, const_reference)
22858
*/
22859
template<typename ScalarType, typename std::enable_if<
22860
std::is_scalar<ScalarType>::value, int>::type = 0>
22861
friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
22862
{
22863
return basic_json(lhs) < rhs;
22864
}
22865
22866
/*!
22867
@brief comparison: less than or equal
22868
22869
Compares whether one JSON value @a lhs is less than or equal to another
22870
JSON value by calculating `not (rhs < lhs)`.
22871
22872
@param[in] lhs first JSON value to consider
22873
@param[in] rhs second JSON value to consider
22874
@return whether @a lhs is less than or equal to @a rhs
22875
22876
@complexity Linear.
22877
22878
@exceptionsafety No-throw guarantee: this function never throws exceptions.
22879
22880
@liveexample{The example demonstrates comparing several JSON
22881
types.,operator__greater}
22882
22883
@since version 1.0.0
22884
*/
22885
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
22886
{
22887
return !(rhs < lhs);
22888
}
22889
22890
/*!
22891
@brief comparison: less than or equal
22892
@copydoc operator<=(const_reference, const_reference)
22893
*/
22894
template<typename ScalarType, typename std::enable_if<
22895
std::is_scalar<ScalarType>::value, int>::type = 0>
22896
friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
22897
{
22898
return lhs <= basic_json(rhs);
22899
}
22900
22901
/*!
22902
@brief comparison: less than or equal
22903
@copydoc operator<=(const_reference, const_reference)
22904
*/
22905
template<typename ScalarType, typename std::enable_if<
22906
std::is_scalar<ScalarType>::value, int>::type = 0>
22907
friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
22908
{
22909
return basic_json(lhs) <= rhs;
22910
}
22911
22912
/*!
22913
@brief comparison: greater than
22914
22915
Compares whether one JSON value @a lhs is greater than another
22916
JSON value by calculating `not (lhs <= rhs)`.
22917
22918
@param[in] lhs first JSON value to consider
22919
@param[in] rhs second JSON value to consider
22920
@return whether @a lhs is greater than to @a rhs
22921
22922
@complexity Linear.
22923
22924
@exceptionsafety No-throw guarantee: this function never throws exceptions.
22925
22926
@liveexample{The example demonstrates comparing several JSON
22927
types.,operator__lessequal}
22928
22929
@since version 1.0.0
22930
*/
22931
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
22932
{
22933
return !(lhs <= rhs);
22934
}
22935
22936
/*!
22937
@brief comparison: greater than
22938
@copydoc operator>(const_reference, const_reference)
22939
*/
22940
template<typename ScalarType, typename std::enable_if<
22941
std::is_scalar<ScalarType>::value, int>::type = 0>
22942
friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
22943
{
22944
return lhs > basic_json(rhs);
22945
}
22946
22947
/*!
22948
@brief comparison: greater than
22949
@copydoc operator>(const_reference, const_reference)
22950
*/
22951
template<typename ScalarType, typename std::enable_if<
22952
std::is_scalar<ScalarType>::value, int>::type = 0>
22953
friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
22954
{
22955
return basic_json(lhs) > rhs;
22956
}
22957
22958
/*!
22959
@brief comparison: greater than or equal
22960
22961
Compares whether one JSON value @a lhs is greater than or equal to another
22962
JSON value by calculating `not (lhs < rhs)`.
22963
22964
@param[in] lhs first JSON value to consider
22965
@param[in] rhs second JSON value to consider
22966
@return whether @a lhs is greater than or equal to @a rhs
22967
22968
@complexity Linear.
22969
22970
@exceptionsafety No-throw guarantee: this function never throws exceptions.
22971
22972
@liveexample{The example demonstrates comparing several JSON
22973
types.,operator__greaterequal}
22974
22975
@since version 1.0.0
22976
*/
22977
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
22978
{
22979
return !(lhs < rhs);
22980
}
22981
22982
/*!
22983
@brief comparison: greater than or equal
22984
@copydoc operator>=(const_reference, const_reference)
22985
*/
22986
template<typename ScalarType, typename std::enable_if<
22987
std::is_scalar<ScalarType>::value, int>::type = 0>
22988
friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
22989
{
22990
return lhs >= basic_json(rhs);
22991
}
22992
22993
/*!
22994
@brief comparison: greater than or equal
22995
@copydoc operator>=(const_reference, const_reference)
22996
*/
22997
template<typename ScalarType, typename std::enable_if<
22998
std::is_scalar<ScalarType>::value, int>::type = 0>
22999
friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
23000
{
23001
return basic_json(lhs) >= rhs;
23002
}
23003
23004
/// @}
23005
23006
///////////////////
23007
// serialization //
23008
///////////////////
23009
23010
/// @name serialization
23011
/// @{
23012
23013
/*!
23014
@brief serialize to stream
23015
23016
Serialize the given JSON value @a j to the output stream @a o. The JSON
23017
value will be serialized using the @ref dump member function.
23018
23019
- The indentation of the output can be controlled with the member variable
23020
`width` of the output stream @a o. For instance, using the manipulator
23021
`std::setw(4)` on @a o sets the indentation level to `4` and the
23022
serialization result is the same as calling `dump(4)`.
23023
23024
- The indentation character can be controlled with the member variable
23025
`fill` of the output stream @a o. For instance, the manipulator
23026
`std::setfill('\\t')` sets indentation to use a tab character rather than
23027
the default space character.
23028
23029
@param[in,out] o stream to serialize to
23030
@param[in] j JSON value to serialize
23031
23032
@return the stream @a o
23033
23034
@throw type_error.316 if a string stored inside the JSON value is not
23035
UTF-8 encoded
23036
23037
@complexity Linear.
23038
23039
@liveexample{The example below shows the serialization with different
23040
parameters to `width` to adjust the indentation level.,operator_serialize}
23041
23042
@since version 1.0.0; indentation character added in version 3.0.0
23043
*/
23044
friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
23045
{
23046
// read width member and use it as indentation parameter if nonzero
23047
const bool pretty_print = o.width() > 0;
23048
const auto indentation = pretty_print ? o.width() : 0;
23049
23050
// reset width to 0 for subsequent calls to this stream
23051
o.width(0);
23052
23053
// do the actual serialization
23054
serializer s(detail::output_adapter<char>(o), o.fill());
23055
s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
23056
return o;
23057
}
23058
23059
/*!
23060
@brief serialize to stream
23061
@deprecated This stream operator is deprecated and will be removed in
23062
future 4.0.0 of the library. Please use
23063
@ref operator<<(std::ostream&, const basic_json&)
23064
instead; that is, replace calls like `j >> o;` with `o << j;`.
23065
@since version 1.0.0; deprecated since version 3.0.0
23066
*/
23067
JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
23068
friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
23069
{
23070
return o << j;
23071
}
23072
23073
/// @}
23074
23075
23076
/////////////////////
23077
// deserialization //
23078
/////////////////////
23079
23080
/// @name deserialization
23081
/// @{
23082
23083
/*!
23084
@brief deserialize from a compatible input
23085
23086
@tparam InputType A compatible input, for instance
23087
- an std::istream object
23088
- a FILE pointer
23089
- a C-style array of characters
23090
- a pointer to a null-terminated string of single byte characters
23091
- an object obj for which begin(obj) and end(obj) produces a valid pair of
23092
iterators.
23093
23094
@param[in] i input to read from
23095
@param[in] cb a parser callback function of type @ref parser_callback_t
23096
which is used to control the deserialization by filtering unwanted values
23097
(optional)
23098
@param[in] allow_exceptions whether to throw exceptions in case of a
23099
parse error (optional, true by default)
23100
@param[in] ignore_comments whether comments should be ignored and treated
23101
like whitespace (true) or yield a parse error (true); (optional, false by
23102
default)
23103
23104
@return deserialized JSON value; in case of a parse error and
23105
@a allow_exceptions set to `false`, the return value will be
23106
value_t::discarded.
23107
23108
@throw parse_error.101 if a parse error occurs; example: `""unexpected end
23109
of input; expected string literal""`
23110
@throw parse_error.102 if to_unicode fails or surrogate error
23111
@throw parse_error.103 if to_unicode fails
23112
23113
@complexity Linear in the length of the input. The parser is a predictive
23114
LL(1) parser. The complexity can be higher if the parser callback function
23115
@a cb or reading from the input @a i has a super-linear complexity.
23116
23117
@note A UTF-8 byte order mark is silently ignored.
23118
23119
@liveexample{The example below demonstrates the `parse()` function reading
23120
from an array.,parse__array__parser_callback_t}
23121
23122
@liveexample{The example below demonstrates the `parse()` function with
23123
and without callback function.,parse__string__parser_callback_t}
23124
23125
@liveexample{The example below demonstrates the `parse()` function with
23126
and without callback function.,parse__istream__parser_callback_t}
23127
23128
@liveexample{The example below demonstrates the `parse()` function reading
23129
from a contiguous container.,parse__contiguouscontainer__parser_callback_t}
23130
23131
@since version 2.0.3 (contiguous containers); version 3.9.0 allowed to
23132
ignore comments.
23133
*/
23134
template<typename InputType>
23135
JSON_HEDLEY_WARN_UNUSED_RESULT
23136
static basic_json parse(InputType&& i,
23137
const parser_callback_t cb = nullptr,
23138
const bool allow_exceptions = true,
23139
const bool ignore_comments = false)
23140
{
23141
basic_json result;
23142
parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
23143
return result;
23144
}
23145
23146
/*!
23147
@brief deserialize from a pair of character iterators
23148
23149
The value_type of the iterator must be a integral type with size of 1, 2 or
23150
4 bytes, which will be interpreted respectively as UTF-8, UTF-16 and UTF-32.
23151
23152
@param[in] first iterator to start of character range
23153
@param[in] last iterator to end of character range
23154
@param[in] cb a parser callback function of type @ref parser_callback_t
23155
which is used to control the deserialization by filtering unwanted values
23156
(optional)
23157
@param[in] allow_exceptions whether to throw exceptions in case of a
23158
parse error (optional, true by default)
23159
@param[in] ignore_comments whether comments should be ignored and treated
23160
like whitespace (true) or yield a parse error (true); (optional, false by
23161
default)
23162
23163
@return deserialized JSON value; in case of a parse error and
23164
@a allow_exceptions set to `false`, the return value will be
23165
value_t::discarded.
23166
23167
@throw parse_error.101 if a parse error occurs; example: `""unexpected end
23168
of input; expected string literal""`
23169
@throw parse_error.102 if to_unicode fails or surrogate error
23170
@throw parse_error.103 if to_unicode fails
23171
*/
23172
template<typename IteratorType>
23173
JSON_HEDLEY_WARN_UNUSED_RESULT
23174
static basic_json parse(IteratorType first,
23175
IteratorType last,
23176
const parser_callback_t cb = nullptr,
23177
const bool allow_exceptions = true,
23178
const bool ignore_comments = false)
23179
{
23180
basic_json result;
23181
parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
23182
return result;
23183
}
23184
23185
JSON_HEDLEY_WARN_UNUSED_RESULT
23186
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
23187
static basic_json parse(detail::span_input_adapter&& i,
23188
const parser_callback_t cb = nullptr,
23189
const bool allow_exceptions = true,
23190
const bool ignore_comments = false)
23191
{
23192
basic_json result;
23193
parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
23194
return result;
23195
}
23196
23197
/*!
23198
@brief check if the input is valid JSON
23199
23200
Unlike the @ref parse(InputType&&, const parser_callback_t,const bool)
23201
function, this function neither throws an exception in case of invalid JSON
23202
input (i.e., a parse error) nor creates diagnostic information.
23203
23204
@tparam InputType A compatible input, for instance
23205
- an std::istream object
23206
- a FILE pointer
23207
- a C-style array of characters
23208
- a pointer to a null-terminated string of single byte characters
23209
- an object obj for which begin(obj) and end(obj) produces a valid pair of
23210
iterators.
23211
23212
@param[in] i input to read from
23213
@param[in] ignore_comments whether comments should be ignored and treated
23214
like whitespace (true) or yield a parse error (true); (optional, false by
23215
default)
23216
23217
@return Whether the input read from @a i is valid JSON.
23218
23219
@complexity Linear in the length of the input. The parser is a predictive
23220
LL(1) parser.
23221
23222
@note A UTF-8 byte order mark is silently ignored.
23223
23224
@liveexample{The example below demonstrates the `accept()` function reading
23225
from a string.,accept__string}
23226
*/
23227
template<typename InputType>
23228
static bool accept(InputType&& i,
23229
const bool ignore_comments = false)
23230
{
23231
return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
23232
}
23233
23234
template<typename IteratorType>
23235
static bool accept(IteratorType first, IteratorType last,
23236
const bool ignore_comments = false)
23237
{
23238
return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
23239
}
23240
23241
JSON_HEDLEY_WARN_UNUSED_RESULT
23242
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
23243
static bool accept(detail::span_input_adapter&& i,
23244
const bool ignore_comments = false)
23245
{
23246
return parser(i.get(), nullptr, false, ignore_comments).accept(true);
23247
}
23248
23249
/*!
23250
@brief generate SAX events
23251
23252
The SAX event lister must follow the interface of @ref json_sax.
23253
23254
This function reads from a compatible input. Examples are:
23255
- an std::istream object
23256
- a FILE pointer
23257
- a C-style array of characters
23258
- a pointer to a null-terminated string of single byte characters
23259
- an object obj for which begin(obj) and end(obj) produces a valid pair of
23260
iterators.
23261
23262
@param[in] i input to read from
23263
@param[in,out] sax SAX event listener
23264
@param[in] format the format to parse (JSON, CBOR, MessagePack, or UBJSON)
23265
@param[in] strict whether the input has to be consumed completely
23266
@param[in] ignore_comments whether comments should be ignored and treated
23267
like whitespace (true) or yield a parse error (true); (optional, false by
23268
default); only applies to the JSON file format.
23269
23270
@return return value of the last processed SAX event
23271
23272
@throw parse_error.101 if a parse error occurs; example: `""unexpected end
23273
of input; expected string literal""`
23274
@throw parse_error.102 if to_unicode fails or surrogate error
23275
@throw parse_error.103 if to_unicode fails
23276
23277
@complexity Linear in the length of the input. The parser is a predictive
23278
LL(1) parser. The complexity can be higher if the SAX consumer @a sax has
23279
a super-linear complexity.
23280
23281
@note A UTF-8 byte order mark is silently ignored.
23282
23283
@liveexample{The example below demonstrates the `sax_parse()` function
23284
reading from string and processing the events with a user-defined SAX
23285
event consumer.,sax_parse}
23286
23287
@since version 3.2.0
23288
*/
23289
template <typename InputType, typename SAX>
23290
JSON_HEDLEY_NON_NULL(2)
23291
static bool sax_parse(InputType&& i, SAX* sax,
23292
input_format_t format = input_format_t::json,
23293
const bool strict = true,
23294
const bool ignore_comments = false)
23295
{
23296
auto ia = detail::input_adapter(std::forward<InputType>(i));
23297
return format == input_format_t::json
23298
? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23299
: detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
23300
}
23301
23302
template<class IteratorType, class SAX>
23303
JSON_HEDLEY_NON_NULL(3)
23304
static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
23305
input_format_t format = input_format_t::json,
23306
const bool strict = true,
23307
const bool ignore_comments = false)
23308
{
23309
auto ia = detail::input_adapter(std::move(first), std::move(last));
23310
return format == input_format_t::json
23311
? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23312
: detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
23313
}
23314
23315
template <typename SAX>
23316
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
23317
JSON_HEDLEY_NON_NULL(2)
23318
static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
23319
input_format_t format = input_format_t::json,
23320
const bool strict = true,
23321
const bool ignore_comments = false)
23322
{
23323
auto ia = i.get();
23324
return format == input_format_t::json
23325
? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23326
: detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
23327
}
23328
23329
/*!
23330
@brief deserialize from stream
23331
@deprecated This stream operator is deprecated and will be removed in
23332
version 4.0.0 of the library. Please use
23333
@ref operator>>(std::istream&, basic_json&)
23334
instead; that is, replace calls like `j << i;` with `i >> j;`.
23335
@since version 1.0.0; deprecated since version 3.0.0
23336
*/
23337
JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
23338
friend std::istream& operator<<(basic_json& j, std::istream& i)
23339
{
23340
return operator>>(i, j);
23341
}
23342
23343
/*!
23344
@brief deserialize from stream
23345
23346
Deserializes an input stream to a JSON value.
23347
23348
@param[in,out] i input stream to read a serialized JSON value from
23349
@param[in,out] j JSON value to write the deserialized input to
23350
23351
@throw parse_error.101 in case of an unexpected token
23352
@throw parse_error.102 if to_unicode fails or surrogate error
23353
@throw parse_error.103 if to_unicode fails
23354
23355
@complexity Linear in the length of the input. The parser is a predictive
23356
LL(1) parser.
23357
23358
@note A UTF-8 byte order mark is silently ignored.
23359
23360
@liveexample{The example below shows how a JSON value is constructed by
23361
reading a serialization from a stream.,operator_deserialize}
23362
23363
@sa parse(std::istream&, const parser_callback_t) for a variant with a
23364
parser callback function to filter values while parsing
23365
23366
@since version 1.0.0
23367
*/
23368
friend std::istream& operator>>(std::istream& i, basic_json& j)
23369
{
23370
parser(detail::input_adapter(i)).parse(false, j);
23371
return i;
23372
}
23373
23374
/// @}
23375
23376
///////////////////////////
23377
// convenience functions //
23378
///////////////////////////
23379
23380
/*!
23381
@brief return the type as string
23382
23383
Returns the type name as string to be used in error messages - usually to
23384
indicate that a function was called on a wrong JSON type.
23385
23386
@return a string representation of a the @a m_type member:
23387
Value type | return value
23388
----------- | -------------
23389
null | `"null"`
23390
boolean | `"boolean"`
23391
string | `"string"`
23392
number | `"number"` (for all number types)
23393
object | `"object"`
23394
array | `"array"`
23395
binary | `"binary"`
23396
discarded | `"discarded"`
23397
23398
@exceptionsafety No-throw guarantee: this function never throws exceptions.
23399
23400
@complexity Constant.
23401
23402
@liveexample{The following code exemplifies `type_name()` for all JSON
23403
types.,type_name}
23404
23405
@sa @ref type() -- return the type of the JSON value
23406
@sa @ref operator value_t() -- return the type of the JSON value (implicit)
23407
23408
@since version 1.0.0, public since 2.1.0, `const char*` and `noexcept`
23409
since 3.0.0
23410
*/
23411
JSON_HEDLEY_RETURNS_NON_NULL
23412
const char* type_name() const noexcept
23413
{
23414
{
23415
switch (m_type)
23416
{
23417
case value_t::null:
23418
return "null";
23419
case value_t::object:
23420
return "object";
23421
case value_t::array:
23422
return "array";
23423
case value_t::string:
23424
return "string";
23425
case value_t::boolean:
23426
return "boolean";
23427
case value_t::binary:
23428
return "binary";
23429
case value_t::discarded:
23430
return "discarded";
23431
default:
23432
return "number";
23433
}
23434
}
23435
}
23436
23437
23438
private:
23439
//////////////////////
23440
// member variables //
23441
//////////////////////
23442
23443
/// the type of the current element
23444
value_t m_type = value_t::null;
23445
23446
/// the value of the current element
23447
json_value m_value = {};
23448
23449
//////////////////////////////////////////
23450
// binary serialization/deserialization //
23451
//////////////////////////////////////////
23452
23453
/// @name binary serialization/deserialization support
23454
/// @{
23455
23456
public:
23457
/*!
23458
@brief create a CBOR serialization of a given JSON value
23459
23460
Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
23461
Binary Object Representation) serialization format. CBOR is a binary
23462
serialization format which aims to be more compact than JSON itself, yet
23463
more efficient to parse.
23464
23465
The library uses the following mapping from JSON values types to
23466
CBOR types according to the CBOR specification (RFC 7049):
23467
23468
JSON value type | value/range | CBOR type | first byte
23469
--------------- | ------------------------------------------ | ---------------------------------- | ---------------
23470
null | `null` | Null | 0xF6
23471
boolean | `true` | True | 0xF5
23472
boolean | `false` | False | 0xF4
23473
number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3B
23474
number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3A
23475
number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39
23476
number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38
23477
number_integer | -24..-1 | Negative integer | 0x20..0x37
23478
number_integer | 0..23 | Integer | 0x00..0x17
23479
number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18
23480
number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19
23481
number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A
23482
number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B
23483
number_unsigned | 0..23 | Integer | 0x00..0x17
23484
number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18
23485
number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19
23486
number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A
23487
number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B
23488
number_float | *any value representable by a float* | Single-Precision Float | 0xFA
23489
number_float | *any value NOT representable by a float* | Double-Precision Float | 0xFB
23490
string | *length*: 0..23 | UTF-8 string | 0x60..0x77
23491
string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78
23492
string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79
23493
string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A
23494
string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B
23495
array | *size*: 0..23 | array | 0x80..0x97
23496
array | *size*: 23..255 | array (1 byte follow) | 0x98
23497
array | *size*: 256..65535 | array (2 bytes follow) | 0x99
23498
array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A
23499
array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B
23500
object | *size*: 0..23 | map | 0xA0..0xB7
23501
object | *size*: 23..255 | map (1 byte follow) | 0xB8
23502
object | *size*: 256..65535 | map (2 bytes follow) | 0xB9
23503
object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA
23504
object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB
23505
binary | *size*: 0..23 | byte string | 0x40..0x57
23506
binary | *size*: 23..255 | byte string (1 byte follow) | 0x58
23507
binary | *size*: 256..65535 | byte string (2 bytes follow) | 0x59
23508
binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A
23509
binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B
23510
23511
@note The mapping is **complete** in the sense that any JSON value type
23512
can be converted to a CBOR value.
23513
23514
@note If NaN or Infinity are stored inside a JSON number, they are
23515
serialized properly. This behavior differs from the @ref dump()
23516
function which serializes NaN or Infinity to `null`.
23517
23518
@note The following CBOR types are not used in the conversion:
23519
- UTF-8 strings terminated by "break" (0x7F)
23520
- arrays terminated by "break" (0x9F)
23521
- maps terminated by "break" (0xBF)
23522
- byte strings terminated by "break" (0x5F)
23523
- date/time (0xC0..0xC1)
23524
- bignum (0xC2..0xC3)
23525
- decimal fraction (0xC4)
23526
- bigfloat (0xC5)
23527
- expected conversions (0xD5..0xD7)
23528
- simple values (0xE0..0xF3, 0xF8)
23529
- undefined (0xF7)
23530
- half-precision floats (0xF9)
23531
- break (0xFF)
23532
23533
@param[in] j JSON value to serialize
23534
@return CBOR serialization as byte vector
23535
23536
@complexity Linear in the size of the JSON value @a j.
23537
23538
@liveexample{The example shows the serialization of a JSON value to a byte
23539
vector in CBOR format.,to_cbor}
23540
23541
@sa http://cbor.io
23542
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
23543
analogous deserialization
23544
@sa @ref to_msgpack(const basic_json&) for the related MessagePack format
23545
@sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
23546
related UBJSON format
23547
23548
@since version 2.0.9; compact representation of floating-point numbers
23549
since version 3.8.0
23550
*/
23551
static std::vector<uint8_t> to_cbor(const basic_json& j)
23552
{
23553
std::vector<uint8_t> result;
23554
to_cbor(j, result);
23555
return result;
23556
}
23557
23558
static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
23559
{
23560
binary_writer<uint8_t>(o).write_cbor(j);
23561
}
23562
23563
static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
23564
{
23565
binary_writer<char>(o).write_cbor(j);
23566
}
23567
23568
/*!
23569
@brief create a MessagePack serialization of a given JSON value
23570
23571
Serializes a given JSON value @a j to a byte vector using the MessagePack
23572
serialization format. MessagePack is a binary serialization format which
23573
aims to be more compact than JSON itself, yet more efficient to parse.
23574
23575
The library uses the following mapping from JSON values types to
23576
MessagePack types according to the MessagePack specification:
23577
23578
JSON value type | value/range | MessagePack type | first byte
23579
--------------- | --------------------------------- | ---------------- | ----------
23580
null | `null` | nil | 0xC0
23581
boolean | `true` | true | 0xC3
23582
boolean | `false` | false | 0xC2
23583
number_integer | -9223372036854775808..-2147483649 | int64 | 0xD3
23584
number_integer | -2147483648..-32769 | int32 | 0xD2
23585
number_integer | -32768..-129 | int16 | 0xD1
23586
number_integer | -128..-33 | int8 | 0xD0
23587
number_integer | -32..-1 | negative fixint | 0xE0..0xFF
23588
number_integer | 0..127 | positive fixint | 0x00..0x7F
23589
number_integer | 128..255 | uint 8 | 0xCC
23590
number_integer | 256..65535 | uint 16 | 0xCD
23591
number_integer | 65536..4294967295 | uint 32 | 0xCE
23592
number_integer | 4294967296..18446744073709551615 | uint 64 | 0xCF
23593
number_unsigned | 0..127 | positive fixint | 0x00..0x7F
23594
number_unsigned | 128..255 | uint 8 | 0xCC
23595
number_unsigned | 256..65535 | uint 16 | 0xCD
23596
number_unsigned | 65536..4294967295 | uint 32 | 0xCE
23597
number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF
23598
number_float | *any value representable by a float* | float 32 | 0xCA
23599
number_float | *any value NOT representable by a float* | float 64 | 0xCB
23600
string | *length*: 0..31 | fixstr | 0xA0..0xBF
23601
string | *length*: 32..255 | str 8 | 0xD9
23602
string | *length*: 256..65535 | str 16 | 0xDA
23603
string | *length*: 65536..4294967295 | str 32 | 0xDB
23604
array | *size*: 0..15 | fixarray | 0x90..0x9F
23605
array | *size*: 16..65535 | array 16 | 0xDC
23606
array | *size*: 65536..4294967295 | array 32 | 0xDD
23607
object | *size*: 0..15 | fix map | 0x80..0x8F
23608
object | *size*: 16..65535 | map 16 | 0xDE
23609
object | *size*: 65536..4294967295 | map 32 | 0xDF
23610
binary | *size*: 0..255 | bin 8 | 0xC4
23611
binary | *size*: 256..65535 | bin 16 | 0xC5
23612
binary | *size*: 65536..4294967295 | bin 32 | 0xC6
23613
23614
@note The mapping is **complete** in the sense that any JSON value type
23615
can be converted to a MessagePack value.
23616
23617
@note The following values can **not** be converted to a MessagePack value:
23618
- strings with more than 4294967295 bytes
23619
- byte strings with more than 4294967295 bytes
23620
- arrays with more than 4294967295 elements
23621
- objects with more than 4294967295 elements
23622
23623
@note Any MessagePack output created @ref to_msgpack can be successfully
23624
parsed by @ref from_msgpack.
23625
23626
@note If NaN or Infinity are stored inside a JSON number, they are
23627
serialized properly. This behavior differs from the @ref dump()
23628
function which serializes NaN or Infinity to `null`.
23629
23630
@param[in] j JSON value to serialize
23631
@return MessagePack serialization as byte vector
23632
23633
@complexity Linear in the size of the JSON value @a j.
23634
23635
@liveexample{The example shows the serialization of a JSON value to a byte
23636
vector in MessagePack format.,to_msgpack}
23637
23638
@sa http://msgpack.org
23639
@sa @ref from_msgpack for the analogous deserialization
23640
@sa @ref to_cbor(const basic_json& for the related CBOR format
23641
@sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
23642
related UBJSON format
23643
23644
@since version 2.0.9
23645
*/
23646
static std::vector<uint8_t> to_msgpack(const basic_json& j)
23647
{
23648
std::vector<uint8_t> result;
23649
to_msgpack(j, result);
23650
return result;
23651
}
23652
23653
static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
23654
{
23655
binary_writer<uint8_t>(o).write_msgpack(j);
23656
}
23657
23658
static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
23659
{
23660
binary_writer<char>(o).write_msgpack(j);
23661
}
23662
23663
/*!
23664
@brief create a UBJSON serialization of a given JSON value
23665
23666
Serializes a given JSON value @a j to a byte vector using the UBJSON
23667
(Universal Binary JSON) serialization format. UBJSON aims to be more compact
23668
than JSON itself, yet more efficient to parse.
23669
23670
The library uses the following mapping from JSON values types to
23671
UBJSON types according to the UBJSON specification:
23672
23673
JSON value type | value/range | UBJSON type | marker
23674
--------------- | --------------------------------- | ----------- | ------
23675
null | `null` | null | `Z`
23676
boolean | `true` | true | `T`
23677
boolean | `false` | false | `F`
23678
number_integer | -9223372036854775808..-2147483649 | int64 | `L`
23679
number_integer | -2147483648..-32769 | int32 | `l`
23680
number_integer | -32768..-129 | int16 | `I`
23681
number_integer | -128..127 | int8 | `i`
23682
number_integer | 128..255 | uint8 | `U`
23683
number_integer | 256..32767 | int16 | `I`
23684
number_integer | 32768..2147483647 | int32 | `l`
23685
number_integer | 2147483648..9223372036854775807 | int64 | `L`
23686
number_unsigned | 0..127 | int8 | `i`
23687
number_unsigned | 128..255 | uint8 | `U`
23688
number_unsigned | 256..32767 | int16 | `I`
23689
number_unsigned | 32768..2147483647 | int32 | `l`
23690
number_unsigned | 2147483648..9223372036854775807 | int64 | `L`
23691
number_unsigned | 2147483649..18446744073709551615 | high-precision | `H`
23692
number_float | *any value* | float64 | `D`
23693
string | *with shortest length indicator* | string | `S`
23694
array | *see notes on optimized format* | array | `[`
23695
object | *see notes on optimized format* | map | `{`
23696
23697
@note The mapping is **complete** in the sense that any JSON value type
23698
can be converted to a UBJSON value.
23699
23700
@note The following values can **not** be converted to a UBJSON value:
23701
- strings with more than 9223372036854775807 bytes (theoretical)
23702
23703
@note The following markers are not used in the conversion:
23704
- `Z`: no-op values are not created.
23705
- `C`: single-byte strings are serialized with `S` markers.
23706
23707
@note Any UBJSON output created @ref to_ubjson can be successfully parsed
23708
by @ref from_ubjson.
23709
23710
@note If NaN or Infinity are stored inside a JSON number, they are
23711
serialized properly. This behavior differs from the @ref dump()
23712
function which serializes NaN or Infinity to `null`.
23713
23714
@note The optimized formats for containers are supported: Parameter
23715
@a use_size adds size information to the beginning of a container and
23716
removes the closing marker. Parameter @a use_type further checks
23717
whether all elements of a container have the same type and adds the
23718
type marker to the beginning of the container. The @a use_type
23719
parameter must only be used together with @a use_size = true. Note
23720
that @a use_size = true alone may result in larger representations -
23721
the benefit of this parameter is that the receiving side is
23722
immediately informed on the number of elements of the container.
23723
23724
@note If the JSON data contains the binary type, the value stored is a list
23725
of integers, as suggested by the UBJSON documentation. In particular,
23726
this means that serialization and the deserialization of a JSON
23727
containing binary values into UBJSON and back will result in a
23728
different JSON object.
23729
23730
@param[in] j JSON value to serialize
23731
@param[in] use_size whether to add size annotations to container types
23732
@param[in] use_type whether to add type annotations to container types
23733
(must be combined with @a use_size = true)
23734
@return UBJSON serialization as byte vector
23735
23736
@complexity Linear in the size of the JSON value @a j.
23737
23738
@liveexample{The example shows the serialization of a JSON value to a byte
23739
vector in UBJSON format.,to_ubjson}
23740
23741
@sa http://ubjson.org
23742
@sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
23743
analogous deserialization
23744
@sa @ref to_cbor(const basic_json& for the related CBOR format
23745
@sa @ref to_msgpack(const basic_json&) for the related MessagePack format
23746
23747
@since version 3.1.0
23748
*/
23749
static std::vector<uint8_t> to_ubjson(const basic_json& j,
23750
const bool use_size = false,
23751
const bool use_type = false)
23752
{
23753
std::vector<uint8_t> result;
23754
to_ubjson(j, result, use_size, use_type);
23755
return result;
23756
}
23757
23758
static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,
23759
const bool use_size = false, const bool use_type = false)
23760
{
23761
binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
23762
}
23763
23764
static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
23765
const bool use_size = false, const bool use_type = false)
23766
{
23767
binary_writer<char>(o).write_ubjson(j, use_size, use_type);
23768
}
23769
23770
23771
/*!
23772
@brief Serializes the given JSON object `j` to BSON and returns a vector
23773
containing the corresponding BSON-representation.
23774
23775
BSON (Binary JSON) is a binary format in which zero or more ordered key/value pairs are
23776
stored as a single entity (a so-called document).
23777
23778
The library uses the following mapping from JSON values types to BSON types:
23779
23780
JSON value type | value/range | BSON type | marker
23781
--------------- | --------------------------------- | ----------- | ------
23782
null | `null` | null | 0x0A
23783
boolean | `true`, `false` | boolean | 0x08
23784
number_integer | -9223372036854775808..-2147483649 | int64 | 0x12
23785
number_integer | -2147483648..2147483647 | int32 | 0x10
23786
number_integer | 2147483648..9223372036854775807 | int64 | 0x12
23787
number_unsigned | 0..2147483647 | int32 | 0x10
23788
number_unsigned | 2147483648..9223372036854775807 | int64 | 0x12
23789
number_unsigned | 9223372036854775808..18446744073709551615| -- | --
23790
number_float | *any value* | double | 0x01
23791
string | *any value* | string | 0x02
23792
array | *any value* | document | 0x04
23793
object | *any value* | document | 0x03
23794
binary | *any value* | binary | 0x05
23795
23796
@warning The mapping is **incomplete**, since only JSON-objects (and things
23797
contained therein) can be serialized to BSON.
23798
Also, integers larger than 9223372036854775807 cannot be serialized to BSON,
23799
and the keys may not contain U+0000, since they are serialized a
23800
zero-terminated c-strings.
23801
23802
@throw out_of_range.407 if `j.is_number_unsigned() && j.get<std::uint64_t>() > 9223372036854775807`
23803
@throw out_of_range.409 if a key in `j` contains a NULL (U+0000)
23804
@throw type_error.317 if `!j.is_object()`
23805
23806
@pre The input `j` is required to be an object: `j.is_object() == true`.
23807
23808
@note Any BSON output created via @ref to_bson can be successfully parsed
23809
by @ref from_bson.
23810
23811
@param[in] j JSON value to serialize
23812
@return BSON serialization as byte vector
23813
23814
@complexity Linear in the size of the JSON value @a j.
23815
23816
@liveexample{The example shows the serialization of a JSON value to a byte
23817
vector in BSON format.,to_bson}
23818
23819
@sa http://bsonspec.org/spec.html
23820
@sa @ref from_bson(detail::input_adapter&&, const bool strict) for the
23821
analogous deserialization
23822
@sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
23823
related UBJSON format
23824
@sa @ref to_cbor(const basic_json&) for the related CBOR format
23825
@sa @ref to_msgpack(const basic_json&) for the related MessagePack format
23826
*/
23827
static std::vector<uint8_t> to_bson(const basic_json& j)
23828
{
23829
std::vector<uint8_t> result;
23830
to_bson(j, result);
23831
return result;
23832
}
23833
23834
/*!
23835
@brief Serializes the given JSON object `j` to BSON and forwards the
23836
corresponding BSON-representation to the given output_adapter `o`.
23837
@param j The JSON object to convert to BSON.
23838
@param o The output adapter that receives the binary BSON representation.
23839
@pre The input `j` shall be an object: `j.is_object() == true`
23840
@sa @ref to_bson(const basic_json&)
23841
*/
23842
static void to_bson(const basic_json& j, detail::output_adapter<uint8_t> o)
23843
{
23844
binary_writer<uint8_t>(o).write_bson(j);
23845
}
23846
23847
/*!
23848
@copydoc to_bson(const basic_json&, detail::output_adapter<uint8_t>)
23849
*/
23850
static void to_bson(const basic_json& j, detail::output_adapter<char> o)
23851
{
23852
binary_writer<char>(o).write_bson(j);
23853
}
23854
23855
23856
/*!
23857
@brief create a JSON value from an input in CBOR format
23858
23859
Deserializes a given input @a i to a JSON value using the CBOR (Concise
23860
Binary Object Representation) serialization format.
23861
23862
The library maps CBOR types to JSON value types as follows:
23863
23864
CBOR type | JSON value type | first byte
23865
---------------------- | --------------- | ----------
23866
Integer | number_unsigned | 0x00..0x17
23867
Unsigned integer | number_unsigned | 0x18
23868
Unsigned integer | number_unsigned | 0x19
23869
Unsigned integer | number_unsigned | 0x1A
23870
Unsigned integer | number_unsigned | 0x1B
23871
Negative integer | number_integer | 0x20..0x37
23872
Negative integer | number_integer | 0x38
23873
Negative integer | number_integer | 0x39
23874
Negative integer | number_integer | 0x3A
23875
Negative integer | number_integer | 0x3B
23876
Byte string | binary | 0x40..0x57
23877
Byte string | binary | 0x58
23878
Byte string | binary | 0x59
23879
Byte string | binary | 0x5A
23880
Byte string | binary | 0x5B
23881
UTF-8 string | string | 0x60..0x77
23882
UTF-8 string | string | 0x78
23883
UTF-8 string | string | 0x79
23884
UTF-8 string | string | 0x7A
23885
UTF-8 string | string | 0x7B
23886
UTF-8 string | string | 0x7F
23887
array | array | 0x80..0x97
23888
array | array | 0x98
23889
array | array | 0x99
23890
array | array | 0x9A
23891
array | array | 0x9B
23892
array | array | 0x9F
23893
map | object | 0xA0..0xB7
23894
map | object | 0xB8
23895
map | object | 0xB9
23896
map | object | 0xBA
23897
map | object | 0xBB
23898
map | object | 0xBF
23899
False | `false` | 0xF4
23900
True | `true` | 0xF5
23901
Null | `null` | 0xF6
23902
Half-Precision Float | number_float | 0xF9
23903
Single-Precision Float | number_float | 0xFA
23904
Double-Precision Float | number_float | 0xFB
23905
23906
@warning The mapping is **incomplete** in the sense that not all CBOR
23907
types can be converted to a JSON value. The following CBOR types
23908
are not supported and will yield parse errors (parse_error.112):
23909
- date/time (0xC0..0xC1)
23910
- bignum (0xC2..0xC3)
23911
- decimal fraction (0xC4)
23912
- bigfloat (0xC5)
23913
- expected conversions (0xD5..0xD7)
23914
- simple values (0xE0..0xF3, 0xF8)
23915
- undefined (0xF7)
23916
23917
@warning CBOR allows map keys of any type, whereas JSON only allows
23918
strings as keys in object values. Therefore, CBOR maps with keys
23919
other than UTF-8 strings are rejected (parse_error.113).
23920
23921
@note Any CBOR output created @ref to_cbor can be successfully parsed by
23922
@ref from_cbor.
23923
23924
@param[in] i an input in CBOR format convertible to an input adapter
23925
@param[in] strict whether to expect the input to be consumed until EOF
23926
(true by default)
23927
@param[in] allow_exceptions whether to throw exceptions in case of a
23928
parse error (optional, true by default)
23929
@param[in] tag_handler how to treat CBOR tags (optional, error by default)
23930
23931
@return deserialized JSON value; in case of a parse error and
23932
@a allow_exceptions set to `false`, the return value will be
23933
value_t::discarded.
23934
23935
@throw parse_error.110 if the given input ends prematurely or the end of
23936
file was not reached when @a strict was set to true
23937
@throw parse_error.112 if unsupported features from CBOR were
23938
used in the given input @a v or if the input is not valid CBOR
23939
@throw parse_error.113 if a string was expected as map key, but not found
23940
23941
@complexity Linear in the size of the input @a i.
23942
23943
@liveexample{The example shows the deserialization of a byte vector in CBOR
23944
format to a JSON value.,from_cbor}
23945
23946
@sa http://cbor.io
23947
@sa @ref to_cbor(const basic_json&) for the analogous serialization
23948
@sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for the
23949
related MessagePack format
23950
@sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
23951
related UBJSON format
23952
23953
@since version 2.0.9; parameter @a start_index since 2.1.1; changed to
23954
consume input adapters, removed start_index parameter, and added
23955
@a strict parameter since 3.0.0; added @a allow_exceptions parameter
23956
since 3.2.0; added @a tag_handler parameter since 3.9.0.
23957
*/
23958
template<typename InputType>
23959
JSON_HEDLEY_WARN_UNUSED_RESULT
23960
static basic_json from_cbor(InputType&& i,
23961
const bool strict = true,
23962
const bool allow_exceptions = true,
23963
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23964
{
23965
basic_json result;
23966
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23967
auto ia = detail::input_adapter(std::forward<InputType>(i));
23968
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23969
return res ? result : basic_json(value_t::discarded);
23970
}
23971
23972
/*!
23973
@copydoc from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t)
23974
*/
23975
template<typename IteratorType>
23976
JSON_HEDLEY_WARN_UNUSED_RESULT
23977
static basic_json from_cbor(IteratorType first, IteratorType last,
23978
const bool strict = true,
23979
const bool allow_exceptions = true,
23980
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23981
{
23982
basic_json result;
23983
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23984
auto ia = detail::input_adapter(std::move(first), std::move(last));
23985
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23986
return res ? result : basic_json(value_t::discarded);
23987
}
23988
23989
template<typename T>
23990
JSON_HEDLEY_WARN_UNUSED_RESULT
23991
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23992
static basic_json from_cbor(const T* ptr, std::size_t len,
23993
const bool strict = true,
23994
const bool allow_exceptions = true,
23995
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23996
{
23997
return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
23998
}
23999
24000
24001
JSON_HEDLEY_WARN_UNUSED_RESULT
24002
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24003
static basic_json from_cbor(detail::span_input_adapter&& i,
24004
const bool strict = true,
24005
const bool allow_exceptions = true,
24006
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24007
{
24008
basic_json result;
24009
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24010
auto ia = i.get();
24011
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
24012
return res ? result : basic_json(value_t::discarded);
24013
}
24014
24015
/*!
24016
@brief create a JSON value from an input in MessagePack format
24017
24018
Deserializes a given input @a i to a JSON value using the MessagePack
24019
serialization format.
24020
24021
The library maps MessagePack types to JSON value types as follows:
24022
24023
MessagePack type | JSON value type | first byte
24024
---------------- | --------------- | ----------
24025
positive fixint | number_unsigned | 0x00..0x7F
24026
fixmap | object | 0x80..0x8F
24027
fixarray | array | 0x90..0x9F
24028
fixstr | string | 0xA0..0xBF
24029
nil | `null` | 0xC0
24030
false | `false` | 0xC2
24031
true | `true` | 0xC3
24032
float 32 | number_float | 0xCA
24033
float 64 | number_float | 0xCB
24034
uint 8 | number_unsigned | 0xCC
24035
uint 16 | number_unsigned | 0xCD
24036
uint 32 | number_unsigned | 0xCE
24037
uint 64 | number_unsigned | 0xCF
24038
int 8 | number_integer | 0xD0
24039
int 16 | number_integer | 0xD1
24040
int 32 | number_integer | 0xD2
24041
int 64 | number_integer | 0xD3
24042
str 8 | string | 0xD9
24043
str 16 | string | 0xDA
24044
str 32 | string | 0xDB
24045
array 16 | array | 0xDC
24046
array 32 | array | 0xDD
24047
map 16 | object | 0xDE
24048
map 32 | object | 0xDF
24049
bin 8 | binary | 0xC4
24050
bin 16 | binary | 0xC5
24051
bin 32 | binary | 0xC6
24052
ext 8 | binary | 0xC7
24053
ext 16 | binary | 0xC8
24054
ext 32 | binary | 0xC9
24055
fixext 1 | binary | 0xD4
24056
fixext 2 | binary | 0xD5
24057
fixext 4 | binary | 0xD6
24058
fixext 8 | binary | 0xD7
24059
fixext 16 | binary | 0xD8
24060
negative fixint | number_integer | 0xE0-0xFF
24061
24062
@note Any MessagePack output created @ref to_msgpack can be successfully
24063
parsed by @ref from_msgpack.
24064
24065
@param[in] i an input in MessagePack format convertible to an input
24066
adapter
24067
@param[in] strict whether to expect the input to be consumed until EOF
24068
(true by default)
24069
@param[in] allow_exceptions whether to throw exceptions in case of a
24070
parse error (optional, true by default)
24071
24072
@return deserialized JSON value; in case of a parse error and
24073
@a allow_exceptions set to `false`, the return value will be
24074
value_t::discarded.
24075
24076
@throw parse_error.110 if the given input ends prematurely or the end of
24077
file was not reached when @a strict was set to true
24078
@throw parse_error.112 if unsupported features from MessagePack were
24079
used in the given input @a i or if the input is not valid MessagePack
24080
@throw parse_error.113 if a string was expected as map key, but not found
24081
24082
@complexity Linear in the size of the input @a i.
24083
24084
@liveexample{The example shows the deserialization of a byte vector in
24085
MessagePack format to a JSON value.,from_msgpack}
24086
24087
@sa http://msgpack.org
24088
@sa @ref to_msgpack(const basic_json&) for the analogous serialization
24089
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
24090
related CBOR format
24091
@sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for
24092
the related UBJSON format
24093
@sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for
24094
the related BSON format
24095
24096
@since version 2.0.9; parameter @a start_index since 2.1.1; changed to
24097
consume input adapters, removed start_index parameter, and added
24098
@a strict parameter since 3.0.0; added @a allow_exceptions parameter
24099
since 3.2.0
24100
*/
24101
template<typename InputType>
24102
JSON_HEDLEY_WARN_UNUSED_RESULT
24103
static basic_json from_msgpack(InputType&& i,
24104
const bool strict = true,
24105
const bool allow_exceptions = true)
24106
{
24107
basic_json result;
24108
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24109
auto ia = detail::input_adapter(std::forward<InputType>(i));
24110
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
24111
return res ? result : basic_json(value_t::discarded);
24112
}
24113
24114
/*!
24115
@copydoc from_msgpack(detail::input_adapter&&, const bool, const bool)
24116
*/
24117
template<typename IteratorType>
24118
JSON_HEDLEY_WARN_UNUSED_RESULT
24119
static basic_json from_msgpack(IteratorType first, IteratorType last,
24120
const bool strict = true,
24121
const bool allow_exceptions = true)
24122
{
24123
basic_json result;
24124
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24125
auto ia = detail::input_adapter(std::move(first), std::move(last));
24126
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
24127
return res ? result : basic_json(value_t::discarded);
24128
}
24129
24130
24131
template<typename T>
24132
JSON_HEDLEY_WARN_UNUSED_RESULT
24133
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24134
static basic_json from_msgpack(const T* ptr, std::size_t len,
24135
const bool strict = true,
24136
const bool allow_exceptions = true)
24137
{
24138
return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
24139
}
24140
24141
JSON_HEDLEY_WARN_UNUSED_RESULT
24142
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24143
static basic_json from_msgpack(detail::span_input_adapter&& i,
24144
const bool strict = true,
24145
const bool allow_exceptions = true)
24146
{
24147
basic_json result;
24148
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24149
auto ia = i.get();
24150
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
24151
return res ? result : basic_json(value_t::discarded);
24152
}
24153
24154
24155
/*!
24156
@brief create a JSON value from an input in UBJSON format
24157
24158
Deserializes a given input @a i to a JSON value using the UBJSON (Universal
24159
Binary JSON) serialization format.
24160
24161
The library maps UBJSON types to JSON value types as follows:
24162
24163
UBJSON type | JSON value type | marker
24164
----------- | --------------------------------------- | ------
24165
no-op | *no value, next value is read* | `N`
24166
null | `null` | `Z`
24167
false | `false` | `F`
24168
true | `true` | `T`
24169
float32 | number_float | `d`
24170
float64 | number_float | `D`
24171
uint8 | number_unsigned | `U`
24172
int8 | number_integer | `i`
24173
int16 | number_integer | `I`
24174
int32 | number_integer | `l`
24175
int64 | number_integer | `L`
24176
high-precision number | number_integer, number_unsigned, or number_float - depends on number string | 'H'
24177
string | string | `S`
24178
char | string | `C`
24179
array | array (optimized values are supported) | `[`
24180
object | object (optimized values are supported) | `{`
24181
24182
@note The mapping is **complete** in the sense that any UBJSON value can
24183
be converted to a JSON value.
24184
24185
@param[in] i an input in UBJSON format convertible to an input adapter
24186
@param[in] strict whether to expect the input to be consumed until EOF
24187
(true by default)
24188
@param[in] allow_exceptions whether to throw exceptions in case of a
24189
parse error (optional, true by default)
24190
24191
@return deserialized JSON value; in case of a parse error and
24192
@a allow_exceptions set to `false`, the return value will be
24193
value_t::discarded.
24194
24195
@throw parse_error.110 if the given input ends prematurely or the end of
24196
file was not reached when @a strict was set to true
24197
@throw parse_error.112 if a parse error occurs
24198
@throw parse_error.113 if a string could not be parsed successfully
24199
24200
@complexity Linear in the size of the input @a i.
24201
24202
@liveexample{The example shows the deserialization of a byte vector in
24203
UBJSON format to a JSON value.,from_ubjson}
24204
24205
@sa http://ubjson.org
24206
@sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
24207
analogous serialization
24208
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
24209
related CBOR format
24210
@sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
24211
the related MessagePack format
24212
@sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for
24213
the related BSON format
24214
24215
@since version 3.1.0; added @a allow_exceptions parameter since 3.2.0
24216
*/
24217
template<typename InputType>
24218
JSON_HEDLEY_WARN_UNUSED_RESULT
24219
static basic_json from_ubjson(InputType&& i,
24220
const bool strict = true,
24221
const bool allow_exceptions = true)
24222
{
24223
basic_json result;
24224
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24225
auto ia = detail::input_adapter(std::forward<InputType>(i));
24226
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
24227
return res ? result : basic_json(value_t::discarded);
24228
}
24229
24230
/*!
24231
@copydoc from_ubjson(detail::input_adapter&&, const bool, const bool)
24232
*/
24233
template<typename IteratorType>
24234
JSON_HEDLEY_WARN_UNUSED_RESULT
24235
static basic_json from_ubjson(IteratorType first, IteratorType last,
24236
const bool strict = true,
24237
const bool allow_exceptions = true)
24238
{
24239
basic_json result;
24240
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24241
auto ia = detail::input_adapter(std::move(first), std::move(last));
24242
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
24243
return res ? result : basic_json(value_t::discarded);
24244
}
24245
24246
template<typename T>
24247
JSON_HEDLEY_WARN_UNUSED_RESULT
24248
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24249
static basic_json from_ubjson(const T* ptr, std::size_t len,
24250
const bool strict = true,
24251
const bool allow_exceptions = true)
24252
{
24253
return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
24254
}
24255
24256
JSON_HEDLEY_WARN_UNUSED_RESULT
24257
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24258
static basic_json from_ubjson(detail::span_input_adapter&& i,
24259
const bool strict = true,
24260
const bool allow_exceptions = true)
24261
{
24262
basic_json result;
24263
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24264
auto ia = i.get();
24265
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
24266
return res ? result : basic_json(value_t::discarded);
24267
}
24268
24269
24270
/*!
24271
@brief Create a JSON value from an input in BSON format
24272
24273
Deserializes a given input @a i to a JSON value using the BSON (Binary JSON)
24274
serialization format.
24275
24276
The library maps BSON record types to JSON value types as follows:
24277
24278
BSON type | BSON marker byte | JSON value type
24279
--------------- | ---------------- | ---------------------------
24280
double | 0x01 | number_float
24281
string | 0x02 | string
24282
document | 0x03 | object
24283
array | 0x04 | array
24284
binary | 0x05 | still unsupported
24285
undefined | 0x06 | still unsupported
24286
ObjectId | 0x07 | still unsupported
24287
boolean | 0x08 | boolean
24288
UTC Date-Time | 0x09 | still unsupported
24289
null | 0x0A | null
24290
Regular Expr. | 0x0B | still unsupported
24291
DB Pointer | 0x0C | still unsupported
24292
JavaScript Code | 0x0D | still unsupported
24293
Symbol | 0x0E | still unsupported
24294
JavaScript Code | 0x0F | still unsupported
24295
int32 | 0x10 | number_integer
24296
Timestamp | 0x11 | still unsupported
24297
128-bit decimal float | 0x13 | still unsupported
24298
Max Key | 0x7F | still unsupported
24299
Min Key | 0xFF | still unsupported
24300
24301
@warning The mapping is **incomplete**. The unsupported mappings
24302
are indicated in the table above.
24303
24304
@param[in] i an input in BSON format convertible to an input adapter
24305
@param[in] strict whether to expect the input to be consumed until EOF
24306
(true by default)
24307
@param[in] allow_exceptions whether to throw exceptions in case of a
24308
parse error (optional, true by default)
24309
24310
@return deserialized JSON value; in case of a parse error and
24311
@a allow_exceptions set to `false`, the return value will be
24312
value_t::discarded.
24313
24314
@throw parse_error.114 if an unsupported BSON record type is encountered
24315
24316
@complexity Linear in the size of the input @a i.
24317
24318
@liveexample{The example shows the deserialization of a byte vector in
24319
BSON format to a JSON value.,from_bson}
24320
24321
@sa http://bsonspec.org/spec.html
24322
@sa @ref to_bson(const basic_json&) for the analogous serialization
24323
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
24324
related CBOR format
24325
@sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
24326
the related MessagePack format
24327
@sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
24328
related UBJSON format
24329
*/
24330
template<typename InputType>
24331
JSON_HEDLEY_WARN_UNUSED_RESULT
24332
static basic_json from_bson(InputType&& i,
24333
const bool strict = true,
24334
const bool allow_exceptions = true)
24335
{
24336
basic_json result;
24337
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24338
auto ia = detail::input_adapter(std::forward<InputType>(i));
24339
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
24340
return res ? result : basic_json(value_t::discarded);
24341
}
24342
24343
/*!
24344
@copydoc from_bson(detail::input_adapter&&, const bool, const bool)
24345
*/
24346
template<typename IteratorType>
24347
JSON_HEDLEY_WARN_UNUSED_RESULT
24348
static basic_json from_bson(IteratorType first, IteratorType last,
24349
const bool strict = true,
24350
const bool allow_exceptions = true)
24351
{
24352
basic_json result;
24353
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24354
auto ia = detail::input_adapter(std::move(first), std::move(last));
24355
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
24356
return res ? result : basic_json(value_t::discarded);
24357
}
24358
24359
template<typename T>
24360
JSON_HEDLEY_WARN_UNUSED_RESULT
24361
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24362
static basic_json from_bson(const T* ptr, std::size_t len,
24363
const bool strict = true,
24364
const bool allow_exceptions = true)
24365
{
24366
return from_bson(ptr, ptr + len, strict, allow_exceptions);
24367
}
24368
24369
JSON_HEDLEY_WARN_UNUSED_RESULT
24370
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24371
static basic_json from_bson(detail::span_input_adapter&& i,
24372
const bool strict = true,
24373
const bool allow_exceptions = true)
24374
{
24375
basic_json result;
24376
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24377
auto ia = i.get();
24378
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
24379
return res ? result : basic_json(value_t::discarded);
24380
}
24381
/// @}
24382
24383
//////////////////////////
24384
// JSON Pointer support //
24385
//////////////////////////
24386
24387
/// @name JSON Pointer functions
24388
/// @{
24389
24390
/*!
24391
@brief access specified element via JSON Pointer
24392
24393
Uses a JSON pointer to retrieve a reference to the respective JSON value.
24394
No bound checking is performed. Similar to @ref operator[](const typename
24395
object_t::key_type&), `null` values are created in arrays and objects if
24396
necessary.
24397
24398
In particular:
24399
- If the JSON pointer points to an object key that does not exist, it
24400
is created an filled with a `null` value before a reference to it
24401
is returned.
24402
- If the JSON pointer points to an array index that does not exist, it
24403
is created an filled with a `null` value before a reference to it
24404
is returned. All indices between the current maximum and the given
24405
index are also filled with `null`.
24406
- The special value `-` is treated as a synonym for the index past the
24407
end.
24408
24409
@param[in] ptr a JSON pointer
24410
24411
@return reference to the element pointed to by @a ptr
24412
24413
@complexity Constant.
24414
24415
@throw parse_error.106 if an array index begins with '0'
24416
@throw parse_error.109 if an array index was not a number
24417
@throw out_of_range.404 if the JSON pointer can not be resolved
24418
24419
@liveexample{The behavior is shown in the example.,operatorjson_pointer}
24420
24421
@since version 2.0.0
24422
*/
24423
reference operator[](const json_pointer& ptr)
24424
{
24425
return ptr.get_unchecked(this);
24426
}
24427
24428
/*!
24429
@brief access specified element via JSON Pointer
24430
24431
Uses a JSON pointer to retrieve a reference to the respective JSON value.
24432
No bound checking is performed. The function does not change the JSON
24433
value; no `null` values are created. In particular, the special value
24434
`-` yields an exception.
24435
24436
@param[in] ptr JSON pointer to the desired element
24437
24438
@return const reference to the element pointed to by @a ptr
24439
24440
@complexity Constant.
24441
24442
@throw parse_error.106 if an array index begins with '0'
24443
@throw parse_error.109 if an array index was not a number
24444
@throw out_of_range.402 if the array index '-' is used
24445
@throw out_of_range.404 if the JSON pointer can not be resolved
24446
24447
@liveexample{The behavior is shown in the example.,operatorjson_pointer_const}
24448
24449
@since version 2.0.0
24450
*/
24451
const_reference operator[](const json_pointer& ptr) const
24452
{
24453
return ptr.get_unchecked(this);
24454
}
24455
24456
/*!
24457
@brief access specified element via JSON Pointer
24458
24459
Returns a reference to the element at with specified JSON pointer @a ptr,
24460
with bounds checking.
24461
24462
@param[in] ptr JSON pointer to the desired element
24463
24464
@return reference to the element pointed to by @a ptr
24465
24466
@throw parse_error.106 if an array index in the passed JSON pointer @a ptr
24467
begins with '0'. See example below.
24468
24469
@throw parse_error.109 if an array index in the passed JSON pointer @a ptr
24470
is not a number. See example below.
24471
24472
@throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
24473
is out of range. See example below.
24474
24475
@throw out_of_range.402 if the array index '-' is used in the passed JSON
24476
pointer @a ptr. As `at` provides checked access (and no elements are
24477
implicitly inserted), the index '-' is always invalid. See example below.
24478
24479
@throw out_of_range.403 if the JSON pointer describes a key of an object
24480
which cannot be found. See example below.
24481
24482
@throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
24483
See example below.
24484
24485
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
24486
changes in the JSON value.
24487
24488
@complexity Constant.
24489
24490
@since version 2.0.0
24491
24492
@liveexample{The behavior is shown in the example.,at_json_pointer}
24493
*/
24494
reference at(const json_pointer& ptr)
24495
{
24496
return ptr.get_checked(this);
24497
}
24498
24499
/*!
24500
@brief access specified element via JSON Pointer
24501
24502
Returns a const reference to the element at with specified JSON pointer @a
24503
ptr, with bounds checking.
24504
24505
@param[in] ptr JSON pointer to the desired element
24506
24507
@return reference to the element pointed to by @a ptr
24508
24509
@throw parse_error.106 if an array index in the passed JSON pointer @a ptr
24510
begins with '0'. See example below.
24511
24512
@throw parse_error.109 if an array index in the passed JSON pointer @a ptr
24513
is not a number. See example below.
24514
24515
@throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
24516
is out of range. See example below.
24517
24518
@throw out_of_range.402 if the array index '-' is used in the passed JSON
24519
pointer @a ptr. As `at` provides checked access (and no elements are
24520
implicitly inserted), the index '-' is always invalid. See example below.
24521
24522
@throw out_of_range.403 if the JSON pointer describes a key of an object
24523
which cannot be found. See example below.
24524
24525
@throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
24526
See example below.
24527
24528
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
24529
changes in the JSON value.
24530
24531
@complexity Constant.
24532
24533
@since version 2.0.0
24534
24535
@liveexample{The behavior is shown in the example.,at_json_pointer_const}
24536
*/
24537
const_reference at(const json_pointer& ptr) const
24538
{
24539
return ptr.get_checked(this);
24540
}
24541
24542
/*!
24543
@brief return flattened JSON value
24544
24545
The function creates a JSON object whose keys are JSON pointers (see [RFC
24546
6901](https://tools.ietf.org/html/rfc6901)) and whose values are all
24547
primitive. The original JSON value can be restored using the @ref
24548
unflatten() function.
24549
24550
@return an object that maps JSON pointers to primitive values
24551
24552
@note Empty objects and arrays are flattened to `null` and will not be
24553
reconstructed correctly by the @ref unflatten() function.
24554
24555
@complexity Linear in the size the JSON value.
24556
24557
@liveexample{The following code shows how a JSON object is flattened to an
24558
object whose keys consist of JSON pointers.,flatten}
24559
24560
@sa @ref unflatten() for the reverse function
24561
24562
@since version 2.0.0
24563
*/
24564
basic_json flatten() const
24565
{
24566
basic_json result(value_t::object);
24567
json_pointer::flatten("", *this, result);
24568
return result;
24569
}
24570
24571
/*!
24572
@brief unflatten a previously flattened JSON value
24573
24574
The function restores the arbitrary nesting of a JSON value that has been
24575
flattened before using the @ref flatten() function. The JSON value must
24576
meet certain constraints:
24577
1. The value must be an object.
24578
2. The keys must be JSON pointers (see
24579
[RFC 6901](https://tools.ietf.org/html/rfc6901))
24580
3. The mapped values must be primitive JSON types.
24581
24582
@return the original JSON from a flattened version
24583
24584
@note Empty objects and arrays are flattened by @ref flatten() to `null`
24585
values and can not unflattened to their original type. Apart from
24586
this example, for a JSON value `j`, the following is always true:
24587
`j == j.flatten().unflatten()`.
24588
24589
@complexity Linear in the size the JSON value.
24590
24591
@throw type_error.314 if value is not an object
24592
@throw type_error.315 if object values are not primitive
24593
24594
@liveexample{The following code shows how a flattened JSON object is
24595
unflattened into the original nested JSON object.,unflatten}
24596
24597
@sa @ref flatten() for the reverse function
24598
24599
@since version 2.0.0
24600
*/
24601
basic_json unflatten() const
24602
{
24603
return json_pointer::unflatten(*this);
24604
}
24605
24606
/// @}
24607
24608
//////////////////////////
24609
// JSON Patch functions //
24610
//////////////////////////
24611
24612
/// @name JSON Patch functions
24613
/// @{
24614
24615
/*!
24616
@brief applies a JSON patch
24617
24618
[JSON Patch](http://jsonpatch.com) defines a JSON document structure for
24619
expressing a sequence of operations to apply to a JSON) document. With
24620
this function, a JSON Patch is applied to the current JSON value by
24621
executing all operations from the patch.
24622
24623
@param[in] json_patch JSON patch document
24624
@return patched document
24625
24626
@note The application of a patch is atomic: Either all operations succeed
24627
and the patched document is returned or an exception is thrown. In
24628
any case, the original value is not changed: the patch is applied
24629
to a copy of the value.
24630
24631
@throw parse_error.104 if the JSON patch does not consist of an array of
24632
objects
24633
24634
@throw parse_error.105 if the JSON patch is malformed (e.g., mandatory
24635
attributes are missing); example: `"operation add must have member path"`
24636
24637
@throw out_of_range.401 if an array index is out of range.
24638
24639
@throw out_of_range.403 if a JSON pointer inside the patch could not be
24640
resolved successfully in the current JSON value; example: `"key baz not
24641
found"`
24642
24643
@throw out_of_range.405 if JSON pointer has no parent ("add", "remove",
24644
"move")
24645
24646
@throw other_error.501 if "test" operation was unsuccessful
24647
24648
@complexity Linear in the size of the JSON value and the length of the
24649
JSON patch. As usually only a fraction of the JSON value is affected by
24650
the patch, the complexity can usually be neglected.
24651
24652
@liveexample{The following code shows how a JSON patch is applied to a
24653
value.,patch}
24654
24655
@sa @ref diff -- create a JSON patch by comparing two JSON values
24656
24657
@sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
24658
@sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901)
24659
24660
@since version 2.0.0
24661
*/
24662
basic_json patch(const basic_json& json_patch) const
24663
{
24664
// make a working copy to apply the patch to
24665
basic_json result = *this;
24666
24667
// the valid JSON Patch operations
24668
enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24669
24670
const auto get_op = [](const std::string & op)
24671
{
24672
if (op == "add")
24673
{
24674
return patch_operations::add;
24675
}
24676
if (op == "remove")
24677
{
24678
return patch_operations::remove;
24679
}
24680
if (op == "replace")
24681
{
24682
return patch_operations::replace;
24683
}
24684
if (op == "move")
24685
{
24686
return patch_operations::move;
24687
}
24688
if (op == "copy")
24689
{
24690
return patch_operations::copy;
24691
}
24692
if (op == "test")
24693
{
24694
return patch_operations::test;
24695
}
24696
24697
return patch_operations::invalid;
24698
};
24699
24700
// wrapper for "add" operation; add value at ptr
24701
const auto operation_add = [&result](json_pointer & ptr, basic_json val)
24702
{
24703
// adding to the root of the target document means replacing it
24704
if (ptr.empty())
24705
{
24706
result = val;
24707
return;
24708
}
24709
24710
// make sure the top element of the pointer exists
24711
json_pointer top_pointer = ptr.top();
24712
if (top_pointer != ptr)
24713
{
24714
result.at(top_pointer);
24715
}
24716
24717
// get reference to parent of JSON pointer ptr
24718
const auto last_path = ptr.back();
24719
ptr.pop_back();
24720
basic_json& parent = result[ptr];
24721
24722
switch (parent.m_type)
24723
{
24724
case value_t::null:
24725
case value_t::object:
24726
{
24727
// use operator[] to add value
24728
parent[last_path] = val;
24729
break;
24730
}
24731
24732
case value_t::array:
24733
{
24734
if (last_path == "-")
24735
{
24736
// special case: append to back
24737
parent.push_back(val);
24738
}
24739
else
24740
{
24741
const auto idx = json_pointer::array_index(last_path);
24742
if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24743
{
24744
// avoid undefined behavior
24745
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
24746
}
24747
24748
// default case: insert add offset
24749
parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24750
}
24751
break;
24752
}
24753
24754
// if there exists a parent it cannot be primitive
24755
default: // LCOV_EXCL_LINE
24756
JSON_ASSERT(false); // LCOV_EXCL_LINE
24757
}
24758
};
24759
24760
// wrapper for "remove" operation; remove value at ptr
24761
const auto operation_remove = [&result](json_pointer & ptr)
24762
{
24763
// get reference to parent of JSON pointer ptr
24764
const auto last_path = ptr.back();
24765
ptr.pop_back();
24766
basic_json& parent = result.at(ptr);
24767
24768
// remove child
24769
if (parent.is_object())
24770
{
24771
// perform range check
24772
auto it = parent.find(last_path);
24773
if (JSON_HEDLEY_LIKELY(it != parent.end()))
24774
{
24775
parent.erase(it);
24776
}
24777
else
24778
{
24779
JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found"));
24780
}
24781
}
24782
else if (parent.is_array())
24783
{
24784
// note erase performs range check
24785
parent.erase(json_pointer::array_index(last_path));
24786
}
24787
};
24788
24789
// type check: top level value must be an array
24790
if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24791
{
24792
JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
24793
}
24794
24795
// iterate and apply the operations
24796
for (const auto& val : json_patch)
24797
{
24798
// wrapper to get a value for an operation
24799
const auto get_value = [&val](const std::string & op,
24800
const std::string & member,
24801
bool string_type) -> basic_json &
24802
{
24803
// find value
24804
auto it = val.m_value.object->find(member);
24805
24806
// context-sensitive error message
24807
const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
24808
24809
// check if desired value is present
24810
if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
24811
{
24812
JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
24813
}
24814
24815
// check if result is of type string
24816
if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24817
{
24818
JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
24819
}
24820
24821
// no error: return value
24822
return it->second;
24823
};
24824
24825
// type check: every element of the array must be an object
24826
if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24827
{
24828
JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
24829
}
24830
24831
// collect mandatory members
24832
const auto op = get_value("op", "op", true).template get<std::string>();
24833
const auto path = get_value(op, "path", true).template get<std::string>();
24834
json_pointer ptr(path);
24835
24836
switch (get_op(op))
24837
{
24838
case patch_operations::add:
24839
{
24840
operation_add(ptr, get_value("add", "value", false));
24841
break;
24842
}
24843
24844
case patch_operations::remove:
24845
{
24846
operation_remove(ptr);
24847
break;
24848
}
24849
24850
case patch_operations::replace:
24851
{
24852
// the "path" location must exist - use at()
24853
result.at(ptr) = get_value("replace", "value", false);
24854
break;
24855
}
24856
24857
case patch_operations::move:
24858
{
24859
const auto from_path = get_value("move", "from", true).template get<std::string>();
24860
json_pointer from_ptr(from_path);
24861
24862
// the "from" location must exist - use at()
24863
basic_json v = result.at(from_ptr);
24864
24865
// The move operation is functionally identical to a
24866
// "remove" operation on the "from" location, followed
24867
// immediately by an "add" operation at the target
24868
// location with the value that was just removed.
24869
operation_remove(from_ptr);
24870
operation_add(ptr, v);
24871
break;
24872
}
24873
24874
case patch_operations::copy:
24875
{
24876
const auto from_path = get_value("copy", "from", true).template get<std::string>();
24877
const json_pointer from_ptr(from_path);
24878
24879
// the "from" location must exist - use at()
24880
basic_json v = result.at(from_ptr);
24881
24882
// The copy is functionally identical to an "add"
24883
// operation at the target location using the value
24884
// specified in the "from" member.
24885
operation_add(ptr, v);
24886
break;
24887
}
24888
24889
case patch_operations::test:
24890
{
24891
bool success = false;
24892
JSON_TRY
24893
{
24894
// check if "value" matches the one at "path"
24895
// the "path" location must exist - use at()
24896
success = (result.at(ptr) == get_value("test", "value", false));
24897
}
24898
JSON_INTERNAL_CATCH (out_of_range&)
24899
{
24900
// ignore out of range errors: success remains false
24901
}
24902
24903
// throw an exception if test fails
24904
if (JSON_HEDLEY_UNLIKELY(!success))
24905
{
24906
JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
24907
}
24908
24909
break;
24910
}
24911
24912
default:
24913
{
24914
// op must be "add", "remove", "replace", "move", "copy", or
24915
// "test"
24916
JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid"));
24917
}
24918
}
24919
}
24920
24921
return result;
24922
}
24923
24924
/*!
24925
@brief creates a diff as a JSON patch
24926
24927
Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can
24928
be changed into the value @a target by calling @ref patch function.
24929
24930
@invariant For two JSON values @a source and @a target, the following code
24931
yields always `true`:
24932
@code {.cpp}
24933
source.patch(diff(source, target)) == target;
24934
@endcode
24935
24936
@note Currently, only `remove`, `add`, and `replace` operations are
24937
generated.
24938
24939
@param[in] source JSON value to compare from
24940
@param[in] target JSON value to compare against
24941
@param[in] path helper value to create JSON pointers
24942
24943
@return a JSON patch to convert the @a source to @a target
24944
24945
@complexity Linear in the lengths of @a source and @a target.
24946
24947
@liveexample{The following code shows how a JSON patch is created as a
24948
diff for two JSON values.,diff}
24949
24950
@sa @ref patch -- apply a JSON patch
24951
@sa @ref merge_patch -- apply a JSON Merge Patch
24952
24953
@sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
24954
24955
@since version 2.0.0
24956
*/
24957
JSON_HEDLEY_WARN_UNUSED_RESULT
24958
static basic_json diff(const basic_json& source, const basic_json& target,
24959
const std::string& path = "")
24960
{
24961
// the patch
24962
basic_json result(value_t::array);
24963
24964
// if the values are the same, return empty patch
24965
if (source == target)
24966
{
24967
return result;
24968
}
24969
24970
if (source.type() != target.type())
24971
{
24972
// different types: replace value
24973
result.push_back(
24974
{
24975
{"op", "replace"}, {"path", path}, {"value", target}
24976
});
24977
return result;
24978
}
24979
24980
switch (source.type())
24981
{
24982
case value_t::array:
24983
{
24984
// first pass: traverse common elements
24985
std::size_t i = 0;
24986
while (i < source.size() && i < target.size())
24987
{
24988
// recursive call to compare array values at index i
24989
auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
24990
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24991
++i;
24992
}
24993
24994
// i now reached the end of at least one array
24995
// in a second pass, traverse the remaining elements
24996
24997
// remove my remaining elements
24998
const auto end_index = static_cast<difference_type>(result.size());
24999
while (i < source.size())
25000
{
25001
// add operations in reverse order to avoid invalid
25002
// indices
25003
result.insert(result.begin() + end_index, object(
25004
{
25005
{"op", "remove"},
25006
{"path", path + "/" + std::to_string(i)}
25007
}));
25008
++i;
25009
}
25010
25011
// add other remaining elements
25012
while (i < target.size())
25013
{
25014
result.push_back(
25015
{
25016
{"op", "add"},
25017
{"path", path + "/-"},
25018
{"value", target[i]}
25019
});
25020
++i;
25021
}
25022
25023
break;
25024
}
25025
25026
case value_t::object:
25027
{
25028
// first pass: traverse this object's elements
25029
for (auto it = source.cbegin(); it != source.cend(); ++it)
25030
{
25031
// escape the key name to be used in a JSON patch
25032
const auto key = json_pointer::escape(it.key());
25033
25034
if (target.find(it.key()) != target.end())
25035
{
25036
// recursive call to compare object values at key it
25037
auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
25038
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25039
}
25040
else
25041
{
25042
// found a key that is not in o -> remove it
25043
result.push_back(object(
25044
{
25045
{"op", "remove"}, {"path", path + "/" + key}
25046
}));
25047
}
25048
}
25049
25050
// second pass: traverse other object's elements
25051
for (auto it = target.cbegin(); it != target.cend(); ++it)
25052
{
25053
if (source.find(it.key()) == source.end())
25054
{
25055
// found a key that is not in this -> add it
25056
const auto key = json_pointer::escape(it.key());
25057
result.push_back(
25058
{
25059
{"op", "add"}, {"path", path + "/" + key},
25060
{"value", it.value()}
25061
});
25062
}
25063
}
25064
25065
break;
25066
}
25067
25068
default:
25069
{
25070
// both primitive type: replace value
25071
result.push_back(
25072
{
25073
{"op", "replace"}, {"path", path}, {"value", target}
25074
});
25075
break;
25076
}
25077
}
25078
25079
return result;
25080
}
25081
25082
/// @}
25083
25084
////////////////////////////////
25085
// JSON Merge Patch functions //
25086
////////////////////////////////
25087
25088
/// @name JSON Merge Patch functions
25089
/// @{
25090
25091
/*!
25092
@brief applies a JSON Merge Patch
25093
25094
The merge patch format is primarily intended for use with the HTTP PATCH
25095
method as a means of describing a set of modifications to a target
25096
resource's content. This function applies a merge patch to the current
25097
JSON value.
25098
25099
The function implements the following algorithm from Section 2 of
25100
[RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396):
25101
25102
```
25103
define MergePatch(Target, Patch):
25104
if Patch is an Object:
25105
if Target is not an Object:
25106
Target = {} // Ignore the contents and set it to an empty Object
25107
for each Name/Value pair in Patch:
25108
if Value is null:
25109
if Name exists in Target:
25110
remove the Name/Value pair from Target
25111
else:
25112
Target[Name] = MergePatch(Target[Name], Value)
25113
return Target
25114
else:
25115
return Patch
25116
```
25117
25118
Thereby, `Target` is the current object; that is, the patch is applied to
25119
the current value.
25120
25121
@param[in] apply_patch the patch to apply
25122
25123
@complexity Linear in the lengths of @a patch.
25124
25125
@liveexample{The following code shows how a JSON Merge Patch is applied to
25126
a JSON document.,merge_patch}
25127
25128
@sa @ref patch -- apply a JSON patch
25129
@sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396)
25130
25131
@since version 3.0.0
25132
*/
25133
void merge_patch(const basic_json& apply_patch)
25134
{
25135
if (apply_patch.is_object())
25136
{
25137
if (!is_object())
25138
{
25139
*this = object();
25140
}
25141
for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
25142
{
25143
if (it.value().is_null())
25144
{
25145
erase(it.key());
25146
}
25147
else
25148
{
25149
operator[](it.key()).merge_patch(it.value());
25150
}
25151
}
25152
}
25153
else
25154
{
25155
*this = apply_patch;
25156
}
25157
}
25158
25159
/// @}
25160
};
25161
25162
/*!
25163
@brief user-defined to_string function for JSON values
25164
25165
This function implements a user-defined to_string for JSON objects.
25166
25167
@param[in] j a JSON object
25168
@return a std::string object
25169
*/
25170
25171
NLOHMANN_BASIC_JSON_TPL_DECLARATION
25172
std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
25173
{
25174
return j.dump();
25175
}
25176
} // namespace nlohmann
25177
25178
///////////////////////
25179
// nonmember support //
25180
///////////////////////
25181
25182
// specialization of std::swap, and std::hash
25183
namespace std
25184
{
25185
25186
/// hash value for JSON objects
25187
template<>
25188
struct hash<nlohmann::json>
25189
{
25190
/*!
25191
@brief return a hash value for a JSON object
25192
25193
@since version 1.0.0
25194
*/
25195
std::size_t operator()(const nlohmann::json& j) const
25196
{
25197
return nlohmann::detail::hash(j);
25198
}
25199
};
25200
25201
/// specialization for std::less<value_t>
25202
/// @note: do not remove the space after '<',
25203
/// see https://github.com/nlohmann/json/pull/679
25204
template<>
25205
struct less<::nlohmann::detail::value_t>
25206
{
25207
/*!
25208
@brief compare two value_t enum values
25209
@since version 3.0.0
25210
*/
25211
bool operator()(nlohmann::detail::value_t lhs,
25212
nlohmann::detail::value_t rhs) const noexcept
25213
{
25214
return nlohmann::detail::operator<(lhs, rhs);
25215
}
25216
};
25217
25218
// C++20 prohibit function specialization in the std namespace.
25219
#ifndef JSON_HAS_CPP_20
25220
25221
/*!
25222
@brief exchanges the values of two JSON objects
25223
25224
@since version 1.0.0
25225
*/
25226
template<>
25227
inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
25228
is_nothrow_move_constructible<nlohmann::json>::value&&
25229
is_nothrow_move_assignable<nlohmann::json>::value
25230
)
25231
{
25232
j1.swap(j2);
25233
}
25234
25235
#endif
25236
25237
} // namespace std
25238
25239
/*!
25240
@brief user-defined string literal for JSON values
25241
25242
This operator implements a user-defined string literal for JSON objects. It
25243
can be used by adding `"_json"` to a string literal and returns a JSON object
25244
if no parse error occurred.
25245
25246
@param[in] s a string representation of a JSON object
25247
@param[in] n the length of string @a s
25248
@return a JSON object
25249
25250
@since version 1.0.0
25251
*/
25252
JSON_HEDLEY_NON_NULL(1)
25253
inline nlohmann::json operator "" _json(const char* s, std::size_t n)
25254
{
25255
return nlohmann::json::parse(s, s + n);
25256
}
25257
25258
/*!
25259
@brief user-defined string literal for JSON pointer
25260
25261
This operator implements a user-defined string literal for JSON Pointers. It
25262
can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer
25263
object if no parse error occurred.
25264
25265
@param[in] s a string representation of a JSON Pointer
25266
@param[in] n the length of string @a s
25267
@return a JSON pointer object
25268
25269
@since version 2.0.0
25270
*/
25271
JSON_HEDLEY_NON_NULL(1)
25272
inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
25273
{
25274
return nlohmann::json::json_pointer(std::string(s, n));
25275
}
25276
25277
// #include <nlohmann/detail/macro_unscope.hpp>
25278
25279
25280
// restore GCC/clang diagnostic settings
25281
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
25282
#pragma GCC diagnostic pop
25283
#endif
25284
#if defined(__clang__)
25285
#pragma GCC diagnostic pop
25286
#endif
25287
25288
// clean up
25289
#undef JSON_ASSERT
25290
#undef JSON_INTERNAL_CATCH
25291
#undef JSON_CATCH
25292
#undef JSON_THROW
25293
#undef JSON_TRY
25294
#undef JSON_HAS_CPP_14
25295
#undef JSON_HAS_CPP_17
25296
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
25297
#undef NLOHMANN_BASIC_JSON_TPL
25298
#undef JSON_EXPLICIT
25299
25300
// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
25301
#undef JSON_HEDLEY_ALWAYS_INLINE
25302
#undef JSON_HEDLEY_ARM_VERSION
25303
#undef JSON_HEDLEY_ARM_VERSION_CHECK
25304
#undef JSON_HEDLEY_ARRAY_PARAM
25305
#undef JSON_HEDLEY_ASSUME
25306
#undef JSON_HEDLEY_BEGIN_C_DECLS
25307
#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
25308
#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
25309
#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
25310
#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
25311
#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
25312
#undef JSON_HEDLEY_CLANG_HAS_FEATURE
25313
#undef JSON_HEDLEY_CLANG_HAS_WARNING
25314
#undef JSON_HEDLEY_COMPCERT_VERSION
25315
#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
25316
#undef JSON_HEDLEY_CONCAT
25317
#undef JSON_HEDLEY_CONCAT3
25318
#undef JSON_HEDLEY_CONCAT3_EX
25319
#undef JSON_HEDLEY_CONCAT_EX
25320
#undef JSON_HEDLEY_CONST
25321
#undef JSON_HEDLEY_CONSTEXPR
25322
#undef JSON_HEDLEY_CONST_CAST
25323
#undef JSON_HEDLEY_CPP_CAST
25324
#undef JSON_HEDLEY_CRAY_VERSION
25325
#undef JSON_HEDLEY_CRAY_VERSION_CHECK
25326
#undef JSON_HEDLEY_C_DECL
25327
#undef JSON_HEDLEY_DEPRECATED
25328
#undef JSON_HEDLEY_DEPRECATED_FOR
25329
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
25330
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
25331
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
25332
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
25333
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
25334
#undef JSON_HEDLEY_DIAGNOSTIC_POP
25335
#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
25336
#undef JSON_HEDLEY_DMC_VERSION
25337
#undef JSON_HEDLEY_DMC_VERSION_CHECK
25338
#undef JSON_HEDLEY_EMPTY_BASES
25339
#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
25340
#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
25341
#undef JSON_HEDLEY_END_C_DECLS
25342
#undef JSON_HEDLEY_FLAGS
25343
#undef JSON_HEDLEY_FLAGS_CAST
25344
#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
25345
#undef JSON_HEDLEY_GCC_HAS_BUILTIN
25346
#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
25347
#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
25348
#undef JSON_HEDLEY_GCC_HAS_EXTENSION
25349
#undef JSON_HEDLEY_GCC_HAS_FEATURE
25350
#undef JSON_HEDLEY_GCC_HAS_WARNING
25351
#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
25352
#undef JSON_HEDLEY_GCC_VERSION
25353
#undef JSON_HEDLEY_GCC_VERSION_CHECK
25354
#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
25355
#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
25356
#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
25357
#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
25358
#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
25359
#undef JSON_HEDLEY_GNUC_HAS_FEATURE
25360
#undef JSON_HEDLEY_GNUC_HAS_WARNING
25361
#undef JSON_HEDLEY_GNUC_VERSION
25362
#undef JSON_HEDLEY_GNUC_VERSION_CHECK
25363
#undef JSON_HEDLEY_HAS_ATTRIBUTE
25364
#undef JSON_HEDLEY_HAS_BUILTIN
25365
#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
25366
#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
25367
#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
25368
#undef JSON_HEDLEY_HAS_EXTENSION
25369
#undef JSON_HEDLEY_HAS_FEATURE
25370
#undef JSON_HEDLEY_HAS_WARNING
25371
#undef JSON_HEDLEY_IAR_VERSION
25372
#undef JSON_HEDLEY_IAR_VERSION_CHECK
25373
#undef JSON_HEDLEY_IBM_VERSION
25374
#undef JSON_HEDLEY_IBM_VERSION_CHECK
25375
#undef JSON_HEDLEY_IMPORT
25376
#undef JSON_HEDLEY_INLINE
25377
#undef JSON_HEDLEY_INTEL_VERSION
25378
#undef JSON_HEDLEY_INTEL_VERSION_CHECK
25379
#undef JSON_HEDLEY_IS_CONSTANT
25380
#undef JSON_HEDLEY_IS_CONSTEXPR_
25381
#undef JSON_HEDLEY_LIKELY
25382
#undef JSON_HEDLEY_MALLOC
25383
#undef JSON_HEDLEY_MESSAGE
25384
#undef JSON_HEDLEY_MSVC_VERSION
25385
#undef JSON_HEDLEY_MSVC_VERSION_CHECK
25386
#undef JSON_HEDLEY_NEVER_INLINE
25387
#undef JSON_HEDLEY_NON_NULL
25388
#undef JSON_HEDLEY_NO_ESCAPE
25389
#undef JSON_HEDLEY_NO_RETURN
25390
#undef JSON_HEDLEY_NO_THROW
25391
#undef JSON_HEDLEY_NULL
25392
#undef JSON_HEDLEY_PELLES_VERSION
25393
#undef JSON_HEDLEY_PELLES_VERSION_CHECK
25394
#undef JSON_HEDLEY_PGI_VERSION
25395
#undef JSON_HEDLEY_PGI_VERSION_CHECK
25396
#undef JSON_HEDLEY_PREDICT
25397
#undef JSON_HEDLEY_PRINTF_FORMAT
25398
#undef JSON_HEDLEY_PRIVATE
25399
#undef JSON_HEDLEY_PUBLIC
25400
#undef JSON_HEDLEY_PURE
25401
#undef JSON_HEDLEY_REINTERPRET_CAST
25402
#undef JSON_HEDLEY_REQUIRE
25403
#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
25404
#undef JSON_HEDLEY_REQUIRE_MSG
25405
#undef JSON_HEDLEY_RESTRICT
25406
#undef JSON_HEDLEY_RETURNS_NON_NULL
25407
#undef JSON_HEDLEY_SENTINEL
25408
#undef JSON_HEDLEY_STATIC_ASSERT
25409
#undef JSON_HEDLEY_STATIC_CAST
25410
#undef JSON_HEDLEY_STRINGIFY
25411
#undef JSON_HEDLEY_STRINGIFY_EX
25412
#undef JSON_HEDLEY_SUNPRO_VERSION
25413
#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
25414
#undef JSON_HEDLEY_TINYC_VERSION
25415
#undef JSON_HEDLEY_TINYC_VERSION_CHECK
25416
#undef JSON_HEDLEY_TI_ARMCL_VERSION
25417
#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
25418
#undef JSON_HEDLEY_TI_CL2000_VERSION
25419
#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
25420
#undef JSON_HEDLEY_TI_CL430_VERSION
25421
#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
25422
#undef JSON_HEDLEY_TI_CL6X_VERSION
25423
#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
25424
#undef JSON_HEDLEY_TI_CL7X_VERSION
25425
#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
25426
#undef JSON_HEDLEY_TI_CLPRU_VERSION
25427
#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
25428
#undef JSON_HEDLEY_TI_VERSION
25429
#undef JSON_HEDLEY_TI_VERSION_CHECK
25430
#undef JSON_HEDLEY_UNAVAILABLE
25431
#undef JSON_HEDLEY_UNLIKELY
25432
#undef JSON_HEDLEY_UNPREDICTABLE
25433
#undef JSON_HEDLEY_UNREACHABLE
25434
#undef JSON_HEDLEY_UNREACHABLE_RETURN
25435
#undef JSON_HEDLEY_VERSION
25436
#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
25437
#undef JSON_HEDLEY_VERSION_DECODE_MINOR
25438
#undef JSON_HEDLEY_VERSION_DECODE_REVISION
25439
#undef JSON_HEDLEY_VERSION_ENCODE
25440
#undef JSON_HEDLEY_WARNING
25441
#undef JSON_HEDLEY_WARN_UNUSED_RESULT
25442
#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
25443
#undef JSON_HEDLEY_FALL_THROUGH
25444
25445
25446
25447
#endif // INCLUDE_NLOHMANN_JSON_HPP_
25448
25449