Instrument Neutral Distributed Interface INDI 2.2.5
indijson.hpp
Go to the documentation of this file.
1/*
2 __ _____ _____ _____
3 __| | __| | | | JSON for Modern C++
4| | |__ | | | | | | version 3.10.5
5|_____|_____|_____|_|___| https://github.com/nlohmann/json
6
7Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8SPDX-License-Identifier: MIT
9Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
10
11Permission is hereby granted, free of charge, to any person obtaining a copy
12of this software and associated documentation files (the "Software"), to deal
13in the Software without restriction, including without limitation the rights
14to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15copies of the Software, and to permit persons to whom the Software is
16furnished to do so, subject to the following conditions:
17
18The above copyright notice and this permission notice shall be included in all
19copies or substantial portions of the Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27SOFTWARE.
28*/
29
30/****************************************************************************\
31 * Note on documentation: The source files contain links to the online *
32 * documentation of the public API at https://json.nlohmann.me. This URL *
33 * contains the most recent documentation and should also be applicable to *
34 * previous versions; documentation for deprecated functions is not *
35 * removed, but marked deprecated. See "Generate documentation" section in *
36 * file docs/README.md. *
37\****************************************************************************/
38
39#ifndef INCLUDE_NLOHMANN_JSON_HPP_
40#define INCLUDE_NLOHMANN_JSON_HPP_
41
42#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
43 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
44 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 10 || NLOHMANN_JSON_VERSION_PATCH != 5
45 #warning "Already included a different version of the library!"
46 #endif
47 #endif
48#endif
49
50#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
51#define NLOHMANN_JSON_VERSION_MINOR 10 // NOLINT(modernize-macro-to-enum)
52#define NLOHMANN_JSON_VERSION_PATCH 5 // NOLINT(modernize-macro-to-enum)
53
54#include <algorithm> // all_of, find, for_each
55#include <cstddef> // nullptr_t, ptrdiff_t, size_t
56#include <functional> // hash, less
57#include <initializer_list> // initializer_list
58#ifndef JSON_NO_IO
59 #include <iosfwd> // istream, ostream
60#endif // JSON_NO_IO
61#include <iterator> // random_access_iterator_tag
62#include <memory> // unique_ptr
63#include <numeric> // accumulate
64#include <string> // string, stoi, to_string
65#include <utility> // declval, forward, move, pair, swap
66#include <vector> // vector
67
68// #include <nlohmann/adl_serializer.hpp>
69
70
71#include <type_traits>
72#include <utility>
73
74// #include <nlohmann/detail/conversions/from_json.hpp>
75
76
77#include <algorithm> // transform
78#include <array> // array
79#include <forward_list> // forward_list
80#include <iterator> // inserter, front_inserter, end
81#include <map> // map
82#include <string> // string
83#include <tuple> // tuple, make_tuple
84#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
85#include <unordered_map> // unordered_map
86#include <utility> // pair, declval
87#include <valarray> // valarray
88
89// #include <nlohmann/detail/exceptions.hpp>
90
91
92#include <cstddef> // nullptr_t
93#include <exception> // exception
94#include <stdexcept> // runtime_error
95#include <string> // to_string
96#include <vector> // vector
97
98// #include <nlohmann/detail/value_t.hpp>
99
100
101#include <array> // array
102#include <cstddef> // size_t
103#include <cstdint> // uint8_t
104#include <string> // string
105
106// #include <nlohmann/detail/macro_scope.hpp>
107
108
109#include <utility> // declval, pair
110// #include <nlohmann/thirdparty/hedley/hedley.hpp>
111
112
113/* Hedley - https://nemequ.github.io/hedley
114 * Created by Evan Nemerson <[email protected]>
115 *
116 * To the extent possible under law, the author(s) have dedicated all
117 * copyright and related and neighboring rights to this software to
118 * the public domain worldwide. This software is distributed without
119 * any warranty.
120 *
121 * For details, see <http://creativecommons.org/publicdomain/zero/1.0/>.
122 * SPDX-License-Identifier: CC0-1.0
123 */
124
125#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
126#if defined(JSON_HEDLEY_VERSION)
127 #undef JSON_HEDLEY_VERSION
128#endif
129#define JSON_HEDLEY_VERSION 15
130
131#if defined(JSON_HEDLEY_STRINGIFY_EX)
132 #undef JSON_HEDLEY_STRINGIFY_EX
133#endif
134#define JSON_HEDLEY_STRINGIFY_EX(x) #x
135
136#if defined(JSON_HEDLEY_STRINGIFY)
137 #undef JSON_HEDLEY_STRINGIFY
138#endif
139#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
140
141#if defined(JSON_HEDLEY_CONCAT_EX)
142 #undef JSON_HEDLEY_CONCAT_EX
143#endif
144#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
145
146#if defined(JSON_HEDLEY_CONCAT)
147 #undef JSON_HEDLEY_CONCAT
148#endif
149#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
150
151#if defined(JSON_HEDLEY_CONCAT3_EX)
152 #undef JSON_HEDLEY_CONCAT3_EX
153#endif
154#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
155
156#if defined(JSON_HEDLEY_CONCAT3)
157 #undef JSON_HEDLEY_CONCAT3
158#endif
159#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
160
161#if defined(JSON_HEDLEY_VERSION_ENCODE)
162 #undef JSON_HEDLEY_VERSION_ENCODE
163#endif
164#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
165
166#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
167 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
168#endif
169#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
170
171#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
172 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
173#endif
174#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
175
176#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
177 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
178#endif
179#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
180
181#if defined(JSON_HEDLEY_GNUC_VERSION)
182 #undef JSON_HEDLEY_GNUC_VERSION
183#endif
184#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
185 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
186#elif defined(__GNUC__)
187 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
188#endif
189
190#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
191 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
192#endif
193#if defined(JSON_HEDLEY_GNUC_VERSION)
194 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
195#else
196 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
197#endif
198
199#if defined(JSON_HEDLEY_MSVC_VERSION)
200 #undef JSON_HEDLEY_MSVC_VERSION
201#endif
202#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
203 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
204#elif defined(_MSC_FULL_VER) && !defined(__ICL)
205 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
206#elif defined(_MSC_VER) && !defined(__ICL)
207 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
208#endif
209
210#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
211 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
212#endif
213#if !defined(JSON_HEDLEY_MSVC_VERSION)
214 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
215#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
216 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
217#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
218 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
219#else
220 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
221#endif
222
223#if defined(JSON_HEDLEY_INTEL_VERSION)
224 #undef JSON_HEDLEY_INTEL_VERSION
225#endif
226#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
227 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
228#elif defined(__INTEL_COMPILER) && !defined(__ICL)
229 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
230#endif
231
232#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
233 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
234#endif
235#if defined(JSON_HEDLEY_INTEL_VERSION)
236 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
237#else
238 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
239#endif
240
241#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
242 #undef JSON_HEDLEY_INTEL_CL_VERSION
243#endif
244#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
245 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
246#endif
247
248#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
249 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
250#endif
251#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
252 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
253#else
254 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
255#endif
256
257#if defined(JSON_HEDLEY_PGI_VERSION)
258 #undef JSON_HEDLEY_PGI_VERSION
259#endif
260#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
261 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
262#endif
263
264#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
265 #undef JSON_HEDLEY_PGI_VERSION_CHECK
266#endif
267#if defined(JSON_HEDLEY_PGI_VERSION)
268 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
269#else
270 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
271#endif
272
273#if defined(JSON_HEDLEY_SUNPRO_VERSION)
274 #undef JSON_HEDLEY_SUNPRO_VERSION
275#endif
276#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
277 #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)
278#elif defined(__SUNPRO_C)
279 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
280#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
281 #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)
282#elif defined(__SUNPRO_CC)
283 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
284#endif
285
286#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
287 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
288#endif
289#if defined(JSON_HEDLEY_SUNPRO_VERSION)
290 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
291#else
292 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
293#endif
294
295#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
296 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
297#endif
298#if defined(__EMSCRIPTEN__)
299 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
300#endif
301
302#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
303 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
304#endif
305#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
306 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
307#else
308 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
309#endif
310
311#if defined(JSON_HEDLEY_ARM_VERSION)
312 #undef JSON_HEDLEY_ARM_VERSION
313#endif
314#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
315 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
316#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
317 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
318#endif
319
320#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
321 #undef JSON_HEDLEY_ARM_VERSION_CHECK
322#endif
323#if defined(JSON_HEDLEY_ARM_VERSION)
324 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
325#else
326 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
327#endif
328
329#if defined(JSON_HEDLEY_IBM_VERSION)
330 #undef JSON_HEDLEY_IBM_VERSION
331#endif
332#if defined(__ibmxl__)
333 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
334#elif defined(__xlC__) && defined(__xlC_ver__)
335 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
336#elif defined(__xlC__)
337 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
338#endif
339
340#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
341 #undef JSON_HEDLEY_IBM_VERSION_CHECK
342#endif
343#if defined(JSON_HEDLEY_IBM_VERSION)
344 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
345#else
346 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
347#endif
348
349#if defined(JSON_HEDLEY_TI_VERSION)
350 #undef JSON_HEDLEY_TI_VERSION
351#endif
352#if \
353 defined(__TI_COMPILER_VERSION__) && \
354 ( \
355 defined(__TMS470__) || defined(__TI_ARM__) || \
356 defined(__MSP430__) || \
357 defined(__TMS320C2000__) \
358 )
359#if (__TI_COMPILER_VERSION__ >= 16000000)
360 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
361#endif
362#endif
363
364#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
365 #undef JSON_HEDLEY_TI_VERSION_CHECK
366#endif
367#if defined(JSON_HEDLEY_TI_VERSION)
368 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
369#else
370 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
371#endif
372
373#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
374 #undef JSON_HEDLEY_TI_CL2000_VERSION
375#endif
376#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
377 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
378#endif
379
380#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
381 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
382#endif
383#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
384 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
385#else
386 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
387#endif
388
389#if defined(JSON_HEDLEY_TI_CL430_VERSION)
390 #undef JSON_HEDLEY_TI_CL430_VERSION
391#endif
392#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
393 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
394#endif
395
396#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
397 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
398#endif
399#if defined(JSON_HEDLEY_TI_CL430_VERSION)
400 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
401#else
402 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
403#endif
404
405#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
406 #undef JSON_HEDLEY_TI_ARMCL_VERSION
407#endif
408#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
409 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
410#endif
411
412#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
413 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
414#endif
415#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
416 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
417#else
418 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
419#endif
420
421#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
422 #undef JSON_HEDLEY_TI_CL6X_VERSION
423#endif
424#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
425 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
426#endif
427
428#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
429 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
430#endif
431#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
432 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
433#else
434 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
435#endif
436
437#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
438 #undef JSON_HEDLEY_TI_CL7X_VERSION
439#endif
440#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
441 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
442#endif
443
444#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
445 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
446#endif
447#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
448 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
449#else
450 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
451#endif
452
453#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
454 #undef JSON_HEDLEY_TI_CLPRU_VERSION
455#endif
456#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
457 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
458#endif
459
460#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
461 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
462#endif
463#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
464 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
465#else
466 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
467#endif
468
469#if defined(JSON_HEDLEY_CRAY_VERSION)
470 #undef JSON_HEDLEY_CRAY_VERSION
471#endif
472#if defined(_CRAYC)
473 #if defined(_RELEASE_PATCHLEVEL)
474 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
475 #else
476 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
477 #endif
478#endif
479
480#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
481 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
482#endif
483#if defined(JSON_HEDLEY_CRAY_VERSION)
484 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
485#else
486 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
487#endif
488
489#if defined(JSON_HEDLEY_IAR_VERSION)
490 #undef JSON_HEDLEY_IAR_VERSION
491#endif
492#if defined(__IAR_SYSTEMS_ICC__)
493 #if __VER__ > 1000
494 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
495 #else
496 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
497 #endif
498#endif
499
500#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
501 #undef JSON_HEDLEY_IAR_VERSION_CHECK
502#endif
503#if defined(JSON_HEDLEY_IAR_VERSION)
504 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
505#else
506 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
507#endif
508
509#if defined(JSON_HEDLEY_TINYC_VERSION)
510 #undef JSON_HEDLEY_TINYC_VERSION
511#endif
512#if defined(__TINYC__)
513 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
514#endif
515
516#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
517 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
518#endif
519#if defined(JSON_HEDLEY_TINYC_VERSION)
520 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
521#else
522 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
523#endif
524
525#if defined(JSON_HEDLEY_DMC_VERSION)
526 #undef JSON_HEDLEY_DMC_VERSION
527#endif
528#if defined(__DMC__)
529 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
530#endif
531
532#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
533 #undef JSON_HEDLEY_DMC_VERSION_CHECK
534#endif
535#if defined(JSON_HEDLEY_DMC_VERSION)
536 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
537#else
538 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
539#endif
540
541#if defined(JSON_HEDLEY_COMPCERT_VERSION)
542 #undef JSON_HEDLEY_COMPCERT_VERSION
543#endif
544#if defined(__COMPCERT_VERSION__)
545 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
546#endif
547
548#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
549 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
550#endif
551#if defined(JSON_HEDLEY_COMPCERT_VERSION)
552 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
553#else
554 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
555#endif
556
557#if defined(JSON_HEDLEY_PELLES_VERSION)
558 #undef JSON_HEDLEY_PELLES_VERSION
559#endif
560#if defined(__POCC__)
561 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
562#endif
563
564#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
565 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
566#endif
567#if defined(JSON_HEDLEY_PELLES_VERSION)
568 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
569#else
570 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
571#endif
572
573#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
574 #undef JSON_HEDLEY_MCST_LCC_VERSION
575#endif
576#if defined(__LCC__) && defined(__LCC_MINOR__)
577 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
578#endif
579
580#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
581 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
582#endif
583#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
584 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
585#else
586 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
587#endif
588
589#if defined(JSON_HEDLEY_GCC_VERSION)
590 #undef JSON_HEDLEY_GCC_VERSION
591#endif
592#if \
593 defined(JSON_HEDLEY_GNUC_VERSION) && \
594 !defined(__clang__) && \
595 !defined(JSON_HEDLEY_INTEL_VERSION) && \
596 !defined(JSON_HEDLEY_PGI_VERSION) && \
597 !defined(JSON_HEDLEY_ARM_VERSION) && \
598 !defined(JSON_HEDLEY_CRAY_VERSION) && \
599 !defined(JSON_HEDLEY_TI_VERSION) && \
600 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
601 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
602 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
603 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
604 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
605 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
606 !defined(__COMPCERT__) && \
607 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
608 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
609#endif
610
611#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
612 #undef JSON_HEDLEY_GCC_VERSION_CHECK
613#endif
614#if defined(JSON_HEDLEY_GCC_VERSION)
615 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
616#else
617 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
618#endif
619
620#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
621 #undef JSON_HEDLEY_HAS_ATTRIBUTE
622#endif
623#if \
624 defined(__has_attribute) && \
625 ( \
626 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
627 )
628# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
629#else
630# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
631#endif
632
633#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
634 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
635#endif
636#if defined(__has_attribute)
637 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
638#else
639 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
640#endif
641
642#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
643 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
644#endif
645#if defined(__has_attribute)
646 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
647#else
648 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
649#endif
650
651#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
652 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
653#endif
654#if \
655 defined(__has_cpp_attribute) && \
656 defined(__cplusplus) && \
657 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
658 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
659#else
660 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
661#endif
662
663#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
664 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
665#endif
666#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
667 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
668#elif \
669 !defined(JSON_HEDLEY_PGI_VERSION) && \
670 !defined(JSON_HEDLEY_IAR_VERSION) && \
671 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
672 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
673 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
674#else
675 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
676#endif
677
678#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
679 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
680#endif
681#if defined(__has_cpp_attribute) && defined(__cplusplus)
682 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
683#else
684 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
685#endif
686
687#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
688 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
689#endif
690#if defined(__has_cpp_attribute) && defined(__cplusplus)
691 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
692#else
693 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
694#endif
695
696#if defined(JSON_HEDLEY_HAS_BUILTIN)
697 #undef JSON_HEDLEY_HAS_BUILTIN
698#endif
699#if defined(__has_builtin)
700 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
701#else
702 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
703#endif
704
705#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
706 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
707#endif
708#if defined(__has_builtin)
709 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
710#else
711 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
712#endif
713
714#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
715 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
716#endif
717#if defined(__has_builtin)
718 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
719#else
720 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
721#endif
722
723#if defined(JSON_HEDLEY_HAS_FEATURE)
724 #undef JSON_HEDLEY_HAS_FEATURE
725#endif
726#if defined(__has_feature)
727 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
728#else
729 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
730#endif
731
732#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
733 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
734#endif
735#if defined(__has_feature)
736 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
737#else
738 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
739#endif
740
741#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
742 #undef JSON_HEDLEY_GCC_HAS_FEATURE
743#endif
744#if defined(__has_feature)
745 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
746#else
747 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
748#endif
749
750#if defined(JSON_HEDLEY_HAS_EXTENSION)
751 #undef JSON_HEDLEY_HAS_EXTENSION
752#endif
753#if defined(__has_extension)
754 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
755#else
756 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
757#endif
758
759#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
760 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
761#endif
762#if defined(__has_extension)
763 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
764#else
765 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
766#endif
767
768#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
769 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
770#endif
771#if defined(__has_extension)
772 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
773#else
774 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
775#endif
776
777#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
778 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
779#endif
780#if defined(__has_declspec_attribute)
781 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
782#else
783 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
784#endif
785
786#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
787 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
788#endif
789#if defined(__has_declspec_attribute)
790 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
791#else
792 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
793#endif
794
795#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
796 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
797#endif
798#if defined(__has_declspec_attribute)
799 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
800#else
801 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
802#endif
803
804#if defined(JSON_HEDLEY_HAS_WARNING)
805 #undef JSON_HEDLEY_HAS_WARNING
806#endif
807#if defined(__has_warning)
808 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
809#else
810 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
811#endif
812
813#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
814 #undef JSON_HEDLEY_GNUC_HAS_WARNING
815#endif
816#if defined(__has_warning)
817 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
818#else
819 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
820#endif
821
822#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
823 #undef JSON_HEDLEY_GCC_HAS_WARNING
824#endif
825#if defined(__has_warning)
826 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
827#else
828 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
829#endif
830
831#if \
832 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
833 defined(__clang__) || \
834 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
835 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
836 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
837 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
838 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
839 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
840 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
841 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
842 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
843 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
844 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
845 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
846 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
847 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
848 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
849 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
850 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
851#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
852 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
853#else
854 #define JSON_HEDLEY_PRAGMA(value)
855#endif
856
857#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
858 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
859#endif
860#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
861 #undef JSON_HEDLEY_DIAGNOSTIC_POP
862#endif
863#if defined(__clang__)
864 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
865 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
866#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
867 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
868 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
869#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
870 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
871 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
872#elif \
873 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
874 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
875 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
876 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
877#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
878 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
879 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
880#elif \
881 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
882 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
883 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
884 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
885 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
886 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
887 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
888 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
889#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
890 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
891 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
892#else
893 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
894 #define JSON_HEDLEY_DIAGNOSTIC_POP
895#endif
896
897/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
898 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
899#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
900 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
901#endif
902#if defined(__cplusplus)
903# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
904# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
905# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
906# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
907 JSON_HEDLEY_DIAGNOSTIC_PUSH \
908 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
909 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
910 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
911 xpr \
912 JSON_HEDLEY_DIAGNOSTIC_POP
913# else
914# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
915 JSON_HEDLEY_DIAGNOSTIC_PUSH \
916 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
917 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
918 xpr \
919 JSON_HEDLEY_DIAGNOSTIC_POP
920# endif
921# else
922# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
923 JSON_HEDLEY_DIAGNOSTIC_PUSH \
924 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
925 xpr \
926 JSON_HEDLEY_DIAGNOSTIC_POP
927# endif
928# endif
929#endif
930#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
931 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
932#endif
933
934#if defined(JSON_HEDLEY_CONST_CAST)
935 #undef JSON_HEDLEY_CONST_CAST
936#endif
937#if defined(__cplusplus)
938# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
939#elif \
940 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
941 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
942 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
943# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
944 JSON_HEDLEY_DIAGNOSTIC_PUSH \
945 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
946 ((T) (expr)); \
947 JSON_HEDLEY_DIAGNOSTIC_POP \
948 }))
949#else
950# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
951#endif
952
953#if defined(JSON_HEDLEY_REINTERPRET_CAST)
954 #undef JSON_HEDLEY_REINTERPRET_CAST
955#endif
956#if defined(__cplusplus)
957 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
958#else
959 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
960#endif
961
962#if defined(JSON_HEDLEY_STATIC_CAST)
963 #undef JSON_HEDLEY_STATIC_CAST
964#endif
965#if defined(__cplusplus)
966 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
967#else
968 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
969#endif
970
971#if defined(JSON_HEDLEY_CPP_CAST)
972 #undef JSON_HEDLEY_CPP_CAST
973#endif
974#if defined(__cplusplus)
975# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
976# define JSON_HEDLEY_CPP_CAST(T, expr) \
977 JSON_HEDLEY_DIAGNOSTIC_PUSH \
978 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
979 ((T) (expr)) \
980 JSON_HEDLEY_DIAGNOSTIC_POP
981# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
982# define JSON_HEDLEY_CPP_CAST(T, expr) \
983 JSON_HEDLEY_DIAGNOSTIC_PUSH \
984 _Pragma("diag_suppress=Pe137") \
985 JSON_HEDLEY_DIAGNOSTIC_POP
986# else
987# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
988# endif
989#else
990# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
991#endif
992
993#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
994 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
995#endif
996#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
997 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
998#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
999 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1000#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1001 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1002#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1003 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1004#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1005 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1006#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1007 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1008#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1009 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1010#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1011 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1012#elif \
1013 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1014 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1015 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1016 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1017 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1018 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1019 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1020 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1021 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1022 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1023 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1024 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1025#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1026 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1027#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1028 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1029#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1030 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1031#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1032 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1033#else
1034 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1035#endif
1036
1037#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1038 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1039#endif
1040#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1041 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1042#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1043 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1044#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1045 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1046#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1047 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1048#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1049 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1050#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1051 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1052#elif \
1053 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1054 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1055 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1056 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1057 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1058#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1059 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1060#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1061 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1062#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1063 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1064#else
1065 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1066#endif
1067
1068#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1069 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1070#endif
1071#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1072 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1073#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1074 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1075#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1076 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1077#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1078 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1079#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1080 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1081#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1082 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1083#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1084 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1085#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1086 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1087#elif \
1088 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1089 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1090 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1091 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1092#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1093 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1094#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1095 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1096#else
1097 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1098#endif
1099
1100#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1101 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1102#endif
1103#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1104 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1105#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1106 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1107#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1108 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1109#else
1110 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1111#endif
1112
1113#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1114 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1115#endif
1116#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1117 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1118#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1119 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1120#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1121 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1122#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1123 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1124#else
1125 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1126#endif
1127
1128#if defined(JSON_HEDLEY_DEPRECATED)
1129 #undef JSON_HEDLEY_DEPRECATED
1130#endif
1131#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1132 #undef JSON_HEDLEY_DEPRECATED_FOR
1133#endif
1134#if \
1135 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1136 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1137 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1138 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1139#elif \
1140 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1141 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1142 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1143 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1144 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1145 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1146 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1147 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1148 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1149 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1150 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1151 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1152 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1153 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1154#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1155 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1156 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1157#elif \
1158 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1159 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1160 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1161 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1162 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1163 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1164 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1165 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1166 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1167 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1168 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1169 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1170 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1171 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1172 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1173 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1174 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1175 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1176#elif \
1177 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1178 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1179 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1180 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1181 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1182#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1183 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1184 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1185#else
1186 #define JSON_HEDLEY_DEPRECATED(since)
1187 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1188#endif
1189
1190#if defined(JSON_HEDLEY_UNAVAILABLE)
1191 #undef JSON_HEDLEY_UNAVAILABLE
1192#endif
1193#if \
1194 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1195 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1196 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1197 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1198 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1199#else
1200 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1201#endif
1202
1203#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1204 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1205#endif
1206#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1207 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1208#endif
1209#if \
1210 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1211 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1212 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1213 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1214 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1215 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1216 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1217 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1218 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1219 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1220 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1221 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1222 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1223 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1224 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1225 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1226 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1227 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1228 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1229#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1230 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1231 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1232#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1233 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1234 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1235#elif defined(_Check_return_) /* SAL */
1236 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1237 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1238#else
1239 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1240 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1241#endif
1242
1243#if defined(JSON_HEDLEY_SENTINEL)
1244 #undef JSON_HEDLEY_SENTINEL
1245#endif
1246#if \
1247 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1248 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1249 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1250 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1251 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1252 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1253#else
1254 #define JSON_HEDLEY_SENTINEL(position)
1255#endif
1256
1257#if defined(JSON_HEDLEY_NO_RETURN)
1258 #undef JSON_HEDLEY_NO_RETURN
1259#endif
1260#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1261 #define JSON_HEDLEY_NO_RETURN __noreturn
1262#elif \
1263 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1264 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1265 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1266#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1267 #define JSON_HEDLEY_NO_RETURN _Noreturn
1268#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1269 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1270#elif \
1271 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1272 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1273 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1274 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1275 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1276 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1277 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1278 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1279 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1280 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1281 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1282 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1283 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1284 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1285 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1286 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1287 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1288 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1289#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1290 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1291#elif \
1292 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1293 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1294 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1295#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1296 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1297#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1298 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1299#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1300 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1301#else
1302 #define JSON_HEDLEY_NO_RETURN
1303#endif
1304
1305#if defined(JSON_HEDLEY_NO_ESCAPE)
1306 #undef JSON_HEDLEY_NO_ESCAPE
1307#endif
1308#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1309 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1310#else
1311 #define JSON_HEDLEY_NO_ESCAPE
1312#endif
1313
1314#if defined(JSON_HEDLEY_UNREACHABLE)
1315 #undef JSON_HEDLEY_UNREACHABLE
1316#endif
1317#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1318 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1319#endif
1320#if defined(JSON_HEDLEY_ASSUME)
1321 #undef JSON_HEDLEY_ASSUME
1322#endif
1323#if \
1324 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1325 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1326 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1327 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1328#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1329 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1330#elif \
1331 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1332 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1333 #if defined(__cplusplus)
1334 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1335 #else
1336 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1337 #endif
1338#endif
1339#if \
1340 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1341 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1342 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1343 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1344 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1345 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1346 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1347 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1348#elif defined(JSON_HEDLEY_ASSUME)
1349 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1350#endif
1351#if !defined(JSON_HEDLEY_ASSUME)
1352 #if defined(JSON_HEDLEY_UNREACHABLE)
1353 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1354 #else
1355 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1356 #endif
1357#endif
1358#if defined(JSON_HEDLEY_UNREACHABLE)
1359 #if \
1360 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1361 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1362 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1363 #else
1364 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1365 #endif
1366#else
1367 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1368#endif
1369#if !defined(JSON_HEDLEY_UNREACHABLE)
1370 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1371#endif
1372
1374#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1375 #pragma clang diagnostic ignored "-Wpedantic"
1376#endif
1377#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1378 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1379#endif
1380#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1381 #if defined(__clang__)
1382 #pragma clang diagnostic ignored "-Wvariadic-macros"
1383 #elif defined(JSON_HEDLEY_GCC_VERSION)
1384 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1385 #endif
1386#endif
1387#if defined(JSON_HEDLEY_NON_NULL)
1388 #undef JSON_HEDLEY_NON_NULL
1389#endif
1390#if \
1391 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1392 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1393 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1394 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1395 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1396#else
1397 #define JSON_HEDLEY_NON_NULL(...)
1398#endif
1400
1401#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1402 #undef JSON_HEDLEY_PRINTF_FORMAT
1403#endif
1404#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1405 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1406#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1407 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1408#elif \
1409 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1410 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1411 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1412 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1413 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1414 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1415 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1416 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1417 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1418 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1419 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1420 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1421 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1422 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1423 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1424 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1425 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1426 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1427#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1428 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1429#else
1430 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1431#endif
1432
1433#if defined(JSON_HEDLEY_CONSTEXPR)
1434 #undef JSON_HEDLEY_CONSTEXPR
1435#endif
1436#if defined(__cplusplus)
1437 #if __cplusplus >= 201103L
1438 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1439 #endif
1440#endif
1441#if !defined(JSON_HEDLEY_CONSTEXPR)
1442 #define JSON_HEDLEY_CONSTEXPR
1443#endif
1444
1445#if defined(JSON_HEDLEY_PREDICT)
1446 #undef JSON_HEDLEY_PREDICT
1447#endif
1448#if defined(JSON_HEDLEY_LIKELY)
1449 #undef JSON_HEDLEY_LIKELY
1450#endif
1451#if defined(JSON_HEDLEY_UNLIKELY)
1452 #undef JSON_HEDLEY_UNLIKELY
1453#endif
1454#if defined(JSON_HEDLEY_UNPREDICTABLE)
1455 #undef JSON_HEDLEY_UNPREDICTABLE
1456#endif
1457#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1458 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1459#endif
1460#if \
1461 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1462 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1463 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1464# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1465# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1466# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1467# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1468# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1469#elif \
1470 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1471 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1472 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1473 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1474 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1475 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1476 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1477 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1478 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1479 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1480 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1481 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1482 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1483 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1484 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1485 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1486# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1487 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1488# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1489 (__extension__ ({ \
1490 double hedley_probability_ = (probability); \
1491 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1492 }))
1493# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1494 (__extension__ ({ \
1495 double hedley_probability_ = (probability); \
1496 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1497 }))
1498# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1499# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1500#else
1501# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1502# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1503# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1504# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1505# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1506#endif
1507#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1508 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1509#endif
1510
1511#if defined(JSON_HEDLEY_MALLOC)
1512 #undef JSON_HEDLEY_MALLOC
1513#endif
1514#if \
1515 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1516 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1517 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1518 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1519 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1520 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1521 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1522 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1523 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1524 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1525 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1526 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1527 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1528 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1529 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1530 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1531 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1532 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1533 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1534#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1535 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1536#elif \
1537 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1538 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1539 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1540#else
1541 #define JSON_HEDLEY_MALLOC
1542#endif
1543
1544#if defined(JSON_HEDLEY_PURE)
1545 #undef JSON_HEDLEY_PURE
1546#endif
1547#if \
1548 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1549 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1550 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1551 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1552 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1553 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1554 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1555 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1556 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1557 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1558 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1559 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1560 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1561 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1562 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1563 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1564 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1565 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1566 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1567# define JSON_HEDLEY_PURE __attribute__((__pure__))
1568#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1569# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1570#elif defined(__cplusplus) && \
1571 ( \
1572 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1573 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1574 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1575 )
1576# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1577#else
1578# define JSON_HEDLEY_PURE
1579#endif
1580
1581#if defined(JSON_HEDLEY_CONST)
1582 #undef JSON_HEDLEY_CONST
1583#endif
1584#if \
1585 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1586 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1587 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1588 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1589 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1590 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1591 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1592 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1593 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1594 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1595 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1596 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1597 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1598 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1599 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1600 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1601 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1602 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1603 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1604 #define JSON_HEDLEY_CONST __attribute__((__const__))
1605#elif \
1606 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1607 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1608#else
1609 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1610#endif
1611
1612#if defined(JSON_HEDLEY_RESTRICT)
1613 #undef JSON_HEDLEY_RESTRICT
1614#endif
1615#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1616 #define JSON_HEDLEY_RESTRICT restrict
1617#elif \
1618 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1619 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1620 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1621 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1622 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1623 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1624 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1625 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1626 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1627 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1628 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1629 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1630 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1631 defined(__clang__) || \
1632 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1633 #define JSON_HEDLEY_RESTRICT __restrict
1634#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1635 #define JSON_HEDLEY_RESTRICT _Restrict
1636#else
1637 #define JSON_HEDLEY_RESTRICT
1638#endif
1639
1640#if defined(JSON_HEDLEY_INLINE)
1641 #undef JSON_HEDLEY_INLINE
1642#endif
1643#if \
1644 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1645 (defined(__cplusplus) && (__cplusplus >= 199711L))
1646 #define JSON_HEDLEY_INLINE inline
1647#elif \
1648 defined(JSON_HEDLEY_GCC_VERSION) || \
1649 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1650 #define JSON_HEDLEY_INLINE __inline__
1651#elif \
1652 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1653 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1654 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1655 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1656 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1657 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1658 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1659 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1660 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1661 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1662 #define JSON_HEDLEY_INLINE __inline
1663#else
1664 #define JSON_HEDLEY_INLINE
1665#endif
1666
1667#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1668 #undef JSON_HEDLEY_ALWAYS_INLINE
1669#endif
1670#if \
1671 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1672 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1673 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1674 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1675 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1676 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1677 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1678 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1679 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1680 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1681 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1682 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1683 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1684 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1685 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1686 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1687 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1688 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1689 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1690# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1691#elif \
1692 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1693 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1694# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1695#elif defined(__cplusplus) && \
1696 ( \
1697 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1698 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1699 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1700 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1701 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1702 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1703 )
1704# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1705#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1706# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1707#else
1708# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1709#endif
1710
1711#if defined(JSON_HEDLEY_NEVER_INLINE)
1712 #undef JSON_HEDLEY_NEVER_INLINE
1713#endif
1714#if \
1715 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1716 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1717 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1718 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1719 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1720 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1721 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1722 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1723 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1724 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1725 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1726 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1727 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1728 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1729 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1730 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1731 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1732 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1733 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1734 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1735#elif \
1736 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1737 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1738 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1739#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1740 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1741#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1742 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1743#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1744 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1745#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1746 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1747#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1748 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1749#else
1750 #define JSON_HEDLEY_NEVER_INLINE
1751#endif
1752
1753#if defined(JSON_HEDLEY_PRIVATE)
1754 #undef JSON_HEDLEY_PRIVATE
1755#endif
1756#if defined(JSON_HEDLEY_PUBLIC)
1757 #undef JSON_HEDLEY_PUBLIC
1758#endif
1759#if defined(JSON_HEDLEY_IMPORT)
1760 #undef JSON_HEDLEY_IMPORT
1761#endif
1762#if defined(_WIN32) || defined(__CYGWIN__)
1763# define JSON_HEDLEY_PRIVATE
1764# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1765# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1766#else
1767# if \
1768 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1769 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1770 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1771 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1772 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1773 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1774 ( \
1775 defined(__TI_EABI__) && \
1776 ( \
1777 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1778 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1779 ) \
1780 ) || \
1781 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1782# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1783# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1784# else
1785# define JSON_HEDLEY_PRIVATE
1786# define JSON_HEDLEY_PUBLIC
1787# endif
1788# define JSON_HEDLEY_IMPORT extern
1789#endif
1790
1791#if defined(JSON_HEDLEY_NO_THROW)
1792 #undef JSON_HEDLEY_NO_THROW
1793#endif
1794#if \
1795 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
1796 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1797 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1798 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1799 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
1800#elif \
1801 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
1802 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1803 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1804 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
1805#else
1806 #define JSON_HEDLEY_NO_THROW
1807#endif
1808
1809#if defined(JSON_HEDLEY_FALL_THROUGH)
1810 #undef JSON_HEDLEY_FALL_THROUGH
1811#endif
1812#if \
1813 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
1814 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
1815 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1816 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
1817#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
1818 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
1819#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
1820 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
1821#elif defined(__fallthrough) /* SAL */
1822 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
1823#else
1824 #define JSON_HEDLEY_FALL_THROUGH
1825#endif
1826
1827#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
1828 #undef JSON_HEDLEY_RETURNS_NON_NULL
1829#endif
1830#if \
1831 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
1832 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
1833 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1834 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
1835#elif defined(_Ret_notnull_) /* SAL */
1836 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
1837#else
1838 #define JSON_HEDLEY_RETURNS_NON_NULL
1839#endif
1840
1841#if defined(JSON_HEDLEY_ARRAY_PARAM)
1842 #undef JSON_HEDLEY_ARRAY_PARAM
1843#endif
1844#if \
1845 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
1846 !defined(__STDC_NO_VLA__) && \
1847 !defined(__cplusplus) && \
1848 !defined(JSON_HEDLEY_PGI_VERSION) && \
1849 !defined(JSON_HEDLEY_TINYC_VERSION)
1850 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
1851#else
1852 #define JSON_HEDLEY_ARRAY_PARAM(name)
1853#endif
1854
1855#if defined(JSON_HEDLEY_IS_CONSTANT)
1856 #undef JSON_HEDLEY_IS_CONSTANT
1857#endif
1858#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
1859 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
1860#endif
1861/* JSON_HEDLEY_IS_CONSTEXPR_ is for
1862 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1863#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1864 #undef JSON_HEDLEY_IS_CONSTEXPR_
1865#endif
1866#if \
1867 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
1868 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1869 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1870 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
1871 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1872 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1873 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1874 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
1875 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1876 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1877 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
1878#endif
1879#if !defined(__cplusplus)
1880# if \
1881 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
1882 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1883 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1884 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1885 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1886 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1887 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
1888#if defined(__INTPTR_TYPE__)
1889 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
1890#else
1891 #include <stdint.h>
1892 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
1893#endif
1894# elif \
1895 ( \
1896 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
1897 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
1898 !defined(JSON_HEDLEY_PGI_VERSION) && \
1899 !defined(JSON_HEDLEY_IAR_VERSION)) || \
1900 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1901 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
1902 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
1903 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1904 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
1905#if defined(__INTPTR_TYPE__)
1906 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
1907#else
1908 #include <stdint.h>
1909 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
1910#endif
1911# elif \
1912 defined(JSON_HEDLEY_GCC_VERSION) || \
1913 defined(JSON_HEDLEY_INTEL_VERSION) || \
1914 defined(JSON_HEDLEY_TINYC_VERSION) || \
1915 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
1916 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
1917 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
1918 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
1919 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
1920 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
1921 defined(__clang__)
1922# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
1923 sizeof(void) != \
1924 sizeof(*( \
1925 1 ? \
1926 ((void*) ((expr) * 0L) ) : \
1927((struct { char v[sizeof(void) * 2]; } *) 1) \
1928 ) \
1929 ) \
1930 )
1931# endif
1932#endif
1933#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1934 #if !defined(JSON_HEDLEY_IS_CONSTANT)
1935 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
1936 #endif
1937 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
1938#else
1939 #if !defined(JSON_HEDLEY_IS_CONSTANT)
1940 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
1941 #endif
1942 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
1943#endif
1944
1945#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
1946 #undef JSON_HEDLEY_BEGIN_C_DECLS
1947#endif
1948#if defined(JSON_HEDLEY_END_C_DECLS)
1949 #undef JSON_HEDLEY_END_C_DECLS
1950#endif
1951#if defined(JSON_HEDLEY_C_DECL)
1952 #undef JSON_HEDLEY_C_DECL
1953#endif
1954#if defined(__cplusplus)
1955 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
1956 #define JSON_HEDLEY_END_C_DECLS }
1957 #define JSON_HEDLEY_C_DECL extern "C"
1958#else
1959 #define JSON_HEDLEY_BEGIN_C_DECLS
1960 #define JSON_HEDLEY_END_C_DECLS
1961 #define JSON_HEDLEY_C_DECL
1962#endif
1963
1964#if defined(JSON_HEDLEY_STATIC_ASSERT)
1965 #undef JSON_HEDLEY_STATIC_ASSERT
1966#endif
1967#if \
1968 !defined(__cplusplus) && ( \
1969 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
1970 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1971 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
1972 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1973 defined(_Static_assert) \
1974 )
1975# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
1976#elif \
1977 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
1978 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
1979 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1980# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
1981#else
1982# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
1983#endif
1984
1985#if defined(JSON_HEDLEY_NULL)
1986 #undef JSON_HEDLEY_NULL
1987#endif
1988#if defined(__cplusplus)
1989 #if __cplusplus >= 201103L
1990 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
1991 #elif defined(NULL)
1992 #define JSON_HEDLEY_NULL NULL
1993 #else
1994 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
1995 #endif
1996#elif defined(NULL)
1997 #define JSON_HEDLEY_NULL NULL
1998#else
1999 #define JSON_HEDLEY_NULL ((void*) 0)
2000#endif
2001
2002#if defined(JSON_HEDLEY_MESSAGE)
2003 #undef JSON_HEDLEY_MESSAGE
2004#endif
2005#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2006# define JSON_HEDLEY_MESSAGE(msg) \
2007 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2008 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2009 JSON_HEDLEY_PRAGMA(message msg) \
2010 JSON_HEDLEY_DIAGNOSTIC_POP
2011#elif \
2012 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2013 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2014# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2015#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2016# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2017#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2018# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2019#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2020# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2021#else
2022# define JSON_HEDLEY_MESSAGE(msg)
2023#endif
2024
2025#if defined(JSON_HEDLEY_WARNING)
2026 #undef JSON_HEDLEY_WARNING
2027#endif
2028#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2029# define JSON_HEDLEY_WARNING(msg) \
2030 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2031 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2032 JSON_HEDLEY_PRAGMA(clang warning msg) \
2033 JSON_HEDLEY_DIAGNOSTIC_POP
2034#elif \
2035 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2036 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2037 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2038# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2039#elif \
2040 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2041 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2042# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2043#else
2044# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2045#endif
2046
2047#if defined(JSON_HEDLEY_REQUIRE)
2048 #undef JSON_HEDLEY_REQUIRE
2049#endif
2050#if defined(JSON_HEDLEY_REQUIRE_MSG)
2051 #undef JSON_HEDLEY_REQUIRE_MSG
2052#endif
2053#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2054# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2055# define JSON_HEDLEY_REQUIRE(expr) \
2056 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2057 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2058 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2059 JSON_HEDLEY_DIAGNOSTIC_POP
2060# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2061 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2062 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2063 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2064 JSON_HEDLEY_DIAGNOSTIC_POP
2065# else
2066# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2067# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2068# endif
2069#else
2070# define JSON_HEDLEY_REQUIRE(expr)
2071# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2072#endif
2073
2074#if defined(JSON_HEDLEY_FLAGS)
2075 #undef JSON_HEDLEY_FLAGS
2076#endif
2077#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2078 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2079#else
2080 #define JSON_HEDLEY_FLAGS
2081#endif
2082
2083#if defined(JSON_HEDLEY_FLAGS_CAST)
2084 #undef JSON_HEDLEY_FLAGS_CAST
2085#endif
2086#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2087# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2088 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2089 _Pragma("warning(disable:188)") \
2090 ((T) (expr)); \
2091 JSON_HEDLEY_DIAGNOSTIC_POP \
2092 }))
2093#else
2094# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2095#endif
2096
2097#if defined(JSON_HEDLEY_EMPTY_BASES)
2098 #undef JSON_HEDLEY_EMPTY_BASES
2099#endif
2100#if \
2101 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2102 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2103 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2104#else
2105 #define JSON_HEDLEY_EMPTY_BASES
2106#endif
2107
2108/* Remaining macros are deprecated. */
2109
2110#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2111 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2112#endif
2113#if defined(__clang__)
2114 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2115#else
2116 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2117#endif
2118
2119#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2120 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2121#endif
2122#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2123
2124#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2125 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2126#endif
2127#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2128
2129#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2130 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2131#endif
2132#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2133
2134#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2135 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2136#endif
2137#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2138
2139#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2140 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2141#endif
2142#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2143
2144#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2145 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2146#endif
2147#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2148
2149#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2150 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2151#endif
2152#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2153
2154#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2155
2156// #include <nlohmann/detail/meta/detected.hpp>
2157
2158
2159#include <type_traits>
2160
2161// #include <nlohmann/detail/meta/void_t.hpp>
2162
2163
2164namespace nlohmann
2165{
2166namespace detail
2167{
2168template<typename ...Ts> struct make_void
2169{
2170 using type = void;
2171};
2172template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
2173} // namespace detail
2174} // namespace nlohmann
2175
2176
2177// https://en.cppreference.com/w/cpp/experimental/is_detected
2178namespace nlohmann
2179{
2180namespace detail
2181{
2183{
2184 nonesuch() = delete;
2185 ~nonesuch() = delete;
2186 nonesuch(nonesuch const&) = delete;
2187 nonesuch(nonesuch const&&) = delete;
2188 void operator=(nonesuch const&) = delete;
2189 void operator=(nonesuch&&) = delete;
2190};
2191
2192template<class Default,
2193 class AlwaysVoid,
2194 template<class...> class Op,
2195 class... Args>
2197{
2198 using value_t = std::false_type;
2199 using type = Default;
2200};
2201
2202template<class Default, template<class...> class Op, class... Args>
2203struct detector<Default, void_t<Op<Args...>>, Op, Args...>
2204{
2205 using value_t = std::true_type;
2206 using type = Op<Args...>;
2207};
2208
2209template<template<class...> class Op, class... Args>
2210using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
2211
2212template<template<class...> class Op, class... Args>
2213struct is_detected_lazy : is_detected<Op, Args...> { };
2214
2215template<template<class...> class Op, class... Args>
2216using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
2217
2218template<class Default, template<class...> class Op, class... Args>
2219using detected_or = detector<Default, void, Op, Args...>;
2220
2221template<class Default, template<class...> class Op, class... Args>
2222using detected_or_t = typename detected_or<Default, Op, Args...>::type;
2223
2224template<class Expected, template<class...> class Op, class... Args>
2225using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
2226
2227template<class To, template<class...> class Op, class... Args>
2229 std::is_convertible<detected_t<Op, Args...>, To>;
2230} // namespace detail
2231} // namespace nlohmann
2232
2233
2234// This file contains all internal macro definitions
2235// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2236
2237// exclude unsupported compilers
2238#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2239 #if defined(__clang__)
2240 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2241 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2242 #endif
2243 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2244 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2245 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2246 #endif
2247 #endif
2248#endif
2249
2250// C++ language standard detection
2251// if the user manually specified the used c++ version this is skipped
2252#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2253 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2254 #define JSON_HAS_CPP_20
2255 #define JSON_HAS_CPP_17
2256 #define JSON_HAS_CPP_14
2257 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2258 #define JSON_HAS_CPP_17
2259 #define JSON_HAS_CPP_14
2260 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2261 #define JSON_HAS_CPP_14
2262 #endif
2263 // the cpp 11 flag is always specified because it is the minimal required version
2264 #define JSON_HAS_CPP_11
2265#endif
2266
2267#ifdef __has_include
2268 #if __has_include(<version>)
2269 #include <version>
2270 #endif
2271#endif
2272
2273#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2274 #ifdef JSON_HAS_CPP_17
2275 #if defined(__cpp_lib_filesystem)
2276 #define JSON_HAS_FILESYSTEM 1
2277 #elif defined(__cpp_lib_experimental_filesystem)
2278 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2279 #elif !defined(__has_include)
2280 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2281 #elif __has_include(<filesystem>)
2282 #define JSON_HAS_FILESYSTEM 1
2283 #elif __has_include(<experimental/filesystem>)
2284 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2285 #endif
2286
2287 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2288 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2289 #undef JSON_HAS_FILESYSTEM
2290 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2291 #endif
2292
2293 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2294 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2295 #undef JSON_HAS_FILESYSTEM
2296 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2297 #endif
2298
2299 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2300 #if defined(__clang_major__) && __clang_major__ < 7
2301 #undef JSON_HAS_FILESYSTEM
2302 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2303 #endif
2304
2305 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2306 #if defined(_MSC_VER) && _MSC_VER < 1914
2307 #undef JSON_HAS_FILESYSTEM
2308 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2309 #endif
2310
2311 // no filesystem support before iOS 13
2312 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2313 #undef JSON_HAS_FILESYSTEM
2314 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2315 #endif
2316
2317 // no filesystem support before macOS Catalina
2318 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2319 #undef JSON_HAS_FILESYSTEM
2320 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2321 #endif
2322 #endif
2323#endif
2324
2325#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2326 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2327#endif
2328
2329#ifndef JSON_HAS_FILESYSTEM
2330 #define JSON_HAS_FILESYSTEM 0
2331#endif
2332
2333#ifndef JSON_HAS_THREE_WAY_COMPARISON
2334 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2335 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2336 #define JSON_HAS_THREE_WAY_COMPARISON 1
2337 #else
2338 #define JSON_HAS_THREE_WAY_COMPARISON 0
2339 #endif
2340#endif
2341
2342#ifndef JSON_HAS_RANGES
2343 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
2344 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2345 #define JSON_HAS_RANGES 0
2346 #elif defined(__cpp_lib_ranges)
2347 #define JSON_HAS_RANGES 1
2348 #else
2349 #define JSON_HAS_RANGES 0
2350 #endif
2351#endif
2352
2353#ifdef JSON_HAS_CPP_17
2354 #define JSON_INLINE_VARIABLE inline
2355#else
2356 #define JSON_INLINE_VARIABLE
2357#endif
2358
2359#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2360 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2361#else
2362 #define JSON_NO_UNIQUE_ADDRESS
2363#endif
2364
2365// disable documentation warnings on clang
2366#if defined(__clang__)
2367 #pragma clang diagnostic push
2368 #pragma clang diagnostic ignored "-Wdocumentation"
2369 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2370#endif
2371
2372// allow disabling exceptions
2373#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2374 #define JSON_THROW(exception) throw exception
2375 #define JSON_TRY try
2376 #define JSON_CATCH(exception) catch(exception)
2377 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2378#else
2379 #include <cstdlib>
2380 #define JSON_THROW(exception) std::abort()
2381 #define JSON_TRY if(true)
2382 #define JSON_CATCH(exception) if(false)
2383 #define JSON_INTERNAL_CATCH(exception) if(false)
2384#endif
2385
2386// override exception macros
2387#if defined(JSON_THROW_USER)
2388 #undef JSON_THROW
2389 #define JSON_THROW JSON_THROW_USER
2390#endif
2391#if defined(JSON_TRY_USER)
2392 #undef JSON_TRY
2393 #define JSON_TRY JSON_TRY_USER
2394#endif
2395#if defined(JSON_CATCH_USER)
2396 #undef JSON_CATCH
2397 #define JSON_CATCH JSON_CATCH_USER
2398 #undef JSON_INTERNAL_CATCH
2399 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2400#endif
2401#if defined(JSON_INTERNAL_CATCH_USER)
2402 #undef JSON_INTERNAL_CATCH
2403 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2404#endif
2405
2406// allow overriding assert
2407#if !defined(JSON_ASSERT)
2408 #include <cassert> // assert
2409 #define JSON_ASSERT(x) assert(x)
2410#endif
2411
2412// allow to access some private functions (needed by the test suite)
2413#if defined(JSON_TESTS_PRIVATE)
2414 #define JSON_PRIVATE_UNLESS_TESTED public
2415#else
2416 #define JSON_PRIVATE_UNLESS_TESTED private
2417#endif
2418
2424#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2425 template<typename BasicJsonType> \
2426 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2427 { \
2428 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2429 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2430 auto it = std::find_if(std::begin(m), std::end(m), \
2431 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2432 { \
2433 return ej_pair.first == e; \
2434 }); \
2435 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2436 } \
2437 template<typename BasicJsonType> \
2438 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2439 { \
2440 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2441 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2442 auto it = std::find_if(std::begin(m), std::end(m), \
2443 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2444 { \
2445 return ej_pair.second == j; \
2446 }); \
2447 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2448 }
2449
2450// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2451// may be removed in the future once the class is split.
2452
2453#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2454 template<template<typename, typename, typename...> class ObjectType, \
2455 template<typename, typename...> class ArrayType, \
2456 class StringType, class BooleanType, class NumberIntegerType, \
2457 class NumberUnsignedType, class NumberFloatType, \
2458 template<typename> class AllocatorType, \
2459 template<typename, typename = void> class JSONSerializer, \
2460 class BinaryType>
2461
2462#define NLOHMANN_BASIC_JSON_TPL \
2463 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2464 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2465 AllocatorType, JSONSerializer, BinaryType>
2466
2467// Macros to simplify conversion from/to types
2468
2469#define NLOHMANN_JSON_EXPAND( x ) x
2470#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
2471#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2472 NLOHMANN_JSON_PASTE64, \
2473 NLOHMANN_JSON_PASTE63, \
2474 NLOHMANN_JSON_PASTE62, \
2475 NLOHMANN_JSON_PASTE61, \
2476 NLOHMANN_JSON_PASTE60, \
2477 NLOHMANN_JSON_PASTE59, \
2478 NLOHMANN_JSON_PASTE58, \
2479 NLOHMANN_JSON_PASTE57, \
2480 NLOHMANN_JSON_PASTE56, \
2481 NLOHMANN_JSON_PASTE55, \
2482 NLOHMANN_JSON_PASTE54, \
2483 NLOHMANN_JSON_PASTE53, \
2484 NLOHMANN_JSON_PASTE52, \
2485 NLOHMANN_JSON_PASTE51, \
2486 NLOHMANN_JSON_PASTE50, \
2487 NLOHMANN_JSON_PASTE49, \
2488 NLOHMANN_JSON_PASTE48, \
2489 NLOHMANN_JSON_PASTE47, \
2490 NLOHMANN_JSON_PASTE46, \
2491 NLOHMANN_JSON_PASTE45, \
2492 NLOHMANN_JSON_PASTE44, \
2493 NLOHMANN_JSON_PASTE43, \
2494 NLOHMANN_JSON_PASTE42, \
2495 NLOHMANN_JSON_PASTE41, \
2496 NLOHMANN_JSON_PASTE40, \
2497 NLOHMANN_JSON_PASTE39, \
2498 NLOHMANN_JSON_PASTE38, \
2499 NLOHMANN_JSON_PASTE37, \
2500 NLOHMANN_JSON_PASTE36, \
2501 NLOHMANN_JSON_PASTE35, \
2502 NLOHMANN_JSON_PASTE34, \
2503 NLOHMANN_JSON_PASTE33, \
2504 NLOHMANN_JSON_PASTE32, \
2505 NLOHMANN_JSON_PASTE31, \
2506 NLOHMANN_JSON_PASTE30, \
2507 NLOHMANN_JSON_PASTE29, \
2508 NLOHMANN_JSON_PASTE28, \
2509 NLOHMANN_JSON_PASTE27, \
2510 NLOHMANN_JSON_PASTE26, \
2511 NLOHMANN_JSON_PASTE25, \
2512 NLOHMANN_JSON_PASTE24, \
2513 NLOHMANN_JSON_PASTE23, \
2514 NLOHMANN_JSON_PASTE22, \
2515 NLOHMANN_JSON_PASTE21, \
2516 NLOHMANN_JSON_PASTE20, \
2517 NLOHMANN_JSON_PASTE19, \
2518 NLOHMANN_JSON_PASTE18, \
2519 NLOHMANN_JSON_PASTE17, \
2520 NLOHMANN_JSON_PASTE16, \
2521 NLOHMANN_JSON_PASTE15, \
2522 NLOHMANN_JSON_PASTE14, \
2523 NLOHMANN_JSON_PASTE13, \
2524 NLOHMANN_JSON_PASTE12, \
2525 NLOHMANN_JSON_PASTE11, \
2526 NLOHMANN_JSON_PASTE10, \
2527 NLOHMANN_JSON_PASTE9, \
2528 NLOHMANN_JSON_PASTE8, \
2529 NLOHMANN_JSON_PASTE7, \
2530 NLOHMANN_JSON_PASTE6, \
2531 NLOHMANN_JSON_PASTE5, \
2532 NLOHMANN_JSON_PASTE4, \
2533 NLOHMANN_JSON_PASTE3, \
2534 NLOHMANN_JSON_PASTE2, \
2535 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2536#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2537#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2538#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2539#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2540#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2541#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)
2542#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)
2543#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)
2544#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)
2545#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)
2546#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)
2547#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)
2548#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)
2549#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)
2550#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)
2551#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)
2552#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)
2553#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)
2554#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)
2555#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)
2556#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)
2557#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)
2558#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)
2559#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)
2560#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)
2561#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)
2562#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)
2563#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)
2564#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)
2565#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)
2566#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)
2567#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)
2568#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)
2569#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)
2570#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)
2571#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)
2572#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)
2573#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)
2574#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)
2575#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)
2576#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)
2577#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)
2578#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)
2579#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)
2580#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)
2581#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)
2582#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)
2583#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)
2584#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)
2585#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)
2586#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)
2587#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)
2588#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)
2589#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)
2590#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)
2591#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)
2592#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)
2593#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)
2594#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)
2595#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)
2596#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)
2597#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)
2598#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)
2599
2600#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2601#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2602#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
2603
2609#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2610 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__)) } \
2611 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__)) }
2612
2613#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2614 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__)) } \
2615 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2616
2622#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2623 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__)) } \
2624 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__)) }
2625
2626#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2627 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__)) } \
2628 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2629
2630
2631// inspired from https://stackoverflow.com/a/26745591
2632// allows to call any std function as if (e.g. with begin):
2633// using std::begin; begin(x);
2634//
2635// it allows using the detected idiom to retrieve the return type
2636// of such an expression
2637#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2638 namespace detail { \
2639 using std::std_name; \
2640 \
2641 template<typename... T> \
2642 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2643 } \
2644 \
2645 namespace detail2 { \
2646 struct std_name##_tag \
2647 { \
2648 }; \
2649 \
2650 template<typename... T> \
2651 std_name##_tag std_name(T&&...); \
2652 \
2653 template<typename... T> \
2654 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2655 \
2656 template<typename... T> \
2657 struct would_call_std_##std_name \
2658 { \
2659 static constexpr auto const value = ::nlohmann::detail:: \
2660 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2661 }; \
2662 } /* namespace detail2 */ \
2663 \
2664 template<typename... T> \
2665 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2666 { \
2667 }
2668
2669#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2670 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2671#endif
2672
2673#if JSON_USE_IMPLICIT_CONVERSIONS
2674 #define JSON_EXPLICIT
2675#else
2676 #define JSON_EXPLICIT explicit
2677#endif
2678
2679#ifndef JSON_DIAGNOSTICS
2680 #define JSON_DIAGNOSTICS 0
2681#endif
2682
2683#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
2684 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
2685#endif
2686
2687#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2688 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2689#endif
2690
2691#if JSON_HAS_THREE_WAY_COMPARISON
2692 #include <compare> // partial_ordering
2693#endif
2694
2695namespace nlohmann
2696{
2697namespace detail
2698{
2700// JSON type enumeration //
2702
2727enum class value_t : std::uint8_t
2728{
2729 null,
2730 object,
2731 array,
2732 string,
2733 boolean,
2736 number_float,
2737 binary,
2738 discarded
2739};
2740
2754#if JSON_HAS_THREE_WAY_COMPARISON
2755 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
2756#else
2757 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2758#endif
2759{
2760 static constexpr std::array<std::uint8_t, 9> order = {{
2761 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
2762 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
2763 6 /* binary */
2764 }
2765 };
2766
2767 const auto l_index = static_cast<std::size_t>(lhs);
2768 const auto r_index = static_cast<std::size_t>(rhs);
2769#if JSON_HAS_THREE_WAY_COMPARISON
2770 if (l_index < order.size() && r_index < order.size())
2771 {
2772 return order[l_index] <=> order[r_index]; // *NOPAD*
2773 }
2774 return std::partial_ordering::unordered;
2775#else
2776 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
2777#endif
2778}
2779
2780// GCC selects the built-in operator< over an operator rewritten from
2781// a user-defined spaceship operator
2782// Clang, MSVC, and ICC select the rewritten candidate
2783// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
2784#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
2785inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2786{
2787 return std::is_lt(lhs <=> rhs); // *NOPAD*
2788}
2789#endif
2790} // namespace detail
2791} // namespace nlohmann
2792
2793// #include <nlohmann/detail/string_escape.hpp>
2794
2795
2796// #include <nlohmann/detail/macro_scope.hpp>
2797
2798
2799namespace nlohmann
2800{
2801namespace detail
2802{
2803
2817template<typename StringType>
2818inline void replace_substring(StringType& s, const StringType& f,
2819 const StringType& t)
2820{
2821 JSON_ASSERT(!f.empty());
2822 for (auto pos = s.find(f); // find first occurrence of f
2823 pos != StringType::npos; // make sure f was found
2824 s.replace(pos, f.size(), t), // replace with t, and
2825 pos = s.find(f, pos + t.size())) // find next occurrence of f
2826 {}
2827}
2828
2836template<typename StringType>
2837inline StringType escape(StringType s)
2838{
2839 replace_substring(s, StringType{"~"}, StringType{"~0"});
2840 replace_substring(s, StringType{"/"}, StringType{"~1"});
2841 return s;
2842}
2843
2851template<typename StringType>
2852static void unescape(StringType& s)
2853{
2854 replace_substring(s, StringType{"~1"}, StringType{"/"});
2855 replace_substring(s, StringType{"~0"}, StringType{"~"});
2856}
2857
2858} // namespace detail
2859} // namespace nlohmann
2860
2861// #include <nlohmann/detail/input/position_t.hpp>
2862
2863
2864#include <cstddef> // size_t
2865
2866namespace nlohmann
2867{
2868namespace detail
2869{
2872{
2874 std::size_t chars_read_total = 0;
2878 std::size_t lines_read = 0;
2879
2881 constexpr operator size_t() const
2882 {
2883 return chars_read_total;
2884 }
2885};
2886
2887} // namespace detail
2888} // namespace nlohmann
2889
2890// #include <nlohmann/detail/macro_scope.hpp>
2891
2892// #include <nlohmann/detail/meta/cpp_future.hpp>
2893
2894
2895#include <cstddef> // size_t
2896#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
2897#include <utility> // index_sequence, make_index_sequence, index_sequence_for
2898
2899// #include <nlohmann/detail/macro_scope.hpp>
2900
2901
2902namespace nlohmann
2903{
2904namespace detail
2905{
2906
2907template<typename T>
2908using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
2909
2910#ifdef JSON_HAS_CPP_14
2911
2912// the following utilities are natively available in C++14
2913using std::enable_if_t;
2914using std::index_sequence;
2915using std::make_index_sequence;
2916using std::index_sequence_for;
2917
2918#else
2919
2920// alias templates to reduce boilerplate
2921template<bool B, typename T = void>
2922using enable_if_t = typename std::enable_if<B, T>::type;
2923
2924// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
2925// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
2926
2928
2929// integer_sequence
2930//
2931// Class template representing a compile-time integer sequence. An instantiation
2932// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
2933// type through its template arguments (which is a common need when
2934// working with C++11 variadic templates). `absl::integer_sequence` is designed
2935// to be a drop-in replacement for C++14's `std::integer_sequence`.
2936//
2937// Example:
2938//
2939// template< class T, T... Ints >
2940// void user_function(integer_sequence<T, Ints...>);
2941//
2942// int main()
2943// {
2944// // user_function's `T` will be deduced to `int` and `Ints...`
2945// // will be deduced to `0, 1, 2, 3, 4`.
2946// user_function(make_integer_sequence<int, 5>());
2947// }
2948template <typename T, T... Ints>
2950{
2951 using value_type = T;
2952 static constexpr std::size_t size() noexcept
2953 {
2954 return sizeof...(Ints);
2955 }
2956};
2957
2958// index_sequence
2959//
2960// A helper template for an `integer_sequence` of `size_t`,
2961// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
2962// `std::index_sequence`.
2963template <size_t... Ints>
2964using index_sequence = integer_sequence<size_t, Ints...>;
2965
2966namespace utility_internal
2967{
2968
2969template <typename Seq, size_t SeqSize, size_t Rem>
2970struct Extend;
2971
2972// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
2973template <typename T, T... Ints, size_t SeqSize>
2974struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
2975{
2976 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
2977};
2978
2979template <typename T, T... Ints, size_t SeqSize>
2980struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
2981{
2982 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
2983};
2984
2985// Recursion helper for 'make_integer_sequence<T, N>'.
2986// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
2987template <typename T, size_t N>
2988struct Gen
2989{
2990 using type =
2991 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
2992};
2993
2994template <typename T>
2995struct Gen<T, 0>
2996{
2998};
2999
3000} // namespace utility_internal
3001
3002// Compile-time sequences of integers
3003
3004// make_integer_sequence
3005//
3006// This template alias is equivalent to
3007// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3008// replacement for C++14's `std::make_integer_sequence`.
3009template <typename T, T N>
3011
3012// make_index_sequence
3013//
3014// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3015// and is designed to be a drop-in replacement for C++14's
3016// `std::make_index_sequence`.
3017template <size_t N>
3019
3020// index_sequence_for
3021//
3022// Converts a typename pack into an index sequence of the same length, and
3023// is designed to be a drop-in replacement for C++14's
3024// `std::index_sequence_for()`
3025template <typename... Ts>
3027
3029
3030#endif
3031
3032// dispatch utility (taken from ranges-v3)
3033template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3034template<> struct priority_tag<0> {};
3035
3036// taken from ranges-v3
3037template<typename T>
3039{
3040 static constexpr T value{};
3041};
3042
3043#ifndef JSON_HAS_CPP_17
3044
3045 template<typename T>
3046 constexpr T static_const<T>::value; // NOLINT(readability-redundant-declaration)
3047
3048#endif
3049
3050} // namespace detail
3051} // namespace nlohmann
3052
3053// #include <nlohmann/detail/meta/type_traits.hpp>
3054
3055
3056#include <limits> // numeric_limits
3057#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3058#include <utility> // declval
3059#include <tuple> // tuple
3060
3061// #include <nlohmann/detail/macro_scope.hpp>
3062
3063
3064// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3065
3066
3067#include <iterator> // random_access_iterator_tag
3068
3069// #include <nlohmann/detail/meta/void_t.hpp>
3070
3071// #include <nlohmann/detail/meta/cpp_future.hpp>
3072
3073
3074namespace nlohmann
3075{
3076namespace detail
3077{
3078template<typename It, typename = void>
3080
3081template<typename It>
3083 It,
3084 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3085 typename It::reference, typename It::iterator_category >>
3086{
3087 using difference_type = typename It::difference_type;
3088 using value_type = typename It::value_type;
3089 using pointer = typename It::pointer;
3090 using reference = typename It::reference;
3091 using iterator_category = typename It::iterator_category;
3092};
3093
3094// This is required as some compilers implement std::iterator_traits in a way that
3095// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3096template<typename T, typename = void>
3098{
3099};
3100
3101template<typename T>
3102struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3103 : iterator_types<T>
3104{
3105};
3106
3107template<typename T>
3109{
3110 using iterator_category = std::random_access_iterator_tag;
3111 using value_type = T;
3112 using difference_type = ptrdiff_t;
3113 using pointer = T*;
3114 using reference = T&;
3115};
3116} // namespace detail
3117} // namespace nlohmann
3118
3119// #include <nlohmann/detail/meta/call_std/begin.hpp>
3120
3121
3122// #include <nlohmann/detail/macro_scope.hpp>
3123
3124
3125namespace nlohmann
3126{
3128} // namespace nlohmann
3129
3130// #include <nlohmann/detail/meta/call_std/end.hpp>
3131
3132
3133// #include <nlohmann/detail/macro_scope.hpp>
3134
3135
3136namespace nlohmann
3137{
3139} // namespace nlohmann
3140
3141// #include <nlohmann/detail/meta/cpp_future.hpp>
3142
3143// #include <nlohmann/detail/meta/detected.hpp>
3144
3145// #include <nlohmann/json_fwd.hpp>
3146#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3147#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3148
3149#include <cstdint> // int64_t, uint64_t
3150#include <map> // map
3151#include <memory> // allocator
3152#include <string> // string
3153#include <vector> // vector
3154
3160namespace nlohmann
3161{
3169template<typename T = void, typename SFINAE = void>
3170struct adl_serializer;
3171
3174template<template<typename U, typename V, typename... Args> class ObjectType =
3175 std::map,
3176 template<typename U, typename... Args> class ArrayType = std::vector,
3177 class StringType = std::string, class BooleanType = bool,
3178 class NumberIntegerType = std::int64_t,
3179 class NumberUnsignedType = std::uint64_t,
3180 class NumberFloatType = double,
3181 template<typename U> class AllocatorType = std::allocator,
3182 template<typename T, typename SFINAE = void> class JSONSerializer =
3183 adl_serializer,
3184 class BinaryType = std::vector<std::uint8_t>>
3185class basic_json;
3186
3189template<typename BasicJsonType>
3190class json_pointer;
3191
3197
3200template<class Key, class T, class IgnoredLess, class Allocator>
3201struct ordered_map;
3202
3206
3207} // namespace nlohmann
3208
3209#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3210
3211
3212namespace nlohmann
3213{
3222namespace detail
3223{
3225// helpers //
3227
3228// Note to maintainers:
3229//
3230// Every trait in this file expects a non CV-qualified type.
3231// The only exceptions are in the 'aliases for detected' section
3232// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3233//
3234// In this case, T has to be properly CV-qualified to constraint the function arguments
3235// (e.g. to_json(BasicJsonType&, const T&))
3236
3237template<typename> struct is_basic_json : std::false_type {};
3238
3240struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3241
3242// used by exceptions create() member functions
3243// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
3244// false_type otherwise
3245template<typename BasicJsonContext>
3247 std::integral_constant < bool,
3248 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3249 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3250{};
3251
3253// json_ref helpers //
3255
3256template<typename>
3257class json_ref;
3258
3259template<typename>
3260struct is_json_ref : std::false_type {};
3261
3262template<typename T>
3263struct is_json_ref<json_ref<T>> : std::true_type {};
3264
3266// aliases for detected //
3268
3269template<typename T>
3270using mapped_type_t = typename T::mapped_type;
3271
3272template<typename T>
3273using key_type_t = typename T::key_type;
3274
3275template<typename T>
3276using value_type_t = typename T::value_type;
3277
3278template<typename T>
3279using difference_type_t = typename T::difference_type;
3280
3281template<typename T>
3282using pointer_t = typename T::pointer;
3283
3284template<typename T>
3285using reference_t = typename T::reference;
3286
3287template<typename T>
3288using iterator_category_t = typename T::iterator_category;
3289
3290template<typename T, typename... Args>
3291using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3292
3293template<typename T, typename... Args>
3294using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3295
3296template<typename T, typename U>
3297using get_template_function = decltype(std::declval<T>().template get<U>());
3298
3299// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3300template<typename BasicJsonType, typename T, typename = void>
3301struct has_from_json : std::false_type {};
3302
3303// trait checking if j.get<T> is valid
3304// use this trait instead of std::is_constructible or std::is_convertible,
3305// both rely on, or make use of implicit conversions, and thus fail when T
3306// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3307template <typename BasicJsonType, typename T>
3312
3313template<typename BasicJsonType, typename T>
3314struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3315{
3316 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3317
3318 static constexpr bool value =
3320 const BasicJsonType&, T&>::value;
3321};
3322
3323// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3324// this overload is used for non-default-constructible user-defined-types
3325template<typename BasicJsonType, typename T, typename = void>
3326struct has_non_default_from_json : std::false_type {};
3327
3328template<typename BasicJsonType, typename T>
3329struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3330{
3331 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3332
3333 static constexpr bool value =
3335 const BasicJsonType&>::value;
3336};
3337
3338// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3339// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3340template<typename BasicJsonType, typename T, typename = void>
3341struct has_to_json : std::false_type {};
3342
3343template<typename BasicJsonType, typename T>
3344struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3345{
3346 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3347
3348 static constexpr bool value =
3349 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3350 T>::value;
3351};
3352
3353template<typename T>
3354using detect_key_compare = typename T::key_compare;
3355
3356template<typename T>
3357struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3358
3359// obtains the actual object key comparator
3360template<typename BasicJsonType>
3362{
3363 using object_t = typename BasicJsonType::object_t;
3364 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3365 using type = typename std::conditional < has_key_compare<object_t>::value,
3366 typename object_t::key_compare, object_comparator_t>::type;
3367};
3368
3369template<typename BasicJsonType>
3371
3373// is_ functions //
3375
3376// https://en.cppreference.com/w/cpp/types/conjunction
3377template<class...> struct conjunction : std::true_type { };
3378template<class B> struct conjunction<B> : B { };
3379template<class B, class... Bn>
3380struct conjunction<B, Bn...>
3381: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3382
3383// https://en.cppreference.com/w/cpp/types/negation
3384template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3385
3386// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3387// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3388// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3389template <typename T>
3390struct is_default_constructible : std::is_default_constructible<T> {};
3391
3392template <typename T1, typename T2>
3393struct is_default_constructible<std::pair<T1, T2>>
3394 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3395
3396template <typename T1, typename T2>
3397struct is_default_constructible<const std::pair<T1, T2>>
3398 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3399
3400template <typename... Ts>
3401struct is_default_constructible<std::tuple<Ts...>>
3402 : conjunction<is_default_constructible<Ts>...> {};
3403
3404template <typename... Ts>
3405struct is_default_constructible<const std::tuple<Ts...>>
3406 : conjunction<is_default_constructible<Ts>...> {};
3407
3408
3409template <typename T, typename... Args>
3410struct is_constructible : std::is_constructible<T, Args...> {};
3411
3412template <typename T1, typename T2>
3413struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3414
3415template <typename T1, typename T2>
3416struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3417
3418template <typename... Ts>
3419struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3420
3421template <typename... Ts>
3422struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3423
3424
3425template<typename T, typename = void>
3426struct is_iterator_traits : std::false_type {};
3427
3428template<typename T>
3442
3443template<typename T>
3445{
3446 private:
3447 using t_ref = typename std::add_lvalue_reference<T>::type;
3448
3449 using iterator = detected_t<result_of_begin, t_ref>;
3450 using sentinel = detected_t<result_of_end, t_ref>;
3451
3452 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3453 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3454 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3455 static constexpr auto is_iterator_begin =
3457
3458 public:
3459 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3460};
3461
3462template<typename R>
3463using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3464
3465template<typename T>
3467
3468// The following implementation of is_complete_type is taken from
3469// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3470// and is written by Xiang Fan who agreed to using it in this library.
3471
3472template<typename T, typename = void>
3473struct is_complete_type : std::false_type {};
3474
3475template<typename T>
3476struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3477
3478template<typename BasicJsonType, typename CompatibleObjectType,
3479 typename = void>
3480struct is_compatible_object_type_impl : std::false_type {};
3481
3482template<typename BasicJsonType, typename CompatibleObjectType>
3484 BasicJsonType, CompatibleObjectType,
3485 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3486 is_detected<key_type_t, CompatibleObjectType>::value >>
3487{
3488 using object_t = typename BasicJsonType::object_t;
3489
3490 // macOS's is_constructible does not play well with nonesuch...
3491 static constexpr bool value =
3492 is_constructible<typename object_t::key_type,
3493 typename CompatibleObjectType::key_type>::value &&
3494 is_constructible<typename object_t::mapped_type,
3495 typename CompatibleObjectType::mapped_type>::value;
3496};
3497
3498template<typename BasicJsonType, typename CompatibleObjectType>
3500 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3501
3502template<typename BasicJsonType, typename ConstructibleObjectType,
3503 typename = void>
3504struct is_constructible_object_type_impl : std::false_type {};
3505
3506template<typename BasicJsonType, typename ConstructibleObjectType>
3508 BasicJsonType, ConstructibleObjectType,
3509 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3510 is_detected<key_type_t, ConstructibleObjectType>::value >>
3511{
3512 using object_t = typename BasicJsonType::object_t;
3513
3514 static constexpr bool value =
3516 (std::is_move_assignable<ConstructibleObjectType>::value ||
3517 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3518 (is_constructible<typename ConstructibleObjectType::key_type,
3519 typename object_t::key_type>::value &&
3520 std::is_same <
3521 typename object_t::mapped_type,
3522 typename ConstructibleObjectType::mapped_type >::value)) ||
3523 (has_from_json<BasicJsonType,
3524 typename ConstructibleObjectType::mapped_type>::value ||
3526 BasicJsonType,
3527 typename ConstructibleObjectType::mapped_type >::value);
3528};
3529
3530template<typename BasicJsonType, typename ConstructibleObjectType>
3532 : is_constructible_object_type_impl<BasicJsonType,
3533 ConstructibleObjectType> {};
3534
3535template<typename BasicJsonType, typename CompatibleStringType>
3541
3542template<typename BasicJsonType, typename ConstructibleStringType>
3544{
3545 // launder type through decltype() to fix compilation failure on ICPC
3546#ifdef __INTEL_COMPILER
3547 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3548#else
3549 using laundered_type = ConstructibleStringType;
3550#endif
3551
3552 static constexpr auto value =
3554 typename BasicJsonType::string_t>::value;
3555};
3556
3557template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3558struct is_compatible_array_type_impl : std::false_type {};
3559
3560template<typename BasicJsonType, typename CompatibleArrayType>
3562 BasicJsonType, CompatibleArrayType,
3563 enable_if_t <
3564 is_detected<iterator_t, CompatibleArrayType>::value&&
3565 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3566// special case for types like std::filesystem::path whose iterator's value_type are themselves
3567// c.f. https://github.com/nlohmann/json/pull/3073
3568 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3569{
3570 static constexpr bool value =
3571 is_constructible<BasicJsonType,
3573};
3574
3575template<typename BasicJsonType, typename CompatibleArrayType>
3577 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3578
3579template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3580struct is_constructible_array_type_impl : std::false_type {};
3581
3582template<typename BasicJsonType, typename ConstructibleArrayType>
3584 BasicJsonType, ConstructibleArrayType,
3585 enable_if_t<std::is_same<ConstructibleArrayType,
3586 typename BasicJsonType::value_type>::value >>
3587 : std::true_type {};
3588
3589template<typename BasicJsonType, typename ConstructibleArrayType>
3591 BasicJsonType, ConstructibleArrayType,
3592 enable_if_t < !std::is_same<ConstructibleArrayType,
3593 typename BasicJsonType::value_type>::value&&
3594 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3595 is_default_constructible<ConstructibleArrayType>::value&&
3596(std::is_move_assignable<ConstructibleArrayType>::value ||
3597 std::is_copy_assignable<ConstructibleArrayType>::value)&&
3598is_detected<iterator_t, ConstructibleArrayType>::value&&
3599is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3600is_detected<range_value_t, ConstructibleArrayType>::value&&
3601// special case for types like std::filesystem::path whose iterator's value_type are themselves
3602// c.f. https://github.com/nlohmann/json/pull/3073
3603!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3605 detected_t<range_value_t, ConstructibleArrayType >>::value >>
3606{
3608
3609 static constexpr bool value =
3610 std::is_same<value_type,
3611 typename BasicJsonType::array_t::value_type>::value ||
3612 has_from_json<BasicJsonType,
3613 value_type>::value ||
3615 BasicJsonType,
3616 value_type >::value;
3617};
3618
3619template<typename BasicJsonType, typename ConstructibleArrayType>
3621 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3622
3623template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3624 typename = void>
3625struct is_compatible_integer_type_impl : std::false_type {};
3626
3627template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3629 RealIntegerType, CompatibleNumberIntegerType,
3630 enable_if_t < std::is_integral<RealIntegerType>::value&&
3631 std::is_integral<CompatibleNumberIntegerType>::value&&
3632 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
3633{
3634 // is there an assert somewhere on overflows?
3635 using RealLimits = std::numeric_limits<RealIntegerType>;
3636 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3637
3638 static constexpr auto value =
3639 is_constructible<RealIntegerType,
3640 CompatibleNumberIntegerType>::value &&
3641 CompatibleLimits::is_integer &&
3642 RealLimits::is_signed == CompatibleLimits::is_signed;
3643};
3644
3645template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3647 : is_compatible_integer_type_impl<RealIntegerType,
3648 CompatibleNumberIntegerType> {};
3649
3650template<typename BasicJsonType, typename CompatibleType, typename = void>
3651struct is_compatible_type_impl: std::false_type {};
3652
3653template<typename BasicJsonType, typename CompatibleType>
3655 BasicJsonType, CompatibleType,
3656 enable_if_t<is_complete_type<CompatibleType>::value >>
3657{
3658 static constexpr bool value =
3660};
3661
3662template<typename BasicJsonType, typename CompatibleType>
3664 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3665
3666template<typename T1, typename T2>
3667struct is_constructible_tuple : std::false_type {};
3668
3669template<typename T1, typename... Args>
3670struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3671
3672template<typename BasicJsonType, typename T>
3673struct is_json_iterator_of : std::false_type {};
3674
3675template<typename BasicJsonType>
3676struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
3677
3678template<typename BasicJsonType>
3679struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
3680{};
3681
3682// checks if a given type T is a template specialization of Primary
3683template<template <typename...> class Primary, typename T>
3684struct is_specialization_of : std::false_type {};
3685
3686template<template <typename...> class Primary, typename... Args>
3687struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
3688
3689template<typename T>
3691
3692// checks if A and B are comparable using Compare functor
3693template<typename Compare, typename A, typename B, typename = void>
3694struct is_comparable : std::false_type {};
3695
3696template<typename Compare, typename A, typename B>
3697struct is_comparable<Compare, A, B, void_t<
3698decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
3699decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
3700>> : std::true_type {};
3701
3702template<typename T>
3703using detect_is_transparent = typename T::is_transparent;
3704
3705// type trait to check if KeyType can be used as object key (without a BasicJsonType)
3706// see is_usable_as_basic_json_key_type below
3707template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
3708 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
3709using is_usable_as_key_type = typename std::conditional <
3711 && !(ExcludeObjectKeyType && std::is_same<KeyType,
3712 ObjectKeyType>::value)
3713 && (!RequireTransparentComparator
3714 || is_detected <detect_is_transparent, Comparator>::value)
3716 std::true_type,
3717 std::false_type >::type;
3718
3719// type trait to check if KeyType can be used as object key
3720// true if:
3721// - KeyType is comparable with BasicJsonType::object_t::key_type
3722// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
3723// - the comparator is transparent or RequireTransparentComparator is false
3724// - KeyType is not a JSON iterator or json_pointer
3725template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
3726 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
3727using is_usable_as_basic_json_key_type = typename std::conditional <
3728 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
3729 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
3730 RequireTransparentComparator, ExcludeObjectKeyType>::value
3732 std::true_type,
3733 std::false_type >::type;
3734
3735template<typename ObjectType, typename KeyType>
3736using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
3737
3738// type trait to check if object_t has an erase() member functions accepting KeyType
3739template<typename BasicJsonType, typename KeyType>
3740using has_erase_with_key_type = typename std::conditional <
3741 is_detected <
3743 typename BasicJsonType::object_t, KeyType >::value,
3744 std::true_type,
3745 std::false_type >::type;
3746
3747// a naive helper to check if a type is an ordered_map (exploits the fact that
3748// ordered_map inherits capacity() from std::vector)
3749template <typename T>
3751{
3752 using one = char;
3753
3754 struct two
3755 {
3756 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3757 };
3758
3759 template <typename C> static one test( decltype(&C::capacity) ) ;
3760 template <typename C> static two test(...);
3761
3762 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
3763};
3764
3765// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
3766template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
3768{
3769 return static_cast<T>(value);
3770}
3771
3772template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
3773T conditional_static_cast(U value)
3774{
3775 return value;
3776}
3777
3778template<typename... Types>
3780
3781template<typename... Types>
3783
3784template<typename... Types>
3786
3787// there's a disjunction trait in another PR; replace when merged
3788template<typename... Types>
3789using same_sign = std::integral_constant < bool,
3790 all_signed<Types...>::value || all_unsigned<Types...>::value >;
3791
3792template<typename OfType, typename T>
3793using never_out_of_range = std::integral_constant < bool,
3794 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
3795 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
3796
3797template<typename OfType, typename T,
3798 bool OfTypeSigned = std::is_signed<OfType>::value,
3799 bool TSigned = std::is_signed<T>::value>
3801
3802template<typename OfType, typename T>
3803struct value_in_range_of_impl2<OfType, T, false, false>
3804{
3805 static constexpr bool test(T val)
3806 {
3807 using CommonType = typename std::common_type<OfType, T>::type;
3808 return static_cast<CommonType>(val) <= static_cast<CommonType>(std::numeric_limits<OfType>::max());
3809 }
3810};
3811
3812template<typename OfType, typename T>
3813struct value_in_range_of_impl2<OfType, T, true, false>
3814{
3815 static constexpr bool test(T val)
3816 {
3817 using CommonType = typename std::common_type<OfType, T>::type;
3818 return static_cast<CommonType>(val) <= static_cast<CommonType>(std::numeric_limits<OfType>::max());
3819 }
3820};
3821
3822template<typename OfType, typename T>
3823struct value_in_range_of_impl2<OfType, T, false, true>
3824{
3825 static constexpr bool test(T val)
3826 {
3827 using CommonType = typename std::common_type<OfType, T>::type;
3828 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>(std::numeric_limits<OfType>::max());
3829 }
3830};
3831
3832
3833template<typename OfType, typename T>
3834struct value_in_range_of_impl2<OfType, T, true, true>
3835{
3836 static constexpr bool test(T val)
3837 {
3838 using CommonType = typename std::common_type<OfType, T>::type;
3839 return static_cast<CommonType>(val) >= static_cast<CommonType>(std::numeric_limits<OfType>::min())
3840 && static_cast<CommonType>(val) <= static_cast<CommonType>(std::numeric_limits<OfType>::max());
3841 }
3842};
3843
3844template<typename OfType, typename T,
3845 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
3848
3849template<typename OfType, typename T>
3850struct value_in_range_of_impl1<OfType, T, false>
3851{
3852 static constexpr bool test(T val)
3853 {
3855 }
3856};
3857
3858template<typename OfType, typename T>
3859struct value_in_range_of_impl1<OfType, T, true>
3860{
3861 static constexpr bool test(T /*val*/)
3862 {
3863 return true;
3864 }
3865};
3866
3867template<typename OfType, typename T>
3868inline constexpr bool value_in_range_of(T val)
3869{
3871}
3872
3873} // namespace detail
3874} // namespace nlohmann
3875
3876// #include <nlohmann/detail/string_concat.hpp>
3877
3878
3879#include <cstring> // strlen
3880#include <string> // string
3881#include <utility> // forward
3882
3883// #include <nlohmann/detail/meta/cpp_future.hpp>
3884
3885// #include <nlohmann/detail/meta/detected.hpp>
3886
3887
3888namespace nlohmann
3889{
3890namespace detail
3891{
3892
3893inline std::size_t concat_length()
3894{
3895 return 0;
3896}
3897
3898template<typename... Args>
3899inline std::size_t concat_length(const char* cstr, Args&& ... rest);
3900
3901template<typename StringType, typename... Args>
3902inline std::size_t concat_length(const StringType& str, Args&& ... rest);
3903
3904template<typename... Args>
3905inline std::size_t concat_length(const char /*c*/, Args&& ... rest)
3906{
3907 return 1 + concat_length(std::forward<Args>(rest)...);
3908}
3909
3910template<typename... Args>
3911inline std::size_t concat_length(const char* cstr, Args&& ... rest)
3912{
3913 // cppcheck-suppress ignoredReturnValue
3914 return ::strlen(cstr) + concat_length(std::forward<Args>(rest)...);
3915}
3916
3917template<typename StringType, typename... Args>
3918inline std::size_t concat_length(const StringType& str, Args&& ... rest)
3919{
3920 return str.size() + concat_length(std::forward<Args>(rest)...);
3921}
3922
3923template<typename OutStringType>
3924inline void concat_into(OutStringType& /*out*/)
3925{}
3926
3927template<typename StringType, typename Arg>
3928using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
3929
3930template<typename StringType, typename Arg>
3932
3933template<typename StringType, typename Arg>
3934using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
3935
3936template<typename StringType, typename Arg>
3938
3939template<typename StringType, typename Arg>
3940using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
3941
3942template<typename StringType, typename Arg>
3944
3945template<typename StringType, typename Arg>
3946using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
3947
3948template<typename StringType, typename Arg>
3950
3951template < typename OutStringType, typename Arg, typename... Args,
3952 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
3954inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
3955
3956template < typename OutStringType, typename Arg, typename... Args,
3957 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
3960inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
3961
3962template < typename OutStringType, typename Arg, typename... Args,
3963 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
3967inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
3968
3969template<typename OutStringType, typename Arg, typename... Args,
3971inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
3972{
3973 out.append(std::forward<Arg>(arg));
3974 concat_into(out, std::forward<Args>(rest)...);
3975}
3976
3977template < typename OutStringType, typename Arg, typename... Args,
3978 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
3979 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
3980inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
3981{
3982 out += std::forward<Arg>(arg);
3983 concat_into(out, std::forward<Args>(rest)...);
3984}
3985
3986template < typename OutStringType, typename Arg, typename... Args,
3987 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
3988 && !detect_string_can_append_op<OutStringType, Arg>::value
3989 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
3990inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
3991{
3992 out.append(arg.begin(), arg.end());
3993 concat_into(out, std::forward<Args>(rest)...);
3994}
3995
3996template < typename OutStringType, typename Arg, typename... Args,
3997 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
3998 && !detect_string_can_append_op<OutStringType, Arg>::value
3999 && !detect_string_can_append_iter<OutStringType, Arg>::value
4000 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4001inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4002{
4003 out.append(arg.data(), arg.size());
4004 concat_into(out, std::forward<Args>(rest)...);
4005}
4006
4007template<typename OutStringType = std::string, typename... Args>
4008inline OutStringType concat(Args && ... args)
4009{
4010 OutStringType str;
4011 str.reserve(concat_length(std::forward<Args>(args)...));
4012 concat_into(str, std::forward<Args>(args)...);
4013 return str;
4014}
4015
4016} // namespace detail
4017} // namespace nlohmann
4018
4019
4020
4021namespace nlohmann
4022{
4023namespace detail
4024{
4026// exceptions //
4028
4031class exception : public std::exception
4032{
4033 public:
4035 const char* what() const noexcept override
4036 {
4037 return m.what();
4038 }
4039
4041 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4042
4043 protected:
4045 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4046
4047 static std::string name(const std::string& ename, int id_)
4048 {
4049 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4050 }
4051
4052 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4053 {
4054 return "";
4055 }
4056
4057 template<typename BasicJsonType>
4058 static std::string diagnostics(const BasicJsonType* leaf_element)
4059 {
4060#if JSON_DIAGNOSTICS
4061 std::vector<std::string> tokens;
4062 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4063 {
4064 switch (current->m_parent->type())
4065 {
4066 case value_t::array:
4067 {
4068 for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
4069 {
4070 if (&current->m_parent->m_value.array->operator[](i) == current)
4071 {
4072 tokens.emplace_back(std::to_string(i));
4073 break;
4074 }
4075 }
4076 break;
4077 }
4078
4079 case value_t::object:
4080 {
4081 for (const auto& element : *current->m_parent->m_value.object)
4082 {
4083 if (&element.second == current)
4084 {
4085 tokens.emplace_back(element.first.c_str());
4086 break;
4087 }
4088 }
4089 break;
4090 }
4091
4092 case value_t::null: // LCOV_EXCL_LINE
4093 case value_t::string: // LCOV_EXCL_LINE
4094 case value_t::boolean: // LCOV_EXCL_LINE
4095 case value_t::number_integer: // LCOV_EXCL_LINE
4096 case value_t::number_unsigned: // LCOV_EXCL_LINE
4097 case value_t::number_float: // LCOV_EXCL_LINE
4098 case value_t::binary: // LCOV_EXCL_LINE
4099 case value_t::discarded: // LCOV_EXCL_LINE
4100 default: // LCOV_EXCL_LINE
4101 break; // LCOV_EXCL_LINE
4102 }
4103 }
4104
4105 if (tokens.empty())
4106 {
4107 return "";
4108 }
4109
4110 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4111 [](const std::string & a, const std::string & b)
4112 {
4113 return concat(a, '/', detail::escape(b));
4114 });
4115 return concat('(', str, ") ");
4116#else
4117 static_cast<void>(leaf_element);
4118 return "";
4119#endif
4120 }
4121
4122 private:
4124 std::runtime_error m;
4125};
4126
4130{
4131 public:
4141 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4142 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4143 {
4144 std::string w = concat(exception::name("parse_error", id_), "parse error",
4145 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4146 return {id_, pos.chars_read_total, w.c_str()};
4147 }
4148
4149 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4150 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4151 {
4152 std::string w = concat(exception::name("parse_error", id_), "parse error",
4153 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4154 ": ", exception::diagnostics(context), what_arg);
4155 return {id_, byte_, w.c_str()};
4156 }
4157
4167 const std::size_t byte;
4168
4169 private:
4170 parse_error(int id_, std::size_t byte_, const char* what_arg)
4171 : exception(id_, what_arg), byte(byte_) {}
4172
4173 static std::string position_string(const position_t& pos)
4174 {
4175 return concat(" at line ", std::to_string(pos.lines_read + 1),
4176 ", column ", std::to_string(pos.chars_read_current_line));
4177 }
4178};
4179
4183{
4184 public:
4185 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4186 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4187 {
4188 std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4189 return {id_, w.c_str()};
4190 }
4191
4192 private:
4194 invalid_iterator(int id_, const char* what_arg)
4195 : exception(id_, what_arg) {}
4196};
4197
4200class type_error : public exception
4201{
4202 public:
4203 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4204 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4205 {
4206 std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4207 return {id_, w.c_str()};
4208 }
4209
4210 private:
4212 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4213};
4214
4218{
4219 public:
4220 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4221 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4222 {
4223 std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4224 return {id_, w.c_str()};
4225 }
4226
4227 private:
4229 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4230};
4231
4235{
4236 public:
4237 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4238 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4239 {
4240 std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4241 return {id_, w.c_str()};
4242 }
4243
4244 private:
4246 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4247};
4248
4249} // namespace detail
4250} // namespace nlohmann
4251
4252// #include <nlohmann/detail/macro_scope.hpp>
4253
4254// #include <nlohmann/detail/meta/cpp_future.hpp>
4255
4256// #include <nlohmann/detail/meta/identity_tag.hpp>
4257
4258
4259namespace nlohmann
4260{
4261namespace detail
4262{
4263// dispatching helper struct
4264template <class T> struct identity_tag {};
4265} // namespace detail
4266} // namespace nlohmann
4267
4268// #include <nlohmann/detail/meta/type_traits.hpp>
4269
4270// #include <nlohmann/detail/string_concat.hpp>
4271
4272// #include <nlohmann/detail/value_t.hpp>
4273
4274
4275#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4276#include <experimental/filesystem>
4277namespace nlohmann::detail
4278{
4279namespace std_fs = std::experimental::filesystem;
4280} // namespace nlohmann::detail
4281#elif JSON_HAS_FILESYSTEM
4282#include <filesystem>
4283namespace nlohmann::detail
4284{
4285namespace std_fs = std::filesystem;
4286} // namespace nlohmann::detail
4287#endif
4288
4289namespace nlohmann
4290{
4291namespace detail
4292{
4293template<typename BasicJsonType>
4294inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4295{
4296 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4297 {
4298 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4299 }
4300 n = nullptr;
4301}
4302
4303// overloads for basic_json template parameters
4304template < typename BasicJsonType, typename ArithmeticType,
4305 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4306 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4307 int > = 0 >
4308void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4309{
4310 switch (static_cast<value_t>(j))
4311 {
4313 {
4314 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4315 break;
4316 }
4318 {
4319 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4320 break;
4321 }
4323 {
4324 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4325 break;
4326 }
4327
4328 case value_t::null:
4329 case value_t::object:
4330 case value_t::array:
4331 case value_t::string:
4332 case value_t::boolean:
4333 case value_t::binary:
4334 case value_t::discarded:
4335 default:
4336 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4337 }
4338}
4339
4340template<typename BasicJsonType>
4341inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4342{
4343 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4344 {
4345 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4346 }
4347 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4348}
4349
4350template<typename BasicJsonType>
4351inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4352{
4353 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4354 {
4355 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4356 }
4357 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4358}
4359
4360template <
4361 typename BasicJsonType, typename StringType,
4362 enable_if_t <
4363 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4364 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4365 && !is_json_ref<StringType>::value, int > = 0 >
4366inline void from_json(const BasicJsonType& j, StringType& s)
4367{
4368 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4369 {
4370 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4371 }
4372
4373 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4374}
4375
4376template<typename BasicJsonType>
4377inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4378{
4379 get_arithmetic_value(j, val);
4380}
4381
4382template<typename BasicJsonType>
4383inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4384{
4385 get_arithmetic_value(j, val);
4386}
4387
4388template<typename BasicJsonType>
4389inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4390{
4391 get_arithmetic_value(j, val);
4392}
4393
4394#if !JSON_DISABLE_ENUM_SERIALIZATION
4395template<typename BasicJsonType, typename EnumType,
4396 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4397inline void from_json(const BasicJsonType& j, EnumType& e)
4398{
4399 typename std::underlying_type<EnumType>::type val;
4400 get_arithmetic_value(j, val);
4401 e = static_cast<EnumType>(val);
4402}
4403#endif // JSON_DISABLE_ENUM_SERIALIZATION
4404
4405// forward_list doesn't have an insert method
4406template<typename BasicJsonType, typename T, typename Allocator,
4407 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4408inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4409{
4410 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4411 {
4412 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4413 }
4414 l.clear();
4415 std::transform(j.rbegin(), j.rend(),
4416 std::front_inserter(l), [](const BasicJsonType & i)
4417 {
4418 return i.template get<T>();
4419 });
4420}
4421
4422// valarray doesn't have an insert method
4423template<typename BasicJsonType, typename T,
4424 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4425inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
4426{
4427 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4428 {
4429 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4430 }
4431 l.resize(j.size());
4432 std::transform(j.begin(), j.end(), std::begin(l),
4433 [](const BasicJsonType & elem)
4434 {
4435 return elem.template get<T>();
4436 });
4437}
4438
4439template<typename BasicJsonType, typename T, std::size_t N>
4440auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4441-> decltype(j.template get<T>(), void())
4442{
4443 for (std::size_t i = 0; i < N; ++i)
4444 {
4445 arr[i] = j.at(i).template get<T>();
4446 }
4447}
4448
4449template<typename BasicJsonType>
4450inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
4451{
4452 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
4453}
4454
4455template<typename BasicJsonType, typename T, std::size_t N>
4456auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
4457 priority_tag<2> /*unused*/)
4458-> decltype(j.template get<T>(), void())
4459{
4460 for (std::size_t i = 0; i < N; ++i)
4461 {
4462 arr[i] = j.at(i).template get<T>();
4463 }
4464}
4465
4466template<typename BasicJsonType, typename ConstructibleArrayType,
4468 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4469 int> = 0>
4470auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4471-> decltype(
4472 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4473 j.template get<typename ConstructibleArrayType::value_type>(),
4474 void())
4475{
4476 using std::end;
4477
4478 ConstructibleArrayType ret;
4479 ret.reserve(j.size());
4480 std::transform(j.begin(), j.end(),
4481 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
4482 {
4483 // get<BasicJsonType>() returns *this, this won't call a from_json
4484 // method when value_type is BasicJsonType
4485 return i.template get<typename ConstructibleArrayType::value_type>();
4486 });
4487 arr = std::move(ret);
4488}
4489
4490template<typename BasicJsonType, typename ConstructibleArrayType,
4492 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4493 int> = 0>
4494inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4495 priority_tag<0> /*unused*/)
4496{
4497 using std::end;
4498
4499 ConstructibleArrayType ret;
4500 std::transform(
4501 j.begin(), j.end(), std::inserter(ret, end(ret)),
4502 [](const BasicJsonType & i)
4503 {
4504 // get<BasicJsonType>() returns *this, this won't call a from_json
4505 // method when value_type is BasicJsonType
4506 return i.template get<typename ConstructibleArrayType::value_type>();
4507 });
4508 arr = std::move(ret);
4509}
4510
4511template < typename BasicJsonType, typename ConstructibleArrayType,
4512 enable_if_t <
4513 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4514 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4516 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4517 !is_basic_json<ConstructibleArrayType>::value,
4518 int > = 0 >
4519auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4520-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4521j.template get<typename ConstructibleArrayType::value_type>(),
4522void())
4523{
4524 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4525 {
4526 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4527 }
4528
4529 from_json_array_impl(j, arr, priority_tag<3> {});
4530}
4531
4532template < typename BasicJsonType, typename T, std::size_t... Idx >
4533std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4534 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4535{
4536 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4537}
4538
4539template < typename BasicJsonType, typename T, std::size_t N >
4540auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4541-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4542{
4543 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4544 {
4545 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4546 }
4547
4548 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4549}
4550
4551template<typename BasicJsonType>
4552inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4553{
4554 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4555 {
4556 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
4557 }
4558
4559 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4560}
4561
4562template<typename BasicJsonType, typename ConstructibleObjectType,
4563 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
4564inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
4565{
4566 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
4567 {
4568 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
4569 }
4570
4571 ConstructibleObjectType ret;
4572 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4573 using value_type = typename ConstructibleObjectType::value_type;
4574 std::transform(
4575 inner_object->begin(), inner_object->end(),
4576 std::inserter(ret, ret.begin()),
4577 [](typename BasicJsonType::object_t::value_type const & p)
4578 {
4579 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
4580 });
4581 obj = std::move(ret);
4582}
4583
4584// overload for arithmetic types, not chosen for basic_json template arguments
4585// (BooleanType, etc..); note: Is it really necessary to provide explicit
4586// overloads for boolean_t etc. in case of a custom BooleanType which is not
4587// an arithmetic type?
4588template < typename BasicJsonType, typename ArithmeticType,
4589 enable_if_t <
4590 std::is_arithmetic<ArithmeticType>::value&&
4591 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
4592 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
4593 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
4594 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4595 int > = 0 >
4596inline void from_json(const BasicJsonType& j, ArithmeticType& val)
4597{
4598 switch (static_cast<value_t>(j))
4599 {
4601 {
4602 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4603 break;
4604 }
4606 {
4607 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4608 break;
4609 }
4611 {
4612 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4613 break;
4614 }
4615 case value_t::boolean:
4616 {
4617 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
4618 break;
4619 }
4620
4621 case value_t::null:
4622 case value_t::object:
4623 case value_t::array:
4624 case value_t::string:
4625 case value_t::binary:
4626 case value_t::discarded:
4627 default:
4628 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4629 }
4630}
4631
4632template<typename BasicJsonType, typename... Args, std::size_t... Idx>
4633std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
4634{
4635 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
4636}
4637
4638template < typename BasicJsonType, class A1, class A2 >
4639std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
4640{
4641 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
4642 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
4643}
4644
4645template<typename BasicJsonType, typename A1, typename A2>
4646inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
4647{
4648 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
4649}
4650
4651template<typename BasicJsonType, typename... Args>
4652std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
4653{
4654 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4655}
4656
4657template<typename BasicJsonType, typename... Args>
4658inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
4659{
4660 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4661}
4662
4663template<typename BasicJsonType, typename TupleRelated>
4664auto from_json(BasicJsonType&& j, TupleRelated&& t)
4665-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
4666{
4667 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4668 {
4669 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4670 }
4671
4672 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
4673}
4674
4675template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
4676 typename = enable_if_t < !std::is_constructible <
4677 typename BasicJsonType::string_t, Key >::value >>
4678inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
4679{
4680 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4681 {
4682 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4683 }
4684 m.clear();
4685 for (const auto& p : j)
4686 {
4687 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
4688 {
4689 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
4690 }
4691 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4692 }
4693}
4694
4695template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
4696 typename = enable_if_t < !std::is_constructible <
4697 typename BasicJsonType::string_t, Key >::value >>
4698inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
4699{
4700 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4701 {
4702 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4703 }
4704 m.clear();
4705 for (const auto& p : j)
4706 {
4707 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
4708 {
4709 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
4710 }
4711 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4712 }
4713}
4714
4715#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4716template<typename BasicJsonType>
4717inline void from_json(const BasicJsonType& j, std_fs::path& p)
4718{
4719 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4720 {
4721 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4722 }
4723 p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4724}
4725#endif
4726
4727struct from_json_fn
4728{
4729 template<typename BasicJsonType, typename T>
4730 auto operator()(const BasicJsonType& j, T&& val) const
4731 noexcept(noexcept(from_json(j, std::forward<T>(val))))
4732 -> decltype(from_json(j, std::forward<T>(val)))
4733 {
4734 return from_json(j, std::forward<T>(val));
4735 }
4736};
4737} // namespace detail
4738
4739#ifndef JSON_HAS_CPP_17
4743namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
4744{
4745#endif
4746JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
4748#ifndef JSON_HAS_CPP_17
4749} // namespace
4750#endif
4751} // namespace nlohmann
4752
4753// #include <nlohmann/detail/conversions/to_json.hpp>
4754
4755
4756#include <algorithm> // copy
4757#include <iterator> // begin, end
4758#include <string> // string
4759#include <tuple> // tuple, get
4760#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
4761#include <utility> // move, forward, declval, pair
4762#include <valarray> // valarray
4763#include <vector> // vector
4764
4765// #include <nlohmann/detail/macro_scope.hpp>
4766
4767// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
4768
4769
4770#include <cstddef> // size_t
4771#include <iterator> // input_iterator_tag
4772#include <string> // string, to_string
4773#include <tuple> // tuple_size, get, tuple_element
4774#include <utility> // move
4775
4776#if JSON_HAS_RANGES
4777 #include <ranges> // enable_borrowed_range
4778#endif
4779
4780// #include <nlohmann/detail/meta/type_traits.hpp>
4781
4782// #include <nlohmann/detail/value_t.hpp>
4783
4784
4785namespace nlohmann
4786{
4787namespace detail
4788{
4789template<typename string_type>
4790void int_to_string( string_type& target, std::size_t value )
4791{
4792 // For ADL
4793 using std::to_string;
4794 target = to_string(value);
4795}
4796template<typename IteratorType> class iteration_proxy_value
4797{
4798 public:
4799 using difference_type = std::ptrdiff_t;
4800 using value_type = iteration_proxy_value;
4801 using pointer = value_type *;
4802 using reference = value_type &;
4803 using iterator_category = std::input_iterator_tag;
4804 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
4805
4806 private:
4808 IteratorType anchor{};
4810 std::size_t array_index = 0;
4812 mutable std::size_t array_index_last = 0;
4814 mutable string_type array_index_str = "0";
4816 string_type empty_str{};
4817
4818 public:
4819 explicit iteration_proxy_value() = default;
4820 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
4821 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
4822 && std::is_nothrow_default_constructible<string_type>::value)
4823 : anchor(std::move(it))
4824 , array_index(array_index_)
4825 {}
4826
4827 iteration_proxy_value(iteration_proxy_value const&) = default;
4828 iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
4829 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
4830 iteration_proxy_value(iteration_proxy_value&&)
4831 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
4832 && std::is_nothrow_move_constructible<string_type>::value) = default;
4833 iteration_proxy_value& operator=(iteration_proxy_value&&)
4834 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
4835 && std::is_nothrow_move_assignable<string_type>::value) = default;
4836 ~iteration_proxy_value() = default;
4837
4839 const iteration_proxy_value& operator*() const
4840 {
4841 return *this;
4842 }
4843
4845 iteration_proxy_value& operator++()
4846 {
4847 ++anchor;
4848 ++array_index;
4849
4850 return *this;
4851 }
4852
4853 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
4854 {
4855 auto tmp = iteration_proxy_value(anchor, array_index);
4856 ++anchor;
4857 ++array_index;
4858 return tmp;
4859 }
4860
4862 bool operator==(const iteration_proxy_value& o) const
4863 {
4864 return anchor == o.anchor;
4865 }
4866
4868 bool operator!=(const iteration_proxy_value& o) const
4869 {
4870 return anchor != o.anchor;
4871 }
4872
4874 const string_type& key() const
4875 {
4876 JSON_ASSERT(anchor.m_object != nullptr);
4877
4878 switch (anchor.m_object->type())
4879 {
4880 // use integer array index as key
4881 case value_t::array:
4882 {
4883 if (array_index != array_index_last)
4884 {
4885 int_to_string( array_index_str, array_index );
4886 array_index_last = array_index;
4887 }
4888 return array_index_str;
4889 }
4890
4891 // use key from the object
4892 case value_t::object:
4893 return anchor.key();
4894
4895 // use an empty key for all primitive types
4896 case value_t::null:
4897 case value_t::string:
4898 case value_t::boolean:
4902 case value_t::binary:
4903 case value_t::discarded:
4904 default:
4905 return empty_str;
4906 }
4907 }
4908
4910 typename IteratorType::reference value() const
4911 {
4912 return anchor.value();
4913 }
4914};
4915
4917template<typename IteratorType> class iteration_proxy
4918{
4919 private:
4921 typename IteratorType::pointer container = nullptr;
4922
4923 public:
4924 explicit iteration_proxy() = default;
4925
4927 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
4928 : container(&cont) {}
4929
4930 iteration_proxy(iteration_proxy const&) = default;
4931 iteration_proxy& operator=(iteration_proxy const&) = default;
4932 iteration_proxy(iteration_proxy&&) noexcept = default;
4933 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
4934 ~iteration_proxy() = default;
4935
4937 iteration_proxy_value<IteratorType> begin() const noexcept
4938 {
4939 return iteration_proxy_value<IteratorType>(container->begin());
4940 }
4941
4943 iteration_proxy_value<IteratorType> end() const noexcept
4944 {
4945 return iteration_proxy_value<IteratorType>(container->end());
4946 }
4947};
4948
4949// Structured Bindings Support
4950// For further reference see https://blog.tartanllama.xyz/structured-bindings/
4951// And see https://github.com/nlohmann/json/pull/1391
4952template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
4953auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
4954{
4955 return i.key();
4956}
4957// Structured Bindings Support
4958// For further reference see https://blog.tartanllama.xyz/structured-bindings/
4959// And see https://github.com/nlohmann/json/pull/1391
4960template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
4961auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
4962{
4963 return i.value();
4964}
4965} // namespace detail
4966} // namespace nlohmann
4967
4968// The Addition to the STD Namespace is required to add
4969// Structured Bindings Support to the iteration_proxy_value class
4970// For further reference see https://blog.tartanllama.xyz/structured-bindings/
4971// And see https://github.com/nlohmann/json/pull/1391
4972namespace std
4973{
4974#if defined(__clang__)
4975 // Fix: https://github.com/nlohmann/json/issues/1401
4976 #pragma clang diagnostic push
4977 #pragma clang diagnostic ignored "-Wmismatched-tags"
4978#endif
4979template<typename IteratorType>
4980class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
4981 : public std::integral_constant<std::size_t, 2> {};
4982
4983template<std::size_t N, typename IteratorType>
4984class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
4985{
4986 public:
4987 using type = decltype(
4988 get<N>(std::declval <
4989 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
4990};
4991#if defined(__clang__)
4992 #pragma clang diagnostic pop
4993#endif
4994} // namespace std
4995
4996#if JSON_HAS_RANGES
4997 template <typename IteratorType>
4998 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
4999#endif
5000
5001// #include <nlohmann/detail/meta/cpp_future.hpp>
5002
5003// #include <nlohmann/detail/meta/type_traits.hpp>
5004
5005// #include <nlohmann/detail/value_t.hpp>
5006
5007
5008#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
5009#include <experimental/filesystem>
5010namespace nlohmann::detail
5011{
5012namespace std_fs = std::experimental::filesystem;
5013} // namespace nlohmann::detail
5014#elif JSON_HAS_FILESYSTEM
5015#include <filesystem>
5016namespace nlohmann::detail
5017{
5018namespace std_fs = std::filesystem;
5019} // namespace nlohmann::detail
5020#endif
5021
5022namespace nlohmann
5023{
5024namespace detail
5025{
5027// constructors //
5029
5030/*
5031 * Note all external_constructor<>::construct functions need to call
5032 * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an
5033 * allocated value (e.g., a string). See bug issue
5034 * https://github.com/nlohmann/json/issues/2865 for more information.
5035 */
5036
5037template<value_t> struct external_constructor;
5038
5039template<>
5041{
5042 template<typename BasicJsonType>
5043 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5044 {
5045 j.m_value.destroy(j.m_type);
5046 j.m_type = value_t::boolean;
5047 j.m_value = b;
5048 j.assert_invariant();
5049 }
5050};
5051
5052template<>
5054{
5055 template<typename BasicJsonType>
5056 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5057 {
5058 j.m_value.destroy(j.m_type);
5059 j.m_type = value_t::string;
5060 j.m_value = s;
5061 j.assert_invariant();
5062 }
5063
5064 template<typename BasicJsonType>
5065 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5066 {
5067 j.m_value.destroy(j.m_type);
5068 j.m_type = value_t::string;
5069 j.m_value = std::move(s);
5070 j.assert_invariant();
5071 }
5072
5073 template < typename BasicJsonType, typename CompatibleStringType,
5074 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5075 int > = 0 >
5076 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5077 {
5078 j.m_value.destroy(j.m_type);
5079 j.m_type = value_t::string;
5080 j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5081 j.assert_invariant();
5082 }
5083};
5084
5085template<>
5087{
5088 template<typename BasicJsonType>
5089 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5090 {
5091 j.m_value.destroy(j.m_type);
5092 j.m_type = value_t::binary;
5093 j.m_value = typename BasicJsonType::binary_t(b);
5094 j.assert_invariant();
5095 }
5096
5097 template<typename BasicJsonType>
5098 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5099 {
5100 j.m_value.destroy(j.m_type);
5101 j.m_type = value_t::binary;
5102 j.m_value = typename BasicJsonType::binary_t(std::move(b));
5103 j.assert_invariant();
5104 }
5105};
5106
5107template<>
5109{
5110 template<typename BasicJsonType>
5111 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5112 {
5113 j.m_value.destroy(j.m_type);
5114 j.m_type = value_t::number_float;
5115 j.m_value = val;
5116 j.assert_invariant();
5117 }
5118};
5119
5120template<>
5122{
5123 template<typename BasicJsonType>
5124 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5125 {
5126 j.m_value.destroy(j.m_type);
5127 j.m_type = value_t::number_unsigned;
5128 j.m_value = val;
5129 j.assert_invariant();
5130 }
5131};
5132
5133template<>
5135{
5136 template<typename BasicJsonType>
5137 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5138 {
5139 j.m_value.destroy(j.m_type);
5140 j.m_type = value_t::number_integer;
5141 j.m_value = val;
5142 j.assert_invariant();
5143 }
5144};
5145
5146template<>
5148{
5149 template<typename BasicJsonType>
5150 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5151 {
5152 j.m_value.destroy(j.m_type);
5153 j.m_type = value_t::array;
5154 j.m_value = arr;
5155 j.set_parents();
5156 j.assert_invariant();
5157 }
5158
5159 template<typename BasicJsonType>
5160 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5161 {
5162 j.m_value.destroy(j.m_type);
5163 j.m_type = value_t::array;
5164 j.m_value = std::move(arr);
5165 j.set_parents();
5166 j.assert_invariant();
5167 }
5168
5169 template < typename BasicJsonType, typename CompatibleArrayType,
5170 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5171 int > = 0 >
5172 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5173 {
5174 using std::begin;
5175 using std::end;
5176
5177 j.m_value.destroy(j.m_type);
5178 j.m_type = value_t::array;
5179 j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5180 j.set_parents();
5181 j.assert_invariant();
5182 }
5183
5184 template<typename BasicJsonType>
5185 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5186 {
5187 j.m_value.destroy(j.m_type);
5188 j.m_type = value_t::array;
5189 j.m_value = value_t::array;
5190 j.m_value.array->reserve(arr.size());
5191 for (const bool x : arr)
5192 {
5193 j.m_value.array->push_back(x);
5194 j.set_parent(j.m_value.array->back());
5195 }
5196 j.assert_invariant();
5197 }
5198
5199 template<typename BasicJsonType, typename T,
5201 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5202 {
5203 j.m_value.destroy(j.m_type);
5204 j.m_type = value_t::array;
5205 j.m_value = value_t::array;
5206 j.m_value.array->resize(arr.size());
5207 if (arr.size() > 0)
5208 {
5209 std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
5210 }
5211 j.set_parents();
5212 j.assert_invariant();
5213 }
5214};
5215
5216template<>
5218{
5219 template<typename BasicJsonType>
5220 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5221 {
5222 j.m_value.destroy(j.m_type);
5223 j.m_type = value_t::object;
5224 j.m_value = obj;
5225 j.set_parents();
5226 j.assert_invariant();
5227 }
5228
5229 template<typename BasicJsonType>
5230 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5231 {
5232 j.m_value.destroy(j.m_type);
5233 j.m_type = value_t::object;
5234 j.m_value = std::move(obj);
5235 j.set_parents();
5236 j.assert_invariant();
5237 }
5238
5239 template < typename BasicJsonType, typename CompatibleObjectType,
5240 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5241 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5242 {
5243 using std::begin;
5244 using std::end;
5245
5246 j.m_value.destroy(j.m_type);
5247 j.m_type = value_t::object;
5248 j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5249 j.set_parents();
5250 j.assert_invariant();
5251 }
5252};
5253
5255// to_json //
5257
5258template<typename BasicJsonType, typename T,
5259 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5260inline void to_json(BasicJsonType& j, T b) noexcept
5261{
5263}
5264
5265template<typename BasicJsonType,
5266 enable_if_t<std::is_convertible<const std::vector<bool>::reference&, typename BasicJsonType::boolean_t>::value, int> = 0>
5267inline void to_json(BasicJsonType& j, const std::vector<bool>::reference& b) noexcept
5268{
5269 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5270}
5271
5272template<typename BasicJsonType, typename CompatibleString,
5273 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5274inline void to_json(BasicJsonType& j, const CompatibleString& s)
5275{
5277}
5278
5279template<typename BasicJsonType>
5280inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5281{
5283}
5284
5285template<typename BasicJsonType, typename FloatType,
5286 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5287inline void to_json(BasicJsonType& j, FloatType val) noexcept
5288{
5289 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
5290}
5291
5292template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
5293 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
5294inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
5295{
5296 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5297}
5298
5299template<typename BasicJsonType, typename CompatibleNumberIntegerType,
5300 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
5301inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
5302{
5303 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
5304}
5305
5306#if !JSON_DISABLE_ENUM_SERIALIZATION
5307template<typename BasicJsonType, typename EnumType,
5308 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5309inline void to_json(BasicJsonType& j, EnumType e) noexcept
5310{
5311 using underlying_type = typename std::underlying_type<EnumType>::type;
5312 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
5313}
5314#endif // JSON_DISABLE_ENUM_SERIALIZATION
5315
5316template<typename BasicJsonType>
5317inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
5318{
5320}
5321
5322template < typename BasicJsonType, typename CompatibleArrayType,
5323 enable_if_t < is_compatible_array_type<BasicJsonType,
5324 CompatibleArrayType>::value&&
5325 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
5327 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
5328 !is_basic_json<CompatibleArrayType>::value,
5329 int > = 0 >
5330inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
5331{
5333}
5334
5335template<typename BasicJsonType>
5336inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
5337{
5339}
5340
5341template<typename BasicJsonType, typename T,
5342 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5343inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
5344{
5346}
5347
5348template<typename BasicJsonType>
5349inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5350{
5352}
5353
5354template < typename BasicJsonType, typename CompatibleObjectType,
5355 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
5356inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
5357{
5359}
5360
5361template<typename BasicJsonType>
5362inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5363{
5365}
5366
5367template <
5368 typename BasicJsonType, typename T, std::size_t N,
5369 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
5370 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5371 int > = 0 >
5372inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5373{
5375}
5376
5377template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
5378inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
5379{
5380 j = { p.first, p.second };
5381}
5382
5383// for https://github.com/nlohmann/json/pull/1134
5384template<typename BasicJsonType, typename T,
5385 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
5386inline void to_json(BasicJsonType& j, const T& b)
5387{
5388 j = { {b.key(), b.value()} };
5389}
5390
5391template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
5392inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
5393{
5394 j = { std::get<Idx>(t)... };
5395}
5396
5397template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
5398inline void to_json(BasicJsonType& j, const T& t)
5399{
5400 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
5401}
5402
5403#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5404template<typename BasicJsonType>
5405inline void to_json(BasicJsonType& j, const std_fs::path& p)
5406{
5407 j = p.string();
5408}
5409#endif
5410
5412{
5413 template<typename BasicJsonType, typename T>
5414 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
5415 -> decltype(to_json(j, std::forward<T>(val)), void())
5416 {
5417 return to_json(j, std::forward<T>(val));
5418 }
5419};
5420} // namespace detail
5421
5422#ifndef JSON_HAS_CPP_17
5426namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5427{
5428#endif
5429JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
5431#ifndef JSON_HAS_CPP_17
5432} // namespace
5433#endif
5434} // namespace nlohmann
5435
5436// #include <nlohmann/detail/meta/identity_tag.hpp>
5437
5438// #include <nlohmann/detail/meta/type_traits.hpp>
5439
5440
5441namespace nlohmann
5442{
5443
5445template<typename ValueType, typename>
5447{
5450 template<typename BasicJsonType, typename TargetType = ValueType>
5451 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
5452 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
5453 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
5454 {
5455 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
5456 }
5457
5460 template<typename BasicJsonType, typename TargetType = ValueType>
5461 static auto from_json(BasicJsonType && j) noexcept(
5462 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
5463 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
5464 {
5465 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
5466 }
5467
5470 template<typename BasicJsonType, typename TargetType = ValueType>
5471 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
5472 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
5473 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
5474 {
5475 ::nlohmann::to_json(j, std::forward<TargetType>(val));
5476 }
5477};
5478} // namespace nlohmann
5479
5480// #include <nlohmann/byte_container_with_subtype.hpp>
5481
5482
5483#include <cstdint> // uint8_t, uint64_t
5484#include <tuple> // tie
5485#include <utility> // move
5486
5487namespace nlohmann
5488{
5489
5492template<typename BinaryType>
5493class byte_container_with_subtype : public BinaryType
5494{
5495 public:
5496 using container_type = BinaryType;
5497 using subtype_type = std::uint64_t;
5498
5501 : container_type()
5502 {}
5503
5506 : container_type(b)
5507 {}
5508
5510 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
5511 : container_type(std::move(b))
5512 {}
5513
5516 : container_type(b)
5517 , m_subtype(subtype_)
5518 , m_has_subtype(true)
5519 {}
5520
5522 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
5523 : container_type(std::move(b))
5524 , m_subtype(subtype_)
5525 , m_has_subtype(true)
5526 {}
5527
5529 {
5530 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
5531 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5532 }
5533
5535 {
5536 return !(rhs == *this);
5537 }
5538
5541 void set_subtype(subtype_type subtype_) noexcept
5542 {
5543 m_subtype = subtype_;
5544 m_has_subtype = true;
5545 }
5546
5549 constexpr subtype_type subtype() const noexcept
5550 {
5551 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
5552 }
5553
5556 constexpr bool has_subtype() const noexcept
5557 {
5558 return m_has_subtype;
5559 }
5560
5563 void clear_subtype() noexcept
5564 {
5565 m_subtype = 0;
5566 m_has_subtype = false;
5567 }
5568
5569 private:
5570 subtype_type m_subtype = 0;
5571 bool m_has_subtype = false;
5572};
5573
5574} // namespace nlohmann
5575
5576// #include <nlohmann/detail/conversions/from_json.hpp>
5577
5578// #include <nlohmann/detail/conversions/to_json.hpp>
5579
5580// #include <nlohmann/detail/exceptions.hpp>
5581
5582// #include <nlohmann/detail/hash.hpp>
5583
5584
5585#include <cstdint> // uint8_t
5586#include <cstddef> // size_t
5587#include <functional> // hash
5588
5589// #include <nlohmann/detail/macro_scope.hpp>
5590
5591// #include <nlohmann/detail/value_t.hpp>
5592
5593
5594namespace nlohmann
5595{
5596namespace detail
5597{
5598
5599// boost::hash_combine
5600inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
5601{
5602 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
5603 return seed;
5604}
5605
5617template<typename BasicJsonType>
5618std::size_t hash(const BasicJsonType& j)
5619{
5620 using string_t = typename BasicJsonType::string_t;
5621 using number_integer_t = typename BasicJsonType::number_integer_t;
5622 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5623 using number_float_t = typename BasicJsonType::number_float_t;
5624
5625 const auto type = static_cast<std::size_t>(j.type());
5626 switch (j.type())
5627 {
5628 case BasicJsonType::value_t::null:
5629 case BasicJsonType::value_t::discarded:
5630 {
5631 return combine(type, 0);
5632 }
5633
5634 case BasicJsonType::value_t::object:
5635 {
5636 auto seed = combine(type, j.size());
5637 for (const auto& element : j.items())
5638 {
5639 const auto h = std::hash<string_t> {}(element.key());
5640 seed = combine(seed, h);
5641 seed = combine(seed, hash(element.value()));
5642 }
5643 return seed;
5644 }
5645
5646 case BasicJsonType::value_t::array:
5647 {
5648 auto seed = combine(type, j.size());
5649 for (const auto& element : j)
5650 {
5651 seed = combine(seed, hash(element));
5652 }
5653 return seed;
5654 }
5655
5656 case BasicJsonType::value_t::string:
5657 {
5658 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
5659 return combine(type, h);
5660 }
5661
5662 case BasicJsonType::value_t::boolean:
5663 {
5664 const auto h = std::hash<bool> {}(j.template get<bool>());
5665 return combine(type, h);
5666 }
5667
5668 case BasicJsonType::value_t::number_integer:
5669 {
5670 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
5671 return combine(type, h);
5672 }
5673
5674 case BasicJsonType::value_t::number_unsigned:
5675 {
5676 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
5677 return combine(type, h);
5678 }
5679
5680 case BasicJsonType::value_t::number_float:
5681 {
5682 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
5683 return combine(type, h);
5684 }
5685
5686 case BasicJsonType::value_t::binary:
5687 {
5688 auto seed = combine(type, j.get_binary().size());
5689 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
5690 seed = combine(seed, h);
5691 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
5692 for (const auto byte : j.get_binary())
5693 {
5694 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
5695 }
5696 return seed;
5697 }
5698
5699 default: // LCOV_EXCL_LINE
5700 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
5701 return 0; // LCOV_EXCL_LINE
5702 }
5703}
5704
5705} // namespace detail
5706} // namespace nlohmann
5707
5708// #include <nlohmann/detail/input/binary_reader.hpp>
5709
5710
5711#include <algorithm> // generate_n
5712#include <array> // array
5713#include <cmath> // ldexp
5714#include <cstddef> // size_t
5715#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
5716#include <cstdio> // snprintf
5717#include <cstring> // memcpy
5718#include <iterator> // back_inserter
5719#include <limits> // numeric_limits
5720#include <string> // char_traits, string
5721#include <utility> // make_pair, move
5722#include <vector> // vector
5723#include <map> // map
5724
5725// #include <nlohmann/detail/exceptions.hpp>
5726
5727// #include <nlohmann/detail/input/input_adapters.hpp>
5728
5729
5730#include <array> // array
5731#include <cstddef> // size_t
5732#include <cstring> // strlen
5733#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
5734#include <memory> // shared_ptr, make_shared, addressof
5735#include <numeric> // accumulate
5736#include <string> // string, char_traits
5737#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
5738#include <utility> // pair, declval
5739
5740#ifndef JSON_NO_IO
5741 #include <cstdio> // FILE *
5742 #include <istream> // istream
5743#endif // JSON_NO_IO
5744
5745// #include <nlohmann/detail/iterators/iterator_traits.hpp>
5746
5747// #include <nlohmann/detail/macro_scope.hpp>
5748
5749
5750namespace nlohmann
5751{
5752namespace detail
5753{
5755enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
5756
5758// input adapters //
5760
5761#ifndef JSON_NO_IO
5766class file_input_adapter
5767{
5768 public:
5769 using char_type = char;
5770
5772 explicit file_input_adapter(std::FILE* f) noexcept
5773 : m_file(f)
5774 {}
5775
5776 // make class move-only
5777 file_input_adapter(const file_input_adapter&) = delete;
5778 file_input_adapter(file_input_adapter&&) noexcept = default;
5779 file_input_adapter& operator=(const file_input_adapter&) = delete;
5780 file_input_adapter& operator=(file_input_adapter&&) = delete;
5781 ~file_input_adapter() = default;
5782
5783 std::char_traits<char>::int_type get_character() noexcept
5784 {
5785 return std::fgetc(m_file);
5786 }
5787
5788 private:
5790 std::FILE* m_file;
5791};
5792
5793
5803class input_stream_adapter
5804{
5805 public:
5806 using char_type = char;
5807
5808 ~input_stream_adapter()
5809 {
5810 // clear stream flags; we use underlying streambuf I/O, do not
5811 // maintain ifstream flags, except eof
5812 if (is != nullptr)
5813 {
5814 is->clear(is->rdstate() & std::ios::eofbit);
5815 }
5816 }
5817
5818 explicit input_stream_adapter(std::istream& i)
5819 : is(&i), sb(i.rdbuf())
5820 {}
5821
5822 // delete because of pointer members
5823 input_stream_adapter(const input_stream_adapter&) = delete;
5824 input_stream_adapter& operator=(input_stream_adapter&) = delete;
5825 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
5826
5827 input_stream_adapter(input_stream_adapter&& rhs) noexcept
5828 : is(rhs.is), sb(rhs.sb)
5829 {
5830 rhs.is = nullptr;
5831 rhs.sb = nullptr;
5832 }
5833
5834 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
5835 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
5836 // end up as the same value, e.g. 0xFFFFFFFF.
5837 std::char_traits<char>::int_type get_character()
5838 {
5839 auto res = sb->sbumpc();
5840 // set eof manually, as we don't use the istream interface.
5841 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
5842 {
5843 is->clear(is->rdstate() | std::ios::eofbit);
5844 }
5845 return res;
5846 }
5847
5848 private:
5850 std::istream* is = nullptr;
5851 std::streambuf* sb = nullptr;
5852};
5853#endif // JSON_NO_IO
5854
5855// General-purpose iterator-based adapter. It might not be as fast as
5856// theoretically possible for some containers, but it is extremely versatile.
5857template<typename IteratorType>
5858class iterator_input_adapter
5859{
5860 public:
5861 using char_type = typename std::iterator_traits<IteratorType>::value_type;
5862
5863 iterator_input_adapter(IteratorType first, IteratorType last)
5864 : current(std::move(first)), end(std::move(last))
5865 {}
5866
5867 typename std::char_traits<char_type>::int_type get_character()
5868 {
5869 if (JSON_HEDLEY_LIKELY(current != end))
5870 {
5871 auto result = std::char_traits<char_type>::to_int_type(*current);
5872 std::advance(current, 1);
5873 return result;
5874 }
5875
5876 return std::char_traits<char_type>::eof();
5877 }
5878
5879 private:
5880 IteratorType current;
5881 IteratorType end;
5882
5883 template<typename BaseInputAdapter, size_t T>
5884 friend struct wide_string_input_helper;
5885
5886 bool empty() const
5887 {
5888 return current == end;
5889 }
5890};
5891
5892
5893template<typename BaseInputAdapter, size_t T>
5894struct wide_string_input_helper;
5895
5896template<typename BaseInputAdapter>
5897struct wide_string_input_helper<BaseInputAdapter, 4>
5898{
5899 // UTF-32
5900 static void fill_buffer(BaseInputAdapter& input,
5901 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
5902 size_t& utf8_bytes_index,
5903 size_t& utf8_bytes_filled)
5904 {
5905 utf8_bytes_index = 0;
5906
5907 if (JSON_HEDLEY_UNLIKELY(input.empty()))
5908 {
5909 utf8_bytes[0] = std::char_traits<char>::eof();
5910 utf8_bytes_filled = 1;
5911 }
5912 else
5913 {
5914 // get the current character
5915 const auto wc = input.get_character();
5916
5917 // UTF-32 to UTF-8 encoding
5918 if (wc < 0x80)
5919 {
5920 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5921 utf8_bytes_filled = 1;
5922 }
5923 else if (wc <= 0x7FF)
5924 {
5925 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
5926 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5927 utf8_bytes_filled = 2;
5928 }
5929 else if (wc <= 0xFFFF)
5930 {
5931 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
5932 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5933 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5934 utf8_bytes_filled = 3;
5935 }
5936 else if (wc <= 0x10FFFF)
5937 {
5938 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
5939 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
5940 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5941 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5942 utf8_bytes_filled = 4;
5943 }
5944 else
5945 {
5946 // unknown character
5947 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5948 utf8_bytes_filled = 1;
5949 }
5950 }
5951 }
5952};
5953
5954template<typename BaseInputAdapter>
5955struct wide_string_input_helper<BaseInputAdapter, 2>
5956{
5957 // UTF-16
5958 static void fill_buffer(BaseInputAdapter& input,
5959 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
5960 size_t& utf8_bytes_index,
5961 size_t& utf8_bytes_filled)
5962 {
5963 utf8_bytes_index = 0;
5964
5965 if (JSON_HEDLEY_UNLIKELY(input.empty()))
5966 {
5967 utf8_bytes[0] = std::char_traits<char>::eof();
5968 utf8_bytes_filled = 1;
5969 }
5970 else
5971 {
5972 // get the current character
5973 const auto wc = input.get_character();
5974
5975 // UTF-16 to UTF-8 encoding
5976 if (wc < 0x80)
5977 {
5978 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
5979 utf8_bytes_filled = 1;
5980 }
5981 else if (wc <= 0x7FF)
5982 {
5983 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
5984 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5985 utf8_bytes_filled = 2;
5986 }
5987 else if (0xD800 > wc || wc >= 0xE000)
5988 {
5989 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
5990 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
5991 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
5992 utf8_bytes_filled = 3;
5993 }
5994 else
5995 {
5996 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
5997 {
5998 const auto wc2 = static_cast<unsigned int>(input.get_character());
5999 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6000 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6001 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6002 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6003 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6004 utf8_bytes_filled = 4;
6005 }
6006 else
6007 {
6008 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6009 utf8_bytes_filled = 1;
6010 }
6011 }
6012 }
6013 }
6014};
6015
6016// Wraps another input adapter to convert wide character types into individual bytes.
6017template<typename BaseInputAdapter, typename WideCharType>
6018class wide_string_input_adapter
6019{
6020 public:
6021 using char_type = char;
6022
6023 wide_string_input_adapter(BaseInputAdapter base)
6024 : base_adapter(base) {}
6025
6026 typename std::char_traits<char>::int_type get_character() noexcept
6027 {
6028 // check if buffer needs to be filled
6029 if (utf8_bytes_index == utf8_bytes_filled)
6030 {
6031 fill_buffer<sizeof(WideCharType)>();
6032
6033 JSON_ASSERT(utf8_bytes_filled > 0);
6034 JSON_ASSERT(utf8_bytes_index == 0);
6035 }
6036
6037 // use buffer
6038 JSON_ASSERT(utf8_bytes_filled > 0);
6039 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6040 return utf8_bytes[utf8_bytes_index++];
6041 }
6042
6043 private:
6044 BaseInputAdapter base_adapter;
6045
6046 template<size_t T>
6047 void fill_buffer()
6048 {
6049 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6050 }
6051
6053 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6054
6056 std::size_t utf8_bytes_index = 0;
6058 std::size_t utf8_bytes_filled = 0;
6059};
6060
6061
6062template<typename IteratorType, typename Enable = void>
6063struct iterator_input_adapter_factory
6064{
6065 using iterator_type = IteratorType;
6066 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6067 using adapter_type = iterator_input_adapter<iterator_type>;
6068
6069 static adapter_type create(IteratorType first, IteratorType last)
6070 {
6071 return adapter_type(std::move(first), std::move(last));
6072 }
6073};
6074
6075template<typename T>
6076struct is_iterator_of_multibyte
6077{
6078 using value_type = typename std::iterator_traits<T>::value_type;
6079 enum
6080 {
6081 value = sizeof(value_type) > 1
6082 };
6083};
6084
6085template<typename IteratorType>
6086struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
6087{
6088 using iterator_type = IteratorType;
6089 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6090 using base_adapter_type = iterator_input_adapter<iterator_type>;
6091 using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
6092
6093 static adapter_type create(IteratorType first, IteratorType last)
6094 {
6095 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6096 }
6097};
6098
6099// General purpose iterator-based input
6100template<typename IteratorType>
6101typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
6102{
6103 using factory_type = iterator_input_adapter_factory<IteratorType>;
6104 return factory_type::create(first, last);
6105}
6106
6107// Convenience shorthand from container to iterator
6108// Enables ADL on begin(container) and end(container)
6109// Encloses the using declarations in namespace for not to leak them to outside scope
6110
6111namespace container_input_adapter_factory_impl
6112{
6113
6114using std::begin;
6115using std::end;
6116
6117template<typename ContainerType, typename Enable = void>
6119
6120template<typename ContainerType>
6122 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6123 {
6124 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6125
6126 static adapter_type create(const ContainerType& container)
6127{
6128 return input_adapter(begin(container), end(container));
6129}
6130 };
6131
6132} // namespace container_input_adapter_factory_impl
6133
6134template<typename ContainerType>
6135typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
6136{
6137 return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
6138}
6139
6140#ifndef JSON_NO_IO
6141// Special cases with fast paths
6142inline file_input_adapter input_adapter(std::FILE* file)
6143{
6144 return file_input_adapter(file);
6145}
6146
6147inline input_stream_adapter input_adapter(std::istream& stream)
6148{
6149 return input_stream_adapter(stream);
6150}
6151
6152inline input_stream_adapter input_adapter(std::istream&& stream)
6153{
6154 return input_stream_adapter(stream);
6155}
6156#endif // JSON_NO_IO
6157
6158using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6159
6160// Null-delimited strings, and the like.
6161template < typename CharT,
6162 typename std::enable_if <
6163 std::is_pointer<CharT>::value&&
6164 !std::is_array<CharT>::value&&
6165 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6166 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6167 int >::type = 0 >
6168contiguous_bytes_input_adapter input_adapter(CharT b)
6169{
6170 auto length = std::strlen(reinterpret_cast<const char*>(b));
6171 const auto* ptr = reinterpret_cast<const char*>(b);
6172 return input_adapter(ptr, ptr + length);
6173}
6174
6175template<typename T, std::size_t N>
6176auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6177{
6178 return input_adapter(array, array + N);
6179}
6180
6181// This class only handles inputs of input_buffer_adapter type.
6182// It's required so that expressions like {ptr, len} can be implicitly cast
6183// to the correct adapter.
6184class span_input_adapter
6185{
6186 public:
6187 template < typename CharT,
6188 typename std::enable_if <
6189 std::is_pointer<CharT>::value&&
6190 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6191 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6192 int >::type = 0 >
6193 span_input_adapter(CharT b, std::size_t l)
6194 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6195
6196 template<class IteratorType,
6197 typename std::enable_if<
6198 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
6199 int>::type = 0>
6200 span_input_adapter(IteratorType first, IteratorType last)
6201 : ia(input_adapter(first, last)) {}
6202
6203 contiguous_bytes_input_adapter&& get()
6204 {
6205 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6206 }
6207
6208 private:
6209 contiguous_bytes_input_adapter ia;
6210};
6211} // namespace detail
6212} // namespace nlohmann
6213
6214// #include <nlohmann/detail/input/json_sax.hpp>
6215
6216
6217#include <cstddef>
6218#include <string> // string
6219#include <utility> // move
6220#include <vector> // vector
6221
6222// #include <nlohmann/detail/exceptions.hpp>
6223
6224// #include <nlohmann/detail/macro_scope.hpp>
6225
6226// #include <nlohmann/detail/string_concat.hpp>
6227
6228
6229namespace nlohmann
6230{
6231
6240template<typename BasicJsonType>
6241struct json_sax
6242{
6243 using number_integer_t = typename BasicJsonType::number_integer_t;
6244 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6245 using number_float_t = typename BasicJsonType::number_float_t;
6246 using string_t = typename BasicJsonType::string_t;
6247 using binary_t = typename BasicJsonType::binary_t;
6248
6253 virtual bool null() = 0;
6254
6260 virtual bool boolean(bool val) = 0;
6261
6267 virtual bool number_integer(number_integer_t val) = 0;
6268
6274 virtual bool number_unsigned(number_unsigned_t val) = 0;
6275
6282 virtual bool number_float(number_float_t val, const string_t& s) = 0;
6283
6290 virtual bool string(string_t& val) = 0;
6291
6298 virtual bool binary(binary_t& val) = 0;
6299
6306 virtual bool start_object(std::size_t elements) = 0;
6307
6314 virtual bool key(string_t& val) = 0;
6315
6320 virtual bool end_object() = 0;
6321
6328 virtual bool start_array(std::size_t elements) = 0;
6329
6334 virtual bool end_array() = 0;
6335
6343 virtual bool parse_error(std::size_t position,
6344 const std::string& last_token,
6345 const detail::exception& ex) = 0;
6346
6347 json_sax() = default;
6348 json_sax(const json_sax&) = default;
6349 json_sax(json_sax&&) noexcept = default;
6350 json_sax& operator=(const json_sax&) = default;
6351 json_sax& operator=(json_sax&&) noexcept = default;
6352 virtual ~json_sax() = default;
6353};
6354
6355
6356namespace detail
6357{
6371template<typename BasicJsonType>
6373{
6374 public:
6375 using number_integer_t = typename BasicJsonType::number_integer_t;
6376 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6377 using number_float_t = typename BasicJsonType::number_float_t;
6378 using string_t = typename BasicJsonType::string_t;
6379 using binary_t = typename BasicJsonType::binary_t;
6380
6386 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
6387 : root(r), allow_exceptions(allow_exceptions_)
6388 {}
6389
6390 // make class move-only
6392 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6394 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6396
6397 bool null()
6398 {
6399 handle_value(nullptr);
6400 return true;
6401 }
6402
6403 bool boolean(bool val)
6404 {
6405 handle_value(val);
6406 return true;
6407 }
6408
6410 {
6411 handle_value(val);
6412 return true;
6413 }
6414
6416 {
6417 handle_value(val);
6418 return true;
6419 }
6420
6421 bool number_float(number_float_t val, const string_t& /*unused*/)
6422 {
6423 handle_value(val);
6424 return true;
6425 }
6426
6427 bool string(string_t& val)
6428 {
6429 handle_value(val);
6430 return true;
6431 }
6432
6433 bool binary(binary_t& val)
6434 {
6435 handle_value(std::move(val));
6436 return true;
6437 }
6438
6439 bool start_object(std::size_t len)
6440 {
6441 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
6442
6443 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6444 {
6445 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6446 }
6447
6448 return true;
6449 }
6450
6451 bool key(string_t& val)
6452 {
6453 JSON_ASSERT(!ref_stack.empty());
6454 JSON_ASSERT(ref_stack.back()->is_object());
6455
6456 // add null at given key and store the reference for later
6457 object_element = &(ref_stack.back()->m_value.object->operator[](val));
6458 return true;
6459 }
6460
6462 {
6463 JSON_ASSERT(!ref_stack.empty());
6464 JSON_ASSERT(ref_stack.back()->is_object());
6465
6466 ref_stack.back()->set_parents();
6467 ref_stack.pop_back();
6468 return true;
6469 }
6470
6471 bool start_array(std::size_t len)
6472 {
6473 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
6474
6475 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6476 {
6477 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
6478 }
6479
6480 return true;
6481 }
6482
6484 {
6485 JSON_ASSERT(!ref_stack.empty());
6486 JSON_ASSERT(ref_stack.back()->is_array());
6487
6488 ref_stack.back()->set_parents();
6489 ref_stack.pop_back();
6490 return true;
6491 }
6492
6493 template<class Exception>
6494 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
6495 const Exception& ex)
6496 {
6497 errored = true;
6498 static_cast<void>(ex);
6499 if (allow_exceptions)
6500 {
6501 JSON_THROW(ex);
6502 }
6503 return false;
6504 }
6505
6506 constexpr bool is_errored() const
6507 {
6508 return errored;
6509 }
6510
6511 private:
6518 template<typename Value>
6520 BasicJsonType* handle_value(Value&& v)
6521 {
6522 if (ref_stack.empty())
6523 {
6524 root = BasicJsonType(std::forward<Value>(v));
6525 return &root;
6526 }
6527
6528 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6529
6530 if (ref_stack.back()->is_array())
6531 {
6532 ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
6533 return &(ref_stack.back()->m_value.array->back());
6534 }
6535
6536 JSON_ASSERT(ref_stack.back()->is_object());
6537 JSON_ASSERT(object_element);
6538 *object_element = BasicJsonType(std::forward<Value>(v));
6539 return object_element;
6540 }
6541
6543 BasicJsonType& root;
6545 std::vector<BasicJsonType*> ref_stack {};
6547 BasicJsonType* object_element = nullptr;
6549 bool errored = false;
6551 const bool allow_exceptions = true;
6552};
6553
6554template<typename BasicJsonType>
6556{
6557 public:
6558 using number_integer_t = typename BasicJsonType::number_integer_t;
6559 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6560 using number_float_t = typename BasicJsonType::number_float_t;
6561 using string_t = typename BasicJsonType::string_t;
6562 using binary_t = typename BasicJsonType::binary_t;
6563 using parser_callback_t = typename BasicJsonType::parser_callback_t;
6564 using parse_event_t = typename BasicJsonType::parse_event_t;
6565
6567 const parser_callback_t cb,
6568 const bool allow_exceptions_ = true)
6569 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
6570 {
6571 keep_stack.push_back(true);
6572 }
6573
6574 // make class move-only
6576 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6578 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6580
6581 bool null()
6582 {
6583 handle_value(nullptr);
6584 return true;
6585 }
6586
6587 bool boolean(bool val)
6588 {
6589 handle_value(val);
6590 return true;
6591 }
6592
6594 {
6595 handle_value(val);
6596 return true;
6597 }
6598
6600 {
6601 handle_value(val);
6602 return true;
6603 }
6604
6605 bool number_float(number_float_t val, const string_t& /*unused*/)
6606 {
6607 handle_value(val);
6608 return true;
6609 }
6610
6611 bool string(string_t& val)
6612 {
6613 handle_value(val);
6614 return true;
6615 }
6616
6617 bool binary(binary_t& val)
6618 {
6619 handle_value(std::move(val));
6620 return true;
6621 }
6622
6623 bool start_object(std::size_t len)
6624 {
6625 // check callback for object start
6626 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
6627 keep_stack.push_back(keep);
6628
6629 auto val = handle_value(BasicJsonType::value_t::object, true);
6630 ref_stack.push_back(val.second);
6631
6632 // check object limit
6633 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6634 {
6635 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6636 }
6637
6638 return true;
6639 }
6640
6641 bool key(string_t& val)
6642 {
6643 BasicJsonType k = BasicJsonType(val);
6644
6645 // check callback for key
6646 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
6647 key_keep_stack.push_back(keep);
6648
6649 // add discarded value at given key and store the reference for later
6650 if (keep && ref_stack.back())
6651 {
6652 object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
6653 }
6654
6655 return true;
6656 }
6657
6659 {
6660 if (ref_stack.back())
6661 {
6662 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
6663 {
6664 // discard object
6665 *ref_stack.back() = discarded;
6666 }
6667 else
6668 {
6669 ref_stack.back()->set_parents();
6670 }
6671 }
6672
6673 JSON_ASSERT(!ref_stack.empty());
6674 JSON_ASSERT(!keep_stack.empty());
6675 ref_stack.pop_back();
6676 keep_stack.pop_back();
6677
6678 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
6679 {
6680 // remove discarded value
6681 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
6682 {
6683 if (it->is_discarded())
6684 {
6685 ref_stack.back()->erase(it);
6686 break;
6687 }
6688 }
6689 }
6690
6691 return true;
6692 }
6693
6694 bool start_array(std::size_t len)
6695 {
6696 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
6697 keep_stack.push_back(keep);
6698
6699 auto val = handle_value(BasicJsonType::value_t::array, true);
6700 ref_stack.push_back(val.second);
6701
6702 // check array limit
6703 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6704 {
6705 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
6706 }
6707
6708 return true;
6709 }
6710
6712 {
6713 bool keep = true;
6714
6715 if (ref_stack.back())
6716 {
6717 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
6718 if (keep)
6719 {
6720 ref_stack.back()->set_parents();
6721 }
6722 else
6723 {
6724 // discard array
6725 *ref_stack.back() = discarded;
6726 }
6727 }
6728
6729 JSON_ASSERT(!ref_stack.empty());
6730 JSON_ASSERT(!keep_stack.empty());
6731 ref_stack.pop_back();
6732 keep_stack.pop_back();
6733
6734 // remove discarded value
6735 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
6736 {
6737 ref_stack.back()->m_value.array->pop_back();
6738 }
6739
6740 return true;
6741 }
6742
6743 template<class Exception>
6744 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
6745 const Exception& ex)
6746 {
6747 errored = true;
6748 static_cast<void>(ex);
6749 if (allow_exceptions)
6750 {
6751 JSON_THROW(ex);
6752 }
6753 return false;
6754 }
6755
6756 constexpr bool is_errored() const
6757 {
6758 return errored;
6759 }
6760
6761 private:
6777 template<typename Value>
6778 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
6779 {
6780 JSON_ASSERT(!keep_stack.empty());
6781
6782 // do not handle this value if we know it would be added to a discarded
6783 // container
6784 if (!keep_stack.back())
6785 {
6786 return {false, nullptr};
6787 }
6788
6789 // create value
6790 auto value = BasicJsonType(std::forward<Value>(v));
6791
6792 // check callback
6793 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
6794
6795 // do not handle this value if we just learnt it shall be discarded
6796 if (!keep)
6797 {
6798 return {false, nullptr};
6799 }
6800
6801 if (ref_stack.empty())
6802 {
6803 root = std::move(value);
6804 return {true, &root};
6805 }
6806
6807 // skip this value if we already decided to skip the parent
6808 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
6809 if (!ref_stack.back())
6810 {
6811 return {false, nullptr};
6812 }
6813
6814 // we now only expect arrays and objects
6815 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6816
6817 // array
6818 if (ref_stack.back()->is_array())
6819 {
6820 ref_stack.back()->m_value.array->emplace_back(std::move(value));
6821 return {true, &(ref_stack.back()->m_value.array->back())};
6822 }
6823
6824 // object
6825 JSON_ASSERT(ref_stack.back()->is_object());
6826 // check if we should store an element for the current key
6827 JSON_ASSERT(!key_keep_stack.empty());
6828 const bool store_element = key_keep_stack.back();
6829 key_keep_stack.pop_back();
6830
6831 if (!store_element)
6832 {
6833 return {false, nullptr};
6834 }
6835
6836 JSON_ASSERT(object_element);
6837 *object_element = std::move(value);
6838 return {true, object_element};
6839 }
6840
6842 BasicJsonType& root;
6844 std::vector<BasicJsonType*> ref_stack {};
6846 std::vector<bool> keep_stack {};
6848 std::vector<bool> key_keep_stack {};
6850 BasicJsonType* object_element = nullptr;
6852 bool errored = false;
6854 const parser_callback_t callback = nullptr;
6856 const bool allow_exceptions = true;
6858 BasicJsonType discarded = BasicJsonType::value_t::discarded;
6859};
6860
6861template<typename BasicJsonType>
6863{
6864 public:
6865 using number_integer_t = typename BasicJsonType::number_integer_t;
6866 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6867 using number_float_t = typename BasicJsonType::number_float_t;
6868 using string_t = typename BasicJsonType::string_t;
6869 using binary_t = typename BasicJsonType::binary_t;
6870
6871 bool null()
6872 {
6873 return true;
6874 }
6875
6876 bool boolean(bool /*unused*/)
6877 {
6878 return true;
6879 }
6880
6882 {
6883 return true;
6884 }
6885
6887 {
6888 return true;
6889 }
6890
6891 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
6892 {
6893 return true;
6894 }
6895
6896 bool string(string_t& /*unused*/)
6897 {
6898 return true;
6899 }
6900
6901 bool binary(binary_t& /*unused*/)
6902 {
6903 return true;
6904 }
6905
6906 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
6907 {
6908 return true;
6909 }
6910
6911 bool key(string_t& /*unused*/)
6912 {
6913 return true;
6914 }
6915
6917 {
6918 return true;
6919 }
6920
6921 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
6922 {
6923 return true;
6924 }
6925
6927 {
6928 return true;
6929 }
6930
6931 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
6932 {
6933 return false;
6934 }
6935};
6936} // namespace detail
6937
6938} // namespace nlohmann
6939
6940// #include <nlohmann/detail/input/lexer.hpp>
6941
6942
6943#include <array> // array
6944#include <clocale> // localeconv
6945#include <cstddef> // size_t
6946#include <cstdio> // snprintf
6947#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
6948#include <initializer_list> // initializer_list
6949#include <string> // char_traits, string
6950#include <utility> // move
6951#include <vector> // vector
6952
6953// #include <nlohmann/detail/input/input_adapters.hpp>
6954
6955// #include <nlohmann/detail/input/position_t.hpp>
6956
6957// #include <nlohmann/detail/macro_scope.hpp>
6958
6959
6960namespace nlohmann
6961{
6962namespace detail
6963{
6965// lexer //
6967
6968template<typename BasicJsonType>
6970{
6971 public:
6993
6997 static const char* token_type_name(const token_type t) noexcept
6998 {
6999 switch (t)
7000 {
7002 return "<uninitialized>";
7004 return "true literal";
7006 return "false literal";
7008 return "null literal";
7010 return "string literal";
7014 return "number literal";
7016 return "'['";
7018 return "'{'";
7020 return "']'";
7022 return "'}'";
7024 return "':'";
7026 return "','";
7028 return "<parse error>";
7030 return "end of input";
7032 return "'[', '{', or a literal";
7033 // LCOV_EXCL_START
7034 default: // catch non-enum values
7035 return "unknown token";
7036 // LCOV_EXCL_STOP
7037 }
7038 }
7039};
7045template<typename BasicJsonType, typename InputAdapterType>
7046class lexer : public lexer_base<BasicJsonType>
7047{
7048 using number_integer_t = typename BasicJsonType::number_integer_t;
7049 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7050 using number_float_t = typename BasicJsonType::number_float_t;
7051 using string_t = typename BasicJsonType::string_t;
7052 using char_type = typename InputAdapterType::char_type;
7053 using char_int_type = typename std::char_traits<char_type>::int_type;
7054
7055 public:
7057
7058 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7059 : ia(std::move(adapter))
7060 , ignore_comments(ignore_comments_)
7061 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7062 {}
7063
7064 // delete because of pointer members
7065 lexer(const lexer&) = delete;
7066 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7067 lexer& operator=(lexer&) = delete;
7068 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7069 ~lexer() = default;
7070
7071 private:
7073 // locales
7075
7078 static char get_decimal_point() noexcept
7079 {
7080 const auto* loc = localeconv();
7081 JSON_ASSERT(loc != nullptr);
7082 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7083 }
7084
7086 // scan functions
7088
7104 int get_codepoint()
7105 {
7106 // this function only makes sense after reading `\u`
7107 JSON_ASSERT(current == 'u');
7108 int codepoint = 0;
7109
7110 const auto factors = { 12u, 8u, 4u, 0u };
7111 for (const auto factor : factors)
7112 {
7113 get();
7114
7115 if (current >= '0' && current <= '9')
7116 {
7117 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7118 }
7119 else if (current >= 'A' && current <= 'F')
7120 {
7121 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7122 }
7123 else if (current >= 'a' && current <= 'f')
7124 {
7125 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7126 }
7127 else
7128 {
7129 return -1;
7130 }
7131 }
7132
7133 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7134 return codepoint;
7135 }
7136
7152 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7153 {
7154 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7155 add(current);
7156
7157 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7158 {
7159 get();
7160 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
7161 {
7162 add(current);
7163 }
7164 else
7165 {
7166 error_message = "invalid string: ill-formed UTF-8 byte";
7167 return false;
7168 }
7169 }
7170
7171 return true;
7172 }
7173
7189 token_type scan_string()
7190 {
7191 // reset token_buffer (ignore opening quote)
7192 reset();
7193
7194 // we entered the function by reading an open quote
7195 JSON_ASSERT(current == '\"');
7196
7197 while (true)
7198 {
7199 // get next character
7200 switch (get())
7201 {
7202 // end of file while parsing string
7203 case std::char_traits<char_type>::eof():
7204 {
7205 error_message = "invalid string: missing closing quote";
7206 return token_type::parse_error;
7207 }
7208
7209 // closing quote
7210 case '\"':
7211 {
7212 return token_type::value_string;
7213 }
7214
7215 // escapes
7216 case '\\':
7217 {
7218 switch (get())
7219 {
7220 // quotation mark
7221 case '\"':
7222 add('\"');
7223 break;
7224 // reverse solidus
7225 case '\\':
7226 add('\\');
7227 break;
7228 // solidus
7229 case '/':
7230 add('/');
7231 break;
7232 // backspace
7233 case 'b':
7234 add('\b');
7235 break;
7236 // form feed
7237 case 'f':
7238 add('\f');
7239 break;
7240 // line feed
7241 case 'n':
7242 add('\n');
7243 break;
7244 // carriage return
7245 case 'r':
7246 add('\r');
7247 break;
7248 // tab
7249 case 't':
7250 add('\t');
7251 break;
7252
7253 // unicode escapes
7254 case 'u':
7255 {
7256 const int codepoint1 = get_codepoint();
7257 int codepoint = codepoint1; // start with codepoint1
7258
7259 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7260 {
7261 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7262 return token_type::parse_error;
7263 }
7264
7265 // check if code point is a high surrogate
7266 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7267 {
7268 // expect next \uxxxx entry
7269 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7270 {
7271 const int codepoint2 = get_codepoint();
7272
7273 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7274 {
7275 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7276 return token_type::parse_error;
7277 }
7278
7279 // check if codepoint2 is a low surrogate
7280 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7281 {
7282 // overwrite codepoint
7283 codepoint = static_cast<int>(
7284 // high surrogate occupies the most significant 22 bits
7285 (static_cast<unsigned int>(codepoint1) << 10u)
7286 // low surrogate occupies the least significant 15 bits
7287 + static_cast<unsigned int>(codepoint2)
7288 // there is still the 0xD800, 0xDC00 and 0x10000 noise
7289 // in the result, so we have to subtract with:
7290 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7291 - 0x35FDC00u);
7292 }
7293 else
7294 {
7295 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7296 return token_type::parse_error;
7297 }
7298 }
7299 else
7300 {
7301 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7302 return token_type::parse_error;
7303 }
7304 }
7305 else
7306 {
7307 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7308 {
7309 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7310 return token_type::parse_error;
7311 }
7312 }
7313
7314 // result of the above calculation yields a proper codepoint
7315 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7316
7317 // translate codepoint into bytes
7318 if (codepoint < 0x80)
7319 {
7320 // 1-byte characters: 0xxxxxxx (ASCII)
7321 add(static_cast<char_int_type>(codepoint));
7322 }
7323 else if (codepoint <= 0x7FF)
7324 {
7325 // 2-byte characters: 110xxxxx 10xxxxxx
7326 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7327 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7328 }
7329 else if (codepoint <= 0xFFFF)
7330 {
7331 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7332 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7333 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7334 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7335 }
7336 else
7337 {
7338 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7339 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7340 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7341 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7342 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7343 }
7344
7345 break;
7346 }
7347
7348 // other characters after escape
7349 default:
7350 error_message = "invalid string: forbidden character after backslash";
7351 return token_type::parse_error;
7352 }
7353
7354 break;
7355 }
7356
7357 // invalid control characters
7358 case 0x00:
7359 {
7360 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7361 return token_type::parse_error;
7362 }
7363
7364 case 0x01:
7365 {
7366 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7367 return token_type::parse_error;
7368 }
7369
7370 case 0x02:
7371 {
7372 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7373 return token_type::parse_error;
7374 }
7375
7376 case 0x03:
7377 {
7378 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7379 return token_type::parse_error;
7380 }
7381
7382 case 0x04:
7383 {
7384 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7385 return token_type::parse_error;
7386 }
7387
7388 case 0x05:
7389 {
7390 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7391 return token_type::parse_error;
7392 }
7393
7394 case 0x06:
7395 {
7396 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7397 return token_type::parse_error;
7398 }
7399
7400 case 0x07:
7401 {
7402 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7403 return token_type::parse_error;
7404 }
7405
7406 case 0x08:
7407 {
7408 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7409 return token_type::parse_error;
7410 }
7411
7412 case 0x09:
7413 {
7414 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7415 return token_type::parse_error;
7416 }
7417
7418 case 0x0A:
7419 {
7420 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7421 return token_type::parse_error;
7422 }
7423
7424 case 0x0B:
7425 {
7426 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7427 return token_type::parse_error;
7428 }
7429
7430 case 0x0C:
7431 {
7432 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7433 return token_type::parse_error;
7434 }
7435
7436 case 0x0D:
7437 {
7438 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7439 return token_type::parse_error;
7440 }
7441
7442 case 0x0E:
7443 {
7444 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7445 return token_type::parse_error;
7446 }
7447
7448 case 0x0F:
7449 {
7450 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7451 return token_type::parse_error;
7452 }
7453
7454 case 0x10:
7455 {
7456 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7457 return token_type::parse_error;
7458 }
7459
7460 case 0x11:
7461 {
7462 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7463 return token_type::parse_error;
7464 }
7465
7466 case 0x12:
7467 {
7468 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7469 return token_type::parse_error;
7470 }
7471
7472 case 0x13:
7473 {
7474 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7475 return token_type::parse_error;
7476 }
7477
7478 case 0x14:
7479 {
7480 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7481 return token_type::parse_error;
7482 }
7483
7484 case 0x15:
7485 {
7486 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7487 return token_type::parse_error;
7488 }
7489
7490 case 0x16:
7491 {
7492 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7493 return token_type::parse_error;
7494 }
7495
7496 case 0x17:
7497 {
7498 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7499 return token_type::parse_error;
7500 }
7501
7502 case 0x18:
7503 {
7504 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7505 return token_type::parse_error;
7506 }
7507
7508 case 0x19:
7509 {
7510 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7511 return token_type::parse_error;
7512 }
7513
7514 case 0x1A:
7515 {
7516 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7517 return token_type::parse_error;
7518 }
7519
7520 case 0x1B:
7521 {
7522 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7523 return token_type::parse_error;
7524 }
7525
7526 case 0x1C:
7527 {
7528 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7529 return token_type::parse_error;
7530 }
7531
7532 case 0x1D:
7533 {
7534 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7535 return token_type::parse_error;
7536 }
7537
7538 case 0x1E:
7539 {
7540 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7541 return token_type::parse_error;
7542 }
7543
7544 case 0x1F:
7545 {
7546 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7547 return token_type::parse_error;
7548 }
7549
7550 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7551 case 0x20:
7552 case 0x21:
7553 case 0x23:
7554 case 0x24:
7555 case 0x25:
7556 case 0x26:
7557 case 0x27:
7558 case 0x28:
7559 case 0x29:
7560 case 0x2A:
7561 case 0x2B:
7562 case 0x2C:
7563 case 0x2D:
7564 case 0x2E:
7565 case 0x2F:
7566 case 0x30:
7567 case 0x31:
7568 case 0x32:
7569 case 0x33:
7570 case 0x34:
7571 case 0x35:
7572 case 0x36:
7573 case 0x37:
7574 case 0x38:
7575 case 0x39:
7576 case 0x3A:
7577 case 0x3B:
7578 case 0x3C:
7579 case 0x3D:
7580 case 0x3E:
7581 case 0x3F:
7582 case 0x40:
7583 case 0x41:
7584 case 0x42:
7585 case 0x43:
7586 case 0x44:
7587 case 0x45:
7588 case 0x46:
7589 case 0x47:
7590 case 0x48:
7591 case 0x49:
7592 case 0x4A:
7593 case 0x4B:
7594 case 0x4C:
7595 case 0x4D:
7596 case 0x4E:
7597 case 0x4F:
7598 case 0x50:
7599 case 0x51:
7600 case 0x52:
7601 case 0x53:
7602 case 0x54:
7603 case 0x55:
7604 case 0x56:
7605 case 0x57:
7606 case 0x58:
7607 case 0x59:
7608 case 0x5A:
7609 case 0x5B:
7610 case 0x5D:
7611 case 0x5E:
7612 case 0x5F:
7613 case 0x60:
7614 case 0x61:
7615 case 0x62:
7616 case 0x63:
7617 case 0x64:
7618 case 0x65:
7619 case 0x66:
7620 case 0x67:
7621 case 0x68:
7622 case 0x69:
7623 case 0x6A:
7624 case 0x6B:
7625 case 0x6C:
7626 case 0x6D:
7627 case 0x6E:
7628 case 0x6F:
7629 case 0x70:
7630 case 0x71:
7631 case 0x72:
7632 case 0x73:
7633 case 0x74:
7634 case 0x75:
7635 case 0x76:
7636 case 0x77:
7637 case 0x78:
7638 case 0x79:
7639 case 0x7A:
7640 case 0x7B:
7641 case 0x7C:
7642 case 0x7D:
7643 case 0x7E:
7644 case 0x7F:
7645 {
7646 add(current);
7647 break;
7648 }
7649
7650 // U+0080..U+07FF: bytes C2..DF 80..BF
7651 case 0xC2:
7652 case 0xC3:
7653 case 0xC4:
7654 case 0xC5:
7655 case 0xC6:
7656 case 0xC7:
7657 case 0xC8:
7658 case 0xC9:
7659 case 0xCA:
7660 case 0xCB:
7661 case 0xCC:
7662 case 0xCD:
7663 case 0xCE:
7664 case 0xCF:
7665 case 0xD0:
7666 case 0xD1:
7667 case 0xD2:
7668 case 0xD3:
7669 case 0xD4:
7670 case 0xD5:
7671 case 0xD6:
7672 case 0xD7:
7673 case 0xD8:
7674 case 0xD9:
7675 case 0xDA:
7676 case 0xDB:
7677 case 0xDC:
7678 case 0xDD:
7679 case 0xDE:
7680 case 0xDF:
7681 {
7682 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
7683 {
7684 return token_type::parse_error;
7685 }
7686 break;
7687 }
7688
7689 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7690 case 0xE0:
7691 {
7692 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7693 {
7694 return token_type::parse_error;
7695 }
7696 break;
7697 }
7698
7699 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7700 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7701 case 0xE1:
7702 case 0xE2:
7703 case 0xE3:
7704 case 0xE4:
7705 case 0xE5:
7706 case 0xE6:
7707 case 0xE7:
7708 case 0xE8:
7709 case 0xE9:
7710 case 0xEA:
7711 case 0xEB:
7712 case 0xEC:
7713 case 0xEE:
7714 case 0xEF:
7715 {
7716 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7717 {
7718 return token_type::parse_error;
7719 }
7720 break;
7721 }
7722
7723 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7724 case 0xED:
7725 {
7726 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7727 {
7728 return token_type::parse_error;
7729 }
7730 break;
7731 }
7732
7733 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7734 case 0xF0:
7735 {
7736 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7737 {
7738 return token_type::parse_error;
7739 }
7740 break;
7741 }
7742
7743 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7744 case 0xF1:
7745 case 0xF2:
7746 case 0xF3:
7747 {
7748 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7749 {
7750 return token_type::parse_error;
7751 }
7752 break;
7753 }
7754
7755 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7756 case 0xF4:
7757 {
7758 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
7759 {
7760 return token_type::parse_error;
7761 }
7762 break;
7763 }
7764
7765 // remaining bytes (80..C1 and F5..FF) are ill-formed
7766 default:
7767 {
7768 error_message = "invalid string: ill-formed UTF-8 byte";
7769 return token_type::parse_error;
7770 }
7771 }
7772 }
7773 }
7774
7779 bool scan_comment()
7780 {
7781 switch (get())
7782 {
7783 // single-line comments skip input until a newline or EOF is read
7784 case '/':
7785 {
7786 while (true)
7787 {
7788 switch (get())
7789 {
7790 case '\n':
7791 case '\r':
7792 case std::char_traits<char_type>::eof():
7793 case '\0':
7794 return true;
7795
7796 default:
7797 break;
7798 }
7799 }
7800 }
7801
7802 // multi-line comments skip input until */ is read
7803 case '*':
7804 {
7805 while (true)
7806 {
7807 switch (get())
7808 {
7809 case std::char_traits<char_type>::eof():
7810 case '\0':
7811 {
7812 error_message = "invalid comment; missing closing '*/'";
7813 return false;
7814 }
7815
7816 case '*':
7817 {
7818 switch (get())
7819 {
7820 case '/':
7821 return true;
7822
7823 default:
7824 {
7825 unget();
7826 continue;
7827 }
7828 }
7829 }
7830
7831 default:
7832 continue;
7833 }
7834 }
7835 }
7836
7837 // unexpected character after reading '/'
7838 default:
7839 {
7840 error_message = "invalid comment; expecting '/' or '*' after '/'";
7841 return false;
7842 }
7843 }
7844 }
7845
7847 static void strtof(float& f, const char* str, char** endptr) noexcept
7848 {
7849 f = std::strtof(str, endptr);
7850 }
7851
7853 static void strtof(double& f, const char* str, char** endptr) noexcept
7854 {
7855 f = std::strtod(str, endptr);
7856 }
7857
7859 static void strtof(long double& f, const char* str, char** endptr) noexcept
7860 {
7861 f = std::strtold(str, endptr);
7862 }
7863
7904 token_type scan_number() // lgtm [cpp/use-of-goto]
7905 {
7906 // reset token_buffer to store the number's bytes
7907 reset();
7908
7909 // the type of the parsed number; initially set to unsigned; will be
7910 // changed if minus sign, decimal point or exponent is read
7911 token_type number_type = token_type::value_unsigned;
7912
7913 // state (init): we just found out we need to scan a number
7914 switch (current)
7915 {
7916 case '-':
7917 {
7918 add(current);
7919 goto scan_number_minus;
7920 }
7921
7922 case '0':
7923 {
7924 add(current);
7925 goto scan_number_zero;
7926 }
7927
7928 case '1':
7929 case '2':
7930 case '3':
7931 case '4':
7932 case '5':
7933 case '6':
7934 case '7':
7935 case '8':
7936 case '9':
7937 {
7938 add(current);
7939 goto scan_number_any1;
7940 }
7941
7942 // all other characters are rejected outside scan_number()
7943 default: // LCOV_EXCL_LINE
7944 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
7945 }
7946
7947scan_number_minus:
7948 // state: we just parsed a leading minus sign
7949 number_type = token_type::value_integer;
7950 switch (get())
7951 {
7952 case '0':
7953 {
7954 add(current);
7955 goto scan_number_zero;
7956 }
7957
7958 case '1':
7959 case '2':
7960 case '3':
7961 case '4':
7962 case '5':
7963 case '6':
7964 case '7':
7965 case '8':
7966 case '9':
7967 {
7968 add(current);
7969 goto scan_number_any1;
7970 }
7971
7972 default:
7973 {
7974 error_message = "invalid number; expected digit after '-'";
7975 return token_type::parse_error;
7976 }
7977 }
7978
7979scan_number_zero:
7980 // state: we just parse a zero (maybe with a leading minus sign)
7981 switch (get())
7982 {
7983 case '.':
7984 {
7985 add(decimal_point_char);
7986 goto scan_number_decimal1;
7987 }
7988
7989 case 'e':
7990 case 'E':
7991 {
7992 add(current);
7993 goto scan_number_exponent;
7994 }
7995
7996 default:
7997 goto scan_number_done;
7998 }
7999
8000scan_number_any1:
8001 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8002 switch (get())
8003 {
8004 case '0':
8005 case '1':
8006 case '2':
8007 case '3':
8008 case '4':
8009 case '5':
8010 case '6':
8011 case '7':
8012 case '8':
8013 case '9':
8014 {
8015 add(current);
8016 goto scan_number_any1;
8017 }
8018
8019 case '.':
8020 {
8021 add(decimal_point_char);
8022 goto scan_number_decimal1;
8023 }
8024
8025 case 'e':
8026 case 'E':
8027 {
8028 add(current);
8029 goto scan_number_exponent;
8030 }
8031
8032 default:
8033 goto scan_number_done;
8034 }
8035
8036scan_number_decimal1:
8037 // state: we just parsed a decimal point
8038 number_type = token_type::value_float;
8039 switch (get())
8040 {
8041 case '0':
8042 case '1':
8043 case '2':
8044 case '3':
8045 case '4':
8046 case '5':
8047 case '6':
8048 case '7':
8049 case '8':
8050 case '9':
8051 {
8052 add(current);
8053 goto scan_number_decimal2;
8054 }
8055
8056 default:
8057 {
8058 error_message = "invalid number; expected digit after '.'";
8059 return token_type::parse_error;
8060 }
8061 }
8062
8063scan_number_decimal2:
8064 // we just parsed at least one number after a decimal point
8065 switch (get())
8066 {
8067 case '0':
8068 case '1':
8069 case '2':
8070 case '3':
8071 case '4':
8072 case '5':
8073 case '6':
8074 case '7':
8075 case '8':
8076 case '9':
8077 {
8078 add(current);
8079 goto scan_number_decimal2;
8080 }
8081
8082 case 'e':
8083 case 'E':
8084 {
8085 add(current);
8086 goto scan_number_exponent;
8087 }
8088
8089 default:
8090 goto scan_number_done;
8091 }
8092
8093scan_number_exponent:
8094 // we just parsed an exponent
8095 number_type = token_type::value_float;
8096 switch (get())
8097 {
8098 case '+':
8099 case '-':
8100 {
8101 add(current);
8102 goto scan_number_sign;
8103 }
8104
8105 case '0':
8106 case '1':
8107 case '2':
8108 case '3':
8109 case '4':
8110 case '5':
8111 case '6':
8112 case '7':
8113 case '8':
8114 case '9':
8115 {
8116 add(current);
8117 goto scan_number_any2;
8118 }
8119
8120 default:
8121 {
8122 error_message =
8123 "invalid number; expected '+', '-', or digit after exponent";
8124 return token_type::parse_error;
8125 }
8126 }
8127
8128scan_number_sign:
8129 // we just parsed an exponent sign
8130 switch (get())
8131 {
8132 case '0':
8133 case '1':
8134 case '2':
8135 case '3':
8136 case '4':
8137 case '5':
8138 case '6':
8139 case '7':
8140 case '8':
8141 case '9':
8142 {
8143 add(current);
8144 goto scan_number_any2;
8145 }
8146
8147 default:
8148 {
8149 error_message = "invalid number; expected digit after exponent sign";
8150 return token_type::parse_error;
8151 }
8152 }
8153
8154scan_number_any2:
8155 // we just parsed a number after the exponent or exponent sign
8156 switch (get())
8157 {
8158 case '0':
8159 case '1':
8160 case '2':
8161 case '3':
8162 case '4':
8163 case '5':
8164 case '6':
8165 case '7':
8166 case '8':
8167 case '9':
8168 {
8169 add(current);
8170 goto scan_number_any2;
8171 }
8172
8173 default:
8174 goto scan_number_done;
8175 }
8176
8177scan_number_done:
8178 // unget the character after the number (we only read it to know that
8179 // we are done scanning a number)
8180 unget();
8181
8182 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8183 errno = 0;
8184
8185 // try to parse integers first and fall back to floats
8186 if (number_type == token_type::value_unsigned)
8187 {
8188 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8189
8190 // we checked the number format before
8191 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8192
8193 if (errno == 0)
8194 {
8195 value_unsigned = static_cast<number_unsigned_t>(x);
8196 if (value_unsigned == x)
8197 {
8198 return token_type::value_unsigned;
8199 }
8200 }
8201 }
8202 else if (number_type == token_type::value_integer)
8203 {
8204 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8205
8206 // we checked the number format before
8207 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8208
8209 if (errno == 0)
8210 {
8211 value_integer = static_cast<number_integer_t>(x);
8212 if (value_integer == x)
8213 {
8214 return token_type::value_integer;
8215 }
8216 }
8217 }
8218
8219 // this code is reached if we parse a floating-point number or if an
8220 // integer conversion above failed
8221 strtof(value_float, token_buffer.data(), &endptr);
8222
8223 // we checked the number format before
8224 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8225
8226 return token_type::value_float;
8227 }
8228
8235 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8236 token_type return_type)
8237 {
8238 JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
8239 for (std::size_t i = 1; i < length; ++i)
8240 {
8241 if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8242 {
8243 error_message = "invalid literal";
8244 return token_type::parse_error;
8245 }
8246 }
8247 return return_type;
8248 }
8249
8251 // input management
8253
8255 void reset() noexcept
8256 {
8257 token_buffer.clear();
8258 token_string.clear();
8259 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
8260 }
8261
8262 /*
8263 @brief get next character from the input
8264
8265 This function provides the interface to the used input adapter. It does
8266 not throw in case the input reached EOF, but returns a
8267 `std::char_traits<char>::eof()` in that case. Stores the scanned characters
8268 for use in error messages.
8269
8270 @return character read from the input
8271 */
8272 char_int_type get()
8273 {
8274 ++position.chars_read_total;
8275 ++position.chars_read_current_line;
8276
8277 if (next_unget)
8278 {
8279 // just reset the next_unget variable and work with current
8280 next_unget = false;
8281 }
8282 else
8283 {
8284 current = ia.get_character();
8285 }
8286
8287 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
8288 {
8289 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
8290 }
8291
8292 if (current == '\n')
8293 {
8294 ++position.lines_read;
8295 position.chars_read_current_line = 0;
8296 }
8297
8298 return current;
8299 }
8300
8309 void unget()
8310 {
8311 next_unget = true;
8312
8313 --position.chars_read_total;
8314
8315 // in case we "unget" a newline, we have to also decrement the lines_read
8316 if (position.chars_read_current_line == 0)
8317 {
8318 if (position.lines_read > 0)
8319 {
8320 --position.lines_read;
8321 }
8322 }
8323 else
8324 {
8325 --position.chars_read_current_line;
8326 }
8327
8328 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
8329 {
8330 JSON_ASSERT(!token_string.empty());
8331 token_string.pop_back();
8332 }
8333 }
8334
8336 void add(char_int_type c)
8337 {
8338 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8339 }
8340
8341 public:
8343 // value getters
8345
8347 constexpr number_integer_t get_number_integer() const noexcept
8348 {
8349 return value_integer;
8350 }
8351
8353 constexpr number_unsigned_t get_number_unsigned() const noexcept
8354 {
8355 return value_unsigned;
8356 }
8357
8359 constexpr number_float_t get_number_float() const noexcept
8360 {
8361 return value_float;
8362 }
8363
8365 string_t& get_string()
8366 {
8367 return token_buffer;
8368 }
8369
8371 // diagnostics
8373
8375 constexpr position_t get_position() const noexcept
8376 {
8377 return position;
8378 }
8379
8383 std::string get_token_string() const
8384 {
8385 // escape control characters
8386 std::string result;
8387 for (const auto c : token_string)
8388 {
8389 if (static_cast<unsigned char>(c) <= '\x1F')
8390 {
8391 // escape control characters
8392 std::array<char, 9> cs{{}};
8393 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8394 result += cs.data();
8395 }
8396 else
8397 {
8398 // add character as is
8399 result.push_back(static_cast<std::string::value_type>(c));
8400 }
8401 }
8402
8403 return result;
8404 }
8405
8408 constexpr const char* get_error_message() const noexcept
8409 {
8410 return error_message;
8411 }
8412
8414 // actual scanner
8416
8422 {
8423 if (get() == 0xEF)
8424 {
8425 // check if we completely parse the BOM
8426 return get() == 0xBB && get() == 0xBF;
8427 }
8428
8429 // the first character is not the beginning of the BOM; unget it to
8430 // process is later
8431 unget();
8432 return true;
8433 }
8434
8436 {
8437 do
8438 {
8439 get();
8440 }
8441 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8442 }
8443
8445 {
8446 // initially, skip the BOM
8447 if (position.chars_read_total == 0 && !skip_bom())
8448 {
8449 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8450 return token_type::parse_error;
8451 }
8452
8453 // read next character and ignore whitespace
8454 skip_whitespace();
8455
8456 // ignore comments
8457 while (ignore_comments && current == '/')
8458 {
8459 if (!scan_comment())
8460 {
8461 return token_type::parse_error;
8462 }
8463
8464 // skip following whitespace
8465 skip_whitespace();
8466 }
8467
8468 switch (current)
8469 {
8470 // structural characters
8471 case '[':
8472 return token_type::begin_array;
8473 case ']':
8474 return token_type::end_array;
8475 case '{':
8476 return token_type::begin_object;
8477 case '}':
8478 return token_type::end_object;
8479 case ':':
8480 return token_type::name_separator;
8481 case ',':
8482 return token_type::value_separator;
8483
8484 // literals
8485 case 't':
8486 {
8487 std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}};
8488 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8489 }
8490 case 'f':
8491 {
8492 std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}};
8493 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8494 }
8495 case 'n':
8496 {
8497 std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}};
8498 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8499 }
8500
8501 // string
8502 case '\"':
8503 return scan_string();
8504
8505 // number
8506 case '-':
8507 case '0':
8508 case '1':
8509 case '2':
8510 case '3':
8511 case '4':
8512 case '5':
8513 case '6':
8514 case '7':
8515 case '8':
8516 case '9':
8517 return scan_number();
8518
8519 // end of input (the null byte is needed when parsing from
8520 // string literals)
8521 case '\0':
8522 case std::char_traits<char_type>::eof():
8523 return token_type::end_of_input;
8524
8525 // error
8526 default:
8527 error_message = "invalid literal";
8528 return token_type::parse_error;
8529 }
8530 }
8531
8532 private:
8534 InputAdapterType ia;
8535
8537 const bool ignore_comments = false;
8538
8540 char_int_type current = std::char_traits<char_type>::eof();
8541
8543 bool next_unget = false;
8544
8546 position_t position {};
8547
8549 std::vector<char_type> token_string {};
8550
8552 string_t token_buffer {};
8553
8555 const char* error_message = "";
8556
8557 // number values
8558 number_integer_t value_integer = 0;
8559 number_unsigned_t value_unsigned = 0;
8560 number_float_t value_float = 0;
8561
8563 const char_int_type decimal_point_char = '.';
8564};
8565} // namespace detail
8566} // namespace nlohmann
8567
8568// #include <nlohmann/detail/macro_scope.hpp>
8569
8570// #include <nlohmann/detail/meta/is_sax.hpp>
8571
8572
8573#include <cstdint> // size_t
8574#include <utility> // declval
8575#include <string> // string
8576
8577// #include <nlohmann/detail/meta/detected.hpp>
8578
8579// #include <nlohmann/detail/meta/type_traits.hpp>
8580
8581
8582namespace nlohmann
8583{
8584namespace detail
8585{
8586template<typename T>
8587using null_function_t = decltype(std::declval<T&>().null());
8588
8589template<typename T>
8590using boolean_function_t =
8591 decltype(std::declval<T&>().boolean(std::declval<bool>()));
8592
8593template<typename T, typename Integer>
8594using number_integer_function_t =
8595 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
8596
8597template<typename T, typename Unsigned>
8598using number_unsigned_function_t =
8599 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
8600
8601template<typename T, typename Float, typename String>
8602using number_float_function_t = decltype(std::declval<T&>().number_float(
8603 std::declval<Float>(), std::declval<const String&>()));
8604
8605template<typename T, typename String>
8606using string_function_t =
8607 decltype(std::declval<T&>().string(std::declval<String&>()));
8608
8609template<typename T, typename Binary>
8610using binary_function_t =
8611 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
8612
8613template<typename T>
8614using start_object_function_t =
8615 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
8616
8617template<typename T, typename String>
8618using key_function_t =
8619 decltype(std::declval<T&>().key(std::declval<String&>()));
8620
8621template<typename T>
8622using end_object_function_t = decltype(std::declval<T&>().end_object());
8623
8624template<typename T>
8625using start_array_function_t =
8626 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
8627
8628template<typename T>
8629using end_array_function_t = decltype(std::declval<T&>().end_array());
8630
8631template<typename T, typename Exception>
8632using parse_error_function_t = decltype(std::declval<T&>().parse_error(
8633 std::declval<std::size_t>(), std::declval<const std::string&>(),
8634 std::declval<const Exception&>()));
8635
8636template<typename SAX, typename BasicJsonType>
8637struct is_sax
8638{
8639 private:
8640 static_assert(is_basic_json<BasicJsonType>::value,
8641 "BasicJsonType must be of type basic_json<...>");
8642
8643 using number_integer_t = typename BasicJsonType::number_integer_t;
8644 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8645 using number_float_t = typename BasicJsonType::number_float_t;
8646 using string_t = typename BasicJsonType::string_t;
8647 using binary_t = typename BasicJsonType::binary_t;
8648 using exception_t = typename BasicJsonType::exception;
8649
8650 public:
8651 static constexpr bool value =
8652 is_detected_exact<bool, null_function_t, SAX>::value &&
8653 is_detected_exact<bool, boolean_function_t, SAX>::value &&
8654 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
8655 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
8656 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
8657 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
8658 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
8659 is_detected_exact<bool, start_object_function_t, SAX>::value &&
8660 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
8661 is_detected_exact<bool, end_object_function_t, SAX>::value &&
8662 is_detected_exact<bool, start_array_function_t, SAX>::value &&
8663 is_detected_exact<bool, end_array_function_t, SAX>::value &&
8664 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
8665};
8666
8667template<typename SAX, typename BasicJsonType>
8668struct is_sax_static_asserts
8669{
8670 private:
8671 static_assert(is_basic_json<BasicJsonType>::value,
8672 "BasicJsonType must be of type basic_json<...>");
8673
8674 using number_integer_t = typename BasicJsonType::number_integer_t;
8675 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8676 using number_float_t = typename BasicJsonType::number_float_t;
8677 using string_t = typename BasicJsonType::string_t;
8678 using binary_t = typename BasicJsonType::binary_t;
8679 using exception_t = typename BasicJsonType::exception;
8680
8681 public:
8682 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
8683 "Missing/invalid function: bool null()");
8684 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
8685 "Missing/invalid function: bool boolean(bool)");
8686 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
8687 "Missing/invalid function: bool boolean(bool)");
8688 static_assert(
8689 is_detected_exact<bool, number_integer_function_t, SAX,
8690 number_integer_t>::value,
8691 "Missing/invalid function: bool number_integer(number_integer_t)");
8692 static_assert(
8693 is_detected_exact<bool, number_unsigned_function_t, SAX,
8694 number_unsigned_t>::value,
8695 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
8696 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
8697 number_float_t, string_t>::value,
8698 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
8699 static_assert(
8700 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
8701 "Missing/invalid function: bool string(string_t&)");
8702 static_assert(
8703 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
8704 "Missing/invalid function: bool binary(binary_t&)");
8705 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
8706 "Missing/invalid function: bool start_object(std::size_t)");
8707 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
8708 "Missing/invalid function: bool key(string_t&)");
8709 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
8710 "Missing/invalid function: bool end_object()");
8711 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
8712 "Missing/invalid function: bool start_array(std::size_t)");
8713 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
8714 "Missing/invalid function: bool end_array()");
8715 static_assert(
8716 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
8717 "Missing/invalid function: bool parse_error(std::size_t, const "
8718 "std::string&, const exception&)");
8719};
8720} // namespace detail
8721} // namespace nlohmann
8722
8723// #include <nlohmann/detail/meta/type_traits.hpp>
8724
8725// #include <nlohmann/detail/string_concat.hpp>
8726
8727// #include <nlohmann/detail/value_t.hpp>
8728
8729
8730namespace nlohmann
8731{
8732namespace detail
8733{
8734
8737{
8738 error,
8739 ignore,
8740 store
8741};
8742
8750static inline bool little_endianness(int num = 1) noexcept
8751{
8752 return *reinterpret_cast<char*>(&num) == 1;
8753}
8754
8755
8757// binary reader //
8759
8763template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
8765{
8766 using number_integer_t = typename BasicJsonType::number_integer_t;
8767 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8768 using number_float_t = typename BasicJsonType::number_float_t;
8769 using string_t = typename BasicJsonType::string_t;
8770 using binary_t = typename BasicJsonType::binary_t;
8771 using json_sax_t = SAX;
8772 using char_type = typename InputAdapterType::char_type;
8773 using char_int_type = typename std::char_traits<char_type>::int_type;
8774
8775 public:
8781 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
8782 {
8783 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
8784 }
8785
8786 // make class move-only
8788 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8790 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8791 ~binary_reader() = default;
8792
8802 bool sax_parse(const input_format_t format,
8803 json_sax_t* sax_,
8804 const bool strict = true,
8805 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
8806 {
8807 sax = sax_;
8808 bool result = false;
8809
8810 switch (format)
8811 {
8812 case input_format_t::bson:
8813 result = parse_bson_internal();
8814 break;
8815
8816 case input_format_t::cbor:
8817 result = parse_cbor_internal(true, tag_handler);
8818 break;
8819
8820 case input_format_t::msgpack:
8821 result = parse_msgpack_internal();
8822 break;
8823
8824 case input_format_t::ubjson:
8825 case input_format_t::bjdata:
8826 result = parse_ubjson_internal();
8827 break;
8828
8829 case input_format_t::json: // LCOV_EXCL_LINE
8830 default: // LCOV_EXCL_LINE
8831 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8832 }
8833
8834 // strict mode: next byte must be EOF
8835 if (result && strict)
8836 {
8837 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
8838 {
8839 get_ignore_noop();
8840 }
8841 else
8842 {
8843 get();
8844 }
8845
8846 if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
8847 {
8848 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
8849 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
8850 }
8851 }
8852
8853 return result;
8854 }
8855
8856 private:
8858 // BSON //
8860
8865 bool parse_bson_internal()
8866 {
8867 std::int32_t document_size{};
8868 get_number<std::int32_t, true>(input_format_t::bson, document_size);
8869
8870 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
8871 {
8872 return false;
8873 }
8874
8875 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
8876 {
8877 return false;
8878 }
8879
8880 return sax->end_object();
8881 }
8882
8890 bool get_bson_cstr(string_t& result)
8891 {
8892 auto out = std::back_inserter(result);
8893 while (true)
8894 {
8895 get();
8896 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
8897 {
8898 return false;
8899 }
8900 if (current == 0x00)
8901 {
8902 return true;
8903 }
8904 *out++ = static_cast<typename string_t::value_type>(current);
8905 }
8906 }
8907
8919 template<typename NumberType>
8920 bool get_bson_string(const NumberType len, string_t& result)
8921 {
8922 if (JSON_HEDLEY_UNLIKELY(len < 1))
8923 {
8924 auto last_token = get_token_string();
8925 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
8926 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
8927 }
8928
8929 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
8930 }
8931
8941 template<typename NumberType>
8942 bool get_bson_binary(const NumberType len, binary_t& result)
8943 {
8944 if (JSON_HEDLEY_UNLIKELY(len < 0))
8945 {
8946 auto last_token = get_token_string();
8947 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
8948 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
8949 }
8950
8951 // All BSON binary values have a subtype
8952 std::uint8_t subtype{};
8953 get_number<std::uint8_t>(input_format_t::bson, subtype);
8954 result.set_subtype(subtype);
8955
8956 return get_binary(input_format_t::bson, len, result);
8957 }
8958
8969 bool parse_bson_element_internal(const char_int_type element_type,
8970 const std::size_t element_type_parse_position)
8971 {
8972 switch (element_type)
8973 {
8974 case 0x01: // double
8975 {
8976 double number{};
8977 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
8978 }
8979
8980 case 0x02: // string
8981 {
8982 std::int32_t len{};
8983 string_t value;
8984 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
8985 }
8986
8987 case 0x03: // object
8988 {
8989 return parse_bson_internal();
8990 }
8991
8992 case 0x04: // array
8993 {
8994 return parse_bson_array();
8995 }
8996
8997 case 0x05: // binary
8998 {
8999 std::int32_t len{};
9000 binary_t value;
9001 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
9002 }
9003
9004 case 0x08: // boolean
9005 {
9006 return sax->boolean(get() != 0);
9007 }
9008
9009 case 0x0A: // null
9010 {
9011 return sax->null();
9012 }
9013
9014 case 0x10: // int32
9015 {
9016 std::int32_t value{};
9017 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9018 }
9019
9020 case 0x12: // int64
9021 {
9022 std::int64_t value{};
9023 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9024 }
9025
9026 default: // anything else not supported (yet)
9027 {
9028 std::array<char, 3> cr{{}};
9029 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
9030 std::string cr_str{cr.data()};
9031 return sax->parse_error(element_type_parse_position, cr_str,
9032 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
9033 }
9034 }
9035 }
9036
9049 bool parse_bson_element_list(const bool is_array)
9050 {
9051 string_t key;
9052
9053 while (auto element_type = get())
9054 {
9055 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
9056 {
9057 return false;
9058 }
9059
9060 const std::size_t element_type_parse_position = chars_read;
9061 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
9062 {
9063 return false;
9064 }
9065
9066 if (!is_array && !sax->key(key))
9067 {
9068 return false;
9069 }
9070
9071 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
9072 {
9073 return false;
9074 }
9075
9076 // get_bson_cstr only appends
9077 key.clear();
9078 }
9079
9080 return true;
9081 }
9082
9087 bool parse_bson_array()
9088 {
9089 std::int32_t document_size{};
9090 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9091
9092 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
9093 {
9094 return false;
9095 }
9096
9097 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
9098 {
9099 return false;
9100 }
9101
9102 return sax->end_array();
9103 }
9104
9106 // CBOR //
9108
9117 bool parse_cbor_internal(const bool get_char,
9118 const cbor_tag_handler_t tag_handler)
9119 {
9120 switch (get_char ? get() : current)
9121 {
9122 // EOF
9123 case std::char_traits<char_type>::eof():
9124 return unexpect_eof(input_format_t::cbor, "value");
9125
9126 // Integer 0x00..0x17 (0..23)
9127 case 0x00:
9128 case 0x01:
9129 case 0x02:
9130 case 0x03:
9131 case 0x04:
9132 case 0x05:
9133 case 0x06:
9134 case 0x07:
9135 case 0x08:
9136 case 0x09:
9137 case 0x0A:
9138 case 0x0B:
9139 case 0x0C:
9140 case 0x0D:
9141 case 0x0E:
9142 case 0x0F:
9143 case 0x10:
9144 case 0x11:
9145 case 0x12:
9146 case 0x13:
9147 case 0x14:
9148 case 0x15:
9149 case 0x16:
9150 case 0x17:
9151 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9152
9153 case 0x18: // Unsigned integer (one-byte uint8_t follows)
9154 {
9155 std::uint8_t number{};
9156 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9157 }
9158
9159 case 0x19: // Unsigned integer (two-byte uint16_t follows)
9160 {
9161 std::uint16_t number{};
9162 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9163 }
9164
9165 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
9166 {
9167 std::uint32_t number{};
9168 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9169 }
9170
9171 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
9172 {
9173 std::uint64_t number{};
9174 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9175 }
9176
9177 // Negative integer -1-0x00..-1-0x17 (-1..-24)
9178 case 0x20:
9179 case 0x21:
9180 case 0x22:
9181 case 0x23:
9182 case 0x24:
9183 case 0x25:
9184 case 0x26:
9185 case 0x27:
9186 case 0x28:
9187 case 0x29:
9188 case 0x2A:
9189 case 0x2B:
9190 case 0x2C:
9191 case 0x2D:
9192 case 0x2E:
9193 case 0x2F:
9194 case 0x30:
9195 case 0x31:
9196 case 0x32:
9197 case 0x33:
9198 case 0x34:
9199 case 0x35:
9200 case 0x36:
9201 case 0x37:
9202 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
9203
9204 case 0x38: // Negative integer (one-byte uint8_t follows)
9205 {
9206 std::uint8_t number{};
9207 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9208 }
9209
9210 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
9211 {
9212 std::uint16_t number{};
9213 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9214 }
9215
9216 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
9217 {
9218 std::uint32_t number{};
9219 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9220 }
9221
9222 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
9223 {
9224 std::uint64_t number{};
9225 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
9226 - static_cast<number_integer_t>(number));
9227 }
9228
9229 // Binary data (0x00..0x17 bytes follow)
9230 case 0x40:
9231 case 0x41:
9232 case 0x42:
9233 case 0x43:
9234 case 0x44:
9235 case 0x45:
9236 case 0x46:
9237 case 0x47:
9238 case 0x48:
9239 case 0x49:
9240 case 0x4A:
9241 case 0x4B:
9242 case 0x4C:
9243 case 0x4D:
9244 case 0x4E:
9245 case 0x4F:
9246 case 0x50:
9247 case 0x51:
9248 case 0x52:
9249 case 0x53:
9250 case 0x54:
9251 case 0x55:
9252 case 0x56:
9253 case 0x57:
9254 case 0x58: // Binary data (one-byte uint8_t for n follows)
9255 case 0x59: // Binary data (two-byte uint16_t for n follow)
9256 case 0x5A: // Binary data (four-byte uint32_t for n follow)
9257 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9258 case 0x5F: // Binary data (indefinite length)
9259 {
9260 binary_t b;
9261 return get_cbor_binary(b) && sax->binary(b);
9262 }
9263
9264 // UTF-8 string (0x00..0x17 bytes follow)
9265 case 0x60:
9266 case 0x61:
9267 case 0x62:
9268 case 0x63:
9269 case 0x64:
9270 case 0x65:
9271 case 0x66:
9272 case 0x67:
9273 case 0x68:
9274 case 0x69:
9275 case 0x6A:
9276 case 0x6B:
9277 case 0x6C:
9278 case 0x6D:
9279 case 0x6E:
9280 case 0x6F:
9281 case 0x70:
9282 case 0x71:
9283 case 0x72:
9284 case 0x73:
9285 case 0x74:
9286 case 0x75:
9287 case 0x76:
9288 case 0x77:
9289 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9290 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9291 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9292 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9293 case 0x7F: // UTF-8 string (indefinite length)
9294 {
9295 string_t s;
9296 return get_cbor_string(s) && sax->string(s);
9297 }
9298
9299 // array (0x00..0x17 data items follow)
9300 case 0x80:
9301 case 0x81:
9302 case 0x82:
9303 case 0x83:
9304 case 0x84:
9305 case 0x85:
9306 case 0x86:
9307 case 0x87:
9308 case 0x88:
9309 case 0x89:
9310 case 0x8A:
9311 case 0x8B:
9312 case 0x8C:
9313 case 0x8D:
9314 case 0x8E:
9315 case 0x8F:
9316 case 0x90:
9317 case 0x91:
9318 case 0x92:
9319 case 0x93:
9320 case 0x94:
9321 case 0x95:
9322 case 0x96:
9323 case 0x97:
9324 return get_cbor_array(
9325 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9326
9327 case 0x98: // array (one-byte uint8_t for n follows)
9328 {
9329 std::uint8_t len{};
9330 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9331 }
9332
9333 case 0x99: // array (two-byte uint16_t for n follow)
9334 {
9335 std::uint16_t len{};
9336 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9337 }
9338
9339 case 0x9A: // array (four-byte uint32_t for n follow)
9340 {
9341 std::uint32_t len{};
9342 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9343 }
9344
9345 case 0x9B: // array (eight-byte uint64_t for n follow)
9346 {
9347 std::uint64_t len{};
9348 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9349 }
9350
9351 case 0x9F: // array (indefinite length)
9352 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
9353
9354 // map (0x00..0x17 pairs of data items follow)
9355 case 0xA0:
9356 case 0xA1:
9357 case 0xA2:
9358 case 0xA3:
9359 case 0xA4:
9360 case 0xA5:
9361 case 0xA6:
9362 case 0xA7:
9363 case 0xA8:
9364 case 0xA9:
9365 case 0xAA:
9366 case 0xAB:
9367 case 0xAC:
9368 case 0xAD:
9369 case 0xAE:
9370 case 0xAF:
9371 case 0xB0:
9372 case 0xB1:
9373 case 0xB2:
9374 case 0xB3:
9375 case 0xB4:
9376 case 0xB5:
9377 case 0xB6:
9378 case 0xB7:
9379 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9380
9381 case 0xB8: // map (one-byte uint8_t for n follows)
9382 {
9383 std::uint8_t len{};
9384 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9385 }
9386
9387 case 0xB9: // map (two-byte uint16_t for n follow)
9388 {
9389 std::uint16_t len{};
9390 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9391 }
9392
9393 case 0xBA: // map (four-byte uint32_t for n follow)
9394 {
9395 std::uint32_t len{};
9396 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9397 }
9398
9399 case 0xBB: // map (eight-byte uint64_t for n follow)
9400 {
9401 std::uint64_t len{};
9402 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9403 }
9404
9405 case 0xBF: // map (indefinite length)
9406 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
9407
9408 case 0xC6: // tagged item
9409 case 0xC7:
9410 case 0xC8:
9411 case 0xC9:
9412 case 0xCA:
9413 case 0xCB:
9414 case 0xCC:
9415 case 0xCD:
9416 case 0xCE:
9417 case 0xCF:
9418 case 0xD0:
9419 case 0xD1:
9420 case 0xD2:
9421 case 0xD3:
9422 case 0xD4:
9423 case 0xD8: // tagged item (1 bytes follow)
9424 case 0xD9: // tagged item (2 bytes follow)
9425 case 0xDA: // tagged item (4 bytes follow)
9426 case 0xDB: // tagged item (8 bytes follow)
9427 {
9428 switch (tag_handler)
9429 {
9431 {
9432 auto last_token = get_token_string();
9433 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9434 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
9435 }
9436
9438 {
9439 // ignore binary subtype
9440 switch (current)
9441 {
9442 case 0xD8:
9443 {
9444 std::uint8_t subtype_to_ignore{};
9445 get_number(input_format_t::cbor, subtype_to_ignore);
9446 break;
9447 }
9448 case 0xD9:
9449 {
9450 std::uint16_t subtype_to_ignore{};
9451 get_number(input_format_t::cbor, subtype_to_ignore);
9452 break;
9453 }
9454 case 0xDA:
9455 {
9456 std::uint32_t subtype_to_ignore{};
9457 get_number(input_format_t::cbor, subtype_to_ignore);
9458 break;
9459 }
9460 case 0xDB:
9461 {
9462 std::uint64_t subtype_to_ignore{};
9463 get_number(input_format_t::cbor, subtype_to_ignore);
9464 break;
9465 }
9466 default:
9467 break;
9468 }
9469 return parse_cbor_internal(true, tag_handler);
9470 }
9471
9473 {
9474 binary_t b;
9475 // use binary subtype and store in binary container
9476 switch (current)
9477 {
9478 case 0xD8:
9479 {
9480 std::uint8_t subtype{};
9481 get_number(input_format_t::cbor, subtype);
9482 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9483 break;
9484 }
9485 case 0xD9:
9486 {
9487 std::uint16_t subtype{};
9488 get_number(input_format_t::cbor, subtype);
9489 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9490 break;
9491 }
9492 case 0xDA:
9493 {
9494 std::uint32_t subtype{};
9495 get_number(input_format_t::cbor, subtype);
9496 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9497 break;
9498 }
9499 case 0xDB:
9500 {
9501 std::uint64_t subtype{};
9502 get_number(input_format_t::cbor, subtype);
9503 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9504 break;
9505 }
9506 default:
9507 return parse_cbor_internal(true, tag_handler);
9508 }
9509 get();
9510 return get_cbor_binary(b) && sax->binary(b);
9511 }
9512
9513 default: // LCOV_EXCL_LINE
9514 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9515 return false; // LCOV_EXCL_LINE
9516 }
9517 }
9518
9519 case 0xF4: // false
9520 return sax->boolean(false);
9521
9522 case 0xF5: // true
9523 return sax->boolean(true);
9524
9525 case 0xF6: // null
9526 return sax->null();
9527
9528 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
9529 {
9530 const auto byte1_raw = get();
9531 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9532 {
9533 return false;
9534 }
9535 const auto byte2_raw = get();
9536 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9537 {
9538 return false;
9539 }
9540
9541 const auto byte1 = static_cast<unsigned char>(byte1_raw);
9542 const auto byte2 = static_cast<unsigned char>(byte2_raw);
9543
9544 // code from RFC 7049, Appendix D, Figure 3:
9545 // As half-precision floating-point numbers were only added
9546 // to IEEE 754 in 2008, today's programming platforms often
9547 // still only have limited support for them. It is very
9548 // easy to include at least decoding support for them even
9549 // without such support. An example of a small decoder for
9550 // half-precision floating-point numbers in the C language
9551 // is shown in Fig. 3.
9552 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
9553 const double val = [&half]
9554 {
9555 const int exp = (half >> 10u) & 0x1Fu;
9556 const unsigned int mant = half & 0x3FFu;
9557 JSON_ASSERT(0 <= exp&& exp <= 32);
9558 JSON_ASSERT(mant <= 1024);
9559 switch (exp)
9560 {
9561 case 0:
9562 return std::ldexp(mant, -24);
9563 case 31:
9564 return (mant == 0)
9565 ? std::numeric_limits<double>::infinity()
9566 : std::numeric_limits<double>::quiet_NaN();
9567 default:
9568 return std::ldexp(mant + 1024, exp - 25);
9569 }
9570 }();
9571 return sax->number_float((half & 0x8000u) != 0
9572 ? static_cast<number_float_t>(-val)
9573 : static_cast<number_float_t>(val), "");
9574 }
9575
9576 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
9577 {
9578 float number{};
9579 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9580 }
9581
9582 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
9583 {
9584 double number{};
9585 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9586 }
9587
9588 default: // anything else (0xFF is handled inside the other types)
9589 {
9590 auto last_token = get_token_string();
9591 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9592 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
9593 }
9594 }
9595 }
9596
9608 bool get_cbor_string(string_t& result)
9609 {
9610 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
9611 {
9612 return false;
9613 }
9614
9615 switch (current)
9616 {
9617 // UTF-8 string (0x00..0x17 bytes follow)
9618 case 0x60:
9619 case 0x61:
9620 case 0x62:
9621 case 0x63:
9622 case 0x64:
9623 case 0x65:
9624 case 0x66:
9625 case 0x67:
9626 case 0x68:
9627 case 0x69:
9628 case 0x6A:
9629 case 0x6B:
9630 case 0x6C:
9631 case 0x6D:
9632 case 0x6E:
9633 case 0x6F:
9634 case 0x70:
9635 case 0x71:
9636 case 0x72:
9637 case 0x73:
9638 case 0x74:
9639 case 0x75:
9640 case 0x76:
9641 case 0x77:
9642 {
9643 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
9644 }
9645
9646 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9647 {
9648 std::uint8_t len{};
9649 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9650 }
9651
9652 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9653 {
9654 std::uint16_t len{};
9655 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9656 }
9657
9658 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9659 {
9660 std::uint32_t len{};
9661 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9662 }
9663
9664 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9665 {
9666 std::uint64_t len{};
9667 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
9668 }
9669
9670 case 0x7F: // UTF-8 string (indefinite length)
9671 {
9672 while (get() != 0xFF)
9673 {
9674 string_t chunk;
9675 if (!get_cbor_string(chunk))
9676 {
9677 return false;
9678 }
9679 result.append(chunk);
9680 }
9681 return true;
9682 }
9683
9684 default:
9685 {
9686 auto last_token = get_token_string();
9687 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
9688 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
9689 }
9690 }
9691 }
9692
9704 bool get_cbor_binary(binary_t& result)
9705 {
9706 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
9707 {
9708 return false;
9709 }
9710
9711 switch (current)
9712 {
9713 // Binary data (0x00..0x17 bytes follow)
9714 case 0x40:
9715 case 0x41:
9716 case 0x42:
9717 case 0x43:
9718 case 0x44:
9719 case 0x45:
9720 case 0x46:
9721 case 0x47:
9722 case 0x48:
9723 case 0x49:
9724 case 0x4A:
9725 case 0x4B:
9726 case 0x4C:
9727 case 0x4D:
9728 case 0x4E:
9729 case 0x4F:
9730 case 0x50:
9731 case 0x51:
9732 case 0x52:
9733 case 0x53:
9734 case 0x54:
9735 case 0x55:
9736 case 0x56:
9737 case 0x57:
9738 {
9739 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
9740 }
9741
9742 case 0x58: // Binary data (one-byte uint8_t for n follows)
9743 {
9744 std::uint8_t len{};
9745 return get_number(input_format_t::cbor, len) &&
9746 get_binary(input_format_t::cbor, len, result);
9747 }
9748
9749 case 0x59: // Binary data (two-byte uint16_t for n follow)
9750 {
9751 std::uint16_t len{};
9752 return get_number(input_format_t::cbor, len) &&
9753 get_binary(input_format_t::cbor, len, result);
9754 }
9755
9756 case 0x5A: // Binary data (four-byte uint32_t for n follow)
9757 {
9758 std::uint32_t len{};
9759 return get_number(input_format_t::cbor, len) &&
9760 get_binary(input_format_t::cbor, len, result);
9761 }
9762
9763 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9764 {
9765 std::uint64_t len{};
9766 return get_number(input_format_t::cbor, len) &&
9767 get_binary(input_format_t::cbor, len, result);
9768 }
9769
9770 case 0x5F: // Binary data (indefinite length)
9771 {
9772 while (get() != 0xFF)
9773 {
9774 binary_t chunk;
9775 if (!get_cbor_binary(chunk))
9776 {
9777 return false;
9778 }
9779 result.insert(result.end(), chunk.begin(), chunk.end());
9780 }
9781 return true;
9782 }
9783
9784 default:
9785 {
9786 auto last_token = get_token_string();
9787 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
9788 exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr));
9789 }
9790 }
9791 }
9792
9799 bool get_cbor_array(const std::size_t len,
9800 const cbor_tag_handler_t tag_handler)
9801 {
9802 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
9803 {
9804 return false;
9805 }
9806
9807 if (len != static_cast<std::size_t>(-1))
9808 {
9809 for (std::size_t i = 0; i < len; ++i)
9810 {
9811 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
9812 {
9813 return false;
9814 }
9815 }
9816 }
9817 else
9818 {
9819 while (get() != 0xFF)
9820 {
9821 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
9822 {
9823 return false;
9824 }
9825 }
9826 }
9827
9828 return sax->end_array();
9829 }
9830
9837 bool get_cbor_object(const std::size_t len,
9838 const cbor_tag_handler_t tag_handler)
9839 {
9840 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
9841 {
9842 return false;
9843 }
9844
9845 if (len != 0)
9846 {
9847 string_t key;
9848 if (len != static_cast<std::size_t>(-1))
9849 {
9850 for (std::size_t i = 0; i < len; ++i)
9851 {
9852 get();
9853 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
9854 {
9855 return false;
9856 }
9857
9858 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
9859 {
9860 return false;
9861 }
9862 key.clear();
9863 }
9864 }
9865 else
9866 {
9867 while (get() != 0xFF)
9868 {
9869 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
9870 {
9871 return false;
9872 }
9873
9874 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
9875 {
9876 return false;
9877 }
9878 key.clear();
9879 }
9880 }
9881 }
9882
9883 return sax->end_object();
9884 }
9885
9887 // MsgPack //
9889
9893 bool parse_msgpack_internal()
9894 {
9895 switch (get())
9896 {
9897 // EOF
9898 case std::char_traits<char_type>::eof():
9899 return unexpect_eof(input_format_t::msgpack, "value");
9900
9901 // positive fixint
9902 case 0x00:
9903 case 0x01:
9904 case 0x02:
9905 case 0x03:
9906 case 0x04:
9907 case 0x05:
9908 case 0x06:
9909 case 0x07:
9910 case 0x08:
9911 case 0x09:
9912 case 0x0A:
9913 case 0x0B:
9914 case 0x0C:
9915 case 0x0D:
9916 case 0x0E:
9917 case 0x0F:
9918 case 0x10:
9919 case 0x11:
9920 case 0x12:
9921 case 0x13:
9922 case 0x14:
9923 case 0x15:
9924 case 0x16:
9925 case 0x17:
9926 case 0x18:
9927 case 0x19:
9928 case 0x1A:
9929 case 0x1B:
9930 case 0x1C:
9931 case 0x1D:
9932 case 0x1E:
9933 case 0x1F:
9934 case 0x20:
9935 case 0x21:
9936 case 0x22:
9937 case 0x23:
9938 case 0x24:
9939 case 0x25:
9940 case 0x26:
9941 case 0x27:
9942 case 0x28:
9943 case 0x29:
9944 case 0x2A:
9945 case 0x2B:
9946 case 0x2C:
9947 case 0x2D:
9948 case 0x2E:
9949 case 0x2F:
9950 case 0x30:
9951 case 0x31:
9952 case 0x32:
9953 case 0x33:
9954 case 0x34:
9955 case 0x35:
9956 case 0x36:
9957 case 0x37:
9958 case 0x38:
9959 case 0x39:
9960 case 0x3A:
9961 case 0x3B:
9962 case 0x3C:
9963 case 0x3D:
9964 case 0x3E:
9965 case 0x3F:
9966 case 0x40:
9967 case 0x41:
9968 case 0x42:
9969 case 0x43:
9970 case 0x44:
9971 case 0x45:
9972 case 0x46:
9973 case 0x47:
9974 case 0x48:
9975 case 0x49:
9976 case 0x4A:
9977 case 0x4B:
9978 case 0x4C:
9979 case 0x4D:
9980 case 0x4E:
9981 case 0x4F:
9982 case 0x50:
9983 case 0x51:
9984 case 0x52:
9985 case 0x53:
9986 case 0x54:
9987 case 0x55:
9988 case 0x56:
9989 case 0x57:
9990 case 0x58:
9991 case 0x59:
9992 case 0x5A:
9993 case 0x5B:
9994 case 0x5C:
9995 case 0x5D:
9996 case 0x5E:
9997 case 0x5F:
9998 case 0x60:
9999 case 0x61:
10000 case 0x62:
10001 case 0x63:
10002 case 0x64:
10003 case 0x65:
10004 case 0x66:
10005 case 0x67:
10006 case 0x68:
10007 case 0x69:
10008 case 0x6A:
10009 case 0x6B:
10010 case 0x6C:
10011 case 0x6D:
10012 case 0x6E:
10013 case 0x6F:
10014 case 0x70:
10015 case 0x71:
10016 case 0x72:
10017 case 0x73:
10018 case 0x74:
10019 case 0x75:
10020 case 0x76:
10021 case 0x77:
10022 case 0x78:
10023 case 0x79:
10024 case 0x7A:
10025 case 0x7B:
10026 case 0x7C:
10027 case 0x7D:
10028 case 0x7E:
10029 case 0x7F:
10030 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10031
10032 // fixmap
10033 case 0x80:
10034 case 0x81:
10035 case 0x82:
10036 case 0x83:
10037 case 0x84:
10038 case 0x85:
10039 case 0x86:
10040 case 0x87:
10041 case 0x88:
10042 case 0x89:
10043 case 0x8A:
10044 case 0x8B:
10045 case 0x8C:
10046 case 0x8D:
10047 case 0x8E:
10048 case 0x8F:
10049 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10050
10051 // fixarray
10052 case 0x90:
10053 case 0x91:
10054 case 0x92:
10055 case 0x93:
10056 case 0x94:
10057 case 0x95:
10058 case 0x96:
10059 case 0x97:
10060 case 0x98:
10061 case 0x99:
10062 case 0x9A:
10063 case 0x9B:
10064 case 0x9C:
10065 case 0x9D:
10066 case 0x9E:
10067 case 0x9F:
10068 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10069
10070 // fixstr
10071 case 0xA0:
10072 case 0xA1:
10073 case 0xA2:
10074 case 0xA3:
10075 case 0xA4:
10076 case 0xA5:
10077 case 0xA6:
10078 case 0xA7:
10079 case 0xA8:
10080 case 0xA9:
10081 case 0xAA:
10082 case 0xAB:
10083 case 0xAC:
10084 case 0xAD:
10085 case 0xAE:
10086 case 0xAF:
10087 case 0xB0:
10088 case 0xB1:
10089 case 0xB2:
10090 case 0xB3:
10091 case 0xB4:
10092 case 0xB5:
10093 case 0xB6:
10094 case 0xB7:
10095 case 0xB8:
10096 case 0xB9:
10097 case 0xBA:
10098 case 0xBB:
10099 case 0xBC:
10100 case 0xBD:
10101 case 0xBE:
10102 case 0xBF:
10103 case 0xD9: // str 8
10104 case 0xDA: // str 16
10105 case 0xDB: // str 32
10106 {
10107 string_t s;
10108 return get_msgpack_string(s) && sax->string(s);
10109 }
10110
10111 case 0xC0: // nil
10112 return sax->null();
10113
10114 case 0xC2: // false
10115 return sax->boolean(false);
10116
10117 case 0xC3: // true
10118 return sax->boolean(true);
10119
10120 case 0xC4: // bin 8
10121 case 0xC5: // bin 16
10122 case 0xC6: // bin 32
10123 case 0xC7: // ext 8
10124 case 0xC8: // ext 16
10125 case 0xC9: // ext 32
10126 case 0xD4: // fixext 1
10127 case 0xD5: // fixext 2
10128 case 0xD6: // fixext 4
10129 case 0xD7: // fixext 8
10130 case 0xD8: // fixext 16
10131 {
10132 binary_t b;
10133 return get_msgpack_binary(b) && sax->binary(b);
10134 }
10135
10136 case 0xCA: // float 32
10137 {
10138 float number{};
10139 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10140 }
10141
10142 case 0xCB: // float 64
10143 {
10144 double number{};
10145 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10146 }
10147
10148 case 0xCC: // uint 8
10149 {
10150 std::uint8_t number{};
10151 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10152 }
10153
10154 case 0xCD: // uint 16
10155 {
10156 std::uint16_t number{};
10157 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10158 }
10159
10160 case 0xCE: // uint 32
10161 {
10162 std::uint32_t number{};
10163 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10164 }
10165
10166 case 0xCF: // uint 64
10167 {
10168 std::uint64_t number{};
10169 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10170 }
10171
10172 case 0xD0: // int 8
10173 {
10174 std::int8_t number{};
10175 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10176 }
10177
10178 case 0xD1: // int 16
10179 {
10180 std::int16_t number{};
10181 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10182 }
10183
10184 case 0xD2: // int 32
10185 {
10186 std::int32_t number{};
10187 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10188 }
10189
10190 case 0xD3: // int 64
10191 {
10192 std::int64_t number{};
10193 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10194 }
10195
10196 case 0xDC: // array 16
10197 {
10198 std::uint16_t len{};
10199 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
10200 }
10201
10202 case 0xDD: // array 32
10203 {
10204 std::uint32_t len{};
10205 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
10206 }
10207
10208 case 0xDE: // map 16
10209 {
10210 std::uint16_t len{};
10211 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
10212 }
10213
10214 case 0xDF: // map 32
10215 {
10216 std::uint32_t len{};
10217 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
10218 }
10219
10220 // negative fixint
10221 case 0xE0:
10222 case 0xE1:
10223 case 0xE2:
10224 case 0xE3:
10225 case 0xE4:
10226 case 0xE5:
10227 case 0xE6:
10228 case 0xE7:
10229 case 0xE8:
10230 case 0xE9:
10231 case 0xEA:
10232 case 0xEB:
10233 case 0xEC:
10234 case 0xED:
10235 case 0xEE:
10236 case 0xEF:
10237 case 0xF0:
10238 case 0xF1:
10239 case 0xF2:
10240 case 0xF3:
10241 case 0xF4:
10242 case 0xF5:
10243 case 0xF6:
10244 case 0xF7:
10245 case 0xF8:
10246 case 0xF9:
10247 case 0xFA:
10248 case 0xFB:
10249 case 0xFC:
10250 case 0xFD:
10251 case 0xFE:
10252 case 0xFF:
10253 return sax->number_integer(static_cast<std::int8_t>(current));
10254
10255 default: // anything else
10256 {
10257 auto last_token = get_token_string();
10258 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10259 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
10260 }
10261 }
10262 }
10263
10274 bool get_msgpack_string(string_t& result)
10275 {
10276 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
10277 {
10278 return false;
10279 }
10280
10281 switch (current)
10282 {
10283 // fixstr
10284 case 0xA0:
10285 case 0xA1:
10286 case 0xA2:
10287 case 0xA3:
10288 case 0xA4:
10289 case 0xA5:
10290 case 0xA6:
10291 case 0xA7:
10292 case 0xA8:
10293 case 0xA9:
10294 case 0xAA:
10295 case 0xAB:
10296 case 0xAC:
10297 case 0xAD:
10298 case 0xAE:
10299 case 0xAF:
10300 case 0xB0:
10301 case 0xB1:
10302 case 0xB2:
10303 case 0xB3:
10304 case 0xB4:
10305 case 0xB5:
10306 case 0xB6:
10307 case 0xB7:
10308 case 0xB8:
10309 case 0xB9:
10310 case 0xBA:
10311 case 0xBB:
10312 case 0xBC:
10313 case 0xBD:
10314 case 0xBE:
10315 case 0xBF:
10316 {
10317 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
10318 }
10319
10320 case 0xD9: // str 8
10321 {
10322 std::uint8_t len{};
10323 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10324 }
10325
10326 case 0xDA: // str 16
10327 {
10328 std::uint16_t len{};
10329 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10330 }
10331
10332 case 0xDB: // str 32
10333 {
10334 std::uint32_t len{};
10335 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10336 }
10337
10338 default:
10339 {
10340 auto last_token = get_token_string();
10341 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10342 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
10343 }
10344 }
10345 }
10346
10357 bool get_msgpack_binary(binary_t& result)
10358 {
10359 // helper function to set the subtype
10360 auto assign_and_return_true = [&result](std::int8_t subtype)
10361 {
10362 result.set_subtype(static_cast<std::uint8_t>(subtype));
10363 return true;
10364 };
10365
10366 switch (current)
10367 {
10368 case 0xC4: // bin 8
10369 {
10370 std::uint8_t len{};
10371 return get_number(input_format_t::msgpack, len) &&
10372 get_binary(input_format_t::msgpack, len, result);
10373 }
10374
10375 case 0xC5: // bin 16
10376 {
10377 std::uint16_t len{};
10378 return get_number(input_format_t::msgpack, len) &&
10379 get_binary(input_format_t::msgpack, len, result);
10380 }
10381
10382 case 0xC6: // bin 32
10383 {
10384 std::uint32_t len{};
10385 return get_number(input_format_t::msgpack, len) &&
10386 get_binary(input_format_t::msgpack, len, result);
10387 }
10388
10389 case 0xC7: // ext 8
10390 {
10391 std::uint8_t len{};
10392 std::int8_t subtype{};
10393 return get_number(input_format_t::msgpack, len) &&
10394 get_number(input_format_t::msgpack, subtype) &&
10395 get_binary(input_format_t::msgpack, len, result) &&
10396 assign_and_return_true(subtype);
10397 }
10398
10399 case 0xC8: // ext 16
10400 {
10401 std::uint16_t len{};
10402 std::int8_t subtype{};
10403 return get_number(input_format_t::msgpack, len) &&
10404 get_number(input_format_t::msgpack, subtype) &&
10405 get_binary(input_format_t::msgpack, len, result) &&
10406 assign_and_return_true(subtype);
10407 }
10408
10409 case 0xC9: // ext 32
10410 {
10411 std::uint32_t len{};
10412 std::int8_t subtype{};
10413 return get_number(input_format_t::msgpack, len) &&
10414 get_number(input_format_t::msgpack, subtype) &&
10415 get_binary(input_format_t::msgpack, len, result) &&
10416 assign_and_return_true(subtype);
10417 }
10418
10419 case 0xD4: // fixext 1
10420 {
10421 std::int8_t subtype{};
10422 return get_number(input_format_t::msgpack, subtype) &&
10423 get_binary(input_format_t::msgpack, 1, result) &&
10424 assign_and_return_true(subtype);
10425 }
10426
10427 case 0xD5: // fixext 2
10428 {
10429 std::int8_t subtype{};
10430 return get_number(input_format_t::msgpack, subtype) &&
10431 get_binary(input_format_t::msgpack, 2, result) &&
10432 assign_and_return_true(subtype);
10433 }
10434
10435 case 0xD6: // fixext 4
10436 {
10437 std::int8_t subtype{};
10438 return get_number(input_format_t::msgpack, subtype) &&
10439 get_binary(input_format_t::msgpack, 4, result) &&
10440 assign_and_return_true(subtype);
10441 }
10442
10443 case 0xD7: // fixext 8
10444 {
10445 std::int8_t subtype{};
10446 return get_number(input_format_t::msgpack, subtype) &&
10447 get_binary(input_format_t::msgpack, 8, result) &&
10448 assign_and_return_true(subtype);
10449 }
10450
10451 case 0xD8: // fixext 16
10452 {
10453 std::int8_t subtype{};
10454 return get_number(input_format_t::msgpack, subtype) &&
10455 get_binary(input_format_t::msgpack, 16, result) &&
10456 assign_and_return_true(subtype);
10457 }
10458
10459 default: // LCOV_EXCL_LINE
10460 return false; // LCOV_EXCL_LINE
10461 }
10462 }
10463
10468 bool get_msgpack_array(const std::size_t len)
10469 {
10470 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10471 {
10472 return false;
10473 }
10474
10475 for (std::size_t i = 0; i < len; ++i)
10476 {
10477 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10478 {
10479 return false;
10480 }
10481 }
10482
10483 return sax->end_array();
10484 }
10485
10490 bool get_msgpack_object(const std::size_t len)
10491 {
10492 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10493 {
10494 return false;
10495 }
10496
10497 string_t key;
10498 for (std::size_t i = 0; i < len; ++i)
10499 {
10500 get();
10501 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
10502 {
10503 return false;
10504 }
10505
10506 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10507 {
10508 return false;
10509 }
10510 key.clear();
10511 }
10512
10513 return sax->end_object();
10514 }
10515
10517 // UBJSON //
10519
10527 bool parse_ubjson_internal(const bool get_char = true)
10528 {
10529 return get_ubjson_value(get_char ? get_ignore_noop() : current);
10530 }
10531
10546 bool get_ubjson_string(string_t& result, const bool get_char = true)
10547 {
10548 if (get_char)
10549 {
10550 get(); // TODO(niels): may we ignore N here?
10551 }
10552
10553 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
10554 {
10555 return false;
10556 }
10557
10558 switch (current)
10559 {
10560 case 'U':
10561 {
10562 std::uint8_t len{};
10563 return get_number(input_format, len) && get_string(input_format, len, result);
10564 }
10565
10566 case 'i':
10567 {
10568 std::int8_t len{};
10569 return get_number(input_format, len) && get_string(input_format, len, result);
10570 }
10571
10572 case 'I':
10573 {
10574 std::int16_t len{};
10575 return get_number(input_format, len) && get_string(input_format, len, result);
10576 }
10577
10578 case 'l':
10579 {
10580 std::int32_t len{};
10581 return get_number(input_format, len) && get_string(input_format, len, result);
10582 }
10583
10584 case 'L':
10585 {
10586 std::int64_t len{};
10587 return get_number(input_format, len) && get_string(input_format, len, result);
10588 }
10589
10590 case 'u':
10591 {
10592 if (input_format != input_format_t::bjdata)
10593 {
10594 break;
10595 }
10596 std::uint16_t len{};
10597 return get_number(input_format, len) && get_string(input_format, len, result);
10598 }
10599
10600 case 'm':
10601 {
10602 if (input_format != input_format_t::bjdata)
10603 {
10604 break;
10605 }
10606 std::uint32_t len{};
10607 return get_number(input_format, len) && get_string(input_format, len, result);
10608 }
10609
10610 case 'M':
10611 {
10612 if (input_format != input_format_t::bjdata)
10613 {
10614 break;
10615 }
10616 std::uint64_t len{};
10617 return get_number(input_format, len) && get_string(input_format, len, result);
10618 }
10619
10620 default:
10621 break;
10622 }
10623 auto last_token = get_token_string();
10624 std::string message;
10625
10626 if (input_format != input_format_t::bjdata)
10627 {
10628 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
10629 }
10630 else
10631 {
10632 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
10633 }
10634 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
10635 }
10636
10641 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
10642 {
10643 std::pair<std::size_t, char_int_type> size_and_type;
10644 size_t dimlen = 0;
10645 bool no_ndarray = true;
10646
10647 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
10648 {
10649 return false;
10650 }
10651
10652 if (size_and_type.first != string_t::npos)
10653 {
10654 if (size_and_type.second != 0)
10655 {
10656 if (size_and_type.second != 'N')
10657 {
10658 for (std::size_t i = 0; i < size_and_type.first; ++i)
10659 {
10660 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
10661 {
10662 return false;
10663 }
10664 dim.push_back(dimlen);
10665 }
10666 }
10667 }
10668 else
10669 {
10670 for (std::size_t i = 0; i < size_and_type.first; ++i)
10671 {
10672 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
10673 {
10674 return false;
10675 }
10676 dim.push_back(dimlen);
10677 }
10678 }
10679 }
10680 else
10681 {
10682 while (current != ']')
10683 {
10684 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
10685 {
10686 return false;
10687 }
10688 dim.push_back(dimlen);
10689 get_ignore_noop();
10690 }
10691 }
10692 return true;
10693 }
10694
10706 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
10707 {
10708 if (prefix == 0)
10709 {
10710 prefix = get_ignore_noop();
10711 }
10712
10713 switch (prefix)
10714 {
10715 case 'U':
10716 {
10717 std::uint8_t number{};
10718 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
10719 {
10720 return false;
10721 }
10722 result = static_cast<std::size_t>(number);
10723 return true;
10724 }
10725
10726 case 'i':
10727 {
10728 std::int8_t number{};
10729 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
10730 {
10731 return false;
10732 }
10733 if (number < 0)
10734 {
10735 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
10736 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
10737 }
10738 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
10739 return true;
10740 }
10741
10742 case 'I':
10743 {
10744 std::int16_t number{};
10745 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
10746 {
10747 return false;
10748 }
10749 if (number < 0)
10750 {
10751 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
10752 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
10753 }
10754 result = static_cast<std::size_t>(number);
10755 return true;
10756 }
10757
10758 case 'l':
10759 {
10760 std::int32_t number{};
10761 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
10762 {
10763 return false;
10764 }
10765 if (number < 0)
10766 {
10767 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
10768 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
10769 }
10770 result = static_cast<std::size_t>(number);
10771 return true;
10772 }
10773
10774 case 'L':
10775 {
10776 std::int64_t number{};
10777 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
10778 {
10779 return false;
10780 }
10781 if (number < 0)
10782 {
10783 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
10784 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
10785 }
10786 if (!value_in_range_of<std::size_t>(number))
10787 {
10788 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
10789 exception_message(input_format, "integer value overflow", "size"), nullptr));
10790 }
10791 result = static_cast<std::size_t>(number);
10792 return true;
10793 }
10794
10795 case 'u':
10796 {
10797 if (input_format != input_format_t::bjdata)
10798 {
10799 break;
10800 }
10801 std::uint16_t number{};
10802 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
10803 {
10804 return false;
10805 }
10806 result = static_cast<std::size_t>(number);
10807 return true;
10808 }
10809
10810 case 'm':
10811 {
10812 if (input_format != input_format_t::bjdata)
10813 {
10814 break;
10815 }
10816 std::uint32_t number{};
10817 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
10818 {
10819 return false;
10820 }
10821 result = conditional_static_cast<std::size_t>(number);
10822 return true;
10823 }
10824
10825 case 'M':
10826 {
10827 if (input_format != input_format_t::bjdata)
10828 {
10829 break;
10830 }
10831 std::uint64_t number{};
10832 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
10833 {
10834 return false;
10835 }
10836 if (!value_in_range_of<std::size_t>(number))
10837 {
10838 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
10839 exception_message(input_format, "integer value overflow", "size"), nullptr));
10840 }
10841 result = detail::conditional_static_cast<std::size_t>(number);
10842 return true;
10843 }
10844
10845 case '[':
10846 {
10847 if (input_format != input_format_t::bjdata)
10848 {
10849 break;
10850 }
10851 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
10852 {
10853 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr));
10854 }
10855 std::vector<size_t> dim;
10856 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
10857 {
10858 return false;
10859 }
10860 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
10861 {
10862 result = dim.at(dim.size() - 1);
10863 return true;
10864 }
10865 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
10866 {
10867 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
10868 {
10869 if ( i == 0 )
10870 {
10871 result = 0;
10872 return true;
10873 }
10874 }
10875
10876 string_t key = "_ArraySize_";
10877 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
10878 {
10879 return false;
10880 }
10881 result = 1;
10882 for (auto i : dim)
10883 {
10884 result *= i;
10885 if (result == 0 || result == string_t::npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be string_t::npos as it is used to initialize size in get_ubjson_size_type()
10886 {
10887 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr));
10888 }
10889 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
10890 {
10891 return false;
10892 }
10893 }
10894 is_ndarray = true;
10895 return sax->end_array();
10896 }
10897 result = 0;
10898 return true;
10899 }
10900
10901 default:
10902 break;
10903 }
10904 auto last_token = get_token_string();
10905 std::string message;
10906
10907 if (input_format != input_format_t::bjdata)
10908 {
10909 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
10910 }
10911 else
10912 {
10913 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
10914 }
10915 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
10916 }
10917
10929 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
10930 {
10931 result.first = string_t::npos; // size
10932 result.second = 0; // type
10933 bool is_ndarray = false;
10934
10935 get_ignore_noop();
10936
10937 if (current == '$')
10938 {
10939 std::vector<char_int_type> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
10940
10941 result.second = get(); // must not ignore 'N', because 'N' maybe the type
10942 if (JSON_HEDLEY_UNLIKELY( input_format == input_format_t::bjdata && std::find(bjdx.begin(), bjdx.end(), result.second) != bjdx.end() ))
10943 {
10944 auto last_token = get_token_string();
10945 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10946 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
10947 }
10948
10949 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
10950 {
10951 return false;
10952 }
10953
10954 get_ignore_noop();
10955 if (JSON_HEDLEY_UNLIKELY(current != '#'))
10956 {
10957 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
10958 {
10959 return false;
10960 }
10961 auto last_token = get_token_string();
10962 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10963 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
10964 }
10965
10966 bool is_error = get_ubjson_size_value(result.first, is_ndarray);
10967 if (input_format == input_format_t::bjdata && is_ndarray)
10968 {
10969 if (inside_ndarray)
10970 {
10971 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
10972 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
10973 }
10974 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
10975 }
10976 return is_error;
10977 }
10978
10979 if (current == '#')
10980 {
10981 bool is_error = get_ubjson_size_value(result.first, is_ndarray);
10982 if (input_format == input_format_t::bjdata && is_ndarray)
10983 {
10984 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
10985 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
10986 }
10987 return is_error;
10988 }
10989
10990 return true;
10991 }
10992
10997 bool get_ubjson_value(const char_int_type prefix)
10998 {
10999 switch (prefix)
11000 {
11001 case std::char_traits<char_type>::eof(): // EOF
11002 return unexpect_eof(input_format, "value");
11003
11004 case 'T': // true
11005 return sax->boolean(true);
11006 case 'F': // false
11007 return sax->boolean(false);
11008
11009 case 'Z': // null
11010 return sax->null();
11011
11012 case 'U':
11013 {
11014 std::uint8_t number{};
11015 return get_number(input_format, number) && sax->number_unsigned(number);
11016 }
11017
11018 case 'i':
11019 {
11020 std::int8_t number{};
11021 return get_number(input_format, number) && sax->number_integer(number);
11022 }
11023
11024 case 'I':
11025 {
11026 std::int16_t number{};
11027 return get_number(input_format, number) && sax->number_integer(number);
11028 }
11029
11030 case 'l':
11031 {
11032 std::int32_t number{};
11033 return get_number(input_format, number) && sax->number_integer(number);
11034 }
11035
11036 case 'L':
11037 {
11038 std::int64_t number{};
11039 return get_number(input_format, number) && sax->number_integer(number);
11040 }
11041
11042 case 'u':
11043 {
11044 if (input_format != input_format_t::bjdata)
11045 {
11046 break;
11047 }
11048 std::uint16_t number{};
11049 return get_number(input_format, number) && sax->number_unsigned(number);
11050 }
11051
11052 case 'm':
11053 {
11054 if (input_format != input_format_t::bjdata)
11055 {
11056 break;
11057 }
11058 std::uint32_t number{};
11059 return get_number(input_format, number) && sax->number_unsigned(number);
11060 }
11061
11062 case 'M':
11063 {
11064 if (input_format != input_format_t::bjdata)
11065 {
11066 break;
11067 }
11068 std::uint64_t number{};
11069 return get_number(input_format, number) && sax->number_unsigned(number);
11070 }
11071
11072 case 'h':
11073 {
11074 if (input_format != input_format_t::bjdata)
11075 {
11076 break;
11077 }
11078 const auto byte1_raw = get();
11079 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11080 {
11081 return false;
11082 }
11083 const auto byte2_raw = get();
11084 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11085 {
11086 return false;
11087 }
11088
11089 const auto byte1 = static_cast<unsigned char>(byte1_raw);
11090 const auto byte2 = static_cast<unsigned char>(byte2_raw);
11091
11092 // code from RFC 7049, Appendix D, Figure 3:
11093 // As half-precision floating-point numbers were only added
11094 // to IEEE 754 in 2008, today's programming platforms often
11095 // still only have limited support for them. It is very
11096 // easy to include at least decoding support for them even
11097 // without such support. An example of a small decoder for
11098 // half-precision floating-point numbers in the C language
11099 // is shown in Fig. 3.
11100 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
11101 const double val = [&half]
11102 {
11103 const int exp = (half >> 10u) & 0x1Fu;
11104 const unsigned int mant = half & 0x3FFu;
11105 JSON_ASSERT(0 <= exp&& exp <= 32);
11106 JSON_ASSERT(mant <= 1024);
11107 switch (exp)
11108 {
11109 case 0:
11110 return std::ldexp(mant, -24);
11111 case 31:
11112 return (mant == 0)
11113 ? std::numeric_limits<double>::infinity()
11114 : std::numeric_limits<double>::quiet_NaN();
11115 default:
11116 return std::ldexp(mant + 1024, exp - 25);
11117 }
11118 }();
11119 return sax->number_float((half & 0x8000u) != 0
11120 ? static_cast<number_float_t>(-val)
11121 : static_cast<number_float_t>(val), "");
11122 }
11123
11124 case 'd':
11125 {
11126 float number{};
11127 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11128 }
11129
11130 case 'D':
11131 {
11132 double number{};
11133 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11134 }
11135
11136 case 'H':
11137 {
11138 return get_ubjson_high_precision_number();
11139 }
11140
11141 case 'C': // char
11142 {
11143 get();
11144 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
11145 {
11146 return false;
11147 }
11148 if (JSON_HEDLEY_UNLIKELY(current > 127))
11149 {
11150 auto last_token = get_token_string();
11151 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11152 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
11153 }
11154 string_t s(1, static_cast<typename string_t::value_type>(current));
11155 return sax->string(s);
11156 }
11157
11158 case 'S': // string
11159 {
11160 string_t s;
11161 return get_ubjson_string(s) && sax->string(s);
11162 }
11163
11164 case '[': // array
11165 return get_ubjson_array();
11166
11167 case '{': // object
11168 return get_ubjson_object();
11169
11170 default: // anything else
11171 break;
11172 }
11173 auto last_token = get_token_string();
11174 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr));
11175 }
11176
11180 bool get_ubjson_array()
11181 {
11182 std::pair<std::size_t, char_int_type> size_and_type;
11183 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11184 {
11185 return false;
11186 }
11187
11188 // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata):
11189 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
11190
11191 if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && (size_and_type.second & (1 << 8)) != 0)
11192 {
11193 std::map<char_int_type, string_t> bjdtype = {{'U', "uint8"}, {'i', "int8"}, {'u', "uint16"}, {'I', "int16"},
11194 {'m', "uint32"}, {'l', "int32"}, {'M', "uint64"}, {'L', "int64"}, {'d', "single"}, {'D', "double"}, {'C', "char"}
11195 };
11196
11197 size_and_type.second &= ~(static_cast<char_int_type>(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker
11198
11199 string_t key = "_ArrayType_";
11200 if (JSON_HEDLEY_UNLIKELY(bjdtype.count(size_and_type.second) == 0))
11201 {
11202 auto last_token = get_token_string();
11203 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11204 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
11205 }
11206
11207 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(bjdtype[size_and_type.second]) ))
11208 {
11209 return false;
11210 }
11211
11212 if (size_and_type.second == 'C')
11213 {
11214 size_and_type.second = 'U';
11215 }
11216
11217 key = "_ArrayData_";
11218 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
11219 {
11220 return false;
11221 }
11222
11223 for (std::size_t i = 0; i < size_and_type.first; ++i)
11224 {
11225 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11226 {
11227 return false;
11228 }
11229 }
11230
11231 return (sax->end_array() && sax->end_object());
11232 }
11233
11234 if (size_and_type.first != string_t::npos)
11235 {
11236 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
11237 {
11238 return false;
11239 }
11240
11241 if (size_and_type.second != 0)
11242 {
11243 if (size_and_type.second != 'N')
11244 {
11245 for (std::size_t i = 0; i < size_and_type.first; ++i)
11246 {
11247 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11248 {
11249 return false;
11250 }
11251 }
11252 }
11253 }
11254 else
11255 {
11256 for (std::size_t i = 0; i < size_and_type.first; ++i)
11257 {
11258 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11259 {
11260 return false;
11261 }
11262 }
11263 }
11264 }
11265 else
11266 {
11267 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
11268 {
11269 return false;
11270 }
11271
11272 while (current != ']')
11273 {
11274 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
11275 {
11276 return false;
11277 }
11278 get_ignore_noop();
11279 }
11280 }
11281
11282 return sax->end_array();
11283 }
11284
11288 bool get_ubjson_object()
11289 {
11290 std::pair<std::size_t, char_int_type> size_and_type;
11291 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11292 {
11293 return false;
11294 }
11295
11296 // do not accept ND-array size in objects in BJData
11297 if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && (size_and_type.second & (1 << 8)) != 0)
11298 {
11299 auto last_token = get_token_string();
11300 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11301 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
11302 }
11303
11304 string_t key;
11305 if (size_and_type.first != string_t::npos)
11306 {
11307 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
11308 {
11309 return false;
11310 }
11311
11312 if (size_and_type.second != 0)
11313 {
11314 for (std::size_t i = 0; i < size_and_type.first; ++i)
11315 {
11316 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11317 {
11318 return false;
11319 }
11320 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11321 {
11322 return false;
11323 }
11324 key.clear();
11325 }
11326 }
11327 else
11328 {
11329 for (std::size_t i = 0; i < size_and_type.first; ++i)
11330 {
11331 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11332 {
11333 return false;
11334 }
11335 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11336 {
11337 return false;
11338 }
11339 key.clear();
11340 }
11341 }
11342 }
11343 else
11344 {
11345 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
11346 {
11347 return false;
11348 }
11349
11350 while (current != '}')
11351 {
11352 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
11353 {
11354 return false;
11355 }
11356 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11357 {
11358 return false;
11359 }
11360 get_ignore_noop();
11361 key.clear();
11362 }
11363 }
11364
11365 return sax->end_object();
11366 }
11367
11368 // Note, no reader for UBJSON binary types is implemented because they do
11369 // not exist
11370
11371 bool get_ubjson_high_precision_number()
11372 {
11373 // get size of following number string
11374 std::size_t size{};
11375 bool no_ndarray = true;
11376 auto res = get_ubjson_size_value(size, no_ndarray);
11377 if (JSON_HEDLEY_UNLIKELY(!res))
11378 {
11379 return res;
11380 }
11381
11382 // get number string
11383 std::vector<char> number_vector;
11384 for (std::size_t i = 0; i < size; ++i)
11385 {
11386 get();
11387 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11388 {
11389 return false;
11390 }
11391 number_vector.push_back(static_cast<char>(current));
11392 }
11393
11394 // parse number string
11395 using ia_type = decltype(detail::input_adapter(number_vector));
11396 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
11397 const auto result_number = number_lexer.scan();
11398 const auto number_string = number_lexer.get_token_string();
11399 const auto result_remainder = number_lexer.scan();
11400
11401 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
11402
11403 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
11404 {
11405 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11406 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11407 }
11408
11409 switch (result_number)
11410 {
11411 case token_type::value_integer:
11412 return sax->number_integer(number_lexer.get_number_integer());
11413 case token_type::value_unsigned:
11414 return sax->number_unsigned(number_lexer.get_number_unsigned());
11415 case token_type::value_float:
11416 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
11417 case token_type::uninitialized:
11418 case token_type::literal_true:
11419 case token_type::literal_false:
11420 case token_type::literal_null:
11421 case token_type::value_string:
11422 case token_type::begin_array:
11423 case token_type::begin_object:
11424 case token_type::end_array:
11425 case token_type::end_object:
11426 case token_type::name_separator:
11427 case token_type::value_separator:
11428 case token_type::parse_error:
11429 case token_type::end_of_input:
11430 case token_type::literal_or_value:
11431 default:
11432 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11433 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11434 }
11435 }
11436
11438 // Utility functions //
11440
11450 char_int_type get()
11451 {
11452 ++chars_read;
11453 return current = ia.get_character();
11454 }
11455
11459 char_int_type get_ignore_noop()
11460 {
11461 do
11462 {
11463 get();
11464 }
11465 while (current == 'N');
11466
11467 return current;
11468 }
11469
11470 /*
11471 @brief read a number from the input
11472
11473 @tparam NumberType the type of the number
11474 @param[in] format the current format (for diagnostics)
11475 @param[out] result number of type @a NumberType
11476
11477 @return whether conversion completed
11478
11479 @note This function needs to respect the system's endianness, because
11480 bytes in CBOR, MessagePack, and UBJSON are stored in network order
11481 (big endian) and therefore need reordering on little endian systems.
11482 On the other hand, BSON and BJData use little endian and should reorder
11483 on big endian systems.
11484 */
11485 template<typename NumberType, bool InputIsLittleEndian = false>
11486 bool get_number(const input_format_t format, NumberType& result)
11487 {
11488 // step 1: read input into array with system's byte order
11489 std::array<std::uint8_t, sizeof(NumberType)> vec{};
11490 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
11491 {
11492 get();
11493 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
11494 {
11495 return false;
11496 }
11497
11498 // reverse byte order prior to conversion if necessary
11499 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
11500 {
11501 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
11502 }
11503 else
11504 {
11505 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
11506 }
11507 }
11508
11509 // step 2: convert array into number of type T and return
11510 std::memcpy(&result, vec.data(), sizeof(NumberType));
11511 return true;
11512 }
11513
11528 template<typename NumberType>
11529 bool get_string(const input_format_t format,
11530 const NumberType len,
11531 string_t& result)
11532 {
11533 bool success = true;
11534 for (NumberType i = 0; i < len; i++)
11535 {
11536 get();
11537 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
11538 {
11539 success = false;
11540 break;
11541 }
11542 result.push_back(static_cast<typename string_t::value_type>(current));
11543 }
11544 return success;
11545 }
11546
11561 template<typename NumberType>
11562 bool get_binary(const input_format_t format,
11563 const NumberType len,
11564 binary_t& result)
11565 {
11566 bool success = true;
11567 for (NumberType i = 0; i < len; i++)
11568 {
11569 get();
11570 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
11571 {
11572 success = false;
11573 break;
11574 }
11575 result.push_back(static_cast<std::uint8_t>(current));
11576 }
11577 return success;
11578 }
11579
11586 bool unexpect_eof(const input_format_t format, const char* context) const
11587 {
11588 if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
11589 {
11590 return sax->parse_error(chars_read, "<end of file>",
11591 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
11592 }
11593 return true;
11594 }
11595
11599 std::string get_token_string() const
11600 {
11601 std::array<char, 3> cr{{}};
11602 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
11603 return std::string{cr.data()};
11604 }
11605
11612 std::string exception_message(const input_format_t format,
11613 const std::string& detail,
11614 const std::string& context) const
11615 {
11616 std::string error_msg = "syntax error while parsing ";
11617
11618 switch (format)
11619 {
11620 case input_format_t::cbor:
11621 error_msg += "CBOR";
11622 break;
11623
11624 case input_format_t::msgpack:
11625 error_msg += "MessagePack";
11626 break;
11627
11628 case input_format_t::ubjson:
11629 error_msg += "UBJSON";
11630 break;
11631
11632 case input_format_t::bson:
11633 error_msg += "BSON";
11634 break;
11635
11636 case input_format_t::bjdata:
11637 error_msg += "BJData";
11638 break;
11639
11640 case input_format_t::json: // LCOV_EXCL_LINE
11641 default: // LCOV_EXCL_LINE
11642 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
11643 }
11644
11645 return concat(error_msg, ' ', context, ": ", detail);
11646 }
11647
11648 private:
11650 InputAdapterType ia;
11651
11653 char_int_type current = std::char_traits<char_type>::eof();
11654
11656 std::size_t chars_read = 0;
11657
11659 const bool is_little_endian = little_endianness();
11660
11662 const input_format_t input_format = input_format_t::json;
11663
11665 json_sax_t* sax = nullptr;
11666};
11667} // namespace detail
11668} // namespace nlohmann
11669
11670// #include <nlohmann/detail/input/input_adapters.hpp>
11671
11672// #include <nlohmann/detail/input/lexer.hpp>
11673
11674// #include <nlohmann/detail/input/parser.hpp>
11675
11676
11677#include <cmath> // isfinite
11678#include <cstdint> // uint8_t
11679#include <functional> // function
11680#include <string> // string
11681#include <utility> // move
11682#include <vector> // vector
11683
11684// #include <nlohmann/detail/exceptions.hpp>
11685
11686// #include <nlohmann/detail/input/input_adapters.hpp>
11687
11688// #include <nlohmann/detail/input/json_sax.hpp>
11689
11690// #include <nlohmann/detail/input/lexer.hpp>
11691
11692// #include <nlohmann/detail/macro_scope.hpp>
11693
11694// #include <nlohmann/detail/meta/is_sax.hpp>
11695
11696// #include <nlohmann/detail/string_concat.hpp>
11697
11698// #include <nlohmann/detail/value_t.hpp>
11699
11700
11701namespace nlohmann
11702{
11703namespace detail
11704{
11706// parser //
11708
11709enum class parse_event_t : std::uint8_t
11710{
11712 object_start,
11714 object_end,
11716 array_start,
11718 array_end,
11720 key,
11722 value
11723};
11724
11725template<typename BasicJsonType>
11726using parser_callback_t =
11727 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
11728
11734template<typename BasicJsonType, typename InputAdapterType>
11735class parser
11736{
11737 using number_integer_t = typename BasicJsonType::number_integer_t;
11738 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
11739 using number_float_t = typename BasicJsonType::number_float_t;
11740 using string_t = typename BasicJsonType::string_t;
11741 using lexer_t = lexer<BasicJsonType, InputAdapterType>;
11742 using token_type = typename lexer_t::token_type;
11743
11744 public:
11746 explicit parser(InputAdapterType&& adapter,
11747 const parser_callback_t<BasicJsonType> cb = nullptr,
11748 const bool allow_exceptions_ = true,
11749 const bool skip_comments = false)
11750 : callback(cb)
11751 , m_lexer(std::move(adapter), skip_comments)
11752 , allow_exceptions(allow_exceptions_)
11753 {
11754 // read first token
11755 get_token();
11756 }
11757
11768 void parse(const bool strict, BasicJsonType& result)
11769 {
11770 if (callback)
11771 {
11772 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
11773 sax_parse_internal(&sdp);
11774
11775 // in strict mode, input must be completely read
11776 if (strict && (get_token() != token_type::end_of_input))
11777 {
11778 sdp.parse_error(m_lexer.get_position(),
11779 m_lexer.get_token_string(),
11780 parse_error::create(101, m_lexer.get_position(),
11781 exception_message(token_type::end_of_input, "value"), nullptr));
11782 }
11783
11784 // in case of an error, return discarded value
11785 if (sdp.is_errored())
11786 {
11787 result = value_t::discarded;
11788 return;
11789 }
11790
11791 // set top-level value to null if it was discarded by the callback
11792 // function
11793 if (result.is_discarded())
11794 {
11795 result = nullptr;
11796 }
11797 }
11798 else
11799 {
11800 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
11801 sax_parse_internal(&sdp);
11802
11803 // in strict mode, input must be completely read
11804 if (strict && (get_token() != token_type::end_of_input))
11805 {
11806 sdp.parse_error(m_lexer.get_position(),
11807 m_lexer.get_token_string(),
11808 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
11809 }
11810
11811 // in case of an error, return discarded value
11812 if (sdp.is_errored())
11813 {
11814 result = value_t::discarded;
11815 return;
11816 }
11817 }
11818
11819 result.assert_invariant();
11820 }
11821
11828 bool accept(const bool strict = true)
11829 {
11830 json_sax_acceptor<BasicJsonType> sax_acceptor;
11831 return sax_parse(&sax_acceptor, strict);
11832 }
11833
11834 template<typename SAX>
11836 bool sax_parse(SAX* sax, const bool strict = true)
11837 {
11838 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
11839 const bool result = sax_parse_internal(sax);
11840
11841 // strict mode: next byte must be EOF
11842 if (result && strict && (get_token() != token_type::end_of_input))
11843 {
11844 return sax->parse_error(m_lexer.get_position(),
11845 m_lexer.get_token_string(),
11846 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
11847 }
11848
11849 return result;
11850 }
11851
11852 private:
11853 template<typename SAX>
11855 bool sax_parse_internal(SAX* sax)
11856 {
11857 // stack to remember the hierarchy of structured values we are parsing
11858 // true = array; false = object
11859 std::vector<bool> states;
11860 // value to avoid a goto (see comment where set to true)
11861 bool skip_to_state_evaluation = false;
11862
11863 while (true)
11864 {
11865 if (!skip_to_state_evaluation)
11866 {
11867 // invariant: get_token() was called before each iteration
11868 switch (last_token)
11869 {
11870 case token_type::begin_object:
11871 {
11872 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
11873 {
11874 return false;
11875 }
11876
11877 // closing } -> we are done
11878 if (get_token() == token_type::end_object)
11879 {
11880 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
11881 {
11882 return false;
11883 }
11884 break;
11885 }
11886
11887 // parse key
11888 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
11889 {
11890 return sax->parse_error(m_lexer.get_position(),
11891 m_lexer.get_token_string(),
11892 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
11893 }
11894 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
11895 {
11896 return false;
11897 }
11898
11899 // parse separator (:)
11900 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
11901 {
11902 return sax->parse_error(m_lexer.get_position(),
11903 m_lexer.get_token_string(),
11904 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
11905 }
11906
11907 // remember we are now inside an object
11908 states.push_back(false);
11909
11910 // parse values
11911 get_token();
11912 continue;
11913 }
11914
11915 case token_type::begin_array:
11916 {
11917 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
11918 {
11919 return false;
11920 }
11921
11922 // closing ] -> we are done
11923 if (get_token() == token_type::end_array)
11924 {
11925 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
11926 {
11927 return false;
11928 }
11929 break;
11930 }
11931
11932 // remember we are now inside an array
11933 states.push_back(true);
11934
11935 // parse values (no need to call get_token)
11936 continue;
11937 }
11938
11939 case token_type::value_float:
11940 {
11941 const auto res = m_lexer.get_number_float();
11942
11943 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
11944 {
11945 return sax->parse_error(m_lexer.get_position(),
11946 m_lexer.get_token_string(),
11947 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
11948 }
11949
11950 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
11951 {
11952 return false;
11953 }
11954
11955 break;
11956 }
11957
11958 case token_type::literal_false:
11959 {
11960 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
11961 {
11962 return false;
11963 }
11964 break;
11965 }
11966
11967 case token_type::literal_null:
11968 {
11969 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
11970 {
11971 return false;
11972 }
11973 break;
11974 }
11975
11976 case token_type::literal_true:
11977 {
11978 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
11979 {
11980 return false;
11981 }
11982 break;
11983 }
11984
11985 case token_type::value_integer:
11986 {
11987 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
11988 {
11989 return false;
11990 }
11991 break;
11992 }
11993
11994 case token_type::value_string:
11995 {
11996 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
11997 {
11998 return false;
11999 }
12000 break;
12001 }
12002
12003 case token_type::value_unsigned:
12004 {
12005 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
12006 {
12007 return false;
12008 }
12009 break;
12010 }
12011
12012 case token_type::parse_error:
12013 {
12014 // using "uninitialized" to avoid "expected" message
12015 return sax->parse_error(m_lexer.get_position(),
12016 m_lexer.get_token_string(),
12017 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
12018 }
12019
12020 case token_type::uninitialized:
12021 case token_type::end_array:
12022 case token_type::end_object:
12023 case token_type::name_separator:
12024 case token_type::value_separator:
12025 case token_type::end_of_input:
12026 case token_type::literal_or_value:
12027 default: // the last token was unexpected
12028 {
12029 return sax->parse_error(m_lexer.get_position(),
12030 m_lexer.get_token_string(),
12031 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12032 }
12033 }
12034 }
12035 else
12036 {
12037 skip_to_state_evaluation = false;
12038 }
12039
12040 // we reached this line after we successfully parsed a value
12041 if (states.empty())
12042 {
12043 // empty stack: we reached the end of the hierarchy: done
12044 return true;
12045 }
12046
12047 if (states.back()) // array
12048 {
12049 // comma -> next value
12050 if (get_token() == token_type::value_separator)
12051 {
12052 // parse a new value
12053 get_token();
12054 continue;
12055 }
12056
12057 // closing ]
12058 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
12059 {
12060 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12061 {
12062 return false;
12063 }
12064
12065 // We are done with this array. Before we can parse a
12066 // new value, we need to evaluate the new state first.
12067 // By setting skip_to_state_evaluation to false, we
12068 // are effectively jumping to the beginning of this if.
12069 JSON_ASSERT(!states.empty());
12070 states.pop_back();
12071 skip_to_state_evaluation = true;
12072 continue;
12073 }
12074
12075 return sax->parse_error(m_lexer.get_position(),
12076 m_lexer.get_token_string(),
12077 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
12078 }
12079
12080 // states.back() is false -> object
12081
12082 // comma -> next value
12083 if (get_token() == token_type::value_separator)
12084 {
12085 // parse key
12086 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
12087 {
12088 return sax->parse_error(m_lexer.get_position(),
12089 m_lexer.get_token_string(),
12090 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12091 }
12092
12093 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12094 {
12095 return false;
12096 }
12097
12098 // parse separator (:)
12099 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12100 {
12101 return sax->parse_error(m_lexer.get_position(),
12102 m_lexer.get_token_string(),
12103 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12104 }
12105
12106 // parse values
12107 get_token();
12108 continue;
12109 }
12110
12111 // closing }
12112 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
12113 {
12114 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12115 {
12116 return false;
12117 }
12118
12119 // We are done with this object. Before we can parse a
12120 // new value, we need to evaluate the new state first.
12121 // By setting skip_to_state_evaluation to false, we
12122 // are effectively jumping to the beginning of this if.
12123 JSON_ASSERT(!states.empty());
12124 states.pop_back();
12125 skip_to_state_evaluation = true;
12126 continue;
12127 }
12128
12129 return sax->parse_error(m_lexer.get_position(),
12130 m_lexer.get_token_string(),
12131 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
12132 }
12133 }
12134
12136 token_type get_token()
12137 {
12138 return last_token = m_lexer.scan();
12139 }
12140
12141 std::string exception_message(const token_type expected, const std::string& context)
12142 {
12143 std::string error_msg = "syntax error ";
12144
12145 if (!context.empty())
12146 {
12147 error_msg += concat("while parsing ", context, ' ');
12148 }
12149
12150 error_msg += "- ";
12151
12152 if (last_token == token_type::parse_error)
12153 {
12154 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
12155 m_lexer.get_token_string(), '\'');
12156 }
12157 else
12158 {
12159 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
12160 }
12161
12162 if (expected != token_type::uninitialized)
12163 {
12164 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
12165 }
12166
12167 return error_msg;
12168 }
12169
12170 private:
12172 const parser_callback_t<BasicJsonType> callback = nullptr;
12174 token_type last_token = token_type::uninitialized;
12176 lexer_t m_lexer;
12178 const bool allow_exceptions = true;
12179};
12180
12181} // namespace detail
12182} // namespace nlohmann
12183
12184// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12185
12186
12187// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12188
12189
12190#include <cstddef> // ptrdiff_t
12191#include <limits> // numeric_limits
12192
12193// #include <nlohmann/detail/macro_scope.hpp>
12194
12195
12196namespace nlohmann
12197{
12198namespace detail
12199{
12200/*
12201@brief an iterator for primitive JSON types
12202
12203This class models an iterator for primitive JSON types (boolean, number,
12204string). It's only purpose is to allow the iterator/const_iterator classes
12205to "iterate" over primitive values. Internally, the iterator is modeled by
12206a `difference_type` variable. Value begin_value (`0`) models the begin,
12207end_value (`1`) models past the end.
12208*/
12209class primitive_iterator_t
12210{
12211 private:
12212 using difference_type = std::ptrdiff_t;
12213 static constexpr difference_type begin_value = 0;
12214 static constexpr difference_type end_value = begin_value + 1;
12215
12218 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
12219
12220 public:
12221 constexpr difference_type get_value() const noexcept
12222 {
12223 return m_it;
12224 }
12225
12227 void set_begin() noexcept
12228 {
12229 m_it = begin_value;
12230 }
12231
12233 void set_end() noexcept
12234 {
12235 m_it = end_value;
12236 }
12237
12239 constexpr bool is_begin() const noexcept
12240 {
12241 return m_it == begin_value;
12242 }
12243
12245 constexpr bool is_end() const noexcept
12246 {
12247 return m_it == end_value;
12248 }
12249
12250 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12251 {
12252 return lhs.m_it == rhs.m_it;
12253 }
12254
12255 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12256 {
12257 return lhs.m_it < rhs.m_it;
12258 }
12259
12260 primitive_iterator_t operator+(difference_type n) noexcept
12261 {
12262 auto result = *this;
12263 result += n;
12264 return result;
12265 }
12266
12267 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12268 {
12269 return lhs.m_it - rhs.m_it;
12270 }
12271
12272 primitive_iterator_t& operator++() noexcept
12273 {
12274 ++m_it;
12275 return *this;
12276 }
12277
12278 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
12279 {
12280 auto result = *this;
12281 ++m_it;
12282 return result;
12283 }
12284
12285 primitive_iterator_t& operator--() noexcept
12286 {
12287 --m_it;
12288 return *this;
12289 }
12290
12291 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
12292 {
12293 auto result = *this;
12294 --m_it;
12295 return result;
12296 }
12297
12298 primitive_iterator_t& operator+=(difference_type n) noexcept
12299 {
12300 m_it += n;
12301 return *this;
12302 }
12303
12304 primitive_iterator_t& operator-=(difference_type n) noexcept
12305 {
12306 m_it -= n;
12307 return *this;
12308 }
12309};
12310} // namespace detail
12311} // namespace nlohmann
12312
12313
12314namespace nlohmann
12315{
12316namespace detail
12317{
12324template<typename BasicJsonType> struct internal_iterator
12325{
12327 typename BasicJsonType::object_t::iterator object_iterator {};
12329 typename BasicJsonType::array_t::iterator array_iterator {};
12331 primitive_iterator_t primitive_iterator {};
12332};
12333} // namespace detail
12334} // namespace nlohmann
12335
12336// #include <nlohmann/detail/iterators/iter_impl.hpp>
12337
12338
12339#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
12340#include <type_traits> // conditional, is_const, remove_const
12341
12342// #include <nlohmann/detail/exceptions.hpp>
12343
12344// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12345
12346// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12347
12348// #include <nlohmann/detail/macro_scope.hpp>
12349
12350// #include <nlohmann/detail/meta/cpp_future.hpp>
12351
12352// #include <nlohmann/detail/meta/type_traits.hpp>
12353
12354// #include <nlohmann/detail/value_t.hpp>
12355
12356
12357namespace nlohmann
12358{
12359namespace detail
12360{
12361// forward declare, to be able to friend it later on
12362template<typename IteratorType> class iteration_proxy;
12363template<typename IteratorType> class iteration_proxy_value;
12364
12381template<typename BasicJsonType>
12382class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
12383{
12385 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
12387 friend other_iter_impl;
12388 friend BasicJsonType;
12389 friend iteration_proxy<iter_impl>;
12390 friend iteration_proxy_value<iter_impl>;
12391
12392 using object_t = typename BasicJsonType::object_t;
12393 using array_t = typename BasicJsonType::array_t;
12394 // make sure BasicJsonType is basic_json or const basic_json
12396 "iter_impl only accepts (const) basic_json");
12397 // superficial check for the LegacyBidirectionalIterator named requirement
12398 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
12399 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
12400 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
12401
12402 public:
12408 using iterator_category = std::bidirectional_iterator_tag;
12409
12411 using value_type = typename BasicJsonType::value_type;
12413 using difference_type = typename BasicJsonType::difference_type;
12415 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
12416 typename BasicJsonType::const_pointer,
12417 typename BasicJsonType::pointer>::type;
12420 typename std::conditional<std::is_const<BasicJsonType>::value,
12421 typename BasicJsonType::const_reference,
12422 typename BasicJsonType::reference>::type;
12423
12424 iter_impl() = default;
12425 ~iter_impl() = default;
12426 iter_impl(iter_impl&&) noexcept = default;
12427 iter_impl& operator=(iter_impl&&) noexcept = default;
12428
12435 explicit iter_impl(pointer object) noexcept : m_object(object)
12436 {
12437 JSON_ASSERT(m_object != nullptr);
12438
12439 switch (m_object->m_type)
12440 {
12441 case value_t::object:
12442 {
12443 m_it.object_iterator = typename object_t::iterator();
12444 break;
12445 }
12446
12447 case value_t::array:
12448 {
12449 m_it.array_iterator = typename array_t::iterator();
12450 break;
12451 }
12452
12453 case value_t::null:
12454 case value_t::string:
12455 case value_t::boolean:
12459 case value_t::binary:
12460 case value_t::discarded:
12461 default:
12462 {
12463 m_it.primitive_iterator = primitive_iterator_t();
12464 break;
12465 }
12466 }
12467 }
12468
12486 : m_object(other.m_object), m_it(other.m_it)
12487 {}
12488
12496 {
12497 if (&other != this)
12498 {
12499 m_object = other.m_object;
12500 m_it = other.m_it;
12501 }
12502 return *this;
12503 }
12504
12510 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
12511 : m_object(other.m_object), m_it(other.m_it)
12512 {}
12513
12520 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
12521 {
12522 m_object = other.m_object;
12523 m_it = other.m_it;
12524 return *this;
12525 }
12526
12532 void set_begin() noexcept
12533 {
12534 JSON_ASSERT(m_object != nullptr);
12535
12536 switch (m_object->m_type)
12537 {
12538 case value_t::object:
12539 {
12540 m_it.object_iterator = m_object->m_value.object->begin();
12541 break;
12542 }
12543
12544 case value_t::array:
12545 {
12546 m_it.array_iterator = m_object->m_value.array->begin();
12547 break;
12548 }
12549
12550 case value_t::null:
12551 {
12552 // set to end so begin()==end() is true: null is empty
12553 m_it.primitive_iterator.set_end();
12554 break;
12555 }
12556
12557 case value_t::string:
12558 case value_t::boolean:
12562 case value_t::binary:
12563 case value_t::discarded:
12564 default:
12565 {
12566 m_it.primitive_iterator.set_begin();
12567 break;
12568 }
12569 }
12570 }
12571
12576 void set_end() noexcept
12577 {
12578 JSON_ASSERT(m_object != nullptr);
12579
12580 switch (m_object->m_type)
12581 {
12582 case value_t::object:
12583 {
12584 m_it.object_iterator = m_object->m_value.object->end();
12585 break;
12586 }
12587
12588 case value_t::array:
12589 {
12590 m_it.array_iterator = m_object->m_value.array->end();
12591 break;
12592 }
12593
12594 case value_t::null:
12595 case value_t::string:
12596 case value_t::boolean:
12600 case value_t::binary:
12601 case value_t::discarded:
12602 default:
12603 {
12604 m_it.primitive_iterator.set_end();
12605 break;
12606 }
12607 }
12608 }
12609
12610 public:
12616 {
12617 JSON_ASSERT(m_object != nullptr);
12618
12619 switch (m_object->m_type)
12620 {
12621 case value_t::object:
12622 {
12623 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
12624 return m_it.object_iterator->second;
12625 }
12626
12627 case value_t::array:
12628 {
12629 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
12630 return *m_it.array_iterator;
12631 }
12632
12633 case value_t::null:
12634 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
12635
12636 case value_t::string:
12637 case value_t::boolean:
12641 case value_t::binary:
12642 case value_t::discarded:
12643 default:
12644 {
12646 {
12647 return *m_object;
12648 }
12649
12650 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
12651 }
12652 }
12653 }
12654
12660 {
12661 JSON_ASSERT(m_object != nullptr);
12662
12663 switch (m_object->m_type)
12664 {
12665 case value_t::object:
12666 {
12667 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
12668 return &(m_it.object_iterator->second);
12669 }
12670
12671 case value_t::array:
12672 {
12673 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
12674 return &*m_it.array_iterator;
12675 }
12676
12677 case value_t::null:
12678 case value_t::string:
12679 case value_t::boolean:
12683 case value_t::binary:
12684 case value_t::discarded:
12685 default:
12686 {
12688 {
12689 return m_object;
12690 }
12691
12692 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
12693 }
12694 }
12695 }
12696
12701 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
12702 {
12703 auto result = *this;
12704 ++(*this);
12705 return result;
12706 }
12707
12713 {
12714 JSON_ASSERT(m_object != nullptr);
12715
12716 switch (m_object->m_type)
12717 {
12718 case value_t::object:
12719 {
12720 std::advance(m_it.object_iterator, 1);
12721 break;
12722 }
12723
12724 case value_t::array:
12725 {
12726 std::advance(m_it.array_iterator, 1);
12727 break;
12728 }
12729
12730 case value_t::null:
12731 case value_t::string:
12732 case value_t::boolean:
12736 case value_t::binary:
12737 case value_t::discarded:
12738 default:
12739 {
12741 break;
12742 }
12743 }
12744
12745 return *this;
12746 }
12747
12752 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
12753 {
12754 auto result = *this;
12755 --(*this);
12756 return result;
12757 }
12758
12764 {
12765 JSON_ASSERT(m_object != nullptr);
12766
12767 switch (m_object->m_type)
12768 {
12769 case value_t::object:
12770 {
12771 std::advance(m_it.object_iterator, -1);
12772 break;
12773 }
12774
12775 case value_t::array:
12776 {
12777 std::advance(m_it.array_iterator, -1);
12778 break;
12779 }
12780
12781 case value_t::null:
12782 case value_t::string:
12783 case value_t::boolean:
12787 case value_t::binary:
12788 case value_t::discarded:
12789 default:
12790 {
12792 break;
12793 }
12794 }
12795
12796 return *this;
12797 }
12798
12803 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
12804 bool operator==(const IterImpl& other) const
12805 {
12806 // if objects are not the same, the comparison is undefined
12807 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
12808 {
12809 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
12810 }
12811
12812 JSON_ASSERT(m_object != nullptr);
12813
12814 switch (m_object->m_type)
12815 {
12816 case value_t::object:
12817 return (m_it.object_iterator == other.m_it.object_iterator);
12818
12819 case value_t::array:
12820 return (m_it.array_iterator == other.m_it.array_iterator);
12821
12822 case value_t::null:
12823 case value_t::string:
12824 case value_t::boolean:
12828 case value_t::binary:
12829 case value_t::discarded:
12830 default:
12831 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
12832 }
12833 }
12834
12839 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
12840 bool operator!=(const IterImpl& other) const
12841 {
12842 return !operator==(other);
12843 }
12844
12849 bool operator<(const iter_impl& other) const
12850 {
12851 // if objects are not the same, the comparison is undefined
12852 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
12853 {
12854 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
12855 }
12856
12857 JSON_ASSERT(m_object != nullptr);
12858
12859 switch (m_object->m_type)
12860 {
12861 case value_t::object:
12862 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
12863
12864 case value_t::array:
12865 return (m_it.array_iterator < other.m_it.array_iterator);
12866
12867 case value_t::null:
12868 case value_t::string:
12869 case value_t::boolean:
12873 case value_t::binary:
12874 case value_t::discarded:
12875 default:
12877 }
12878 }
12879
12884 bool operator<=(const iter_impl& other) const
12885 {
12886 return !other.operator < (*this);
12887 }
12888
12893 bool operator>(const iter_impl& other) const
12894 {
12895 return !operator<=(other);
12896 }
12897
12902 bool operator>=(const iter_impl& other) const
12903 {
12904 return !operator<(other);
12905 }
12906
12912 {
12913 JSON_ASSERT(m_object != nullptr);
12914
12915 switch (m_object->m_type)
12916 {
12917 case value_t::object:
12918 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
12919
12920 case value_t::array:
12921 {
12922 std::advance(m_it.array_iterator, i);
12923 break;
12924 }
12925
12926 case value_t::null:
12927 case value_t::string:
12928 case value_t::boolean:
12932 case value_t::binary:
12933 case value_t::discarded:
12934 default:
12935 {
12937 break;
12938 }
12939 }
12940
12941 return *this;
12942 }
12943
12949 {
12950 return operator+=(-i);
12951 }
12952
12958 {
12959 auto result = *this;
12960 result += i;
12961 return result;
12962 }
12963
12969 {
12970 auto result = it;
12971 result += i;
12972 return result;
12973 }
12974
12980 {
12981 auto result = *this;
12982 result -= i;
12983 return result;
12984 }
12985
12991 {
12992 JSON_ASSERT(m_object != nullptr);
12993
12994 switch (m_object->m_type)
12995 {
12996 case value_t::object:
12997 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
12998
12999 case value_t::array:
13000 return m_it.array_iterator - other.m_it.array_iterator;
13001
13002 case value_t::null:
13003 case value_t::string:
13004 case value_t::boolean:
13008 case value_t::binary:
13009 case value_t::discarded:
13010 default:
13012 }
13013 }
13014
13020 {
13021 JSON_ASSERT(m_object != nullptr);
13022
13023 switch (m_object->m_type)
13024 {
13025 case value_t::object:
13026 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
13027
13028 case value_t::array:
13029 return *std::next(m_it.array_iterator, n);
13030
13031 case value_t::null:
13032 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13033
13034 case value_t::string:
13035 case value_t::boolean:
13039 case value_t::binary:
13040 case value_t::discarded:
13041 default:
13042 {
13043 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
13044 {
13045 return *m_object;
13046 }
13047
13048 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13049 }
13050 }
13051 }
13052
13057 const typename object_t::key_type& key() const
13058 {
13059 JSON_ASSERT(m_object != nullptr);
13060
13061 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
13062 {
13063 return m_it.object_iterator->first;
13064 }
13065
13066 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
13067 }
13068
13074 {
13075 return operator*();
13076 }
13077
13080 pointer m_object = nullptr;
13083};
13084} // namespace detail
13085} // namespace nlohmann
13086
13087// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
13088
13089// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
13090
13091
13092#include <cstddef> // ptrdiff_t
13093#include <iterator> // reverse_iterator
13094#include <utility> // declval
13095
13096namespace nlohmann
13097{
13098namespace detail
13099{
13101// reverse_iterator //
13103
13122template<typename Base>
13123class json_reverse_iterator : public std::reverse_iterator<Base>
13124{
13125 public:
13126 using difference_type = std::ptrdiff_t;
13128 using base_iterator = std::reverse_iterator<Base>;
13130 using reference = typename Base::reference;
13131
13133 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
13134 : base_iterator(it) {}
13135
13137 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
13138
13140 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
13141 {
13142 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
13143 }
13144
13147 {
13148 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
13149 }
13150
13152 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
13153 {
13154 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
13155 }
13156
13159 {
13160 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
13161 }
13162
13165 {
13166 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
13167 }
13168
13171 {
13172 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
13173 }
13174
13177 {
13178 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
13179 }
13180
13183 {
13184 return base_iterator(*this) - base_iterator(other);
13185 }
13186
13189 {
13190 return *(this->operator+(n));
13191 }
13192
13194 auto key() const -> decltype(std::declval<Base>().key())
13195 {
13196 auto it = --this->base();
13197 return it.key();
13198 }
13199
13202 {
13203 auto it = --this->base();
13204 return it.operator * ();
13205 }
13206};
13207} // namespace detail
13208} // namespace nlohmann
13209
13210// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13211
13212// #include <nlohmann/detail/json_pointer.hpp>
13213
13214
13215#include <algorithm> // all_of
13216#include <cctype> // isdigit
13217#include <cerrno> // errno, ERANGE
13218#include <cstdlib> // strtoull
13219#include <limits> // max
13220#include <numeric> // accumulate
13221#include <string> // string
13222#include <utility> // move
13223#include <vector> // vector
13224
13225// #include <nlohmann/detail/exceptions.hpp>
13226
13227// #include <nlohmann/detail/macro_scope.hpp>
13228
13229// #include <nlohmann/detail/string_concat.hpp>
13230
13231// #include <nlohmann/detail/string_escape.hpp>
13232
13233// #include <nlohmann/detail/value_t.hpp>
13234
13235
13236namespace nlohmann
13237{
13238
13241template<typename RefStringType>
13243{
13244 // allow basic_json to access private members
13246 friend class basic_json;
13247
13248 template<typename>
13249 friend class json_pointer;
13250
13251 template<typename T>
13252 struct string_t_helper
13253 {
13254 using type = T;
13255 };
13256
13258 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
13259 {
13260 using type = StringType;
13261 };
13262
13263 public:
13264 // for backwards compatibility accept BasicJsonType
13265 using string_t = typename string_t_helper<RefStringType>::type;
13266
13269 explicit json_pointer(const string_t& s = "")
13270 : reference_tokens(split(s))
13271 {}
13272
13276 {
13277 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
13278 string_t{},
13279 [](const string_t& a, const string_t& b)
13280 {
13281 return detail::concat(a, '/', detail::escape(b));
13282 });
13283 }
13284
13287 operator string_t() const
13288 {
13289 return to_string();
13290 }
13291
13295 {
13296 reference_tokens.insert(reference_tokens.end(),
13297 ptr.reference_tokens.begin(),
13298 ptr.reference_tokens.end());
13299 return *this;
13300 }
13301
13305 {
13306 push_back(std::move(token));
13307 return *this;
13308 }
13309
13312 json_pointer& operator/=(std::size_t array_idx)
13313 {
13314 return *this /= std::to_string(array_idx);
13315 }
13316
13320 const json_pointer& rhs)
13321 {
13322 return json_pointer(lhs) /= rhs;
13323 }
13324
13327 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
13328 {
13329 return json_pointer(lhs) /= std::move(token);
13330 }
13331
13334 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
13335 {
13336 return json_pointer(lhs) /= array_idx;
13337 }
13338
13342 {
13343 if (empty())
13344 {
13345 return *this;
13346 }
13347
13348 json_pointer res = *this;
13349 res.pop_back();
13350 return res;
13351 }
13352
13356 {
13358 {
13359 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13360 }
13361
13362 reference_tokens.pop_back();
13363 }
13364
13367 const string_t& back() const
13368 {
13370 {
13371 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13372 }
13373
13374 return reference_tokens.back();
13375 }
13376
13379 void push_back(const string_t& token)
13380 {
13381 reference_tokens.push_back(token);
13382 }
13383
13386 void push_back(string_t&& token)
13387 {
13388 reference_tokens.push_back(std::move(token));
13389 }
13390
13393 bool empty() const noexcept
13394 {
13395 return reference_tokens.empty();
13396 }
13397
13398 private:
13409 template<typename BasicJsonType>
13410 static typename BasicJsonType::size_type array_index(const string_t& s)
13411 {
13412 using size_type = typename BasicJsonType::size_type;
13413
13414 // error condition (cf. RFC 6901, Sect. 4)
13415 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
13416 {
13417 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
13418 }
13419
13420 // error condition (cf. RFC 6901, Sect. 4)
13421 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
13422 {
13423 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
13424 }
13425
13426 const char* p = s.c_str();
13427 char* p_end = nullptr;
13428 errno = 0; // strtoull doesn't reset errno
13429 unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
13430 if (p == p_end // invalid input or empty string
13431 || errno == ERANGE // out of range
13432 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
13433 {
13434 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
13435 }
13436
13437 // only triggered on special platforms (like 32bit), see also
13438 // https://github.com/nlohmann/json/pull/2203
13439 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
13440 {
13441 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
13442 }
13443
13444 return static_cast<size_type>(res);
13445 }
13446
13448 json_pointer top() const
13449 {
13451 {
13452 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13453 }
13454
13455 json_pointer result = *this;
13456 result.reference_tokens = {reference_tokens[0]};
13457 return result;
13458 }
13459
13460 private:
13469 template<typename BasicJsonType>
13470 BasicJsonType& get_and_create(BasicJsonType& j) const
13471 {
13472 auto* result = &j;
13473
13474 // in case no reference tokens exist, return a reference to the JSON value
13475 // j which will be overwritten by a primitive value
13476 for (const auto& reference_token : reference_tokens)
13477 {
13478 switch (result->type())
13479 {
13481 {
13482 if (reference_token == "0")
13483 {
13484 // start a new array if reference token is 0
13485 result = &result->operator[](0);
13486 }
13487 else
13488 {
13489 // start a new object otherwise
13490 result = &result->operator[](reference_token);
13491 }
13492 break;
13493 }
13494
13496 {
13497 // create an entry in the object
13498 result = &result->operator[](reference_token);
13499 break;
13500 }
13501
13503 {
13504 // create an entry in the array
13505 result = &result->operator[](array_index<BasicJsonType>(reference_token));
13506 break;
13507 }
13508
13509 /*
13510 The following code is only reached if there exists a reference
13511 token _and_ the current value is primitive. In this case, we have
13512 an error situation, because primitive values may only occur as
13513 single value; that is, with an empty list of reference tokens.
13514 */
13522 default:
13523 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
13524 }
13525 }
13526
13527 return *result;
13528 }
13529
13549 template<typename BasicJsonType>
13550 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
13551 {
13552 for (const auto& reference_token : reference_tokens)
13553 {
13554 // convert null values to arrays or objects before continuing
13555 if (ptr->is_null())
13556 {
13557 // check if reference token is a number
13558 const bool nums =
13559 std::all_of(reference_token.begin(), reference_token.end(),
13560 [](const unsigned char x)
13561 {
13562 return std::isdigit(x);
13563 });
13564
13565 // change value to array for numbers or "-" or to object otherwise
13566 *ptr = (nums || reference_token == "-")
13568 : detail::value_t::object;
13569 }
13570
13571 switch (ptr->type())
13572 {
13574 {
13575 // use unchecked object access
13576 ptr = &ptr->operator[](reference_token);
13577 break;
13578 }
13579
13581 {
13582 if (reference_token == "-")
13583 {
13584 // explicitly treat "-" as index beyond the end
13585 ptr = &ptr->operator[](ptr->m_value.array->size());
13586 }
13587 else
13588 {
13589 // convert array index to number; unchecked access
13590 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
13591 }
13592 break;
13593 }
13594
13603 default:
13604 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
13605 }
13606 }
13607
13608 return *ptr;
13609 }
13610
13617 template<typename BasicJsonType>
13618 BasicJsonType& get_checked(BasicJsonType* ptr) const
13619 {
13620 for (const auto& reference_token : reference_tokens)
13621 {
13622 switch (ptr->type())
13623 {
13625 {
13626 // note: at performs range check
13627 ptr = &ptr->at(reference_token);
13628 break;
13629 }
13630
13632 {
13633 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
13634 {
13635 // "-" always fails the range check
13637 "array index '-' (", std::to_string(ptr->m_value.array->size()),
13638 ") is out of range"), ptr));
13639 }
13640
13641 // note: at performs range check
13642 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
13643 break;
13644 }
13645
13654 default:
13655 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
13656 }
13657 }
13658
13659 return *ptr;
13660 }
13661
13675 template<typename BasicJsonType>
13676 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
13677 {
13678 for (const auto& reference_token : reference_tokens)
13679 {
13680 switch (ptr->type())
13681 {
13683 {
13684 // use unchecked object access
13685 ptr = &ptr->operator[](reference_token);
13686 break;
13687 }
13688
13690 {
13691 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
13692 {
13693 // "-" cannot be used for const access
13694 JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr));
13695 }
13696
13697 // use unchecked array access
13698 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
13699 break;
13700 }
13701
13710 default:
13711 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
13712 }
13713 }
13714
13715 return *ptr;
13716 }
13717
13724 template<typename BasicJsonType>
13725 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
13726 {
13727 for (const auto& reference_token : reference_tokens)
13728 {
13729 switch (ptr->type())
13730 {
13732 {
13733 // note: at performs range check
13734 ptr = &ptr->at(reference_token);
13735 break;
13736 }
13737
13739 {
13740 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
13741 {
13742 // "-" always fails the range check
13744 "array index '-' (", std::to_string(ptr->m_value.array->size()),
13745 ") is out of range"), ptr));
13746 }
13747
13748 // note: at performs range check
13749 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
13750 break;
13751 }
13752
13761 default:
13762 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
13763 }
13764 }
13765
13766 return *ptr;
13767 }
13768
13773 template<typename BasicJsonType>
13774 bool contains(const BasicJsonType* ptr) const
13775 {
13776 for (const auto& reference_token : reference_tokens)
13777 {
13778 switch (ptr->type())
13779 {
13781 {
13782 if (!ptr->contains(reference_token))
13783 {
13784 // we did not find the key in the object
13785 return false;
13786 }
13787
13788 ptr = &ptr->operator[](reference_token);
13789 break;
13790 }
13791
13793 {
13794 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
13795 {
13796 // "-" always fails the range check
13797 return false;
13798 }
13799 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
13800 {
13801 // invalid char
13802 return false;
13803 }
13804 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
13805 {
13806 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
13807 {
13808 // first char should be between '1' and '9'
13809 return false;
13810 }
13811 for (std::size_t i = 1; i < reference_token.size(); i++)
13812 {
13813 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
13814 {
13815 // other char should be between '0' and '9'
13816 return false;
13817 }
13818 }
13819 }
13820
13821 const auto idx = array_index<BasicJsonType>(reference_token);
13822 if (idx >= ptr->size())
13823 {
13824 // index out of range
13825 return false;
13826 }
13827
13828 ptr = &ptr->operator[](idx);
13829 break;
13830 }
13831
13840 default:
13841 {
13842 // we do not expect primitive values if there is still a
13843 // reference token to process
13844 return false;
13845 }
13846 }
13847 }
13848
13849 // no reference token left means we found a primitive value
13850 return true;
13851 }
13852
13862 static std::vector<string_t> split(const string_t& reference_string)
13863 {
13864 std::vector<string_t> result;
13865
13866 // special case: empty reference string -> no reference tokens
13867 if (reference_string.empty())
13868 {
13869 return result;
13870 }
13871
13872 // check if nonempty reference string begins with slash
13873 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
13874 {
13875 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
13876 }
13877
13878 // extract the reference tokens:
13879 // - slash: position of the last read slash (or end of string)
13880 // - start: position after the previous slash
13881 for (
13882 // search for the first slash after the first character
13883 std::size_t slash = reference_string.find_first_of('/', 1),
13884 // set the beginning of the first reference token
13885 start = 1;
13886 // we can stop if start == 0 (if slash == string_t::npos)
13887 start != 0;
13888 // set the beginning of the next reference token
13889 // (will eventually be 0 if slash == string_t::npos)
13890 start = (slash == string_t::npos) ? 0 : slash + 1,
13891 // find next slash
13892 slash = reference_string.find_first_of('/', start))
13893 {
13894 // use the text between the beginning of the reference token
13895 // (start) and the last slash (slash).
13896 auto reference_token = reference_string.substr(start, slash - start);
13897
13898 // check reference tokens are properly escaped
13899 for (std::size_t pos = reference_token.find_first_of('~');
13900 pos != string_t::npos;
13901 pos = reference_token.find_first_of('~', pos + 1))
13902 {
13903 JSON_ASSERT(reference_token[pos] == '~');
13904
13905 // ~ must be followed by 0 or 1
13906 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
13907 (reference_token[pos + 1] != '0' &&
13908 reference_token[pos + 1] != '1')))
13909 {
13910 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
13911 }
13912 }
13913
13914 // finally, store the reference token
13915 detail::unescape(reference_token);
13916 result.push_back(reference_token);
13917 }
13918
13919 return result;
13920 }
13921
13922 private:
13930 template<typename BasicJsonType>
13931 static void flatten(const string_t& reference_string,
13932 const BasicJsonType& value,
13933 BasicJsonType& result)
13934 {
13935 switch (value.type())
13936 {
13938 {
13939 if (value.m_value.array->empty())
13940 {
13941 // flatten empty array as null
13942 result[reference_string] = nullptr;
13943 }
13944 else
13945 {
13946 // iterate array and use index as reference string
13947 for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
13948 {
13949 flatten(detail::concat(reference_string, '/', std::to_string(i)),
13950 value.m_value.array->operator[](i), result);
13951 }
13952 }
13953 break;
13954 }
13955
13957 {
13958 if (value.m_value.object->empty())
13959 {
13960 // flatten empty object as null
13961 result[reference_string] = nullptr;
13962 }
13963 else
13964 {
13965 // iterate object and use keys as reference string
13966 for (const auto& element : *value.m_value.object)
13967 {
13968 flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
13969 }
13970 }
13971 break;
13972 }
13973
13982 default:
13983 {
13984 // add primitive value with its reference string
13985 result[reference_string] = value;
13986 break;
13987 }
13988 }
13989 }
13990
14001 template<typename BasicJsonType>
14002 static BasicJsonType
14003 unflatten(const BasicJsonType& value)
14004 {
14005 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
14006 {
14007 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
14008 }
14009
14010 BasicJsonType result;
14011
14012 // iterate the JSON object values
14013 for (const auto& element : *value.m_value.object)
14014 {
14015 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
14016 {
14017 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
14018 }
14019
14020 // assign value to reference pointed to by JSON pointer; Note that if
14021 // the JSON pointer is "" (i.e., points to the whole value), function
14022 // get_and_create returns a reference to result itself. An assignment
14023 // will then create a primitive value.
14024 json_pointer(element.first).get_and_create(result) = element.second;
14025 }
14026
14027 return result;
14028 }
14029
14030 // can't use conversion operator because of ambiguity
14031 json_pointer<string_t> convert() const&
14032 {
14033 json_pointer<string_t> result;
14034 result.reference_tokens = reference_tokens;
14035 return result;
14036 }
14037
14038 json_pointer<string_t> convert()&&
14039 {
14040 json_pointer<string_t> result;
14041 result.reference_tokens = std::move(reference_tokens);
14042 return result;
14043 }
14044
14056 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14057 // NOLINTNEXTLINE(readability-redundant-declaration)
14058 friend bool operator==(json_pointer<RefStringTypeLhs> const& lhs,
14059 json_pointer<RefStringTypeRhs> const& rhs) noexcept;
14060
14072 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14073 // NOLINTNEXTLINE(readability-redundant-declaration)
14074 friend bool operator!=(json_pointer<RefStringTypeLhs> const& lhs,
14075 json_pointer<RefStringTypeRhs> const& rhs) noexcept;
14076
14078 std::vector<string_t> reference_tokens;
14079};
14080
14081// functions cannot be defined inside class due to ODR violations
14082template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14084 json_pointer<RefStringTypeRhs> const& rhs) noexcept
14085{
14086 return lhs.reference_tokens == rhs.reference_tokens;
14087}
14088
14089template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14091 json_pointer<RefStringTypeRhs> const& rhs) noexcept
14092{
14093 return !(lhs == rhs);
14094}
14095} // namespace nlohmann
14096
14097// #include <nlohmann/detail/json_ref.hpp>
14098
14099
14100#include <initializer_list>
14101#include <utility>
14102
14103// #include <nlohmann/detail/meta/type_traits.hpp>
14104
14105
14106namespace nlohmann
14107{
14108namespace detail
14109{
14110template<typename BasicJsonType>
14112{
14113 public:
14114 using value_type = BasicJsonType;
14115
14117 : owned_value(std::move(value))
14118 {}
14119
14120 json_ref(const value_type& value)
14121 : value_ref(&value)
14122 {}
14123
14124 json_ref(std::initializer_list<json_ref> init)
14125 : owned_value(init)
14126 {}
14127
14128 template <
14129 class... Args,
14130 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
14131 json_ref(Args && ... args)
14132 : owned_value(std::forward<Args>(args)...)
14133 {}
14134
14135 // class should be movable only
14136 json_ref(json_ref&&) noexcept = default;
14137 json_ref(const json_ref&) = delete;
14138 json_ref& operator=(const json_ref&) = delete;
14139 json_ref& operator=(json_ref&&) = delete;
14140 ~json_ref() = default;
14141
14143 {
14144 if (value_ref == nullptr)
14145 {
14146 return std::move(owned_value);
14147 }
14148 return *value_ref;
14149 }
14150
14151 value_type const& operator*() const
14152 {
14153 return value_ref ? *value_ref : owned_value;
14154 }
14155
14156 value_type const* operator->() const
14157 {
14158 return &** this;
14159 }
14160
14161 private:
14162 mutable value_type owned_value = nullptr;
14163 value_type const* value_ref = nullptr;
14164};
14165} // namespace detail
14166} // namespace nlohmann
14167
14168// #include <nlohmann/detail/macro_scope.hpp>
14169
14170// #include <nlohmann/detail/string_concat.hpp>
14171
14172// #include <nlohmann/detail/string_escape.hpp>
14173
14174// #include <nlohmann/detail/meta/cpp_future.hpp>
14175
14176// #include <nlohmann/detail/meta/type_traits.hpp>
14177
14178// #include <nlohmann/detail/output/binary_writer.hpp>
14179
14180
14181#include <algorithm> // reverse
14182#include <array> // array
14183#include <map> // map
14184#include <cmath> // isnan, isinf
14185#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
14186#include <cstring> // memcpy
14187#include <limits> // numeric_limits
14188#include <string> // string
14189#include <utility> // move
14190#include <vector> // vector
14191
14192// #include <nlohmann/detail/input/binary_reader.hpp>
14193
14194// #include <nlohmann/detail/macro_scope.hpp>
14195
14196// #include <nlohmann/detail/output/output_adapters.hpp>
14197
14198
14199#include <algorithm> // copy
14200#include <cstddef> // size_t
14201#include <iterator> // back_inserter
14202#include <memory> // shared_ptr, make_shared
14203#include <string> // basic_string
14204#include <vector> // vector
14205
14206#ifndef JSON_NO_IO
14207 #include <ios> // streamsize
14208 #include <ostream> // basic_ostream
14209#endif // JSON_NO_IO
14210
14211// #include <nlohmann/detail/macro_scope.hpp>
14212
14213
14214namespace nlohmann
14215{
14216namespace detail
14217{
14219template<typename CharType> struct output_adapter_protocol
14220{
14221 virtual void write_character(CharType c) = 0;
14222 virtual void write_characters(const CharType* s, std::size_t length) = 0;
14223 virtual ~output_adapter_protocol() = default;
14224
14225 output_adapter_protocol() = default;
14226 output_adapter_protocol(const output_adapter_protocol&) = default;
14227 output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
14228 output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
14229 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
14230};
14231
14233template<typename CharType>
14234using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
14235
14237template<typename CharType, typename AllocatorType = std::allocator<CharType>>
14238class output_vector_adapter : public output_adapter_protocol<CharType>
14239{
14240 public:
14241 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
14242 : v(vec)
14243 {}
14244
14245 void write_character(CharType c) override
14246 {
14247 v.push_back(c);
14248 }
14249
14251 void write_characters(const CharType* s, std::size_t length) override
14252 {
14253 v.insert(v.end(), s, s + length);
14254 }
14255
14256 private:
14257 std::vector<CharType, AllocatorType>& v;
14258};
14259
14260#ifndef JSON_NO_IO
14262template<typename CharType>
14263class output_stream_adapter : public output_adapter_protocol<CharType>
14264{
14265 public:
14266 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
14267 : stream(s)
14268 {}
14269
14270 void write_character(CharType c) override
14271 {
14272 stream.put(c);
14273 }
14274
14276 void write_characters(const CharType* s, std::size_t length) override
14277 {
14278 stream.write(s, static_cast<std::streamsize>(length));
14279 }
14280
14281 private:
14282 std::basic_ostream<CharType>& stream;
14283};
14284#endif // JSON_NO_IO
14285
14287template<typename CharType, typename StringType = std::basic_string<CharType>>
14288class output_string_adapter : public output_adapter_protocol<CharType>
14289{
14290 public:
14291 explicit output_string_adapter(StringType& s) noexcept
14292 : str(s)
14293 {}
14294
14295 void write_character(CharType c) override
14296 {
14297 str.push_back(c);
14298 }
14299
14301 void write_characters(const CharType* s, std::size_t length) override
14302 {
14303 str.append(s, length);
14304 }
14305
14306 private:
14307 StringType& str;
14308};
14309
14310template<typename CharType, typename StringType = std::basic_string<CharType>>
14311class output_adapter
14312{
14313 public:
14314 template<typename AllocatorType = std::allocator<CharType>>
14315 output_adapter(std::vector<CharType, AllocatorType>& vec)
14316 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
14317
14318#ifndef JSON_NO_IO
14319 output_adapter(std::basic_ostream<CharType>& s)
14320 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
14321#endif // JSON_NO_IO
14322
14323 output_adapter(StringType& s)
14324 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
14325
14326 operator output_adapter_t<CharType>()
14327 {
14328 return oa;
14329 }
14330
14331 private:
14332 output_adapter_t<CharType> oa = nullptr;
14333};
14334} // namespace detail
14335} // namespace nlohmann
14336
14337// #include <nlohmann/detail/string_concat.hpp>
14338
14339
14340namespace nlohmann
14341{
14342namespace detail
14343{
14345// binary writer //
14347
14351template<typename BasicJsonType, typename CharType>
14352class binary_writer
14353{
14354 using string_t = typename BasicJsonType::string_t;
14355 using binary_t = typename BasicJsonType::binary_t;
14356 using number_float_t = typename BasicJsonType::number_float_t;
14357
14358 public:
14364 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
14365 {
14366 JSON_ASSERT(oa);
14367 }
14368
14373 void write_bson(const BasicJsonType& j)
14374 {
14375 switch (j.type())
14376 {
14377 case value_t::object:
14378 {
14379 write_bson_object(*j.m_value.object);
14380 break;
14381 }
14382
14383 case value_t::null:
14384 case value_t::array:
14385 case value_t::string:
14386 case value_t::boolean:
14387 case value_t::number_integer:
14388 case value_t::number_unsigned:
14389 case value_t::number_float:
14390 case value_t::binary:
14391 case value_t::discarded:
14392 default:
14393 {
14394 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
14395 }
14396 }
14397 }
14398
14402 void write_cbor(const BasicJsonType& j)
14403 {
14404 switch (j.type())
14405 {
14406 case value_t::null:
14407 {
14408 oa->write_character(to_char_type(0xF6));
14409 break;
14410 }
14411
14412 case value_t::boolean:
14413 {
14414 oa->write_character(j.m_value.boolean
14415 ? to_char_type(0xF5)
14416 : to_char_type(0xF4));
14417 break;
14418 }
14419
14420 case value_t::number_integer:
14421 {
14422 if (j.m_value.number_integer >= 0)
14423 {
14424 // CBOR does not differentiate between positive signed
14425 // integers and unsigned integers. Therefore, we used the
14426 // code from the value_t::number_unsigned case here.
14427 if (j.m_value.number_integer <= 0x17)
14428 {
14429 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
14430 }
14431 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
14432 {
14433 oa->write_character(to_char_type(0x18));
14434 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
14435 }
14436 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
14437 {
14438 oa->write_character(to_char_type(0x19));
14439 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
14440 }
14441 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
14442 {
14443 oa->write_character(to_char_type(0x1A));
14444 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
14445 }
14446 else
14447 {
14448 oa->write_character(to_char_type(0x1B));
14449 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
14450 }
14451 }
14452 else
14453 {
14454 // The conversions below encode the sign in the first
14455 // byte, and the value is converted to a positive number.
14456 const auto positive_number = -1 - j.m_value.number_integer;
14457 if (j.m_value.number_integer >= -24)
14458 {
14459 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
14460 }
14461 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
14462 {
14463 oa->write_character(to_char_type(0x38));
14464 write_number(static_cast<std::uint8_t>(positive_number));
14465 }
14466 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
14467 {
14468 oa->write_character(to_char_type(0x39));
14469 write_number(static_cast<std::uint16_t>(positive_number));
14470 }
14471 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
14472 {
14473 oa->write_character(to_char_type(0x3A));
14474 write_number(static_cast<std::uint32_t>(positive_number));
14475 }
14476 else
14477 {
14478 oa->write_character(to_char_type(0x3B));
14479 write_number(static_cast<std::uint64_t>(positive_number));
14480 }
14481 }
14482 break;
14483 }
14484
14485 case value_t::number_unsigned:
14486 {
14487 if (j.m_value.number_unsigned <= 0x17)
14488 {
14489 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
14490 }
14491 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
14492 {
14493 oa->write_character(to_char_type(0x18));
14494 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
14495 }
14496 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
14497 {
14498 oa->write_character(to_char_type(0x19));
14499 write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
14500 }
14501 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
14502 {
14503 oa->write_character(to_char_type(0x1A));
14504 write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
14505 }
14506 else
14507 {
14508 oa->write_character(to_char_type(0x1B));
14509 write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
14510 }
14511 break;
14512 }
14513
14514 case value_t::number_float:
14515 {
14516 if (std::isnan(j.m_value.number_float))
14517 {
14518 // NaN is 0xf97e00 in CBOR
14519 oa->write_character(to_char_type(0xF9));
14520 oa->write_character(to_char_type(0x7E));
14521 oa->write_character(to_char_type(0x00));
14522 }
14523 else if (std::isinf(j.m_value.number_float))
14524 {
14525 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
14526 oa->write_character(to_char_type(0xf9));
14527 oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
14528 oa->write_character(to_char_type(0x00));
14529 }
14530 else
14531 {
14532 write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
14533 }
14534 break;
14535 }
14536
14537 case value_t::string:
14538 {
14539 // step 1: write control byte and the string length
14540 const auto N = j.m_value.string->size();
14541 if (N <= 0x17)
14542 {
14543 write_number(static_cast<std::uint8_t>(0x60 + N));
14544 }
14545 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
14546 {
14547 oa->write_character(to_char_type(0x78));
14548 write_number(static_cast<std::uint8_t>(N));
14549 }
14550 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
14551 {
14552 oa->write_character(to_char_type(0x79));
14553 write_number(static_cast<std::uint16_t>(N));
14554 }
14555 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
14556 {
14557 oa->write_character(to_char_type(0x7A));
14558 write_number(static_cast<std::uint32_t>(N));
14559 }
14560 // LCOV_EXCL_START
14561 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
14562 {
14563 oa->write_character(to_char_type(0x7B));
14564 write_number(static_cast<std::uint64_t>(N));
14565 }
14566 // LCOV_EXCL_STOP
14567
14568 // step 2: write the string
14569 oa->write_characters(
14570 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
14571 j.m_value.string->size());
14572 break;
14573 }
14574
14575 case value_t::array:
14576 {
14577 // step 1: write control byte and the array size
14578 const auto N = j.m_value.array->size();
14579 if (N <= 0x17)
14580 {
14581 write_number(static_cast<std::uint8_t>(0x80 + N));
14582 }
14583 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
14584 {
14585 oa->write_character(to_char_type(0x98));
14586 write_number(static_cast<std::uint8_t>(N));
14587 }
14588 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
14589 {
14590 oa->write_character(to_char_type(0x99));
14591 write_number(static_cast<std::uint16_t>(N));
14592 }
14593 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
14594 {
14595 oa->write_character(to_char_type(0x9A));
14596 write_number(static_cast<std::uint32_t>(N));
14597 }
14598 // LCOV_EXCL_START
14599 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
14600 {
14601 oa->write_character(to_char_type(0x9B));
14602 write_number(static_cast<std::uint64_t>(N));
14603 }
14604 // LCOV_EXCL_STOP
14605
14606 // step 2: write each element
14607 for (const auto& el : *j.m_value.array)
14608 {
14609 write_cbor(el);
14610 }
14611 break;
14612 }
14613
14614 case value_t::binary:
14615 {
14616 if (j.m_value.binary->has_subtype())
14617 {
14618 if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
14619 {
14620 write_number(static_cast<std::uint8_t>(0xd8));
14621 write_number(static_cast<std::uint8_t>(j.m_value.binary->subtype()));
14622 }
14623 else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
14624 {
14625 write_number(static_cast<std::uint8_t>(0xd9));
14626 write_number(static_cast<std::uint16_t>(j.m_value.binary->subtype()));
14627 }
14628 else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
14629 {
14630 write_number(static_cast<std::uint8_t>(0xda));
14631 write_number(static_cast<std::uint32_t>(j.m_value.binary->subtype()));
14632 }
14633 else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
14634 {
14635 write_number(static_cast<std::uint8_t>(0xdb));
14636 write_number(static_cast<std::uint64_t>(j.m_value.binary->subtype()));
14637 }
14638 }
14639
14640 // step 1: write control byte and the binary array size
14641 const auto N = j.m_value.binary->size();
14642 if (N <= 0x17)
14643 {
14644 write_number(static_cast<std::uint8_t>(0x40 + N));
14645 }
14646 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
14647 {
14648 oa->write_character(to_char_type(0x58));
14649 write_number(static_cast<std::uint8_t>(N));
14650 }
14651 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
14652 {
14653 oa->write_character(to_char_type(0x59));
14654 write_number(static_cast<std::uint16_t>(N));
14655 }
14656 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
14657 {
14658 oa->write_character(to_char_type(0x5A));
14659 write_number(static_cast<std::uint32_t>(N));
14660 }
14661 // LCOV_EXCL_START
14662 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
14663 {
14664 oa->write_character(to_char_type(0x5B));
14665 write_number(static_cast<std::uint64_t>(N));
14666 }
14667 // LCOV_EXCL_STOP
14668
14669 // step 2: write each element
14670 oa->write_characters(
14671 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
14672 N);
14673
14674 break;
14675 }
14676
14677 case value_t::object:
14678 {
14679 // step 1: write control byte and the object size
14680 const auto N = j.m_value.object->size();
14681 if (N <= 0x17)
14682 {
14683 write_number(static_cast<std::uint8_t>(0xA0 + N));
14684 }
14685 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
14686 {
14687 oa->write_character(to_char_type(0xB8));
14688 write_number(static_cast<std::uint8_t>(N));
14689 }
14690 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
14691 {
14692 oa->write_character(to_char_type(0xB9));
14693 write_number(static_cast<std::uint16_t>(N));
14694 }
14695 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
14696 {
14697 oa->write_character(to_char_type(0xBA));
14698 write_number(static_cast<std::uint32_t>(N));
14699 }
14700 // LCOV_EXCL_START
14701 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
14702 {
14703 oa->write_character(to_char_type(0xBB));
14704 write_number(static_cast<std::uint64_t>(N));
14705 }
14706 // LCOV_EXCL_STOP
14707
14708 // step 2: write each element
14709 for (const auto& el : *j.m_value.object)
14710 {
14711 write_cbor(el.first);
14712 write_cbor(el.second);
14713 }
14714 break;
14715 }
14716
14717 case value_t::discarded:
14718 default:
14719 break;
14720 }
14721 }
14722
14726 void write_msgpack(const BasicJsonType& j)
14727 {
14728 switch (j.type())
14729 {
14730 case value_t::null: // nil
14731 {
14732 oa->write_character(to_char_type(0xC0));
14733 break;
14734 }
14735
14736 case value_t::boolean: // true and false
14737 {
14738 oa->write_character(j.m_value.boolean
14739 ? to_char_type(0xC3)
14740 : to_char_type(0xC2));
14741 break;
14742 }
14743
14744 case value_t::number_integer:
14745 {
14746 if (j.m_value.number_integer >= 0)
14747 {
14748 // MessagePack does not differentiate between positive
14749 // signed integers and unsigned integers. Therefore, we used
14750 // the code from the value_t::number_unsigned case here.
14751 if (j.m_value.number_unsigned < 128)
14752 {
14753 // positive fixnum
14754 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
14755 }
14756 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
14757 {
14758 // uint 8
14759 oa->write_character(to_char_type(0xCC));
14760 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
14761 }
14762 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
14763 {
14764 // uint 16
14765 oa->write_character(to_char_type(0xCD));
14766 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
14767 }
14768 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
14769 {
14770 // uint 32
14771 oa->write_character(to_char_type(0xCE));
14772 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
14773 }
14774 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
14775 {
14776 // uint 64
14777 oa->write_character(to_char_type(0xCF));
14778 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
14779 }
14780 }
14781 else
14782 {
14783 if (j.m_value.number_integer >= -32)
14784 {
14785 // negative fixnum
14786 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
14787 }
14788 else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
14789 j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
14790 {
14791 // int 8
14792 oa->write_character(to_char_type(0xD0));
14793 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
14794 }
14795 else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
14796 j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
14797 {
14798 // int 16
14799 oa->write_character(to_char_type(0xD1));
14800 write_number(static_cast<std::int16_t>(j.m_value.number_integer));
14801 }
14802 else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
14803 j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
14804 {
14805 // int 32
14806 oa->write_character(to_char_type(0xD2));
14807 write_number(static_cast<std::int32_t>(j.m_value.number_integer));
14808 }
14809 else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
14810 j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
14811 {
14812 // int 64
14813 oa->write_character(to_char_type(0xD3));
14814 write_number(static_cast<std::int64_t>(j.m_value.number_integer));
14815 }
14816 }
14817 break;
14818 }
14819
14820 case value_t::number_unsigned:
14821 {
14822 if (j.m_value.number_unsigned < 128)
14823 {
14824 // positive fixnum
14825 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
14826 }
14827 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
14828 {
14829 // uint 8
14830 oa->write_character(to_char_type(0xCC));
14831 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
14832 }
14833 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
14834 {
14835 // uint 16
14836 oa->write_character(to_char_type(0xCD));
14837 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
14838 }
14839 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
14840 {
14841 // uint 32
14842 oa->write_character(to_char_type(0xCE));
14843 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
14844 }
14845 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
14846 {
14847 // uint 64
14848 oa->write_character(to_char_type(0xCF));
14849 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
14850 }
14851 break;
14852 }
14853
14854 case value_t::number_float:
14855 {
14856 write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
14857 break;
14858 }
14859
14860 case value_t::string:
14861 {
14862 // step 1: write control byte and the string length
14863 const auto N = j.m_value.string->size();
14864 if (N <= 31)
14865 {
14866 // fixstr
14867 write_number(static_cast<std::uint8_t>(0xA0 | N));
14868 }
14869 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
14870 {
14871 // str 8
14872 oa->write_character(to_char_type(0xD9));
14873 write_number(static_cast<std::uint8_t>(N));
14874 }
14875 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
14876 {
14877 // str 16
14878 oa->write_character(to_char_type(0xDA));
14879 write_number(static_cast<std::uint16_t>(N));
14880 }
14881 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
14882 {
14883 // str 32
14884 oa->write_character(to_char_type(0xDB));
14885 write_number(static_cast<std::uint32_t>(N));
14886 }
14887
14888 // step 2: write the string
14889 oa->write_characters(
14890 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
14891 j.m_value.string->size());
14892 break;
14893 }
14894
14895 case value_t::array:
14896 {
14897 // step 1: write control byte and the array size
14898 const auto N = j.m_value.array->size();
14899 if (N <= 15)
14900 {
14901 // fixarray
14902 write_number(static_cast<std::uint8_t>(0x90 | N));
14903 }
14904 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
14905 {
14906 // array 16
14907 oa->write_character(to_char_type(0xDC));
14908 write_number(static_cast<std::uint16_t>(N));
14909 }
14910 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
14911 {
14912 // array 32
14913 oa->write_character(to_char_type(0xDD));
14914 write_number(static_cast<std::uint32_t>(N));
14915 }
14916
14917 // step 2: write each element
14918 for (const auto& el : *j.m_value.array)
14919 {
14920 write_msgpack(el);
14921 }
14922 break;
14923 }
14924
14925 case value_t::binary:
14926 {
14927 // step 0: determine if the binary type has a set subtype to
14928 // determine whether or not to use the ext or fixext types
14929 const bool use_ext = j.m_value.binary->has_subtype();
14930
14931 // step 1: write control byte and the byte string length
14932 const auto N = j.m_value.binary->size();
14933 if (N <= (std::numeric_limits<std::uint8_t>::max)())
14934 {
14935 std::uint8_t output_type{};
14936 bool fixed = true;
14937 if (use_ext)
14938 {
14939 switch (N)
14940 {
14941 case 1:
14942 output_type = 0xD4; // fixext 1
14943 break;
14944 case 2:
14945 output_type = 0xD5; // fixext 2
14946 break;
14947 case 4:
14948 output_type = 0xD6; // fixext 4
14949 break;
14950 case 8:
14951 output_type = 0xD7; // fixext 8
14952 break;
14953 case 16:
14954 output_type = 0xD8; // fixext 16
14955 break;
14956 default:
14957 output_type = 0xC7; // ext 8
14958 fixed = false;
14959 break;
14960 }
14961
14962 }
14963 else
14964 {
14965 output_type = 0xC4; // bin 8
14966 fixed = false;
14967 }
14968
14969 oa->write_character(to_char_type(output_type));
14970 if (!fixed)
14971 {
14972 write_number(static_cast<std::uint8_t>(N));
14973 }
14974 }
14975 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
14976 {
14977 std::uint8_t output_type = use_ext
14978 ? 0xC8 // ext 16
14979 : 0xC5; // bin 16
14980
14981 oa->write_character(to_char_type(output_type));
14982 write_number(static_cast<std::uint16_t>(N));
14983 }
14984 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
14985 {
14986 std::uint8_t output_type = use_ext
14987 ? 0xC9 // ext 32
14988 : 0xC6; // bin 32
14989
14990 oa->write_character(to_char_type(output_type));
14991 write_number(static_cast<std::uint32_t>(N));
14992 }
14993
14994 // step 1.5: if this is an ext type, write the subtype
14995 if (use_ext)
14996 {
14997 write_number(static_cast<std::int8_t>(j.m_value.binary->subtype()));
14998 }
14999
15000 // step 2: write the byte string
15001 oa->write_characters(
15002 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
15003 N);
15004
15005 break;
15006 }
15007
15008 case value_t::object:
15009 {
15010 // step 1: write control byte and the object size
15011 const auto N = j.m_value.object->size();
15012 if (N <= 15)
15013 {
15014 // fixmap
15015 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
15016 }
15017 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15018 {
15019 // map 16
15020 oa->write_character(to_char_type(0xDE));
15021 write_number(static_cast<std::uint16_t>(N));
15022 }
15023 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15024 {
15025 // map 32
15026 oa->write_character(to_char_type(0xDF));
15027 write_number(static_cast<std::uint32_t>(N));
15028 }
15029
15030 // step 2: write each element
15031 for (const auto& el : *j.m_value.object)
15032 {
15033 write_msgpack(el.first);
15034 write_msgpack(el.second);
15035 }
15036 break;
15037 }
15038
15039 case value_t::discarded:
15040 default:
15041 break;
15042 }
15043 }
15044
15052 void write_ubjson(const BasicJsonType& j, const bool use_count,
15053 const bool use_type, const bool add_prefix = true,
15054 const bool use_bjdata = false)
15055 {
15056 switch (j.type())
15057 {
15058 case value_t::null:
15059 {
15060 if (add_prefix)
15061 {
15062 oa->write_character(to_char_type('Z'));
15063 }
15064 break;
15065 }
15066
15067 case value_t::boolean:
15068 {
15069 if (add_prefix)
15070 {
15071 oa->write_character(j.m_value.boolean
15072 ? to_char_type('T')
15073 : to_char_type('F'));
15074 }
15075 break;
15076 }
15077
15078 case value_t::number_integer:
15079 {
15080 write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix, use_bjdata);
15081 break;
15082 }
15083
15084 case value_t::number_unsigned:
15085 {
15086 write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix, use_bjdata);
15087 break;
15088 }
15089
15090 case value_t::number_float:
15091 {
15092 write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix, use_bjdata);
15093 break;
15094 }
15095
15096 case value_t::string:
15097 {
15098 if (add_prefix)
15099 {
15100 oa->write_character(to_char_type('S'));
15101 }
15102 write_number_with_ubjson_prefix(j.m_value.string->size(), true, use_bjdata);
15103 oa->write_characters(
15104 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
15105 j.m_value.string->size());
15106 break;
15107 }
15108
15109 case value_t::array:
15110 {
15111 if (add_prefix)
15112 {
15113 oa->write_character(to_char_type('['));
15114 }
15115
15116 bool prefix_required = true;
15117 if (use_type && !j.m_value.array->empty())
15118 {
15119 JSON_ASSERT(use_count);
15120 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15121 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
15122 [this, first_prefix, use_bjdata](const BasicJsonType & v)
15123 {
15124 return ubjson_prefix(v, use_bjdata) == first_prefix;
15125 });
15126
15127 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15128
15129 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15130 {
15131 prefix_required = false;
15132 oa->write_character(to_char_type('$'));
15133 oa->write_character(first_prefix);
15134 }
15135 }
15136
15137 if (use_count)
15138 {
15139 oa->write_character(to_char_type('#'));
15140 write_number_with_ubjson_prefix(j.m_value.array->size(), true, use_bjdata);
15141 }
15142
15143 for (const auto& el : *j.m_value.array)
15144 {
15145 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
15146 }
15147
15148 if (!use_count)
15149 {
15150 oa->write_character(to_char_type(']'));
15151 }
15152
15153 break;
15154 }
15155
15156 case value_t::binary:
15157 {
15158 if (add_prefix)
15159 {
15160 oa->write_character(to_char_type('['));
15161 }
15162
15163 if (use_type && !j.m_value.binary->empty())
15164 {
15165 JSON_ASSERT(use_count);
15166 oa->write_character(to_char_type('$'));
15167 oa->write_character('U');
15168 }
15169
15170 if (use_count)
15171 {
15172 oa->write_character(to_char_type('#'));
15173 write_number_with_ubjson_prefix(j.m_value.binary->size(), true, use_bjdata);
15174 }
15175
15176 if (use_type)
15177 {
15178 oa->write_characters(
15179 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
15180 j.m_value.binary->size());
15181 }
15182 else
15183 {
15184 for (size_t i = 0; i < j.m_value.binary->size(); ++i)
15185 {
15186 oa->write_character(to_char_type('U'));
15187 oa->write_character(j.m_value.binary->data()[i]);
15188 }
15189 }
15190
15191 if (!use_count)
15192 {
15193 oa->write_character(to_char_type(']'));
15194 }
15195
15196 break;
15197 }
15198
15199 case value_t::object:
15200 {
15201 if (use_bjdata && j.m_value.object->size() == 3 && j.m_value.object->find("_ArrayType_") != j.m_value.object->end() && j.m_value.object->find("_ArraySize_") != j.m_value.object->end() && j.m_value.object->find("_ArrayData_") != j.m_value.object->end())
15202 {
15203 if (!write_bjdata_ndarray(*j.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
15204 {
15205 break;
15206 }
15207 }
15208
15209 if (add_prefix)
15210 {
15211 oa->write_character(to_char_type('{'));
15212 }
15213
15214 bool prefix_required = true;
15215 if (use_type && !j.m_value.object->empty())
15216 {
15217 JSON_ASSERT(use_count);
15218 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15219 const bool same_prefix = std::all_of(j.begin(), j.end(),
15220 [this, first_prefix, use_bjdata](const BasicJsonType & v)
15221 {
15222 return ubjson_prefix(v, use_bjdata) == first_prefix;
15223 });
15224
15225 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15226
15227 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15228 {
15229 prefix_required = false;
15230 oa->write_character(to_char_type('$'));
15231 oa->write_character(first_prefix);
15232 }
15233 }
15234
15235 if (use_count)
15236 {
15237 oa->write_character(to_char_type('#'));
15238 write_number_with_ubjson_prefix(j.m_value.object->size(), true, use_bjdata);
15239 }
15240
15241 for (const auto& el : *j.m_value.object)
15242 {
15243 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
15244 oa->write_characters(
15245 reinterpret_cast<const CharType*>(el.first.c_str()),
15246 el.first.size());
15247 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
15248 }
15249
15250 if (!use_count)
15251 {
15252 oa->write_character(to_char_type('}'));
15253 }
15254
15255 break;
15256 }
15257
15258 case value_t::discarded:
15259 default:
15260 break;
15261 }
15262 }
15263
15264 private:
15266 // BSON //
15268
15273 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
15274 {
15275 const auto it = name.find(static_cast<typename string_t::value_type>(0));
15276 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
15277 {
15278 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
15279 static_cast<void>(j);
15280 }
15281
15282 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
15283 }
15284
15288 void write_bson_entry_header(const string_t& name,
15289 const std::uint8_t element_type)
15290 {
15291 oa->write_character(to_char_type(element_type)); // boolean
15292 oa->write_characters(
15293 reinterpret_cast<const CharType*>(name.c_str()),
15294 name.size() + 1u);
15295 }
15296
15300 void write_bson_boolean(const string_t& name,
15301 const bool value)
15302 {
15303 write_bson_entry_header(name, 0x08);
15304 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
15305 }
15306
15310 void write_bson_double(const string_t& name,
15311 const double value)
15312 {
15313 write_bson_entry_header(name, 0x01);
15314 write_number<double>(value, true);
15315 }
15316
15320 static std::size_t calc_bson_string_size(const string_t& value)
15321 {
15322 return sizeof(std::int32_t) + value.size() + 1ul;
15323 }
15324
15328 void write_bson_string(const string_t& name,
15329 const string_t& value)
15330 {
15331 write_bson_entry_header(name, 0x02);
15332
15333 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
15334 oa->write_characters(
15335 reinterpret_cast<const CharType*>(value.c_str()),
15336 value.size() + 1);
15337 }
15338
15342 void write_bson_null(const string_t& name)
15343 {
15344 write_bson_entry_header(name, 0x0A);
15345 }
15346
15350 static std::size_t calc_bson_integer_size(const std::int64_t value)
15351 {
15352 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
15353 ? sizeof(std::int32_t)
15354 : sizeof(std::int64_t);
15355 }
15356
15360 void write_bson_integer(const string_t& name,
15361 const std::int64_t value)
15362 {
15363 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
15364 {
15365 write_bson_entry_header(name, 0x10); // int32
15366 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
15367 }
15368 else
15369 {
15370 write_bson_entry_header(name, 0x12); // int64
15371 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
15372 }
15373 }
15374
15378 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
15379 {
15380 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
15381 ? sizeof(std::int32_t)
15382 : sizeof(std::int64_t);
15383 }
15384
15388 void write_bson_unsigned(const string_t& name,
15389 const BasicJsonType& j)
15390 {
15391 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
15392 {
15393 write_bson_entry_header(name, 0x10 /* int32 */);
15394 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_value.number_unsigned), true);
15395 }
15396 else if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
15397 {
15398 write_bson_entry_header(name, 0x12 /* int64 */);
15399 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_value.number_unsigned), true);
15400 }
15401 else
15402 {
15403 JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
15404 }
15405 }
15406
15410 void write_bson_object_entry(const string_t& name,
15411 const typename BasicJsonType::object_t& value)
15412 {
15413 write_bson_entry_header(name, 0x03); // object
15414 write_bson_object(value);
15415 }
15416
15420 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
15421 {
15422 std::size_t array_index = 0ul;
15423
15424 const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
15425 {
15426 return result + calc_bson_element_size(std::to_string(array_index++), el);
15427 });
15428
15429 return sizeof(std::int32_t) + embedded_document_size + 1ul;
15430 }
15431
15435 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
15436 {
15437 return sizeof(std::int32_t) + value.size() + 1ul;
15438 }
15439
15443 void write_bson_array(const string_t& name,
15444 const typename BasicJsonType::array_t& value)
15445 {
15446 write_bson_entry_header(name, 0x04); // array
15447 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
15448
15449 std::size_t array_index = 0ul;
15450
15451 for (const auto& el : value)
15452 {
15453 write_bson_element(std::to_string(array_index++), el);
15454 }
15455
15456 oa->write_character(to_char_type(0x00));
15457 }
15458
15462 void write_bson_binary(const string_t& name,
15463 const binary_t& value)
15464 {
15465 write_bson_entry_header(name, 0x05);
15466
15467 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
15468 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
15469
15470 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
15471 }
15472
15477 static std::size_t calc_bson_element_size(const string_t& name,
15478 const BasicJsonType& j)
15479 {
15480 const auto header_size = calc_bson_entry_header_size(name, j);
15481 switch (j.type())
15482 {
15483 case value_t::object:
15484 return header_size + calc_bson_object_size(*j.m_value.object);
15485
15486 case value_t::array:
15487 return header_size + calc_bson_array_size(*j.m_value.array);
15488
15489 case value_t::binary:
15490 return header_size + calc_bson_binary_size(*j.m_value.binary);
15491
15492 case value_t::boolean:
15493 return header_size + 1ul;
15494
15495 case value_t::number_float:
15496 return header_size + 8ul;
15497
15498 case value_t::number_integer:
15499 return header_size + calc_bson_integer_size(j.m_value.number_integer);
15500
15501 case value_t::number_unsigned:
15502 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
15503
15504 case value_t::string:
15505 return header_size + calc_bson_string_size(*j.m_value.string);
15506
15507 case value_t::null:
15508 return header_size + 0ul;
15509
15510 // LCOV_EXCL_START
15511 case value_t::discarded:
15512 default:
15513 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
15514 return 0ul;
15515 // LCOV_EXCL_STOP
15516 }
15517 }
15518
15525 void write_bson_element(const string_t& name,
15526 const BasicJsonType& j)
15527 {
15528 switch (j.type())
15529 {
15530 case value_t::object:
15531 return write_bson_object_entry(name, *j.m_value.object);
15532
15533 case value_t::array:
15534 return write_bson_array(name, *j.m_value.array);
15535
15536 case value_t::binary:
15537 return write_bson_binary(name, *j.m_value.binary);
15538
15539 case value_t::boolean:
15540 return write_bson_boolean(name, j.m_value.boolean);
15541
15542 case value_t::number_float:
15543 return write_bson_double(name, j.m_value.number_float);
15544
15545 case value_t::number_integer:
15546 return write_bson_integer(name, j.m_value.number_integer);
15547
15548 case value_t::number_unsigned:
15549 return write_bson_unsigned(name, j);
15550
15551 case value_t::string:
15552 return write_bson_string(name, *j.m_value.string);
15553
15554 case value_t::null:
15555 return write_bson_null(name);
15556
15557 // LCOV_EXCL_START
15558 case value_t::discarded:
15559 default:
15560 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
15561 return;
15562 // LCOV_EXCL_STOP
15563 }
15564 }
15565
15572 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
15573 {
15574 std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
15575 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
15576 {
15577 return result += calc_bson_element_size(el.first, el.second);
15578 });
15579
15580 return sizeof(std::int32_t) + document_size + 1ul;
15581 }
15582
15587 void write_bson_object(const typename BasicJsonType::object_t& value)
15588 {
15589 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
15590
15591 for (const auto& el : value)
15592 {
15593 write_bson_element(el.first, el.second);
15594 }
15595
15596 oa->write_character(to_char_type(0x00));
15597 }
15598
15600 // CBOR //
15602
15603 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
15604 {
15605 return to_char_type(0xFA); // Single-Precision Float
15606 }
15607
15608 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
15609 {
15610 return to_char_type(0xFB); // Double-Precision Float
15611 }
15612
15614 // MsgPack //
15616
15617 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
15618 {
15619 return to_char_type(0xCA); // float 32
15620 }
15621
15622 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
15623 {
15624 return to_char_type(0xCB); // float 64
15625 }
15626
15628 // UBJSON //
15630
15631 // UBJSON: write number (floating point)
15632 template<typename NumberType, typename std::enable_if<
15633 std::is_floating_point<NumberType>::value, int>::type = 0>
15634 void write_number_with_ubjson_prefix(const NumberType n,
15635 const bool add_prefix,
15636 const bool use_bjdata)
15637 {
15638 if (add_prefix)
15639 {
15640 oa->write_character(get_ubjson_float_prefix(n));
15641 }
15642 write_number(n, use_bjdata);
15643 }
15644
15645 // UBJSON: write number (unsigned integer)
15646 template<typename NumberType, typename std::enable_if<
15647 std::is_unsigned<NumberType>::value, int>::type = 0>
15648 void write_number_with_ubjson_prefix(const NumberType n,
15649 const bool add_prefix,
15650 const bool use_bjdata)
15651 {
15652 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
15653 {
15654 if (add_prefix)
15655 {
15656 oa->write_character(to_char_type('i')); // int8
15657 }
15658 write_number(static_cast<std::uint8_t>(n), use_bjdata);
15659 }
15660 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
15661 {
15662 if (add_prefix)
15663 {
15664 oa->write_character(to_char_type('U')); // uint8
15665 }
15666 write_number(static_cast<std::uint8_t>(n), use_bjdata);
15667 }
15668 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
15669 {
15670 if (add_prefix)
15671 {
15672 oa->write_character(to_char_type('I')); // int16
15673 }
15674 write_number(static_cast<std::int16_t>(n), use_bjdata);
15675 }
15676 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
15677 {
15678 if (add_prefix)
15679 {
15680 oa->write_character(to_char_type('u')); // uint16 - bjdata only
15681 }
15682 write_number(static_cast<std::uint16_t>(n), use_bjdata);
15683 }
15684 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
15685 {
15686 if (add_prefix)
15687 {
15688 oa->write_character(to_char_type('l')); // int32
15689 }
15690 write_number(static_cast<std::int32_t>(n), use_bjdata);
15691 }
15692 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
15693 {
15694 if (add_prefix)
15695 {
15696 oa->write_character(to_char_type('m')); // uint32 - bjdata only
15697 }
15698 write_number(static_cast<std::uint32_t>(n), use_bjdata);
15699 }
15700 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
15701 {
15702 if (add_prefix)
15703 {
15704 oa->write_character(to_char_type('L')); // int64
15705 }
15706 write_number(static_cast<std::int64_t>(n), use_bjdata);
15707 }
15708 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
15709 {
15710 if (add_prefix)
15711 {
15712 oa->write_character(to_char_type('M')); // uint64 - bjdata only
15713 }
15714 write_number(static_cast<std::uint64_t>(n), use_bjdata);
15715 }
15716 else
15717 {
15718 if (add_prefix)
15719 {
15720 oa->write_character(to_char_type('H')); // high-precision number
15721 }
15722
15723 const auto number = BasicJsonType(n).dump();
15724 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
15725 for (std::size_t i = 0; i < number.size(); ++i)
15726 {
15727 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
15728 }
15729 }
15730 }
15731
15732 // UBJSON: write number (signed integer)
15733 template < typename NumberType, typename std::enable_if <
15734 std::is_signed<NumberType>::value&&
15735 !std::is_floating_point<NumberType>::value, int >::type = 0 >
15736 void write_number_with_ubjson_prefix(const NumberType n,
15737 const bool add_prefix,
15738 const bool use_bjdata)
15739 {
15740 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
15741 {
15742 if (add_prefix)
15743 {
15744 oa->write_character(to_char_type('i')); // int8
15745 }
15746 write_number(static_cast<std::int8_t>(n), use_bjdata);
15747 }
15748 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)()))
15749 {
15750 if (add_prefix)
15751 {
15752 oa->write_character(to_char_type('U')); // uint8
15753 }
15754 write_number(static_cast<std::uint8_t>(n), use_bjdata);
15755 }
15756 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
15757 {
15758 if (add_prefix)
15759 {
15760 oa->write_character(to_char_type('I')); // int16
15761 }
15762 write_number(static_cast<std::int16_t>(n), use_bjdata);
15763 }
15764 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
15765 {
15766 if (add_prefix)
15767 {
15768 oa->write_character(to_char_type('u')); // uint16 - bjdata only
15769 }
15770 write_number(static_cast<uint16_t>(n), use_bjdata);
15771 }
15772 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
15773 {
15774 if (add_prefix)
15775 {
15776 oa->write_character(to_char_type('l')); // int32
15777 }
15778 write_number(static_cast<std::int32_t>(n), use_bjdata);
15779 }
15780 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
15781 {
15782 if (add_prefix)
15783 {
15784 oa->write_character(to_char_type('m')); // uint32 - bjdata only
15785 }
15786 write_number(static_cast<uint32_t>(n), use_bjdata);
15787 }
15788 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
15789 {
15790 if (add_prefix)
15791 {
15792 oa->write_character(to_char_type('L')); // int64
15793 }
15794 write_number(static_cast<std::int64_t>(n), use_bjdata);
15795 }
15796 // LCOV_EXCL_START
15797 else
15798 {
15799 if (add_prefix)
15800 {
15801 oa->write_character(to_char_type('H')); // high-precision number
15802 }
15803
15804 const auto number = BasicJsonType(n).dump();
15805 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
15806 for (std::size_t i = 0; i < number.size(); ++i)
15807 {
15808 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
15809 }
15810 }
15811 // LCOV_EXCL_STOP
15812 }
15813
15817 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
15818 {
15819 switch (j.type())
15820 {
15821 case value_t::null:
15822 return 'Z';
15823
15824 case value_t::boolean:
15825 return j.m_value.boolean ? 'T' : 'F';
15826
15827 case value_t::number_integer:
15828 {
15829 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)())
15830 {
15831 return 'i';
15832 }
15833 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)())
15834 {
15835 return 'U';
15836 }
15837 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)())
15838 {
15839 return 'I';
15840 }
15841 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
15842 {
15843 return 'u';
15844 }
15845 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)())
15846 {
15847 return 'l';
15848 }
15849 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
15850 {
15851 return 'm';
15852 }
15853 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)())
15854 {
15855 return 'L';
15856 }
15857 // anything else is treated as high-precision number
15858 return 'H'; // LCOV_EXCL_LINE
15859 }
15860
15861 case value_t::number_unsigned:
15862 {
15863 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
15864 {
15865 return 'i';
15866 }
15867 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
15868 {
15869 return 'U';
15870 }
15871 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
15872 {
15873 return 'I';
15874 }
15875 if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
15876 {
15877 return 'u';
15878 }
15879 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
15880 {
15881 return 'l';
15882 }
15883 if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
15884 {
15885 return 'm';
15886 }
15887 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
15888 {
15889 return 'L';
15890 }
15891 if (use_bjdata && j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15892 {
15893 return 'M';
15894 }
15895 // anything else is treated as high-precision number
15896 return 'H'; // LCOV_EXCL_LINE
15897 }
15898
15899 case value_t::number_float:
15900 return get_ubjson_float_prefix(j.m_value.number_float);
15901
15902 case value_t::string:
15903 return 'S';
15904
15905 case value_t::array: // fallthrough
15906 case value_t::binary:
15907 return '[';
15908
15909 case value_t::object:
15910 return '{';
15911
15912 case value_t::discarded:
15913 default: // discarded values
15914 return 'N';
15915 }
15916 }
15917
15918 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
15919 {
15920 return 'd'; // float 32
15921 }
15922
15923 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
15924 {
15925 return 'D'; // float 64
15926 }
15927
15931 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
15932 {
15933 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
15934 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
15935 };
15936
15937 string_t key = "_ArrayType_";
15938 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
15939 if (it == bjdtype.end())
15940 {
15941 return true;
15942 }
15943 CharType dtype = it->second;
15944
15945 key = "_ArraySize_";
15946 std::size_t len = (value.at(key).empty() ? 0 : 1);
15947 for (const auto& el : value.at(key))
15948 {
15949 len *= static_cast<std::size_t>(el.m_value.number_unsigned);
15950 }
15951
15952 key = "_ArrayData_";
15953 if (value.at(key).size() != len)
15954 {
15955 return true;
15956 }
15957
15958 oa->write_character('[');
15959 oa->write_character('$');
15960 oa->write_character(dtype);
15961 oa->write_character('#');
15962
15963 key = "_ArraySize_";
15964 write_ubjson(value.at(key), use_count, use_type, true, true);
15965
15966 key = "_ArrayData_";
15967 if (dtype == 'U' || dtype == 'C')
15968 {
15969 for (const auto& el : value.at(key))
15970 {
15971 write_number(static_cast<std::uint8_t>(el.m_value.number_unsigned), true);
15972 }
15973 }
15974 else if (dtype == 'i')
15975 {
15976 for (const auto& el : value.at(key))
15977 {
15978 write_number(static_cast<std::int8_t>(el.m_value.number_integer), true);
15979 }
15980 }
15981 else if (dtype == 'u')
15982 {
15983 for (const auto& el : value.at(key))
15984 {
15985 write_number(static_cast<std::uint16_t>(el.m_value.number_unsigned), true);
15986 }
15987 }
15988 else if (dtype == 'I')
15989 {
15990 for (const auto& el : value.at(key))
15991 {
15992 write_number(static_cast<std::int16_t>(el.m_value.number_integer), true);
15993 }
15994 }
15995 else if (dtype == 'm')
15996 {
15997 for (const auto& el : value.at(key))
15998 {
15999 write_number(static_cast<std::uint32_t>(el.m_value.number_unsigned), true);
16000 }
16001 }
16002 else if (dtype == 'l')
16003 {
16004 for (const auto& el : value.at(key))
16005 {
16006 write_number(static_cast<std::int32_t>(el.m_value.number_integer), true);
16007 }
16008 }
16009 else if (dtype == 'M')
16010 {
16011 for (const auto& el : value.at(key))
16012 {
16013 write_number(static_cast<std::uint64_t>(el.m_value.number_unsigned), true);
16014 }
16015 }
16016 else if (dtype == 'L')
16017 {
16018 for (const auto& el : value.at(key))
16019 {
16020 write_number(static_cast<std::int64_t>(el.m_value.number_integer), true);
16021 }
16022 }
16023 else if (dtype == 'd')
16024 {
16025 for (const auto& el : value.at(key))
16026 {
16027 write_number(static_cast<float>(el.m_value.number_float), true);
16028 }
16029 }
16030 else if (dtype == 'D')
16031 {
16032 for (const auto& el : value.at(key))
16033 {
16034 write_number(static_cast<double>(el.m_value.number_float), true);
16035 }
16036 }
16037 return false;
16038 }
16039
16041 // Utility functions //
16043
16044 /*
16045 @brief write a number to output input
16046 @param[in] n number of type @a NumberType
16047 @param[in] OutputIsLittleEndian Set to true if output data is
16048 required to be little endian
16049 @tparam NumberType the type of the number
16050
16051 @note This function needs to respect the system's endianness, because bytes
16052 in CBOR, MessagePack, and UBJSON are stored in network order (big
16053 endian) and therefore need reordering on little endian systems.
16054 On the other hand, BSON and BJData use little endian and should reorder
16055 on big endian systems.
16056 */
16057 template<typename NumberType>
16058 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
16059 {
16060 // step 1: write number to array of length NumberType
16061 std::array<CharType, sizeof(NumberType)> vec{};
16062 std::memcpy(vec.data(), &n, sizeof(NumberType));
16063
16064 // step 2: write array to output (with possible reordering)
16065 if (is_little_endian != OutputIsLittleEndian)
16066 {
16067 // reverse byte order prior to conversion if necessary
16068 std::reverse(vec.begin(), vec.end());
16069 }
16070
16071 oa->write_characters(vec.data(), sizeof(NumberType));
16072 }
16073
16074 void write_compact_float(const number_float_t n, detail::input_format_t format)
16075 {
16076#ifdef __GNUC__
16077#pragma GCC diagnostic push
16078#pragma GCC diagnostic ignored "-Wfloat-equal"
16079#endif
16080 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
16081 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
16082 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
16083 {
16084 oa->write_character(format == detail::input_format_t::cbor
16085 ? get_cbor_float_prefix(static_cast<float>(n))
16086 : get_msgpack_float_prefix(static_cast<float>(n)));
16087 write_number(static_cast<float>(n));
16088 }
16089 else
16090 {
16091 oa->write_character(format == detail::input_format_t::cbor
16092 ? get_cbor_float_prefix(n)
16093 : get_msgpack_float_prefix(n));
16094 write_number(n);
16095 }
16096#ifdef __GNUC__
16097#pragma GCC diagnostic pop
16098#endif
16099 }
16100
16101 public:
16102 // The following to_char_type functions are implement the conversion
16103 // between uint8_t and CharType. In case CharType is not unsigned,
16104 // such a conversion is required to allow values greater than 128.
16105 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
16106 template < typename C = CharType,
16107 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
16108 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16109 {
16110 return *reinterpret_cast<char*>(&x);
16111 }
16112
16113 template < typename C = CharType,
16114 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
16115 static CharType to_char_type(std::uint8_t x) noexcept
16116 {
16117 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
16118 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
16119 CharType result;
16120 std::memcpy(&result, &x, sizeof(x));
16121 return result;
16122 }
16123
16124 template<typename C = CharType,
16125 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
16126 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16127 {
16128 return x;
16129 }
16130
16131 template < typename InputCharType, typename C = CharType,
16132 enable_if_t <
16133 std::is_signed<C>::value &&
16134 std::is_signed<char>::value &&
16135 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
16136 > * = nullptr >
16137 static constexpr CharType to_char_type(InputCharType x) noexcept
16138 {
16139 return x;
16140 }
16141
16142 private:
16144 const bool is_little_endian = little_endianness();
16145
16147 output_adapter_t<CharType> oa = nullptr;
16148};
16149} // namespace detail
16150} // namespace nlohmann
16151
16152// #include <nlohmann/detail/output/output_adapters.hpp>
16153
16154// #include <nlohmann/detail/output/serializer.hpp>
16155
16156
16157#include <algorithm> // reverse, remove, fill, find, none_of
16158#include <array> // array
16159#include <clocale> // localeconv, lconv
16160#include <cmath> // labs, isfinite, isnan, signbit
16161#include <cstddef> // size_t, ptrdiff_t
16162#include <cstdint> // uint8_t
16163#include <cstdio> // snprintf
16164#include <limits> // numeric_limits
16165#include <string> // string, char_traits
16166#include <iomanip> // setfill, setw
16167#include <type_traits> // is_same
16168#include <utility> // move
16169
16170// #include <nlohmann/detail/conversions/to_chars.hpp>
16171
16172
16173#include <array> // array
16174#include <cmath> // signbit, isfinite
16175#include <cstdint> // intN_t, uintN_t
16176#include <cstring> // memcpy, memmove
16177#include <limits> // numeric_limits
16178#include <type_traits> // conditional
16179
16180// #include <nlohmann/detail/macro_scope.hpp>
16181
16182
16183namespace nlohmann
16184{
16185namespace detail
16186{
16187
16207namespace dtoa_impl
16208{
16209
16210template<typename Target, typename Source>
16211Target reinterpret_bits(const Source source)
16212{
16213 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
16214
16215 Target target;
16216 std::memcpy(&target, &source, sizeof(Source));
16217 return target;
16218}
16219
16220struct diyfp // f * 2^e
16221{
16222 static constexpr int kPrecision = 64; // = q
16223
16224 std::uint64_t f = 0;
16225 int e = 0;
16226
16227 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
16228
16233 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
16234 {
16235 JSON_ASSERT(x.e == y.e);
16236 JSON_ASSERT(x.f >= y.f);
16237
16238 return {x.f - y.f, x.e};
16239 }
16240
16245 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
16246 {
16247 static_assert(kPrecision == 64, "internal error");
16248
16249 // Computes:
16250 // f = round((x.f * y.f) / 2^q)
16251 // e = x.e + y.e + q
16252
16253 // Emulate the 64-bit * 64-bit multiplication:
16254 //
16255 // p = u * v
16256 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
16257 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
16258 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
16259 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
16260 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
16261 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
16262 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
16263 //
16264 // (Since Q might be larger than 2^32 - 1)
16265 //
16266 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
16267 //
16268 // (Q_hi + H does not overflow a 64-bit int)
16269 //
16270 // = p_lo + 2^64 p_hi
16271
16272 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
16273 const std::uint64_t u_hi = x.f >> 32u;
16274 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
16275 const std::uint64_t v_hi = y.f >> 32u;
16276
16277 const std::uint64_t p0 = u_lo * v_lo;
16278 const std::uint64_t p1 = u_lo * v_hi;
16279 const std::uint64_t p2 = u_hi * v_lo;
16280 const std::uint64_t p3 = u_hi * v_hi;
16281
16282 const std::uint64_t p0_hi = p0 >> 32u;
16283 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
16284 const std::uint64_t p1_hi = p1 >> 32u;
16285 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
16286 const std::uint64_t p2_hi = p2 >> 32u;
16287
16288 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
16289
16290 // The full product might now be computed as
16291 //
16292 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
16293 // p_lo = p0_lo + (Q << 32)
16294 //
16295 // But in this particular case here, the full p_lo is not required.
16296 // Effectively we only need to add the highest bit in p_lo to p_hi (and
16297 // Q_hi + 1 does not overflow).
16298
16299 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
16300
16301 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
16302
16303 return {h, x.e + y.e + 64};
16304 }
16305
16310 static diyfp normalize(diyfp x) noexcept
16311 {
16312 JSON_ASSERT(x.f != 0);
16313
16314 while ((x.f >> 63u) == 0)
16315 {
16316 x.f <<= 1u;
16317 x.e--;
16318 }
16319
16320 return x;
16321 }
16322
16327 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
16328 {
16329 const int delta = x.e - target_exponent;
16330
16331 JSON_ASSERT(delta >= 0);
16332 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
16333
16334 return {x.f << delta, target_exponent};
16335 }
16336};
16337
16338struct boundaries
16339{
16340 diyfp w;
16341 diyfp minus;
16342 diyfp plus;
16343};
16344
16351template<typename FloatType>
16352boundaries compute_boundaries(FloatType value)
16353{
16354 JSON_ASSERT(std::isfinite(value));
16355 JSON_ASSERT(value > 0);
16356
16357 // Convert the IEEE representation into a diyfp.
16358 //
16359 // If v is denormal:
16360 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
16361 // If v is normalized:
16362 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
16363
16364 static_assert(std::numeric_limits<FloatType>::is_iec559,
16365 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
16366
16367 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
16368 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
16369 constexpr int kMinExp = 1 - kBias;
16370 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
16371
16372 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
16373
16374 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
16375 const std::uint64_t E = bits >> (kPrecision - 1);
16376 const std::uint64_t F = bits & (kHiddenBit - 1);
16377
16378 const bool is_denormal = E == 0;
16379 const diyfp v = is_denormal
16380 ? diyfp(F, kMinExp)
16381 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
16382
16383 // Compute the boundaries m- and m+ of the floating-point value
16384 // v = f * 2^e.
16385 //
16386 // Determine v- and v+, the floating-point predecessor and successor if v,
16387 // respectively.
16388 //
16389 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
16390 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
16391 //
16392 // v+ = v + 2^e
16393 //
16394 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
16395 // between m- and m+ round to v, regardless of how the input rounding
16396 // algorithm breaks ties.
16397 //
16398 // ---+-------------+-------------+-------------+-------------+--- (A)
16399 // v- m- v m+ v+
16400 //
16401 // -----------------+------+------+-------------+-------------+--- (B)
16402 // v- m- v m+ v+
16403
16404 const bool lower_boundary_is_closer = F == 0 && E > 1;
16405 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
16406 const diyfp m_minus = lower_boundary_is_closer
16407 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
16408 : diyfp(2 * v.f - 1, v.e - 1); // (A)
16409
16410 // Determine the normalized w+ = m+.
16411 const diyfp w_plus = diyfp::normalize(m_plus);
16412
16413 // Determine w- = m- such that e_(w-) = e_(w+).
16414 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
16415
16416 return {diyfp::normalize(v), w_minus, w_plus};
16417}
16418
16419// Given normalized diyfp w, Grisu needs to find a (normalized) cached
16420// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
16421// within a certain range [alpha, gamma] (Definition 3.2 from [1])
16422//
16423// alpha <= e = e_c + e_w + q <= gamma
16424//
16425// or
16426//
16427// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
16428// <= f_c * f_w * 2^gamma
16429//
16430// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
16431//
16432// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
16433//
16434// or
16435//
16436// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
16437//
16438// The choice of (alpha,gamma) determines the size of the table and the form of
16439// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
16440// in practice:
16441//
16442// The idea is to cut the number c * w = f * 2^e into two parts, which can be
16443// processed independently: An integral part p1, and a fractional part p2:
16444//
16445// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
16446// = (f div 2^-e) + (f mod 2^-e) * 2^e
16447// = p1 + p2 * 2^e
16448//
16449// The conversion of p1 into decimal form requires a series of divisions and
16450// modulos by (a power of) 10. These operations are faster for 32-bit than for
16451// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
16452// achieved by choosing
16453//
16454// -e >= 32 or e <= -32 := gamma
16455//
16456// In order to convert the fractional part
16457//
16458// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
16459//
16460// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
16461// d[-i] are extracted in order:
16462//
16463// (10 * p2) div 2^-e = d[-1]
16464// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
16465//
16466// The multiplication by 10 must not overflow. It is sufficient to choose
16467//
16468// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
16469//
16470// Since p2 = f mod 2^-e < 2^-e,
16471//
16472// -e <= 60 or e >= -60 := alpha
16473
16474constexpr int kAlpha = -60;
16475constexpr int kGamma = -32;
16476
16477struct cached_power // c = f * 2^e ~= 10^k
16478{
16479 std::uint64_t f;
16480 int e;
16481 int k;
16482};
16483
16491inline cached_power get_cached_power_for_binary_exponent(int e)
16492{
16493 // Now
16494 //
16495 // alpha <= e_c + e + q <= gamma (1)
16496 // ==> f_c * 2^alpha <= c * 2^e * 2^q
16497 //
16498 // and since the c's are normalized, 2^(q-1) <= f_c,
16499 //
16500 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
16501 // ==> 2^(alpha - e - 1) <= c
16502 //
16503 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
16504 //
16505 // k = ceil( log_10( 2^(alpha - e - 1) ) )
16506 // = ceil( (alpha - e - 1) * log_10(2) )
16507 //
16508 // From the paper:
16509 // "In theory the result of the procedure could be wrong since c is rounded,
16510 // and the computation itself is approximated [...]. In practice, however,
16511 // this simple function is sufficient."
16512 //
16513 // For IEEE double precision floating-point numbers converted into
16514 // normalized diyfp's w = f * 2^e, with q = 64,
16515 //
16516 // e >= -1022 (min IEEE exponent)
16517 // -52 (p - 1)
16518 // -52 (p - 1, possibly normalize denormal IEEE numbers)
16519 // -11 (normalize the diyfp)
16520 // = -1137
16521 //
16522 // and
16523 //
16524 // e <= +1023 (max IEEE exponent)
16525 // -52 (p - 1)
16526 // -11 (normalize the diyfp)
16527 // = 960
16528 //
16529 // This binary exponent range [-1137,960] results in a decimal exponent
16530 // range [-307,324]. One does not need to store a cached power for each
16531 // k in this range. For each such k it suffices to find a cached power
16532 // such that the exponent of the product lies in [alpha,gamma].
16533 // This implies that the difference of the decimal exponents of adjacent
16534 // table entries must be less than or equal to
16535 //
16536 // floor( (gamma - alpha) * log_10(2) ) = 8.
16537 //
16538 // (A smaller distance gamma-alpha would require a larger table.)
16539
16540 // NB:
16541 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
16542
16543 constexpr int kCachedPowersMinDecExp = -300;
16544 constexpr int kCachedPowersDecStep = 8;
16545
16546 static constexpr std::array<cached_power, 79> kCachedPowers =
16547 {
16548 {
16549 { 0xAB70FE17C79AC6CA, -1060, -300 },
16550 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
16551 { 0xBE5691EF416BD60C, -1007, -284 },
16552 { 0x8DD01FAD907FFC3C, -980, -276 },
16553 { 0xD3515C2831559A83, -954, -268 },
16554 { 0x9D71AC8FADA6C9B5, -927, -260 },
16555 { 0xEA9C227723EE8BCB, -901, -252 },
16556 { 0xAECC49914078536D, -874, -244 },
16557 { 0x823C12795DB6CE57, -847, -236 },
16558 { 0xC21094364DFB5637, -821, -228 },
16559 { 0x9096EA6F3848984F, -794, -220 },
16560 { 0xD77485CB25823AC7, -768, -212 },
16561 { 0xA086CFCD97BF97F4, -741, -204 },
16562 { 0xEF340A98172AACE5, -715, -196 },
16563 { 0xB23867FB2A35B28E, -688, -188 },
16564 { 0x84C8D4DFD2C63F3B, -661, -180 },
16565 { 0xC5DD44271AD3CDBA, -635, -172 },
16566 { 0x936B9FCEBB25C996, -608, -164 },
16567 { 0xDBAC6C247D62A584, -582, -156 },
16568 { 0xA3AB66580D5FDAF6, -555, -148 },
16569 { 0xF3E2F893DEC3F126, -529, -140 },
16570 { 0xB5B5ADA8AAFF80B8, -502, -132 },
16571 { 0x87625F056C7C4A8B, -475, -124 },
16572 { 0xC9BCFF6034C13053, -449, -116 },
16573 { 0x964E858C91BA2655, -422, -108 },
16574 { 0xDFF9772470297EBD, -396, -100 },
16575 { 0xA6DFBD9FB8E5B88F, -369, -92 },
16576 { 0xF8A95FCF88747D94, -343, -84 },
16577 { 0xB94470938FA89BCF, -316, -76 },
16578 { 0x8A08F0F8BF0F156B, -289, -68 },
16579 { 0xCDB02555653131B6, -263, -60 },
16580 { 0x993FE2C6D07B7FAC, -236, -52 },
16581 { 0xE45C10C42A2B3B06, -210, -44 },
16582 { 0xAA242499697392D3, -183, -36 },
16583 { 0xFD87B5F28300CA0E, -157, -28 },
16584 { 0xBCE5086492111AEB, -130, -20 },
16585 { 0x8CBCCC096F5088CC, -103, -12 },
16586 { 0xD1B71758E219652C, -77, -4 },
16587 { 0x9C40000000000000, -50, 4 },
16588 { 0xE8D4A51000000000, -24, 12 },
16589 { 0xAD78EBC5AC620000, 3, 20 },
16590 { 0x813F3978F8940984, 30, 28 },
16591 { 0xC097CE7BC90715B3, 56, 36 },
16592 { 0x8F7E32CE7BEA5C70, 83, 44 },
16593 { 0xD5D238A4ABE98068, 109, 52 },
16594 { 0x9F4F2726179A2245, 136, 60 },
16595 { 0xED63A231D4C4FB27, 162, 68 },
16596 { 0xB0DE65388CC8ADA8, 189, 76 },
16597 { 0x83C7088E1AAB65DB, 216, 84 },
16598 { 0xC45D1DF942711D9A, 242, 92 },
16599 { 0x924D692CA61BE758, 269, 100 },
16600 { 0xDA01EE641A708DEA, 295, 108 },
16601 { 0xA26DA3999AEF774A, 322, 116 },
16602 { 0xF209787BB47D6B85, 348, 124 },
16603 { 0xB454E4A179DD1877, 375, 132 },
16604 { 0x865B86925B9BC5C2, 402, 140 },
16605 { 0xC83553C5C8965D3D, 428, 148 },
16606 { 0x952AB45CFA97A0B3, 455, 156 },
16607 { 0xDE469FBD99A05FE3, 481, 164 },
16608 { 0xA59BC234DB398C25, 508, 172 },
16609 { 0xF6C69A72A3989F5C, 534, 180 },
16610 { 0xB7DCBF5354E9BECE, 561, 188 },
16611 { 0x88FCF317F22241E2, 588, 196 },
16612 { 0xCC20CE9BD35C78A5, 614, 204 },
16613 { 0x98165AF37B2153DF, 641, 212 },
16614 { 0xE2A0B5DC971F303A, 667, 220 },
16615 { 0xA8D9D1535CE3B396, 694, 228 },
16616 { 0xFB9B7CD9A4A7443C, 720, 236 },
16617 { 0xBB764C4CA7A44410, 747, 244 },
16618 { 0x8BAB8EEFB6409C1A, 774, 252 },
16619 { 0xD01FEF10A657842C, 800, 260 },
16620 { 0x9B10A4E5E9913129, 827, 268 },
16621 { 0xE7109BFBA19C0C9D, 853, 276 },
16622 { 0xAC2820D9623BF429, 880, 284 },
16623 { 0x80444B5E7AA7CF85, 907, 292 },
16624 { 0xBF21E44003ACDD2D, 933, 300 },
16625 { 0x8E679C2F5E44FF8F, 960, 308 },
16626 { 0xD433179D9C8CB841, 986, 316 },
16627 { 0x9E19DB92B4E31BA9, 1013, 324 },
16628 }
16629 };
16630
16631 // This computation gives exactly the same results for k as
16632 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
16633 // for |e| <= 1500, but doesn't require floating-point operations.
16634 // NB: log_10(2) ~= 78913 / 2^18
16635 JSON_ASSERT(e >= -1500);
16636 JSON_ASSERT(e <= 1500);
16637 const int f = kAlpha - e - 1;
16638 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
16639
16640 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
16641 JSON_ASSERT(index >= 0);
16642 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
16643
16644 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
16645 JSON_ASSERT(kAlpha <= cached.e + e + 64);
16646 JSON_ASSERT(kGamma >= cached.e + e + 64);
16647
16648 return cached;
16649}
16650
16655inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
16656{
16657 // LCOV_EXCL_START
16658 if (n >= 1000000000)
16659 {
16660 pow10 = 1000000000;
16661 return 10;
16662 }
16663 // LCOV_EXCL_STOP
16664 if (n >= 100000000)
16665 {
16666 pow10 = 100000000;
16667 return 9;
16668 }
16669 if (n >= 10000000)
16670 {
16671 pow10 = 10000000;
16672 return 8;
16673 }
16674 if (n >= 1000000)
16675 {
16676 pow10 = 1000000;
16677 return 7;
16678 }
16679 if (n >= 100000)
16680 {
16681 pow10 = 100000;
16682 return 6;
16683 }
16684 if (n >= 10000)
16685 {
16686 pow10 = 10000;
16687 return 5;
16688 }
16689 if (n >= 1000)
16690 {
16691 pow10 = 1000;
16692 return 4;
16693 }
16694 if (n >= 100)
16695 {
16696 pow10 = 100;
16697 return 3;
16698 }
16699 if (n >= 10)
16700 {
16701 pow10 = 10;
16702 return 2;
16703 }
16704
16705 pow10 = 1;
16706 return 1;
16707}
16708
16709inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
16710 std::uint64_t rest, std::uint64_t ten_k)
16711{
16712 JSON_ASSERT(len >= 1);
16713 JSON_ASSERT(dist <= delta);
16714 JSON_ASSERT(rest <= delta);
16715 JSON_ASSERT(ten_k > 0);
16716
16717 // <--------------------------- delta ---->
16718 // <---- dist --------->
16719 // --------------[------------------+-------------------]--------------
16720 // M- w M+
16721 //
16722 // ten_k
16723 // <------>
16724 // <---- rest ---->
16725 // --------------[------------------+----+--------------]--------------
16726 // w V
16727 // = buf * 10^k
16728 //
16729 // ten_k represents a unit-in-the-last-place in the decimal representation
16730 // stored in buf.
16731 // Decrement buf by ten_k while this takes buf closer to w.
16732
16733 // The tests are written in this order to avoid overflow in unsigned
16734 // integer arithmetic.
16735
16736 while (rest < dist
16737 && delta - rest >= ten_k
16738 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
16739 {
16740 JSON_ASSERT(buf[len - 1] != '0');
16741 buf[len - 1]--;
16742 rest += ten_k;
16743 }
16744}
16745
16750inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
16751 diyfp M_minus, diyfp w, diyfp M_plus)
16752{
16753 static_assert(kAlpha >= -60, "internal error");
16754 static_assert(kGamma <= -32, "internal error");
16755
16756 // Generates the digits (and the exponent) of a decimal floating-point
16757 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
16758 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
16759 //
16760 // <--------------------------- delta ---->
16761 // <---- dist --------->
16762 // --------------[------------------+-------------------]--------------
16763 // M- w M+
16764 //
16765 // Grisu2 generates the digits of M+ from left to right and stops as soon as
16766 // V is in [M-,M+].
16767
16768 JSON_ASSERT(M_plus.e >= kAlpha);
16769 JSON_ASSERT(M_plus.e <= kGamma);
16770
16771 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
16772 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
16773
16774 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
16775 //
16776 // M+ = f * 2^e
16777 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
16778 // = ((p1 ) * 2^-e + (p2 )) * 2^e
16779 // = p1 + p2 * 2^e
16780
16781 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
16782
16783 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.)
16784 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
16785
16786 // 1)
16787 //
16788 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
16789
16790 JSON_ASSERT(p1 > 0);
16791
16792 std::uint32_t pow10{};
16793 const int k = find_largest_pow10(p1, pow10);
16794
16795 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
16796 //
16797 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
16798 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
16799 //
16800 // M+ = p1 + p2 * 2^e
16801 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
16802 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
16803 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
16804 //
16805 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
16806 //
16807 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
16808 //
16809 // but stop as soon as
16810 //
16811 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
16812
16813 int n = k;
16814 while (n > 0)
16815 {
16816 // Invariants:
16817 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
16818 // pow10 = 10^(n-1) <= p1 < 10^n
16819 //
16820 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
16821 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
16822 //
16823 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
16824 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
16825 //
16826 JSON_ASSERT(d <= 9);
16827 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
16828 //
16829 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
16830 //
16831 p1 = r;
16832 n--;
16833 //
16834 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
16835 // pow10 = 10^n
16836 //
16837
16838 // Now check if enough digits have been generated.
16839 // Compute
16840 //
16841 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
16842 //
16843 // Note:
16844 // Since rest and delta share the same exponent e, it suffices to
16845 // compare the significands.
16846 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
16847 if (rest <= delta)
16848 {
16849 // V = buffer * 10^n, with M- <= V <= M+.
16850
16851 decimal_exponent += n;
16852
16853 // We may now just stop. But instead look if the buffer could be
16854 // decremented to bring V closer to w.
16855 //
16856 // pow10 = 10^n is now 1 ulp in the decimal representation V.
16857 // The rounding procedure works with diyfp's with an implicit
16858 // exponent of e.
16859 //
16860 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
16861 //
16862 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
16863 grisu2_round(buffer, length, dist, delta, rest, ten_n);
16864
16865 return;
16866 }
16867
16868 pow10 /= 10;
16869 //
16870 // pow10 = 10^(n-1) <= p1 < 10^n
16871 // Invariants restored.
16872 }
16873
16874 // 2)
16875 //
16876 // The digits of the integral part have been generated:
16877 //
16878 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
16879 // = buffer + p2 * 2^e
16880 //
16881 // Now generate the digits of the fractional part p2 * 2^e.
16882 //
16883 // Note:
16884 // No decimal point is generated: the exponent is adjusted instead.
16885 //
16886 // p2 actually represents the fraction
16887 //
16888 // p2 * 2^e
16889 // = p2 / 2^-e
16890 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
16891 //
16892 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
16893 //
16894 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
16895 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
16896 //
16897 // using
16898 //
16899 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
16900 // = ( d) * 2^-e + ( r)
16901 //
16902 // or
16903 // 10^m * p2 * 2^e = d + r * 2^e
16904 //
16905 // i.e.
16906 //
16907 // M+ = buffer + p2 * 2^e
16908 // = buffer + 10^-m * (d + r * 2^e)
16909 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
16910 //
16911 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
16912
16913 JSON_ASSERT(p2 > delta);
16914
16915 int m = 0;
16916 for (;;)
16917 {
16918 // Invariant:
16919 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
16920 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
16921 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
16922 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
16923 //
16924 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
16925 p2 *= 10;
16926 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
16927 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
16928 //
16929 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
16930 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
16931 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
16932 //
16933 JSON_ASSERT(d <= 9);
16934 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
16935 //
16936 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
16937 //
16938 p2 = r;
16939 m++;
16940 //
16941 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
16942 // Invariant restored.
16943
16944 // Check if enough digits have been generated.
16945 //
16946 // 10^-m * p2 * 2^e <= delta * 2^e
16947 // p2 * 2^e <= 10^m * delta * 2^e
16948 // p2 <= 10^m * delta
16949 delta *= 10;
16950 dist *= 10;
16951 if (p2 <= delta)
16952 {
16953 break;
16954 }
16955 }
16956
16957 // V = buffer * 10^-m, with M- <= V <= M+.
16958
16959 decimal_exponent -= m;
16960
16961 // 1 ulp in the decimal representation is now 10^-m.
16962 // Since delta and dist are now scaled by 10^m, we need to do the
16963 // same with ulp in order to keep the units in sync.
16964 //
16965 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
16966 //
16967 const std::uint64_t ten_m = one.f;
16968 grisu2_round(buffer, length, dist, delta, p2, ten_m);
16969
16970 // By construction this algorithm generates the shortest possible decimal
16971 // number (Loitsch, Theorem 6.2) which rounds back to w.
16972 // For an input number of precision p, at least
16973 //
16974 // N = 1 + ceil(p * log_10(2))
16975 //
16976 // decimal digits are sufficient to identify all binary floating-point
16977 // numbers (Matula, "In-and-Out conversions").
16978 // This implies that the algorithm does not produce more than N decimal
16979 // digits.
16980 //
16981 // N = 17 for p = 53 (IEEE double precision)
16982 // N = 9 for p = 24 (IEEE single precision)
16983}
16984
16991inline void grisu2(char* buf, int& len, int& decimal_exponent,
16992 diyfp m_minus, diyfp v, diyfp m_plus)
16993{
16994 JSON_ASSERT(m_plus.e == m_minus.e);
16995 JSON_ASSERT(m_plus.e == v.e);
16996
16997 // --------(-----------------------+-----------------------)-------- (A)
16998 // m- v m+
16999 //
17000 // --------------------(-----------+-----------------------)-------- (B)
17001 // m- v m+
17002 //
17003 // First scale v (and m- and m+) such that the exponent is in the range
17004 // [alpha, gamma].
17005
17006 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
17007
17008 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
17009
17010 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
17011 const diyfp w = diyfp::mul(v, c_minus_k);
17012 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
17013 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
17014
17015 // ----(---+---)---------------(---+---)---------------(---+---)----
17016 // w- w w+
17017 // = c*m- = c*v = c*m+
17018 //
17019 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
17020 // w+ are now off by a small amount.
17021 // In fact:
17022 //
17023 // w - v * 10^k < 1 ulp
17024 //
17025 // To account for this inaccuracy, add resp. subtract 1 ulp.
17026 //
17027 // --------+---[---------------(---+---)---------------]---+--------
17028 // w- M- w M+ w+
17029 //
17030 // Now any number in [M-, M+] (bounds included) will round to w when input,
17031 // regardless of how the input rounding algorithm breaks ties.
17032 //
17033 // And digit_gen generates the shortest possible such number in [M-, M+].
17034 // Note that this does not mean that Grisu2 always generates the shortest
17035 // possible number in the interval (m-, m+).
17036 const diyfp M_minus(w_minus.f + 1, w_minus.e);
17037 const diyfp M_plus (w_plus.f - 1, w_plus.e );
17038
17039 decimal_exponent = -cached.k; // = -(-k) = k
17040
17041 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
17042}
17043
17049template<typename FloatType>
17051void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
17052{
17053 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
17054 "internal error: not enough precision");
17055
17056 JSON_ASSERT(std::isfinite(value));
17057 JSON_ASSERT(value > 0);
17058
17059 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
17060 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
17061 // decimal representations are not exactly "short".
17062 //
17063 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
17064 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
17065 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
17066 // does.
17067 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
17068 // representation using the corresponding std::from_chars function recovers value exactly". That
17069 // indicates that single precision floating-point numbers should be recovered using
17070 // 'std::strtof'.
17071 //
17072 // NB: If the neighbors are computed for single-precision numbers, there is a single float
17073 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
17074 // value is off by 1 ulp.
17075#if 0
17076 const boundaries w = compute_boundaries(static_cast<double>(value));
17077#else
17078 const boundaries w = compute_boundaries(value);
17079#endif
17080
17081 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
17082}
17083
17091inline char* append_exponent(char* buf, int e)
17092{
17093 JSON_ASSERT(e > -1000);
17094 JSON_ASSERT(e < 1000);
17095
17096 if (e < 0)
17097 {
17098 e = -e;
17099 *buf++ = '-';
17100 }
17101 else
17102 {
17103 *buf++ = '+';
17104 }
17105
17106 auto k = static_cast<std::uint32_t>(e);
17107 if (k < 10)
17108 {
17109 // Always print at least two digits in the exponent.
17110 // This is for compatibility with printf("%g").
17111 *buf++ = '0';
17112 *buf++ = static_cast<char>('0' + k);
17113 }
17114 else if (k < 100)
17115 {
17116 *buf++ = static_cast<char>('0' + k / 10);
17117 k %= 10;
17118 *buf++ = static_cast<char>('0' + k);
17119 }
17120 else
17121 {
17122 *buf++ = static_cast<char>('0' + k / 100);
17123 k %= 100;
17124 *buf++ = static_cast<char>('0' + k / 10);
17125 k %= 10;
17126 *buf++ = static_cast<char>('0' + k);
17127 }
17128
17129 return buf;
17130}
17131
17143inline char* format_buffer(char* buf, int len, int decimal_exponent,
17144 int min_exp, int max_exp)
17145{
17146 JSON_ASSERT(min_exp < 0);
17147 JSON_ASSERT(max_exp > 0);
17148
17149 const int k = len;
17150 const int n = len + decimal_exponent;
17151
17152 // v = buf * 10^(n-k)
17153 // k is the length of the buffer (number of decimal digits)
17154 // n is the position of the decimal point relative to the start of the buffer.
17155
17156 if (k <= n && n <= max_exp)
17157 {
17158 // digits[000]
17159 // len <= max_exp + 2
17160
17161 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
17162 // Make it look like a floating-point number (#362, #378)
17163 buf[n + 0] = '.';
17164 buf[n + 1] = '0';
17165 return buf + (static_cast<size_t>(n) + 2);
17166 }
17167
17168 if (0 < n && n <= max_exp)
17169 {
17170 // dig.its
17171 // len <= max_digits10 + 1
17172
17173 JSON_ASSERT(k > n);
17174
17175 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
17176 buf[n] = '.';
17177 return buf + (static_cast<size_t>(k) + 1U);
17178 }
17179
17180 if (min_exp < n && n <= 0)
17181 {
17182 // 0.[000]digits
17183 // len <= 2 + (-min_exp - 1) + max_digits10
17184
17185 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
17186 buf[0] = '0';
17187 buf[1] = '.';
17188 std::memset(buf + 2, '0', static_cast<size_t>(-n));
17189 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
17190 }
17191
17192 if (k == 1)
17193 {
17194 // dE+123
17195 // len <= 1 + 5
17196
17197 buf += 1;
17198 }
17199 else
17200 {
17201 // d.igitsE+123
17202 // len <= max_digits10 + 1 + 5
17203
17204 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
17205 buf[1] = '.';
17206 buf += 1 + static_cast<size_t>(k);
17207 }
17208
17209 *buf++ = 'e';
17210 return append_exponent(buf, n - 1);
17211}
17212
17213} // namespace dtoa_impl
17214
17225template<typename FloatType>
17228char* to_chars(char* first, const char* last, FloatType value)
17229{
17230 static_cast<void>(last); // maybe unused - fix warning
17231 JSON_ASSERT(std::isfinite(value));
17232
17233 // Use signbit(value) instead of (value < 0) since signbit works for -0.
17234 if (std::signbit(value))
17235 {
17236 value = -value;
17237 *first++ = '-';
17238 }
17239
17240#ifdef __GNUC__
17241#pragma GCC diagnostic push
17242#pragma GCC diagnostic ignored "-Wfloat-equal"
17243#endif
17244 if (value == 0) // +-0
17245 {
17246 *first++ = '0';
17247 // Make it look like a floating-point number (#362, #378)
17248 *first++ = '.';
17249 *first++ = '0';
17250 return first;
17251 }
17252#ifdef __GNUC__
17253#pragma GCC diagnostic pop
17254#endif
17255
17256 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
17257
17258 // Compute v = buffer * 10^decimal_exponent.
17259 // The decimal digits are stored in the buffer, which needs to be interpreted
17260 // as an unsigned decimal integer.
17261 // len is the length of the buffer, i.e. the number of decimal digits.
17262 int len = 0;
17263 int decimal_exponent = 0;
17264 dtoa_impl::grisu2(first, len, decimal_exponent, value);
17265
17266 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
17267
17268 // Format the buffer like printf("%.*g", prec, value)
17269 constexpr int kMinExp = -4;
17270 // Use digits10 here to increase compatibility with version 2.
17271 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
17272
17273 JSON_ASSERT(last - first >= kMaxExp + 2);
17274 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
17275 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
17276
17277 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
17278}
17279
17280} // namespace detail
17281} // namespace nlohmann
17282
17283// #include <nlohmann/detail/exceptions.hpp>
17284
17285// #include <nlohmann/detail/macro_scope.hpp>
17286
17287// #include <nlohmann/detail/meta/cpp_future.hpp>
17288
17289// #include <nlohmann/detail/output/binary_writer.hpp>
17290
17291// #include <nlohmann/detail/output/output_adapters.hpp>
17292
17293// #include <nlohmann/detail/string_concat.hpp>
17294
17295// #include <nlohmann/detail/value_t.hpp>
17296
17297
17298namespace nlohmann
17299{
17300namespace detail
17301{
17303// serialization //
17305
17308{
17309 strict,
17310 replace,
17311 ignore
17312};
17313
17314template<typename BasicJsonType>
17316{
17317 using string_t = typename BasicJsonType::string_t;
17318 using number_float_t = typename BasicJsonType::number_float_t;
17319 using number_integer_t = typename BasicJsonType::number_integer_t;
17320 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
17321 using binary_char_t = typename BasicJsonType::binary_t::value_type;
17322 static constexpr std::uint8_t UTF8_ACCEPT = 0;
17323 static constexpr std::uint8_t UTF8_REJECT = 1;
17324
17325 public:
17331 serializer(output_adapter_t<char> s, const char ichar,
17333 : o(std::move(s))
17334 , loc(std::localeconv())
17335 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
17336 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
17337 , indent_char(ichar)
17339 , error_handler(error_handler_)
17340 {}
17341
17342 // delete because of pointer members
17343 serializer(const serializer&) = delete;
17347 ~serializer() = default;
17348
17371 void dump(const BasicJsonType& val,
17372 const bool pretty_print,
17373 const bool ensure_ascii,
17374 const unsigned int indent_step,
17375 const unsigned int current_indent = 0)
17376 {
17377 switch (val.m_type)
17378 {
17379 case value_t::object:
17380 {
17381 if (val.m_value.object->empty())
17382 {
17383 o->write_characters("{}", 2);
17384 return;
17385 }
17386
17387 if (pretty_print)
17388 {
17389 o->write_characters("{\n", 2);
17390
17391 // variable to hold indentation for recursive calls
17392 const auto new_indent = current_indent + indent_step;
17393 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
17394 {
17395 indent_string.resize(indent_string.size() * 2, ' ');
17396 }
17397
17398 // first n-1 elements
17399 auto i = val.m_value.object->cbegin();
17400 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
17401 {
17402 o->write_characters(indent_string.c_str(), new_indent);
17403 o->write_character('\"');
17404 dump_escaped(i->first, ensure_ascii);
17405 o->write_characters("\": ", 3);
17406 dump(i->second, true, ensure_ascii, indent_step, new_indent);
17407 o->write_characters(",\n", 2);
17408 }
17409
17410 // last element
17411 JSON_ASSERT(i != val.m_value.object->cend());
17412 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
17413 o->write_characters(indent_string.c_str(), new_indent);
17414 o->write_character('\"');
17415 dump_escaped(i->first, ensure_ascii);
17416 o->write_characters("\": ", 3);
17417 dump(i->second, true, ensure_ascii, indent_step, new_indent);
17418
17419 o->write_character('\n');
17420 o->write_characters(indent_string.c_str(), current_indent);
17421 o->write_character('}');
17422 }
17423 else
17424 {
17425 o->write_character('{');
17426
17427 // first n-1 elements
17428 auto i = val.m_value.object->cbegin();
17429 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
17430 {
17431 o->write_character('\"');
17432 dump_escaped(i->first, ensure_ascii);
17433 o->write_characters("\":", 2);
17434 dump(i->second, false, ensure_ascii, indent_step, current_indent);
17435 o->write_character(',');
17436 }
17437
17438 // last element
17439 JSON_ASSERT(i != val.m_value.object->cend());
17440 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
17441 o->write_character('\"');
17442 dump_escaped(i->first, ensure_ascii);
17443 o->write_characters("\":", 2);
17444 dump(i->second, false, ensure_ascii, indent_step, current_indent);
17445
17446 o->write_character('}');
17447 }
17448
17449 return;
17450 }
17451
17452 case value_t::array:
17453 {
17454 if (val.m_value.array->empty())
17455 {
17456 o->write_characters("[]", 2);
17457 return;
17458 }
17459
17460 if (pretty_print)
17461 {
17462 o->write_characters("[\n", 2);
17463
17464 // variable to hold indentation for recursive calls
17465 const auto new_indent = current_indent + indent_step;
17466 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
17467 {
17468 indent_string.resize(indent_string.size() * 2, ' ');
17469 }
17470
17471 // first n-1 elements
17472 for (auto i = val.m_value.array->cbegin();
17473 i != val.m_value.array->cend() - 1; ++i)
17474 {
17475 o->write_characters(indent_string.c_str(), new_indent);
17476 dump(*i, true, ensure_ascii, indent_step, new_indent);
17477 o->write_characters(",\n", 2);
17478 }
17479
17480 // last element
17481 JSON_ASSERT(!val.m_value.array->empty());
17482 o->write_characters(indent_string.c_str(), new_indent);
17483 dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
17484
17485 o->write_character('\n');
17486 o->write_characters(indent_string.c_str(), current_indent);
17487 o->write_character(']');
17488 }
17489 else
17490 {
17491 o->write_character('[');
17492
17493 // first n-1 elements
17494 for (auto i = val.m_value.array->cbegin();
17495 i != val.m_value.array->cend() - 1; ++i)
17496 {
17497 dump(*i, false, ensure_ascii, indent_step, current_indent);
17498 o->write_character(',');
17499 }
17500
17501 // last element
17502 JSON_ASSERT(!val.m_value.array->empty());
17503 dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
17504
17505 o->write_character(']');
17506 }
17507
17508 return;
17509 }
17510
17511 case value_t::string:
17512 {
17513 o->write_character('\"');
17514 dump_escaped(*val.m_value.string, ensure_ascii);
17515 o->write_character('\"');
17516 return;
17517 }
17518
17519 case value_t::binary:
17520 {
17521 if (pretty_print)
17522 {
17523 o->write_characters("{\n", 2);
17524
17525 // variable to hold indentation for recursive calls
17526 const auto new_indent = current_indent + indent_step;
17527 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
17528 {
17529 indent_string.resize(indent_string.size() * 2, ' ');
17530 }
17531
17532 o->write_characters(indent_string.c_str(), new_indent);
17533
17534 o->write_characters("\"bytes\": [", 10);
17535
17536 if (!val.m_value.binary->empty())
17537 {
17538 for (auto i = val.m_value.binary->cbegin();
17539 i != val.m_value.binary->cend() - 1; ++i)
17540 {
17541 dump_integer(*i);
17542 o->write_characters(", ", 2);
17543 }
17544 dump_integer(val.m_value.binary->back());
17545 }
17546
17547 o->write_characters("],\n", 3);
17548 o->write_characters(indent_string.c_str(), new_indent);
17549
17550 o->write_characters("\"subtype\": ", 11);
17551 if (val.m_value.binary->has_subtype())
17552 {
17553 dump_integer(val.m_value.binary->subtype());
17554 }
17555 else
17556 {
17557 o->write_characters("null", 4);
17558 }
17559 o->write_character('\n');
17560 o->write_characters(indent_string.c_str(), current_indent);
17561 o->write_character('}');
17562 }
17563 else
17564 {
17565 o->write_characters("{\"bytes\":[", 10);
17566
17567 if (!val.m_value.binary->empty())
17568 {
17569 for (auto i = val.m_value.binary->cbegin();
17570 i != val.m_value.binary->cend() - 1; ++i)
17571 {
17572 dump_integer(*i);
17573 o->write_character(',');
17574 }
17575 dump_integer(val.m_value.binary->back());
17576 }
17577
17578 o->write_characters("],\"subtype\":", 12);
17579 if (val.m_value.binary->has_subtype())
17580 {
17581 dump_integer(val.m_value.binary->subtype());
17582 o->write_character('}');
17583 }
17584 else
17585 {
17586 o->write_characters("null}", 5);
17587 }
17588 }
17589 return;
17590 }
17591
17592 case value_t::boolean:
17593 {
17594 if (val.m_value.boolean)
17595 {
17596 o->write_characters("true", 4);
17597 }
17598 else
17599 {
17600 o->write_characters("false", 5);
17601 }
17602 return;
17603 }
17604
17606 {
17607 dump_integer(val.m_value.number_integer);
17608 return;
17609 }
17610
17612 {
17613 dump_integer(val.m_value.number_unsigned);
17614 return;
17615 }
17616
17618 {
17619 dump_float(val.m_value.number_float);
17620 return;
17621 }
17622
17623 case value_t::discarded:
17624 {
17625 o->write_characters("<discarded>", 11);
17626 return;
17627 }
17628
17629 case value_t::null:
17630 {
17631 o->write_characters("null", 4);
17632 return;
17633 }
17634
17635 default: // LCOV_EXCL_LINE
17636 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
17637 }
17638 }
17639
17655 void dump_escaped(const string_t& s, const bool ensure_ascii)
17656 {
17657 std::uint32_t codepoint{};
17658 std::uint8_t state = UTF8_ACCEPT;
17659 std::size_t bytes = 0; // number of bytes written to string_buffer
17660
17661 // number of bytes written at the point of the last valid byte
17663 std::size_t undumped_chars = 0;
17664
17665 for (std::size_t i = 0; i < s.size(); ++i)
17666 {
17667 const auto byte = static_cast<std::uint8_t>(s[i]);
17668
17669 switch (decode(state, codepoint, byte))
17670 {
17671 case UTF8_ACCEPT: // decode found a new code point
17672 {
17673 switch (codepoint)
17674 {
17675 case 0x08: // backspace
17676 {
17677 string_buffer[bytes++] = '\\';
17678 string_buffer[bytes++] = 'b';
17679 break;
17680 }
17681
17682 case 0x09: // horizontal tab
17683 {
17684 string_buffer[bytes++] = '\\';
17685 string_buffer[bytes++] = 't';
17686 break;
17687 }
17688
17689 case 0x0A: // newline
17690 {
17691 string_buffer[bytes++] = '\\';
17692 string_buffer[bytes++] = 'n';
17693 break;
17694 }
17695
17696 case 0x0C: // formfeed
17697 {
17698 string_buffer[bytes++] = '\\';
17699 string_buffer[bytes++] = 'f';
17700 break;
17701 }
17702
17703 case 0x0D: // carriage return
17704 {
17705 string_buffer[bytes++] = '\\';
17706 string_buffer[bytes++] = 'r';
17707 break;
17708 }
17709
17710 case 0x22: // quotation mark
17711 {
17712 string_buffer[bytes++] = '\\';
17713 string_buffer[bytes++] = '\"';
17714 break;
17715 }
17716
17717 case 0x5C: // reverse solidus
17718 {
17719 string_buffer[bytes++] = '\\';
17720 string_buffer[bytes++] = '\\';
17721 break;
17722 }
17723
17724 default:
17725 {
17726 // escape control characters (0x00..0x1F) or, if
17727 // ensure_ascii parameter is used, non-ASCII characters
17728 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
17729 {
17730 if (codepoint <= 0xFFFF)
17731 {
17732 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
17733 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
17734 static_cast<std::uint16_t>(codepoint)));
17735 bytes += 6;
17736 }
17737 else
17738 {
17739 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
17740 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
17741 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
17742 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
17743 bytes += 12;
17744 }
17745 }
17746 else
17747 {
17748 // copy byte to buffer (all previous bytes
17749 // been copied have in default case above)
17750 string_buffer[bytes++] = s[i];
17751 }
17752 break;
17753 }
17754 }
17755
17756 // write buffer and reset index; there must be 13 bytes
17757 // left, as this is the maximal number of bytes to be
17758 // written ("\uxxxx\uxxxx\0") for one code point
17759 if (string_buffer.size() - bytes < 13)
17760 {
17761 o->write_characters(string_buffer.data(), bytes);
17762 bytes = 0;
17763 }
17764
17765 // remember the byte position of this accept
17767 undumped_chars = 0;
17768 break;
17769 }
17770
17771 case UTF8_REJECT: // decode found invalid UTF-8 byte
17772 {
17773 switch (error_handler)
17774 {
17776 {
17777 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
17778 }
17779
17782 {
17783 // in case we saw this character the first time, we
17784 // would like to read it again, because the byte
17785 // may be OK for itself, but just not OK for the
17786 // previous sequence
17787 if (undumped_chars > 0)
17788 {
17789 --i;
17790 }
17791
17792 // reset length buffer to the last accepted index;
17793 // thus removing/ignoring the invalid characters
17795
17797 {
17798 // add a replacement character
17799 if (ensure_ascii)
17800 {
17801 string_buffer[bytes++] = '\\';
17802 string_buffer[bytes++] = 'u';
17803 string_buffer[bytes++] = 'f';
17804 string_buffer[bytes++] = 'f';
17805 string_buffer[bytes++] = 'f';
17806 string_buffer[bytes++] = 'd';
17807 }
17808 else
17809 {
17810 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
17811 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
17812 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
17813 }
17814
17815 // write buffer and reset index; there must be 13 bytes
17816 // left, as this is the maximal number of bytes to be
17817 // written ("\uxxxx\uxxxx\0") for one code point
17818 if (string_buffer.size() - bytes < 13)
17819 {
17820 o->write_characters(string_buffer.data(), bytes);
17821 bytes = 0;
17822 }
17823
17825 }
17826
17827 undumped_chars = 0;
17828
17829 // continue processing the string
17830 state = UTF8_ACCEPT;
17831 break;
17832 }
17833
17834 default: // LCOV_EXCL_LINE
17835 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
17836 }
17837 break;
17838 }
17839
17840 default: // decode found yet incomplete multi-byte code point
17841 {
17842 if (!ensure_ascii)
17843 {
17844 // code point will not be escaped - copy byte to buffer
17845 string_buffer[bytes++] = s[i];
17846 }
17848 break;
17849 }
17850 }
17851 }
17852
17853 // we finished processing the string
17854 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
17855 {
17856 // write buffer
17857 if (bytes > 0)
17858 {
17859 o->write_characters(string_buffer.data(), bytes);
17860 }
17861 }
17862 else
17863 {
17864 // we finish reading, but do not accept: string was incomplete
17865 switch (error_handler)
17866 {
17868 {
17869 JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
17870 }
17871
17873 {
17874 // write all accepted bytes
17875 o->write_characters(string_buffer.data(), bytes_after_last_accept);
17876 break;
17877 }
17878
17880 {
17881 // write all accepted bytes
17882 o->write_characters(string_buffer.data(), bytes_after_last_accept);
17883 // add a replacement character
17884 if (ensure_ascii)
17885 {
17886 o->write_characters("\\ufffd", 6);
17887 }
17888 else
17889 {
17890 o->write_characters("\xEF\xBF\xBD", 3);
17891 }
17892 break;
17893 }
17894
17895 default: // LCOV_EXCL_LINE
17896 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
17897 }
17898 }
17899 }
17900
17901 private:
17910 inline unsigned int count_digits(number_unsigned_t x) noexcept
17911 {
17912 unsigned int n_digits = 1;
17913 for (;;)
17914 {
17915 if (x < 10)
17916 {
17917 return n_digits;
17918 }
17919 if (x < 100)
17920 {
17921 return n_digits + 1;
17922 }
17923 if (x < 1000)
17924 {
17925 return n_digits + 2;
17926 }
17927 if (x < 10000)
17928 {
17929 return n_digits + 3;
17930 }
17931 x = x / 10000u;
17932 n_digits += 4;
17933 }
17934 }
17935
17941 static std::string hex_bytes(std::uint8_t byte)
17942 {
17943 std::string result = "FF";
17944 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
17945 result[0] = nibble_to_hex[byte / 16];
17946 result[1] = nibble_to_hex[byte % 16];
17947 return result;
17948 }
17949
17950 // templates to avoid warnings about useless casts
17951 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
17952 bool is_negative_number(NumberType x)
17953 {
17954 return x < 0;
17955 }
17956
17957 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
17958 bool is_negative_number(NumberType /*unused*/)
17959 {
17960 return false;
17961 }
17962
17972 template < typename NumberType, detail::enable_if_t <
17973 std::is_integral<NumberType>::value ||
17974 std::is_same<NumberType, number_unsigned_t>::value ||
17975 std::is_same<NumberType, number_integer_t>::value ||
17976 std::is_same<NumberType, binary_char_t>::value,
17977 int > = 0 >
17978 void dump_integer(NumberType x)
17979 {
17980 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
17981 {
17982 {
17983 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
17984 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
17985 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
17986 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
17987 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
17988 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
17989 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
17990 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
17991 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
17992 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
17993 }
17994 };
17995
17996 // special case for "0"
17997 if (x == 0)
17998 {
17999 o->write_character('0');
18000 return;
18001 }
18002
18003 // use a pointer to fill the buffer
18004 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18005
18006 number_unsigned_t abs_value;
18007
18008 unsigned int n_chars{};
18009
18010 if (is_negative_number(x))
18011 {
18012 *buffer_ptr = '-';
18013 abs_value = remove_sign(static_cast<number_integer_t>(x));
18014
18015 // account one more byte for the minus sign
18016 n_chars = 1 + count_digits(abs_value);
18017 }
18018 else
18019 {
18020 abs_value = static_cast<number_unsigned_t>(x);
18021 n_chars = count_digits(abs_value);
18022 }
18023
18024 // spare 1 byte for '\0'
18025 JSON_ASSERT(n_chars < number_buffer.size() - 1);
18026
18027 // jump to the end to generate the string from backward,
18028 // so we later avoid reversing the result
18029 buffer_ptr += n_chars;
18030
18031 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
18032 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
18033 while (abs_value >= 100)
18034 {
18035 const auto digits_index = static_cast<unsigned>((abs_value % 100));
18036 abs_value /= 100;
18037 *(--buffer_ptr) = digits_to_99[digits_index][1];
18038 *(--buffer_ptr) = digits_to_99[digits_index][0];
18039 }
18040
18041 if (abs_value >= 10)
18042 {
18043 const auto digits_index = static_cast<unsigned>(abs_value);
18044 *(--buffer_ptr) = digits_to_99[digits_index][1];
18045 *(--buffer_ptr) = digits_to_99[digits_index][0];
18046 }
18047 else
18048 {
18049 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
18050 }
18051
18052 o->write_characters(number_buffer.data(), n_chars);
18053 }
18054
18063 void dump_float(number_float_t x)
18064 {
18065 // NaN / inf
18066 if (!std::isfinite(x))
18067 {
18068 o->write_characters("null", 4);
18069 return;
18070 }
18071
18072 // If number_float_t is an IEEE-754 single or double precision number,
18073 // use the Grisu2 algorithm to produce short numbers which are
18074 // guaranteed to round-trip, using strtof and strtod, resp.
18075 //
18076 // NB: The test below works if <long double> == <double>.
18077 static constexpr bool is_ieee_single_or_double
18078 = (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) ||
18079 (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);
18080
18081 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
18082 }
18083
18084 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
18085 {
18086 auto* begin = number_buffer.data();
18087 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
18088
18089 o->write_characters(begin, static_cast<size_t>(end - begin));
18090 }
18091
18092 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
18093 {
18094 // get number of digits for a float -> text -> float round-trip
18095 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
18096
18097 // the actual conversion
18098 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18099 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
18100
18101 // negative value indicates an error
18102 JSON_ASSERT(len > 0);
18103 // check if buffer was large enough
18104 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
18105
18106 // erase thousands separator
18107 if (thousands_sep != '\0')
18108 {
18109 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
18110 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
18111 std::fill(end, number_buffer.end(), '\0');
18112 JSON_ASSERT((end - number_buffer.begin()) <= len);
18113 len = (end - number_buffer.begin());
18114 }
18115
18116 // convert decimal point to '.'
18117 if (decimal_point != '\0' && decimal_point != '.')
18118 {
18119 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
18120 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
18121 if (dec_pos != number_buffer.end())
18122 {
18123 *dec_pos = '.';
18124 }
18125 }
18126
18127 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
18128
18129 // determine if we need to append ".0"
18130 const bool value_is_int_like =
18131 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
18132 [](char c)
18133 {
18134 return c == '.' || c == 'e';
18135 });
18136
18137 if (value_is_int_like)
18138 {
18139 o->write_characters(".0", 2);
18140 }
18141 }
18142
18164 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
18165 {
18166 static const std::array<std::uint8_t, 400> utf8d =
18167 {
18168 {
18169 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
18170 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
18171 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
18172 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
18173 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
18174 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
18175 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
18176 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
18177 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
18178 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
18179 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
18180 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
18181 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
18182 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
18183 }
18184 };
18185
18186 JSON_ASSERT(byte < utf8d.size());
18187 const std::uint8_t type = utf8d[byte];
18188
18189 codep = (state != UTF8_ACCEPT)
18190 ? (byte & 0x3fu) | (codep << 6u)
18191 : (0xFFu >> type) & (byte);
18192
18193 std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
18194 JSON_ASSERT(index < 400);
18195 state = utf8d[index];
18196 return state;
18197 }
18198
18199 /*
18200 * Overload to make the compiler happy while it is instantiating
18201 * dump_integer for number_unsigned_t.
18202 * Must never be called.
18203 */
18204 number_unsigned_t remove_sign(number_unsigned_t x)
18205 {
18206 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18207 return x; // LCOV_EXCL_LINE
18208 }
18209
18210 /*
18211 * Helper function for dump_integer
18212 *
18213 * This function takes a negative signed integer and returns its absolute
18214 * value as unsigned integer. The plus/minus shuffling is necessary as we can
18215 * not directly remove the sign of an arbitrary signed integer as the
18216 * absolute values of INT_MIN and INT_MAX are usually not the same. See
18217 * #1708 for details.
18218 */
18219 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
18220 {
18221 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
18222 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
18223 }
18224
18225 private:
18227 output_adapter_t<char> o = nullptr;
18228
18230 std::array<char, 64> number_buffer{{}};
18231
18233 const std::lconv* loc = nullptr;
18235 const char thousands_sep = '\0';
18237 const char decimal_point = '\0';
18238
18240 std::array<char, 512> string_buffer{{}};
18241
18243 const char indent_char;
18246
18249};
18250} // namespace detail
18251} // namespace nlohmann
18252
18253// #include <nlohmann/detail/value_t.hpp>
18254
18255// #include <nlohmann/json_fwd.hpp>
18256
18257// #include <nlohmann/ordered_map.hpp>
18258
18259
18260#include <functional> // equal_to, less
18261#include <initializer_list> // initializer_list
18262#include <iterator> // input_iterator_tag, iterator_traits
18263#include <memory> // allocator
18264#include <stdexcept> // for out_of_range
18265#include <type_traits> // enable_if, is_convertible
18266#include <utility> // pair
18267#include <vector> // vector
18268
18269// #include <nlohmann/detail/macro_scope.hpp>
18270
18271// #include <nlohmann/detail/meta/type_traits.hpp>
18272
18273
18274namespace nlohmann
18275{
18276
18279template <class Key, class T, class IgnoredLess = std::less<Key>,
18280 class Allocator = std::allocator<std::pair<const Key, T>>>
18281 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
18282{
18283 using key_type = Key;
18284 using mapped_type = T;
18285 using Container = std::vector<std::pair<const Key, T>, Allocator>;
18286 using iterator = typename Container::iterator;
18287 using const_iterator = typename Container::const_iterator;
18288 using size_type = typename Container::size_type;
18289 using value_type = typename Container::value_type;
18290#ifdef JSON_HAS_CPP_14
18291 using key_compare = std::equal_to<>;
18292#else
18293 using key_compare = std::equal_to<Key>;
18294#endif
18295
18296 // Explicit constructors instead of `using Container::Container`
18297 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
18298 ordered_map() noexcept(noexcept(Container())) : Container{} {}
18299 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
18300 template <class It>
18301 ordered_map(It first, It last, const Allocator& alloc = Allocator())
18302 : Container{first, last, alloc} {}
18303 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
18304 : Container{init, alloc} {}
18305
18306 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
18307 {
18308 for (auto it = this->begin(); it != this->end(); ++it)
18309 {
18310 if (m_compare(it->first, key))
18311 {
18312 return {it, false};
18313 }
18314 }
18315 Container::emplace_back(key, std::forward<T>(t));
18316 return {std::prev(this->end()), true};
18317 }
18318
18319 template<class KeyType, detail::enable_if_t<
18321 std::pair<iterator, bool> emplace(KeyType && key, T && t)
18322 {
18323 for (auto it = this->begin(); it != this->end(); ++it)
18324 {
18325 if (m_compare(it->first, key))
18326 {
18327 return {it, false};
18328 }
18329 }
18330 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
18331 return {std::prev(this->end()), true};
18332 }
18333
18334 T& operator[](const key_type& key)
18335 {
18336 return emplace(key, T{}).first->second;
18337 }
18338
18339 template<class KeyType, detail::enable_if_t<
18341 T & operator[](KeyType && key)
18342 {
18343 return emplace(std::forward<KeyType>(key), T{}).first->second;
18344 }
18345
18346 const T& operator[](const key_type& key) const
18347 {
18348 return at(key);
18349 }
18350
18351 template<class KeyType, detail::enable_if_t<
18353 const T & operator[](KeyType && key) const
18354 {
18355 return at(std::forward<KeyType>(key));
18356 }
18357
18358 T& at(const key_type& key)
18359 {
18360 for (auto it = this->begin(); it != this->end(); ++it)
18361 {
18362 if (m_compare(it->first, key))
18363 {
18364 return it->second;
18365 }
18366 }
18367
18368 JSON_THROW(std::out_of_range("key not found"));
18369 }
18370
18371 template<class KeyType, detail::enable_if_t<
18373 T & at(KeyType && key)
18374 {
18375 for (auto it = this->begin(); it != this->end(); ++it)
18376 {
18377 if (m_compare(it->first, key))
18378 {
18379 return it->second;
18380 }
18381 }
18382
18383 JSON_THROW(std::out_of_range("key not found"));
18384 }
18385
18386 const T& at(const key_type& key) const
18387 {
18388 for (auto it = this->begin(); it != this->end(); ++it)
18389 {
18390 if (m_compare(it->first, key))
18391 {
18392 return it->second;
18393 }
18394 }
18395
18396 JSON_THROW(std::out_of_range("key not found"));
18397 }
18398
18399 template<class KeyType, detail::enable_if_t<
18401 const T & at(KeyType && key) const
18402 {
18403 for (auto it = this->begin(); it != this->end(); ++it)
18404 {
18405 if (m_compare(it->first, key))
18406 {
18407 return it->second;
18408 }
18409 }
18410
18411 JSON_THROW(std::out_of_range("key not found"));
18412 }
18413
18415 {
18416 for (auto it = this->begin(); it != this->end(); ++it)
18417 {
18418 if (m_compare(it->first, key))
18419 {
18420 // Since we cannot move const Keys, re-construct them in place
18421 for (auto next = it; ++next != this->end(); ++it)
18422 {
18423 it->~value_type(); // Destroy but keep allocation
18424 new (&*it) value_type{std::move(*next)};
18425 }
18426 Container::pop_back();
18427 return 1;
18428 }
18429 }
18430 return 0;
18431 }
18432
18433 template<class KeyType, detail::enable_if_t<
18435 size_type erase(KeyType && key)
18436 {
18437 for (auto it = this->begin(); it != this->end(); ++it)
18438 {
18439 if (m_compare(it->first, key))
18440 {
18441 // Since we cannot move const Keys, re-construct them in place
18442 for (auto next = it; ++next != this->end(); ++it)
18443 {
18444 it->~value_type(); // Destroy but keep allocation
18445 new (&*it) value_type{std::move(*next)};
18446 }
18447 Container::pop_back();
18448 return 1;
18449 }
18450 }
18451 return 0;
18452 }
18453
18455 {
18456 return erase(pos, std::next(pos));
18457 }
18458
18460 {
18461 if (first == last)
18462 {
18463 return first;
18464 }
18465
18466 const auto elements_affected = std::distance(first, last);
18467 const auto offset = std::distance(Container::begin(), first);
18468
18469 // This is the start situation. We need to delete elements_affected
18470 // elements (3 in this example: e, f, g), and need to return an
18471 // iterator past the last deleted element (h in this example).
18472 // Note that offset is the distance from the start of the vector
18473 // to first. We will need this later.
18474
18475 // [ a, b, c, d, e, f, g, h, i, j ]
18476 // ^ ^
18477 // first last
18478
18479 // Since we cannot move const Keys, we re-construct them in place.
18480 // We start at first and re-construct (viz. copy) the elements from
18481 // the back of the vector. Example for first iteration:
18482
18483 // ,--------.
18484 // v | destroy e and re-construct with h
18485 // [ a, b, c, d, e, f, g, h, i, j ]
18486 // ^ ^
18487 // it it + elements_affected
18488
18489 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
18490 {
18491 it->~value_type(); // destroy but keep allocation
18492 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
18493 }
18494
18495 // [ a, b, c, d, h, i, j, h, i, j ]
18496 // ^ ^
18497 // first last
18498
18499 // remove the unneeded elements at the end of the vector
18500 Container::resize(this->size() - static_cast<size_type>(elements_affected));
18501
18502 // [ a, b, c, d, h, i, j ]
18503 // ^ ^
18504 // first last
18505
18506 // first is now pointing past the last deleted element, but we cannot
18507 // use this iterator, because it may have been invalidated by the
18508 // resize call. Instead, we can return begin() + offset.
18509 return Container::begin() + offset;
18510 }
18511
18512 size_type count(const key_type& key) const
18513 {
18514 for (auto it = this->begin(); it != this->end(); ++it)
18515 {
18516 if (m_compare(it->first, key))
18517 {
18518 return 1;
18519 }
18520 }
18521 return 0;
18522 }
18523
18524 template<class KeyType, detail::enable_if_t<
18526 size_type count(KeyType && key) const
18527 {
18528 for (auto it = this->begin(); it != this->end(); ++it)
18529 {
18530 if (m_compare(it->first, key))
18531 {
18532 return 1;
18533 }
18534 }
18535 return 0;
18536 }
18537
18539 {
18540 for (auto it = this->begin(); it != this->end(); ++it)
18541 {
18542 if (m_compare(it->first, key))
18543 {
18544 return it;
18545 }
18546 }
18547 return Container::end();
18548 }
18549
18550 template<class KeyType, detail::enable_if_t<
18552 iterator find(KeyType && key)
18553 {
18554 for (auto it = this->begin(); it != this->end(); ++it)
18555 {
18556 if (m_compare(it->first, key))
18557 {
18558 return it;
18559 }
18560 }
18561 return Container::end();
18562 }
18563
18564 const_iterator find(const key_type& key) const
18565 {
18566 for (auto it = this->begin(); it != this->end(); ++it)
18567 {
18568 if (m_compare(it->first, key))
18569 {
18570 return it;
18571 }
18572 }
18573 return Container::end();
18574 }
18575
18576 std::pair<iterator, bool> insert( value_type&& value )
18577 {
18578 return emplace(value.first, std::move(value.second));
18579 }
18580
18581 std::pair<iterator, bool> insert( const value_type& value )
18582 {
18583 for (auto it = this->begin(); it != this->end(); ++it)
18584 {
18585 if (m_compare(it->first, value.first))
18586 {
18587 return {it, false};
18588 }
18589 }
18590 Container::push_back(value);
18591 return {--this->end(), true};
18592 }
18593
18594 template<typename InputIt>
18595 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
18596 std::input_iterator_tag>::value>::type;
18597
18598 template<typename InputIt, typename = require_input_iter<InputIt>>
18599 void insert(InputIt first, InputIt last)
18600 {
18601 for (auto it = first; it != last; ++it)
18602 {
18603 insert(*it);
18604 }
18605 }
18606
18607private:
18609};
18610
18611} // namespace nlohmann
18612
18613
18614#if defined(JSON_HAS_CPP_17)
18615 #include <any>
18616 #include <string_view>
18617#endif
18618
18624namespace nlohmann
18625{
18626
18646class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
18647{
18648 private:
18649 template<detail::value_t> friend struct detail::external_constructor;
18650
18651 template<typename>
18652 friend class ::nlohmann::json_pointer;
18653 // can be restored when json_pointer backwards compatibility is removed
18654 // friend ::nlohmann::json_pointer<StringType>;
18655
18656 template<typename BasicJsonType, typename InputType>
18657 friend class ::nlohmann::detail::parser;
18658 friend ::nlohmann::detail::serializer<basic_json>;
18659 template<typename BasicJsonType>
18660 friend class ::nlohmann::detail::iter_impl;
18661 template<typename BasicJsonType, typename CharType>
18662 friend class ::nlohmann::detail::binary_writer;
18663 template<typename BasicJsonType, typename InputType, typename SAX>
18664 friend class ::nlohmann::detail::binary_reader;
18665 template<typename BasicJsonType>
18666 friend class ::nlohmann::detail::json_sax_dom_parser;
18667 template<typename BasicJsonType>
18668 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
18669 friend class ::nlohmann::detail::exception;
18670
18672 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
18673
18675 // convenience aliases for types residing in namespace detail;
18677
18678 template<typename InputAdapterType>
18679 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
18680 InputAdapterType adapter,
18681 detail::parser_callback_t<basic_json>cb = nullptr,
18682 const bool allow_exceptions = true,
18683 const bool ignore_comments = false
18684 )
18685 {
18686 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
18687 std::move(cb), allow_exceptions, ignore_comments);
18688 }
18689
18690 private:
18691 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
18692 template<typename BasicJsonType>
18694 template<typename BasicJsonType>
18696 template<typename Iterator>
18697 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
18698 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
18699
18700 template<typename CharType>
18701 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
18702
18703 template<typename InputType>
18705 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
18706
18709
18710 public:
18714 template<typename T, typename SFINAE>
18715 using json_serializer = JSONSerializer<T, SFINAE>;
18721 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
18722
18723 using input_format_t = detail::input_format_t;
18725 using json_sax_t = json_sax<basic_json>;
18726
18728 // exceptions //
18730
18734
18741
18743
18744
18746 // container types //
18748
18753
18756
18761
18763 using difference_type = std::ptrdiff_t;
18765 using size_type = std::size_t;
18766
18768 using allocator_type = AllocatorType<basic_json>;
18769
18771 using pointer = typename std::allocator_traits<allocator_type>::pointer;
18773 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
18774
18783
18785
18786
18790 {
18791 return allocator_type();
18792 }
18793
18798 {
18799 basic_json result;
18800
18801 result["copyright"] = "(C) 2013-2022 Niels Lohmann";
18802 result["name"] = "JSON for Modern C++";
18803 result["url"] = "https://github.com/nlohmann/json";
18804 result["version"]["string"] =
18805 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
18806 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
18807 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
18808 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
18809 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
18810 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
18811
18812#ifdef _WIN32
18813 result["platform"] = "win32";
18814#elif defined __linux__
18815 result["platform"] = "linux";
18816#elif defined __APPLE__
18817 result["platform"] = "apple";
18818#elif defined __unix__
18819 result["platform"] = "unix";
18820#else
18821 result["platform"] = "unknown";
18822#endif
18823
18824#if defined(__ICC) || defined(__INTEL_COMPILER)
18825 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
18826#elif defined(__clang__)
18827 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
18828#elif defined(__GNUC__) || defined(__GNUG__)
18829 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
18830 std::to_string(__GNUC__), '.',
18831 std::to_string(__GNUC_MINOR__), '.',
18832 std::to_string(__GNUC_PATCHLEVEL__))
18833 }
18834 };
18835#elif defined(__HP_cc) || defined(__HP_aCC)
18836 result["compiler"] = "hp"
18837#elif defined(__IBMCPP__)
18838 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
18839#elif defined(_MSC_VER)
18840 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
18841#elif defined(__PGI)
18842 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
18843#elif defined(__SUNPRO_CC)
18844 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
18845#else
18846 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
18847#endif
18848
18849
18850#if defined(_MSVC_LANG)
18851 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
18852#elif defined(__cplusplus)
18853 result["compiler"]["c++"] = std::to_string(__cplusplus);
18854#else
18855 result["compiler"]["c++"] = "unknown";
18856#endif
18857 return result;
18858 }
18859
18860
18862 // JSON value data types //
18864
18869
18874#if defined(JSON_HAS_CPP_14)
18875 // use of transparent comparator avoids unnecessary repeated construction of temporaries
18876 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
18877 using default_object_comparator_t = std::less<>;
18878#else
18879 using default_object_comparator_t = std::less<StringType>;
18880#endif
18881
18884 using object_t = ObjectType<StringType,
18885 basic_json,
18887 AllocatorType<std::pair<const StringType,
18888 basic_json>>>;
18889
18892 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
18893
18896 using string_t = StringType;
18897
18900 using boolean_t = BooleanType;
18901
18904 using number_integer_t = NumberIntegerType;
18905
18908 using number_unsigned_t = NumberUnsignedType;
18909
18912 using number_float_t = NumberFloatType;
18913
18917
18921
18923
18924 private:
18925
18927 template<typename T, typename... Args>
18929 static T* create(Args&& ... args)
18930 {
18931 AllocatorType<T> alloc;
18932 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
18933
18934 auto deleter = [&](T * obj)
18935 {
18936 AllocatorTraits::deallocate(alloc, obj, 1);
18937 };
18938 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
18939 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
18940 JSON_ASSERT(obj != nullptr);
18941 return obj.release();
18942 }
18943
18945 // JSON value storage //
18947
18974 union json_value
18975 {
18979 array_t* array;
18981 string_t* string;
18983 binary_t* binary;
18985 boolean_t boolean;
18987 number_integer_t number_integer;
18989 number_unsigned_t number_unsigned;
18991 number_float_t number_float;
18992
18994 json_value() = default;
18996 json_value(boolean_t v) noexcept : boolean(v) {}
18998 json_value(number_integer_t v) noexcept : number_integer(v) {}
19000 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
19002 json_value(number_float_t v) noexcept : number_float(v) {}
19004 json_value(value_t t)
19005 {
19006 switch (t)
19007 {
19008 case value_t::object:
19009 {
19010 object = create<object_t>();
19011 break;
19012 }
19013
19014 case value_t::array:
19015 {
19016 array = create<array_t>();
19017 break;
19018 }
19019
19020 case value_t::string:
19021 {
19022 string = create<string_t>("");
19023 break;
19024 }
19025
19026 case value_t::binary:
19027 {
19028 binary = create<binary_t>();
19029 break;
19030 }
19031
19032 case value_t::boolean:
19033 {
19034 boolean = static_cast<boolean_t>(false);
19035 break;
19036 }
19037
19038 case value_t::number_integer:
19039 {
19040 number_integer = static_cast<number_integer_t>(0);
19041 break;
19042 }
19043
19044 case value_t::number_unsigned:
19045 {
19046 number_unsigned = static_cast<number_unsigned_t>(0);
19047 break;
19048 }
19049
19050 case value_t::number_float:
19051 {
19052 number_float = static_cast<number_float_t>(0.0);
19053 break;
19054 }
19055
19056 case value_t::null:
19057 {
19058 object = nullptr; // silence warning, see #821
19059 break;
19060 }
19061
19062 case value_t::discarded:
19063 default:
19064 {
19065 object = nullptr; // silence warning, see #821
19066 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
19067 {
19068 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5", nullptr)); // LCOV_EXCL_LINE
19069 }
19070 break;
19071 }
19072 }
19073 }
19074
19076 json_value(const string_t& value) : string(create<string_t>(value)) {}
19077
19079 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
19080
19082 json_value(const object_t& value) : object(create<object_t>(value)) {}
19083
19085 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
19086
19088 json_value(const array_t& value) : array(create<array_t>(value)) {}
19089
19091 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
19092
19094 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
19095
19097 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
19098
19100 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
19101
19103 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
19104
19105 void destroy(value_t t)
19106 {
19107 if (t == value_t::array || t == value_t::object)
19108 {
19109 // flatten the current json_value to a heap-allocated stack
19110 std::vector<basic_json> stack;
19111
19112 // move the top-level items to stack
19113 if (t == value_t::array)
19114 {
19115 stack.reserve(array->size());
19116 std::move(array->begin(), array->end(), std::back_inserter(stack));
19117 }
19118 else
19119 {
19120 stack.reserve(object->size());
19121 for (auto&& it : *object)
19122 {
19123 stack.push_back(std::move(it.second));
19124 }
19125 }
19126
19127 while (!stack.empty())
19128 {
19129 // move the last item to local variable to be processed
19130 basic_json current_item(std::move(stack.back()));
19131 stack.pop_back();
19132
19133 // if current_item is array/object, move
19134 // its children to the stack to be processed later
19135 if (current_item.is_array())
19136 {
19137 std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack));
19138
19139 current_item.m_value.array->clear();
19140 }
19141 else if (current_item.is_object())
19142 {
19143 for (auto&& it : *current_item.m_value.object)
19144 {
19145 stack.push_back(std::move(it.second));
19146 }
19147
19148 current_item.m_value.object->clear();
19149 }
19150
19151 // it's now safe that current_item get destructed
19152 // since it doesn't have any children
19153 }
19154 }
19155
19156 switch (t)
19157 {
19158 case value_t::object:
19159 {
19160 AllocatorType<object_t> alloc;
19161 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
19162 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
19163 break;
19164 }
19165
19166 case value_t::array:
19167 {
19168 AllocatorType<array_t> alloc;
19169 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
19170 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
19171 break;
19172 }
19173
19174 case value_t::string:
19175 {
19176 AllocatorType<string_t> alloc;
19177 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
19178 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
19179 break;
19180 }
19181
19182 case value_t::binary:
19183 {
19184 AllocatorType<binary_t> alloc;
19185 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
19186 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
19187 break;
19188 }
19189
19190 case value_t::null:
19191 case value_t::boolean:
19192 case value_t::number_integer:
19193 case value_t::number_unsigned:
19194 case value_t::number_float:
19195 case value_t::discarded:
19196 default:
19197 {
19198 break;
19199 }
19200 }
19201 }
19202 };
19203
19204 private:
19223 void assert_invariant(bool check_parents = true) const noexcept
19224 {
19225 JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
19226 JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
19227 JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
19228 JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
19229
19230#if JSON_DIAGNOSTICS
19231 JSON_TRY
19232 {
19233 // cppcheck-suppress assertWithSideEffect
19234 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
19235 {
19236 return j.m_parent == this;
19237 }));
19238 }
19239 JSON_CATCH(...) {} // LCOV_EXCL_LINE
19240#endif
19241 static_cast<void>(check_parents);
19242 }
19243
19244 void set_parents()
19245 {
19246#if JSON_DIAGNOSTICS
19247 switch (m_type)
19248 {
19249 case value_t::array:
19250 {
19251 for (auto& element : *m_value.array)
19252 {
19253 element.m_parent = this;
19254 }
19255 break;
19256 }
19257
19258 case value_t::object:
19259 {
19260 for (auto& element : *m_value.object)
19261 {
19262 element.second.m_parent = this;
19263 }
19264 break;
19265 }
19266
19267 case value_t::null:
19268 case value_t::string:
19269 case value_t::boolean:
19270 case value_t::number_integer:
19271 case value_t::number_unsigned:
19272 case value_t::number_float:
19273 case value_t::binary:
19274 case value_t::discarded:
19275 default:
19276 break;
19277 }
19278#endif
19279 }
19280
19281 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
19282 {
19283#if JSON_DIAGNOSTICS
19284 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
19285 {
19286 (it + i)->m_parent = this;
19287 }
19288#else
19289 static_cast<void>(count_set_parents);
19290#endif
19291 return it;
19292 }
19293
19294 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
19295 {
19296#if JSON_DIAGNOSTICS
19297 if (old_capacity != static_cast<std::size_t>(-1))
19298 {
19299 // see https://github.com/nlohmann/json/issues/2838
19300 JSON_ASSERT(type() == value_t::array);
19301 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
19302 {
19303 // capacity has changed: update all parents
19304 set_parents();
19305 return j;
19306 }
19307 }
19308
19309 // ordered_json uses a vector internally, so pointers could have
19310 // been invalidated; see https://github.com/nlohmann/json/issues/2962
19311#ifdef JSON_HEDLEY_MSVC_VERSION
19312#pragma warning(push )
19313#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
19314#endif
19316 {
19317 set_parents();
19318 return j;
19319 }
19320#ifdef JSON_HEDLEY_MSVC_VERSION
19321#pragma warning( pop )
19322#endif
19323
19324 j.m_parent = this;
19325#else
19326 static_cast<void>(j);
19327 static_cast<void>(old_capacity);
19328#endif
19329 return j;
19330 }
19331
19332 public:
19334 // JSON parser callback //
19336
19339 using parse_event_t = detail::parse_event_t;
19340
19343 using parser_callback_t = detail::parser_callback_t<basic_json>;
19344
19346 // constructors //
19348
19353
19357 : m_type(v), m_value(v)
19358 {
19359 assert_invariant();
19360 }
19361
19364 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
19365 : basic_json(value_t::null)
19366 {
19367 assert_invariant();
19368 }
19369
19372 template < typename CompatibleType,
19376 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
19377 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
19378 std::forward<CompatibleType>(val))))
19379 {
19380 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
19381 set_parents();
19382 assert_invariant();
19383 }
19384
19387 template < typename BasicJsonType,
19389 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
19390 basic_json(const BasicJsonType& val)
19391 {
19392 using other_boolean_t = typename BasicJsonType::boolean_t;
19393 using other_number_float_t = typename BasicJsonType::number_float_t;
19394 using other_number_integer_t = typename BasicJsonType::number_integer_t;
19395 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
19396 using other_string_t = typename BasicJsonType::string_t;
19397 using other_object_t = typename BasicJsonType::object_t;
19398 using other_array_t = typename BasicJsonType::array_t;
19399 using other_binary_t = typename BasicJsonType::binary_t;
19400
19401 switch (val.type())
19402 {
19403 case value_t::boolean:
19404 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
19405 break;
19406 case value_t::number_float:
19407 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
19408 break;
19409 case value_t::number_integer:
19410 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
19411 break;
19412 case value_t::number_unsigned:
19413 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
19414 break;
19415 case value_t::string:
19416 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
19417 break;
19418 case value_t::object:
19419 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
19420 break;
19421 case value_t::array:
19422 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
19423 break;
19424 case value_t::binary:
19425 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
19426 break;
19427 case value_t::null:
19428 *this = nullptr;
19429 break;
19430 case value_t::discarded:
19431 m_type = value_t::discarded;
19432 break;
19433 default: // LCOV_EXCL_LINE
19434 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19435 }
19436 JSON_ASSERT(m_type == val.type());
19437 set_parents();
19438 assert_invariant();
19439 }
19440
19444 bool type_deduction = true,
19445 value_t manual_type = value_t::array)
19446 {
19447 // check if each element is an array with two elements whose first
19448 // element is a string
19449 bool is_an_object = std::all_of(init.begin(), init.end(),
19450 [](const detail::json_ref<basic_json>& element_ref)
19451 {
19452 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
19453 });
19454
19455 // adjust type if type deduction is not wanted
19456 if (!type_deduction)
19457 {
19458 // if array is wanted, do not create an object though possible
19459 if (manual_type == value_t::array)
19460 {
19461 is_an_object = false;
19462 }
19463
19464 // if object is wanted but impossible, throw an exception
19465 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
19466 {
19467 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
19468 }
19469 }
19470
19471 if (is_an_object)
19472 {
19473 // the initializer list is a list of pairs -> create object
19474 m_type = value_t::object;
19475 m_value = value_t::object;
19476
19477 for (auto& element_ref : init)
19478 {
19479 auto element = element_ref.moved_or_copied();
19481 std::move(*((*element.m_value.array)[0].m_value.string)),
19482 std::move((*element.m_value.array)[1]));
19483 }
19484 }
19485 else
19486 {
19487 // the initializer list describes an array -> create array
19488 m_type = value_t::array;
19489 m_value.array = create<array_t>(init.begin(), init.end());
19490 }
19491
19492 set_parents();
19493 assert_invariant();
19494 }
19495
19500 {
19501 auto res = basic_json();
19502 res.m_type = value_t::binary;
19503 res.m_value = init;
19504 return res;
19505 }
19506
19511 {
19512 auto res = basic_json();
19513 res.m_type = value_t::binary;
19514 res.m_value = binary_t(init, subtype);
19515 return res;
19516 }
19517
19522 {
19523 auto res = basic_json();
19524 res.m_type = value_t::binary;
19525 res.m_value = std::move(init);
19526 return res;
19527 }
19528
19533 {
19534 auto res = basic_json();
19535 res.m_type = value_t::binary;
19536 res.m_value = binary_t(std::move(init), subtype);
19537 return res;
19538 }
19539
19544 {
19545 return basic_json(init, false, value_t::array);
19546 }
19547
19552 {
19553 return basic_json(init, false, value_t::object);
19554 }
19555
19559 : m_type(value_t::array)
19560 {
19561 m_value.array = create<array_t>(cnt, val);
19562 set_parents();
19563 assert_invariant();
19564 }
19565
19568 template < class InputIT, typename std::enable_if <
19569 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
19570 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
19571 basic_json(InputIT first, InputIT last)
19572 {
19573 JSON_ASSERT(first.m_object != nullptr);
19574 JSON_ASSERT(last.m_object != nullptr);
19575
19576 // make sure iterator fits the current value
19577 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
19578 {
19579 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
19580 }
19581
19582 // copy type from first iterator
19583 m_type = first.m_object->m_type;
19584
19585 // check if iterator range is complete for primitive values
19586 switch (m_type)
19587 {
19588 case value_t::boolean:
19589 case value_t::number_float:
19590 case value_t::number_integer:
19591 case value_t::number_unsigned:
19592 case value_t::string:
19593 {
19594 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
19595 || !last.m_it.primitive_iterator.is_end()))
19596 {
19597 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
19598 }
19599 break;
19600 }
19601
19602 case value_t::null:
19603 case value_t::object:
19604 case value_t::array:
19605 case value_t::binary:
19606 case value_t::discarded:
19607 default:
19608 break;
19609 }
19610
19611 switch (m_type)
19612 {
19613 case value_t::number_integer:
19614 {
19615 m_value.number_integer = first.m_object->m_value.number_integer;
19616 break;
19617 }
19618
19619 case value_t::number_unsigned:
19620 {
19621 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
19622 break;
19623 }
19624
19625 case value_t::number_float:
19626 {
19627 m_value.number_float = first.m_object->m_value.number_float;
19628 break;
19629 }
19630
19631 case value_t::boolean:
19632 {
19633 m_value.boolean = first.m_object->m_value.boolean;
19634 break;
19635 }
19636
19637 case value_t::string:
19638 {
19639 m_value = *first.m_object->m_value.string;
19640 break;
19641 }
19642
19643 case value_t::object:
19644 {
19645 m_value.object = create<object_t>(first.m_it.object_iterator,
19646 last.m_it.object_iterator);
19647 break;
19648 }
19649
19650 case value_t::array:
19651 {
19652 m_value.array = create<array_t>(first.m_it.array_iterator,
19653 last.m_it.array_iterator);
19654 break;
19655 }
19656
19657 case value_t::binary:
19658 {
19659 m_value = *first.m_object->m_value.binary;
19660 break;
19661 }
19662
19663 case value_t::null:
19664 case value_t::discarded:
19665 default:
19666 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
19667 }
19668
19669 set_parents();
19670 assert_invariant();
19671 }
19672
19673
19675 // other constructors and destructor //
19677
19678 template<typename JsonRef,
19680 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
19681 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
19682
19686 : m_type(other.m_type)
19687 {
19688 // check of passed value is valid
19689 other.assert_invariant();
19690
19691 switch (m_type)
19692 {
19693 case value_t::object:
19694 {
19695 m_value = *other.m_value.object;
19696 break;
19697 }
19698
19699 case value_t::array:
19700 {
19701 m_value = *other.m_value.array;
19702 break;
19703 }
19704
19705 case value_t::string:
19706 {
19707 m_value = *other.m_value.string;
19708 break;
19709 }
19710
19711 case value_t::boolean:
19712 {
19713 m_value = other.m_value.boolean;
19714 break;
19715 }
19716
19717 case value_t::number_integer:
19718 {
19719 m_value = other.m_value.number_integer;
19720 break;
19721 }
19722
19723 case value_t::number_unsigned:
19724 {
19725 m_value = other.m_value.number_unsigned;
19726 break;
19727 }
19728
19729 case value_t::number_float:
19730 {
19731 m_value = other.m_value.number_float;
19732 break;
19733 }
19734
19735 case value_t::binary:
19736 {
19737 m_value = *other.m_value.binary;
19738 break;
19739 }
19740
19741 case value_t::null:
19742 case value_t::discarded:
19743 default:
19744 break;
19745 }
19746
19747 set_parents();
19748 assert_invariant();
19749 }
19750
19753 basic_json(basic_json&& other) noexcept
19754 : m_type(std::move(other.m_type)),
19755 m_value(std::move(other.m_value))
19756 {
19757 // check that passed value is valid
19758 other.assert_invariant(false);
19759
19760 // invalidate payload
19761 other.m_type = value_t::null;
19762 other.m_value = {};
19763
19764 set_parents();
19765 assert_invariant();
19766 }
19767
19771 std::is_nothrow_move_constructible<value_t>::value&&
19772 std::is_nothrow_move_assignable<value_t>::value&&
19773 std::is_nothrow_move_constructible<json_value>::value&&
19774 std::is_nothrow_move_assignable<json_value>::value
19775 )
19776 {
19777 // check that passed value is valid
19778 other.assert_invariant();
19779
19780 using std::swap;
19781 swap(m_type, other.m_type);
19782 swap(m_value, other.m_value);
19783
19784 set_parents();
19785 assert_invariant();
19786 return *this;
19787 }
19788
19791 ~basic_json() noexcept
19792 {
19793 assert_invariant(false);
19794 m_value.destroy(m_type);
19795 }
19796
19798
19799 public:
19801 // object inspection //
19803
19807
19810 string_t dump(const int indent = -1,
19811 const char indent_char = ' ',
19812 const bool ensure_ascii = false,
19813 const error_handler_t error_handler = error_handler_t::strict) const
19814 {
19815 string_t result;
19816 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
19817
19818 if (indent >= 0)
19819 {
19820 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
19821 }
19822 else
19823 {
19824 s.dump(*this, false, ensure_ascii, 0);
19825 }
19826
19827 return result;
19828 }
19829
19832 constexpr value_t type() const noexcept
19833 {
19834 return m_type;
19835 }
19836
19839 constexpr bool is_primitive() const noexcept
19840 {
19841 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
19842 }
19843
19846 constexpr bool is_structured() const noexcept
19847 {
19848 return is_array() || is_object();
19849 }
19850
19853 constexpr bool is_null() const noexcept
19854 {
19855 return m_type == value_t::null;
19856 }
19857
19860 constexpr bool is_boolean() const noexcept
19861 {
19862 return m_type == value_t::boolean;
19863 }
19864
19867 constexpr bool is_number() const noexcept
19868 {
19869 return is_number_integer() || is_number_float();
19870 }
19871
19874 constexpr bool is_number_integer() const noexcept
19875 {
19876 return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
19877 }
19878
19881 constexpr bool is_number_unsigned() const noexcept
19882 {
19883 return m_type == value_t::number_unsigned;
19884 }
19885
19888 constexpr bool is_number_float() const noexcept
19889 {
19890 return m_type == value_t::number_float;
19891 }
19892
19895 constexpr bool is_object() const noexcept
19896 {
19897 return m_type == value_t::object;
19898 }
19899
19902 constexpr bool is_array() const noexcept
19903 {
19904 return m_type == value_t::array;
19905 }
19906
19909 constexpr bool is_string() const noexcept
19910 {
19911 return m_type == value_t::string;
19912 }
19913
19916 constexpr bool is_binary() const noexcept
19917 {
19918 return m_type == value_t::binary;
19919 }
19920
19923 constexpr bool is_discarded() const noexcept
19924 {
19925 return m_type == value_t::discarded;
19926 }
19927
19930 constexpr operator value_t() const noexcept
19931 {
19932 return m_type;
19933 }
19934
19936
19937 private:
19939 // value access //
19941
19943 boolean_t get_impl(boolean_t* /*unused*/) const
19944 {
19946 {
19947 return m_value.boolean;
19948 }
19949
19950 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
19951 }
19952
19954 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
19955 {
19956 return is_object() ? m_value.object : nullptr;
19957 }
19958
19960 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
19961 {
19962 return is_object() ? m_value.object : nullptr;
19963 }
19964
19966 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
19967 {
19968 return is_array() ? m_value.array : nullptr;
19969 }
19970
19972 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
19973 {
19974 return is_array() ? m_value.array : nullptr;
19975 }
19976
19978 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
19979 {
19980 return is_string() ? m_value.string : nullptr;
19981 }
19982
19984 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
19985 {
19986 return is_string() ? m_value.string : nullptr;
19987 }
19988
19990 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
19991 {
19992 return is_boolean() ? &m_value.boolean : nullptr;
19993 }
19994
19996 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
19997 {
19998 return is_boolean() ? &m_value.boolean : nullptr;
19999 }
20000
20002 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
20003 {
20004 return is_number_integer() ? &m_value.number_integer : nullptr;
20005 }
20006
20008 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
20009 {
20010 return is_number_integer() ? &m_value.number_integer : nullptr;
20011 }
20012
20014 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
20015 {
20016 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
20017 }
20018
20020 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
20021 {
20022 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
20023 }
20024
20026 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
20027 {
20028 return is_number_float() ? &m_value.number_float : nullptr;
20029 }
20030
20032 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
20033 {
20034 return is_number_float() ? &m_value.number_float : nullptr;
20035 }
20036
20038 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
20039 {
20040 return is_binary() ? m_value.binary : nullptr;
20041 }
20042
20044 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
20045 {
20046 return is_binary() ? m_value.binary : nullptr;
20047 }
20048
20060 template<typename ReferenceType, typename ThisType>
20061 static ReferenceType get_ref_impl(ThisType& obj)
20062 {
20063 // delegate the call to get_ptr<>()
20064 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
20065
20066 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
20067 {
20068 return *ptr;
20069 }
20070
20071 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
20072 }
20073
20074 public:
20078
20081 template<typename PointerType, typename std::enable_if<
20082 std::is_pointer<PointerType>::value, int>::type = 0>
20083 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20084 {
20085 // delegate the call to get_impl_ptr<>()
20086 return get_impl_ptr(static_cast<PointerType>(nullptr));
20087 }
20088
20091 template < typename PointerType, typename std::enable_if <
20092 std::is_pointer<PointerType>::value&&
20093 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
20094 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20095 {
20096 // delegate the call to get_impl_ptr<>() const
20097 return get_impl_ptr(static_cast<PointerType>(nullptr));
20098 }
20099
20100 private:
20139 template < typename ValueType,
20143 int > = 0 >
20144 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
20145 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
20146 {
20147 auto ret = ValueType();
20148 JSONSerializer<ValueType>::from_json(*this, ret);
20149 return ret;
20150 }
20151
20182 template < typename ValueType,
20184 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
20185 int > = 0 >
20186 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
20187 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
20188 {
20189 return JSONSerializer<ValueType>::from_json(*this);
20190 }
20191
20207 template < typename BasicJsonType,
20209 detail::is_basic_json<BasicJsonType>::value,
20210 int > = 0 >
20211 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
20212 {
20213 return *this;
20214 }
20215
20230 template<typename BasicJsonType,
20232 std::is_same<BasicJsonType, basic_json_t>::value,
20233 int> = 0>
20234 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
20235 {
20236 return *this;
20237 }
20238
20243 template<typename PointerType,
20245 std::is_pointer<PointerType>::value,
20246 int> = 0>
20247 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
20248 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
20249 {
20250 // delegate the call to get_ptr
20251 return get_ptr<PointerType>();
20252 }
20253
20254 public:
20278 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
20279#if defined(JSON_HAS_CPP_14)
20280 constexpr
20281#endif
20282 auto get() const noexcept(
20283 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
20284 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
20285 {
20286 // we cannot static_assert on ValueTypeCV being non-const, because
20287 // there is support for get<const basic_json_t>(), which is why we
20288 // still need the uncvref
20289 static_assert(!std::is_reference<ValueTypeCV>::value,
20290 "get() cannot be used with reference types, you might want to use get_ref()");
20291 return get_impl<ValueType>(detail::priority_tag<4> {});
20292 }
20293
20321 template<typename PointerType, typename std::enable_if<
20322 std::is_pointer<PointerType>::value, int>::type = 0>
20323 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
20324 {
20325 // delegate the call to get_ptr
20326 return get_ptr<PointerType>();
20327 }
20328
20331 template < typename ValueType,
20335 int > = 0 >
20336 ValueType & get_to(ValueType& v) const noexcept(noexcept(
20337 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
20338 {
20339 JSONSerializer<ValueType>::from_json(*this, v);
20340 return v;
20341 }
20342
20343 // specialization to allow calling get_to with a basic_json value
20344 // see https://github.com/nlohmann/json/issues/2175
20345 template<typename ValueType,
20348 int> = 0>
20349 ValueType & get_to(ValueType& v) const
20350 {
20351 v = *this;
20352 return v;
20353 }
20354
20355 template <
20356 typename T, std::size_t N,
20357 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
20360 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
20361 noexcept(noexcept(JSONSerializer<Array>::from_json(
20362 std::declval<const basic_json_t&>(), v)))
20363 {
20364 JSONSerializer<Array>::from_json(*this, v);
20365 return v;
20366 }
20367
20370 template<typename ReferenceType, typename std::enable_if<
20371 std::is_reference<ReferenceType>::value, int>::type = 0>
20372 ReferenceType get_ref()
20373 {
20374 // delegate call to get_ref_impl
20375 return get_ref_impl<ReferenceType>(*this);
20376 }
20377
20380 template < typename ReferenceType, typename std::enable_if <
20381 std::is_reference<ReferenceType>::value&&
20382 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
20383 ReferenceType get_ref() const
20384 {
20385 // delegate call to get_ref_impl
20386 return get_ref_impl<ReferenceType>(*this);
20387 }
20388
20418 template < typename ValueType, typename std::enable_if <
20426#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
20428#endif
20429#if defined(JSON_HAS_CPP_17)
20431#endif
20433 >::value, int >::type = 0 >
20434 JSON_EXPLICIT operator ValueType() const
20435 {
20436 // delegate the call to get<>() const
20437 return get<ValueType>();
20438 }
20439
20443 {
20444 if (!is_binary())
20445 {
20446 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
20447 }
20448
20449 return *get_ptr<binary_t*>();
20450 }
20451
20454 const binary_t& get_binary() const
20455 {
20456 if (!is_binary())
20457 {
20458 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
20459 }
20460
20461 return *get_ptr<const binary_t*>();
20462 }
20463
20465
20466
20468 // element access //
20470
20474
20478 {
20479 // at only works for arrays
20481 {
20482 JSON_TRY
20483 {
20484 return set_parent(m_value.array->at(idx));
20485 }
20486 JSON_CATCH (std::out_of_range&)
20487 {
20488 // create better exception explanation
20489 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
20490 }
20491 }
20492 else
20493 {
20494 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20495 }
20496 }
20497
20501 {
20502 // at only works for arrays
20504 {
20505 JSON_TRY
20506 {
20507 return m_value.array->at(idx);
20508 }
20509 JSON_CATCH (std::out_of_range&)
20510 {
20511 // create better exception explanation
20512 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
20513 }
20514 }
20515 else
20516 {
20517 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20518 }
20519 }
20520
20523 reference at(const typename object_t::key_type& key)
20524 {
20525 // at only works for objects
20527 {
20528 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20529 }
20530
20531 auto it = m_value.object->find(key);
20532 if (it == m_value.object->end())
20533 {
20534 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
20535 }
20536 return set_parent(it->second);
20537 }
20538
20541 template<class KeyType, detail::enable_if_t<
20543 reference at(KeyType && key)
20544 {
20545 // at only works for objects
20547 {
20548 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20549 }
20550
20551 auto it = m_value.object->find(std::forward<KeyType>(key));
20552 if (it == m_value.object->end())
20553 {
20554 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
20555 }
20556 return set_parent(it->second);
20557 }
20558
20561 const_reference at(const typename object_t::key_type& key) const
20562 {
20563 // at only works for objects
20565 {
20566 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20567 }
20568
20569 auto it = m_value.object->find(key);
20570 if (it == m_value.object->end())
20571 {
20572 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
20573 }
20574 return it->second;
20575 }
20576
20579 template<class KeyType, detail::enable_if_t<
20581 const_reference at(KeyType && key) const
20582 {
20583 // at only works for objects
20585 {
20586 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20587 }
20588
20589 auto it = m_value.object->find(std::forward<KeyType>(key));
20590 if (it == m_value.object->end())
20591 {
20592 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
20593 }
20594 return it->second;
20595 }
20596
20600 {
20601 // implicitly convert null value to an empty array
20602 if (is_null())
20603 {
20604 m_type = value_t::array;
20605 m_value.array = create<array_t>();
20606 assert_invariant();
20607 }
20608
20609 // operator[] only works for arrays
20611 {
20612 // fill up array with null values if given idx is outside range
20613 if (idx >= m_value.array->size())
20614 {
20615#if JSON_DIAGNOSTICS
20616 // remember array size & capacity before resizing
20617 const auto old_size = m_value.array->size();
20618 const auto old_capacity = m_value.array->capacity();
20619#endif
20620 m_value.array->resize(idx + 1);
20621
20622#if JSON_DIAGNOSTICS
20623 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
20624 {
20625 // capacity has changed: update all parents
20626 set_parents();
20627 }
20628 else
20629 {
20630 // set parent for values added above
20631 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
20632 }
20633#endif
20634 assert_invariant();
20635 }
20636
20637 return m_value.array->operator[](idx);
20638 }
20639
20640 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
20641 }
20642
20646 {
20647 // const operator[] only works for arrays
20649 {
20650 return m_value.array->operator[](idx);
20651 }
20652
20653 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
20654 }
20655
20658 reference operator[](typename object_t::key_type key)
20659 {
20660 // implicitly convert null value to an empty object
20661 if (is_null())
20662 {
20663 m_type = value_t::object;
20664 m_value.object = create<object_t>();
20665 assert_invariant();
20666 }
20667
20668 // operator[] only works for objects
20670 {
20671 auto result = m_value.object->emplace(std::move(key), nullptr);
20672 return set_parent(result.first->second);
20673 }
20674
20675 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
20676 }
20677
20680 const_reference operator[](const typename object_t::key_type& key) const
20681 {
20682 // const operator[] only works for objects
20684 {
20685 auto it = m_value.object->find(key);
20686 JSON_ASSERT(it != m_value.object->end());
20687 return it->second;
20688 }
20689
20690 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
20691 }
20692
20693 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
20694 // (they seemingly cannot be constrained to resolve the ambiguity)
20695 template<typename T>
20697 {
20698 return operator[](typename object_t::key_type(key));
20699 }
20700
20701 template<typename T>
20703 {
20704 return operator[](typename object_t::key_type(key));
20705 }
20706
20709 template<class KeyType, detail::enable_if_t<
20711 reference operator[](KeyType && key)
20712 {
20713 // implicitly convert null value to an empty object
20714 if (is_null())
20715 {
20716 m_type = value_t::object;
20717 m_value.object = create<object_t>();
20718 assert_invariant();
20719 }
20720
20721 // operator[] only works for objects
20723 {
20724 auto result = m_value.object->emplace(std::forward<KeyType>(key), nullptr);
20725 return set_parent(result.first->second);
20726 }
20727
20728 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
20729 }
20730
20733 template<class KeyType, detail::enable_if_t<
20735 const_reference operator[](KeyType && key) const
20736 {
20737 // const operator[] only works for objects
20739 {
20740 auto it = m_value.object->find(std::forward<KeyType>(key));
20741 JSON_ASSERT(it != m_value.object->end());
20742 return it->second;
20743 }
20744
20745 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
20746 }
20747
20750 // this is the value(const typename object_t::key_type&) overload
20751 template < class KeyType, class ValueType, detail::enable_if_t <
20752 std::is_same<KeyType, typename object_t::key_type>::value
20754 && !std::is_same<value_t, ValueType>::value, int > = 0 >
20755 typename std::decay<ValueType>::type value(const KeyType& key, ValueType && default_value) const
20756 {
20757 // value only works for objects
20759 {
20760 // if key is found, return value and given default value otherwise
20761 const auto it = find(key);
20762 if (it != end())
20763 {
20764 return it->template get<typename std::decay<ValueType>::type>();
20765 }
20766
20767 return std::forward<ValueType>(default_value);
20768 }
20769
20770 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
20771 }
20772
20776 string_t value(const typename object_t::key_type& key, const char* default_value) const
20777 {
20778 return value(key, string_t(default_value));
20779 }
20780
20781 // these two functions, in conjunction with value(const KeyType &, ValueType &&),
20782 // resolve an ambiguity that would otherwise occur between the json_pointer and
20783 // typename object_t::key_type & overloads
20784 template < class ValueType, detail::enable_if_t <
20786 && !std::is_same<value_t, ValueType>::value, int > = 0 >
20787 typename std::decay<ValueType>::type value(const char* key, ValueType && default_value) const
20788 {
20789 return value(typename object_t::key_type(key), std::forward<ValueType>(default_value));
20790 }
20791
20792 string_t value(const char* key, const char* default_value) const
20793 {
20794 return value(typename object_t::key_type(key), string_t(default_value));
20795 }
20796
20800 template < class KeyType, class ValueType, detail::enable_if_t <
20802 && !std::is_same<value_t, ValueType>::value
20804 typename std::decay<ValueType>::type value(KeyType && key, ValueType && default_value) const
20805 {
20806 // value only works for objects
20808 {
20809 // if key is found, return value and given default value otherwise
20810 const auto it = find(std::forward<KeyType>(key));
20811 if (it != end())
20812 {
20813 return it->template get<typename std::decay<ValueType>::type>();
20814 }
20815
20816 return std::forward<ValueType>(default_value);
20817 }
20818
20819 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
20820 }
20821
20825 template < class KeyType, detail::enable_if_t <
20827 string_t value(KeyType && key, const char* default_value) const
20828 {
20829 return value(std::forward<KeyType>(key), string_t(default_value));
20830 }
20831
20834 template < class ValueType, detail::enable_if_t <
20836 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
20837 {
20838 // value only works for objects
20840 {
20841 // if pointer resolves a value, return it or use default value
20842 JSON_TRY
20843 {
20844 return ptr.get_checked(this).template get<ValueType>();
20845 }
20847 {
20848 return default_value;
20849 }
20850 }
20851
20852 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
20853 }
20854
20855 template < class ValueType, class BasicJsonType, detail::enable_if_t <
20858 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
20859 {
20860 return value(ptr.convert(), default_value);
20861 }
20862
20867 string_t value(const json_pointer& ptr, const char* default_value) const
20868 {
20869 return value(ptr, string_t(default_value));
20870 }
20871
20872 template<typename BasicJsonType>
20875 string_t value(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr, const char* default_value) const
20876 {
20877 return value(ptr.convert(), default_value);
20878 }
20879
20883 {
20884 return *begin();
20885 }
20886
20890 {
20891 return *cbegin();
20892 }
20893
20897 {
20898 auto tmp = end();
20899 --tmp;
20900 return *tmp;
20901 }
20902
20906 {
20907 auto tmp = cend();
20908 --tmp;
20909 return *tmp;
20910 }
20911
20914 template < class IteratorType, detail::enable_if_t <
20915 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
20916 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
20917 IteratorType erase(IteratorType pos)
20918 {
20919 // make sure iterator fits the current value
20920 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
20921 {
20922 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
20923 }
20924
20925 IteratorType result = end();
20926
20927 switch (m_type)
20928 {
20929 case value_t::boolean:
20930 case value_t::number_float:
20931 case value_t::number_integer:
20932 case value_t::number_unsigned:
20933 case value_t::string:
20934 case value_t::binary:
20935 {
20936 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
20937 {
20938 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
20939 }
20940
20941 if (is_string())
20942 {
20943 AllocatorType<string_t> alloc;
20944 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
20945 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
20946 m_value.string = nullptr;
20947 }
20948 else if (is_binary())
20949 {
20950 AllocatorType<binary_t> alloc;
20951 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
20952 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
20953 m_value.binary = nullptr;
20954 }
20955
20956 m_type = value_t::null;
20957 assert_invariant();
20958 break;
20959 }
20960
20961 case value_t::object:
20962 {
20963 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
20964 break;
20965 }
20966
20967 case value_t::array:
20968 {
20969 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
20970 break;
20971 }
20972
20973 case value_t::null:
20974 case value_t::discarded:
20975 default:
20976 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
20977 }
20978
20979 return result;
20980 }
20981
20984 template < class IteratorType, detail::enable_if_t <
20985 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
20986 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
20987 IteratorType erase(IteratorType first, IteratorType last)
20988 {
20989 // make sure iterator fits the current value
20990 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
20991 {
20992 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
20993 }
20994
20995 IteratorType result = end();
20996
20997 switch (m_type)
20998 {
20999 case value_t::boolean:
21000 case value_t::number_float:
21001 case value_t::number_integer:
21002 case value_t::number_unsigned:
21003 case value_t::string:
21004 case value_t::binary:
21005 {
21006 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
21007 || !last.m_it.primitive_iterator.is_end()))
21008 {
21009 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
21010 }
21011
21012 if (is_string())
21013 {
21014 AllocatorType<string_t> alloc;
21015 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
21016 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
21017 m_value.string = nullptr;
21018 }
21019 else if (is_binary())
21020 {
21021 AllocatorType<binary_t> alloc;
21022 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
21023 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
21024 m_value.binary = nullptr;
21025 }
21026
21027 m_type = value_t::null;
21028 assert_invariant();
21029 break;
21030 }
21031
21032 case value_t::object:
21033 {
21034 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
21035 last.m_it.object_iterator);
21036 break;
21037 }
21038
21039 case value_t::array:
21040 {
21041 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
21042 last.m_it.array_iterator);
21043 break;
21044 }
21045
21046 case value_t::null:
21047 case value_t::discarded:
21048 default:
21049 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21050 }
21051
21052 return result;
21053 }
21054
21055 private:
21056 template < typename KeyType, detail::enable_if_t <
21058 size_type erase_internal(KeyType && key)
21059 {
21060 // this erase only works for objects
21062 {
21063 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21064 }
21065
21066 return m_value.object->erase(std::forward<KeyType>(key));
21067 }
21068
21069 template < typename KeyType, detail::enable_if_t <
21070 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
21071 size_type erase_internal(KeyType && key)
21072 {
21073 // this erase only works for objects
21075 {
21076 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21077 }
21078
21079 const auto it = m_value.object->find(std::forward<KeyType>(key));
21080 if (it != m_value.object->end())
21081 {
21082 m_value.object->erase(it);
21083 return 1;
21084 }
21085 return 0;
21086 }
21087
21088 public:
21089
21092 size_type erase(const typename object_t::key_type& key)
21093 {
21094 // the indirection via erase_internal() is added to avoid making this
21095 // function a template and thus de-rank it during overload resolution
21096 return erase_internal(key);
21097 }
21098
21101 template<class KeyType, detail::enable_if_t<
21103 size_type erase(KeyType && key)
21104 {
21105 return erase_internal(std::forward<KeyType>(key));
21106 }
21107
21110 void erase(const size_type idx)
21111 {
21112 // this erase only works for arrays
21114 {
21115 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
21116 {
21117 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21118 }
21119
21120 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
21121 }
21122 else
21123 {
21124 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21125 }
21126 }
21127
21129
21130
21132 // lookup //
21134
21137
21140 iterator find(const typename object_t::key_type& key)
21141 {
21142 auto result = end();
21143
21144 if (is_object())
21145 {
21146 result.m_it.object_iterator = m_value.object->find(key);
21147 }
21148
21149 return result;
21150 }
21151
21154 const_iterator find(const typename object_t::key_type& key) const
21155 {
21156 auto result = cend();
21157
21158 if (is_object())
21159 {
21160 result.m_it.object_iterator = m_value.object->find(key);
21161 }
21162
21163 return result;
21164 }
21165
21168 template<class KeyType, detail::enable_if_t<
21170 iterator find(KeyType && key)
21171 {
21172 auto result = end();
21173
21174 if (is_object())
21175 {
21176 result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
21177 }
21178
21179 return result;
21180 }
21181
21184 template<class KeyType, detail::enable_if_t<
21186 const_iterator find(KeyType && key) const
21187 {
21188 auto result = cend();
21189
21190 if (is_object())
21191 {
21192 result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
21193 }
21194
21195 return result;
21196 }
21197
21200 size_type count(const typename object_t::key_type& key) const
21201 {
21202 // return 0 for all nonobject types
21203 return is_object() ? m_value.object->count(key) : 0;
21204 }
21205
21208 template<class KeyType, detail::enable_if_t<
21210 size_type count(KeyType && key) const
21211 {
21212 // return 0 for all nonobject types
21213 return is_object() ? m_value.object->count(std::forward<KeyType>(key)) : 0;
21214 }
21215
21218 bool contains(const typename object_t::key_type& key) const
21219 {
21220 return is_object() && m_value.object->find(key) != m_value.object->end();
21221 }
21222
21225 template<class KeyType, detail::enable_if_t<
21227 bool contains(KeyType && key) const
21228 {
21229 return is_object() && m_value.object->find(std::forward<KeyType>(key)) != m_value.object->end();
21230 }
21231
21234 bool contains(const json_pointer& ptr) const
21235 {
21236 return ptr.contains(this);
21237 }
21238
21239 template<typename BasicJsonType>
21241 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType> ptr) const
21242 {
21243 return ptr.contains(this);
21244 }
21245
21247
21248
21250 // iterators //
21252
21255
21258 iterator begin() noexcept
21259 {
21260 iterator result(this);
21261 result.set_begin();
21262 return result;
21263 }
21264
21267 const_iterator begin() const noexcept
21268 {
21269 return cbegin();
21270 }
21271
21274 const_iterator cbegin() const noexcept
21275 {
21276 const_iterator result(this);
21277 result.set_begin();
21278 return result;
21279 }
21280
21283 iterator end() noexcept
21284 {
21285 iterator result(this);
21286 result.set_end();
21287 return result;
21288 }
21289
21292 const_iterator end() const noexcept
21293 {
21294 return cend();
21295 }
21296
21299 const_iterator cend() const noexcept
21300 {
21301 const_iterator result(this);
21302 result.set_end();
21303 return result;
21304 }
21305
21309 {
21310 return reverse_iterator(end());
21311 }
21312
21316 {
21317 return crbegin();
21318 }
21319
21323 {
21324 return reverse_iterator(begin());
21325 }
21326
21330 {
21331 return crend();
21332 }
21333
21337 {
21338 return const_reverse_iterator(cend());
21339 }
21340
21344 {
21346 }
21347
21348 public:
21355 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
21356 {
21357 return ref.items();
21358 }
21359
21366 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
21367 {
21368 return ref.items();
21369 }
21370
21373 iteration_proxy<iterator> items() noexcept
21374 {
21375 return iteration_proxy<iterator>(*this);
21376 }
21377
21380 iteration_proxy<const_iterator> items() const noexcept
21381 {
21382 return iteration_proxy<const_iterator>(*this);
21383 }
21384
21386
21387
21389 // capacity //
21391
21394
21397 bool empty() const noexcept
21398 {
21399 switch (m_type)
21400 {
21401 case value_t::null:
21402 {
21403 // null values are empty
21404 return true;
21405 }
21406
21407 case value_t::array:
21408 {
21409 // delegate call to array_t::empty()
21410 return m_value.array->empty();
21411 }
21412
21413 case value_t::object:
21414 {
21415 // delegate call to object_t::empty()
21416 return m_value.object->empty();
21417 }
21418
21419 case value_t::string:
21420 case value_t::boolean:
21421 case value_t::number_integer:
21422 case value_t::number_unsigned:
21423 case value_t::number_float:
21424 case value_t::binary:
21425 case value_t::discarded:
21426 default:
21427 {
21428 // all other types are nonempty
21429 return false;
21430 }
21431 }
21432 }
21433
21436 size_type size() const noexcept
21437 {
21438 switch (m_type)
21439 {
21440 case value_t::null:
21441 {
21442 // null values are empty
21443 return 0;
21444 }
21445
21446 case value_t::array:
21447 {
21448 // delegate call to array_t::size()
21449 return m_value.array->size();
21450 }
21451
21452 case value_t::object:
21453 {
21454 // delegate call to object_t::size()
21455 return m_value.object->size();
21456 }
21457
21458 case value_t::string:
21459 case value_t::boolean:
21460 case value_t::number_integer:
21461 case value_t::number_unsigned:
21462 case value_t::number_float:
21463 case value_t::binary:
21464 case value_t::discarded:
21465 default:
21466 {
21467 // all other types have size 1
21468 return 1;
21469 }
21470 }
21471 }
21472
21475 size_type max_size() const noexcept
21476 {
21477 switch (m_type)
21478 {
21479 case value_t::array:
21480 {
21481 // delegate call to array_t::max_size()
21482 return m_value.array->max_size();
21483 }
21484
21485 case value_t::object:
21486 {
21487 // delegate call to object_t::max_size()
21488 return m_value.object->max_size();
21489 }
21490
21491 case value_t::null:
21492 case value_t::string:
21493 case value_t::boolean:
21494 case value_t::number_integer:
21495 case value_t::number_unsigned:
21496 case value_t::number_float:
21497 case value_t::binary:
21498 case value_t::discarded:
21499 default:
21500 {
21501 // all other types have max_size() == size()
21502 return size();
21503 }
21504 }
21505 }
21506
21508
21509
21511 // modifiers //
21513
21516
21519 void clear() noexcept
21520 {
21521 switch (m_type)
21522 {
21523 case value_t::number_integer:
21524 {
21525 m_value.number_integer = 0;
21526 break;
21527 }
21528
21529 case value_t::number_unsigned:
21530 {
21531 m_value.number_unsigned = 0;
21532 break;
21533 }
21534
21535 case value_t::number_float:
21536 {
21537 m_value.number_float = 0.0;
21538 break;
21539 }
21540
21541 case value_t::boolean:
21542 {
21543 m_value.boolean = false;
21544 break;
21545 }
21546
21547 case value_t::string:
21548 {
21549 m_value.string->clear();
21550 break;
21551 }
21552
21553 case value_t::binary:
21554 {
21555 m_value.binary->clear();
21556 break;
21557 }
21558
21559 case value_t::array:
21560 {
21561 m_value.array->clear();
21562 break;
21563 }
21564
21565 case value_t::object:
21566 {
21567 m_value.object->clear();
21568 break;
21569 }
21570
21571 case value_t::null:
21572 case value_t::discarded:
21573 default:
21574 break;
21575 }
21576 }
21577
21581 {
21582 // push_back only works for null objects or arrays
21583 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
21584 {
21585 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
21586 }
21587
21588 // transform null object into an array
21589 if (is_null())
21590 {
21591 m_type = value_t::array;
21592 m_value = value_t::array;
21593 assert_invariant();
21594 }
21595
21596 // add element to array (move semantics)
21597 const auto old_capacity = m_value.array->capacity();
21598 m_value.array->push_back(std::move(val));
21599 set_parent(m_value.array->back(), old_capacity);
21600 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
21601 }
21602
21606 {
21607 push_back(std::move(val));
21608 return *this;
21609 }
21610
21613 void push_back(const basic_json& val)
21614 {
21615 // push_back only works for null objects or arrays
21616 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
21617 {
21618 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
21619 }
21620
21621 // transform null object into an array
21622 if (is_null())
21623 {
21624 m_type = value_t::array;
21625 m_value = value_t::array;
21626 assert_invariant();
21627 }
21628
21629 // add element to array
21630 const auto old_capacity = m_value.array->capacity();
21631 m_value.array->push_back(val);
21632 set_parent(m_value.array->back(), old_capacity);
21633 }
21634
21638 {
21639 push_back(val);
21640 return *this;
21641 }
21642
21645 void push_back(const typename object_t::value_type& val)
21646 {
21647 // push_back only works for null objects or objects
21648 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
21649 {
21650 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
21651 }
21652
21653 // transform null object into an object
21654 if (is_null())
21655 {
21656 m_type = value_t::object;
21657 m_value = value_t::object;
21658 assert_invariant();
21659 }
21660
21661 // add element to object
21662 auto res = m_value.object->insert(val);
21663 set_parent(res.first->second);
21664 }
21665
21668 reference operator+=(const typename object_t::value_type& val)
21669 {
21670 push_back(val);
21671 return *this;
21672 }
21673
21677 {
21678 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
21679 {
21680 basic_json&& key = init.begin()->moved_or_copied();
21681 push_back(typename object_t::value_type(
21682 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
21683 }
21684 else
21685 {
21687 }
21688 }
21689
21693 {
21694 push_back(init);
21695 return *this;
21696 }
21697
21700 template<class... Args>
21701 reference emplace_back(Args&& ... args)
21702 {
21703 // emplace_back only works for null objects or arrays
21704 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
21705 {
21706 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
21707 }
21708
21709 // transform null object into an array
21710 if (is_null())
21711 {
21712 m_type = value_t::array;
21713 m_value = value_t::array;
21714 assert_invariant();
21715 }
21716
21717 // add element to array (perfect forwarding)
21718 const auto old_capacity = m_value.array->capacity();
21719 m_value.array->emplace_back(std::forward<Args>(args)...);
21720 return set_parent(m_value.array->back(), old_capacity);
21721 }
21722
21725 template<class... Args>
21726 std::pair<iterator, bool> emplace(Args&& ... args)
21727 {
21728 // emplace only works for null objects or arrays
21729 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
21730 {
21731 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
21732 }
21733
21734 // transform null object into an object
21735 if (is_null())
21736 {
21737 m_type = value_t::object;
21738 m_value = value_t::object;
21739 assert_invariant();
21740 }
21741
21742 // add element to array (perfect forwarding)
21743 auto res = m_value.object->emplace(std::forward<Args>(args)...);
21744 set_parent(res.first->second);
21745
21746 // create result iterator and set iterator to the result of emplace
21747 auto it = begin();
21748 it.m_it.object_iterator = res.first;
21749
21750 // return pair of iterator and boolean
21751 return {it, res.second};
21752 }
21753
21757 template<typename... Args>
21759 {
21760 iterator result(this);
21761 JSON_ASSERT(m_value.array != nullptr);
21762
21763 auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
21764 m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
21765 result.m_it.array_iterator = m_value.array->begin() + insert_pos;
21766
21767 // This could have been written as:
21768 // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
21769 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
21770
21771 set_parents();
21772 return result;
21773 }
21774
21778 {
21779 // insert only works for arrays
21781 {
21782 // check if iterator pos fits to this JSON value
21783 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
21784 {
21785 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21786 }
21787
21788 // insert to array and return iterator
21789 return insert_iterator(pos, val);
21790 }
21791
21792 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
21793 }
21794
21798 {
21799 return insert(pos, val);
21800 }
21801
21805 {
21806 // insert only works for arrays
21808 {
21809 // check if iterator pos fits to this JSON value
21810 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
21811 {
21812 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21813 }
21814
21815 // insert to array and return iterator
21816 return insert_iterator(pos, cnt, val);
21817 }
21818
21819 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
21820 }
21821
21825 {
21826 // insert only works for arrays
21828 {
21829 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
21830 }
21831
21832 // check if iterator pos fits to this JSON value
21833 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
21834 {
21835 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21836 }
21837
21838 // check if range iterators belong to the same JSON object
21839 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
21840 {
21841 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
21842 }
21843
21844 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
21845 {
21846 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
21847 }
21848
21849 // insert to array and return iterator
21850 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
21851 }
21852
21856 {
21857 // insert only works for arrays
21859 {
21860 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
21861 }
21862
21863 // check if iterator pos fits to this JSON value
21864 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
21865 {
21866 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21867 }
21868
21869 // insert to array and return iterator
21870 return insert_iterator(pos, ilist.begin(), ilist.end());
21871 }
21872
21876 {
21877 // insert only works for objects
21879 {
21880 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
21881 }
21882
21883 // check if range iterators belong to the same JSON object
21884 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
21885 {
21886 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
21887 }
21888
21889 // passed iterators must belong to objects
21890 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
21891 {
21892 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
21893 }
21894
21895 m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
21896 }
21897
21900 void update(const_reference j, bool merge_objects = false)
21901 {
21902 update(j.begin(), j.end(), merge_objects);
21903 }
21904
21907 void update(const_iterator first, const_iterator last, bool merge_objects = false)
21908 {
21909 // implicitly convert null value to an empty object
21910 if (is_null())
21911 {
21912 m_type = value_t::object;
21913 m_value.object = create<object_t>();
21914 assert_invariant();
21915 }
21916
21918 {
21919 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
21920 }
21921
21922 // check if range iterators belong to the same JSON object
21923 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
21924 {
21925 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
21926 }
21927
21928 // passed iterators must belong to objects
21929 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
21930 {
21931 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
21932 }
21933
21934 for (auto it = first; it != last; ++it)
21935 {
21936 if (merge_objects && it.value().is_object())
21937 {
21938 auto it2 = m_value.object->find(it.key());
21939 if (it2 != m_value.object->end())
21940 {
21941 it2->second.update(it.value(), true);
21942 continue;
21943 }
21944 }
21945 m_value.object->operator[](it.key()) = it.value();
21946#if JSON_DIAGNOSTICS
21947 m_value.object->operator[](it.key()).m_parent = this;
21948#endif
21949 }
21950 }
21951
21954 void swap(reference other) noexcept (
21955 std::is_nothrow_move_constructible<value_t>::value&&
21956 std::is_nothrow_move_assignable<value_t>::value&&
21957 std::is_nothrow_move_constructible<json_value>::value&&
21958 std::is_nothrow_move_assignable<json_value>::value
21959 )
21960 {
21961 std::swap(m_type, other.m_type);
21962 std::swap(m_value, other.m_value);
21963
21964 set_parents();
21965 other.set_parents();
21966 assert_invariant();
21967 }
21968
21971 friend void swap(reference left, reference right) noexcept (
21972 std::is_nothrow_move_constructible<value_t>::value&&
21973 std::is_nothrow_move_assignable<value_t>::value&&
21974 std::is_nothrow_move_constructible<json_value>::value&&
21975 std::is_nothrow_move_assignable<json_value>::value
21976 )
21977 {
21978 left.swap(right);
21979 }
21980
21983 void swap(array_t& other) // NOLINT(bugprone-exception-escape)
21984 {
21985 // swap only works for arrays
21987 {
21988 std::swap(*(m_value.array), other);
21989 }
21990 else
21991 {
21992 JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this));
21993 }
21994 }
21995
21998 void swap(object_t& other) // NOLINT(bugprone-exception-escape)
21999 {
22000 // swap only works for objects
22002 {
22003 std::swap(*(m_value.object), other);
22004 }
22005 else
22006 {
22007 JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this));
22008 }
22009 }
22010
22013 void swap(string_t& other) // NOLINT(bugprone-exception-escape)
22014 {
22015 // swap only works for strings
22017 {
22018 std::swap(*(m_value.string), other);
22019 }
22020 else
22021 {
22022 JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this));
22023 }
22024 }
22025
22028 void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
22029 {
22030 // swap only works for strings
22032 {
22033 std::swap(*(m_value.binary), other);
22034 }
22035 else
22036 {
22037 JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this));
22038 }
22039 }
22040
22043 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
22044 {
22045 // swap only works for strings
22047 {
22048 std::swap(*(m_value.binary), other);
22049 }
22050 else
22051 {
22052 JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this));
22053 }
22054 }
22055
22057
22059 // lexicographical comparison operators //
22061
22064
22065 // note parentheses around operands are necessary; see
22066 // https://github.com/nlohmann/json/issues/1530
22067#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
22068 const auto lhs_type = lhs.type(); \
22069 const auto rhs_type = rhs.type(); \
22070 \
22071 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
22072 { \
22073 switch (lhs_type) \
22074 { \
22075 case value_t::array: \
22076 return (*lhs.m_value.array) op (*rhs.m_value.array); \
22077 \
22078 case value_t::object: \
22079 return (*lhs.m_value.object) op (*rhs.m_value.object); \
22080 \
22081 case value_t::null: \
22082 return (null_result); \
22083 \
22084 case value_t::string: \
22085 return (*lhs.m_value.string) op (*rhs.m_value.string); \
22086 \
22087 case value_t::boolean: \
22088 return (lhs.m_value.boolean) op (rhs.m_value.boolean); \
22089 \
22090 case value_t::number_integer: \
22091 return (lhs.m_value.number_integer) op (rhs.m_value.number_integer); \
22092 \
22093 case value_t::number_unsigned: \
22094 return (lhs.m_value.number_unsigned) op (rhs.m_value.number_unsigned); \
22095 \
22096 case value_t::number_float: \
22097 return (lhs.m_value.number_float) op (rhs.m_value.number_float); \
22098 \
22099 case value_t::binary: \
22100 return (*lhs.m_value.binary) op (*rhs.m_value.binary); \
22101 \
22102 case value_t::discarded: \
22103 default: \
22104 return (unordered_result); \
22105 } \
22106 } \
22107 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
22108 { \
22109 return static_cast<number_float_t>(lhs.m_value.number_integer) op rhs.m_value.number_float; \
22110 } \
22111 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
22112 { \
22113 return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_integer); \
22114 } \
22115 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
22116 { \
22117 return static_cast<number_float_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_float; \
22118 } \
22119 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
22120 { \
22121 return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_unsigned); \
22122 } \
22123 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
22124 { \
22125 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_integer; \
22126 } \
22127 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
22128 { \
22129 return lhs.m_value.number_integer op static_cast<number_integer_t>(rhs.m_value.number_unsigned); \
22130 } \
22131 else if(compares_unordered(lhs, rhs))\
22132 {\
22133 return (unordered_result);\
22134 }\
22135 \
22136 return (default_result);
22137
22139 // returns true if:
22140 // - any operand is NaN and the other operand is of number type
22141 // - any operand is discarded
22142 // in legacy mode, discarded values are considered ordered if
22143 // an operation is computed as an odd number of inverses of others
22144 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
22145 {
22146 if ((lhs.is_number_float() && std::isnan(lhs.m_value.number_float) && rhs.is_number())
22147 || (rhs.is_number_float() && std::isnan(rhs.m_value.number_float) && lhs.is_number()))
22148 {
22149 return true;
22150 }
22151#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22152 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
22153#else
22154 static_cast<void>(inverse);
22155 return lhs.is_discarded() || rhs.is_discarded();
22156#endif
22157 }
22158
22159 private:
22160 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
22161 {
22162 return compares_unordered(*this, rhs, inverse);
22163 }
22164
22165 public:
22166#if JSON_HAS_THREE_WAY_COMPARISON
22169 bool operator==(const_reference rhs) const noexcept
22170 {
22171#ifdef __GNUC__
22172#pragma GCC diagnostic push
22173#pragma GCC diagnostic ignored "-Wfloat-equal"
22174#endif
22175 const_reference lhs = *this;
22176 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
22177#ifdef __GNUC__
22178#pragma GCC diagnostic pop
22179#endif
22180 }
22181
22184 template<typename ScalarType>
22185 requires std::is_scalar_v<ScalarType>
22186 bool operator==(ScalarType rhs) const noexcept
22187 {
22188 return *this == basic_json(rhs);
22189 }
22190
22193 bool operator!=(const_reference rhs) const noexcept
22194 {
22195 if (compares_unordered(rhs, true))
22196 {
22197 return false;
22198 }
22199 return !operator==(rhs);
22200 }
22201
22204 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
22205 {
22206 const_reference lhs = *this;
22207 // default_result is used if we cannot compare values. In that case,
22208 // we compare types.
22209 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
22210 std::partial_ordering::equivalent,
22211 std::partial_ordering::unordered,
22212 lhs_type <=> rhs_type) // *NOPAD*
22213 }
22214
22217 template<typename ScalarType>
22218 requires std::is_scalar_v<ScalarType>
22219 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
22220 {
22221 return *this <=> basic_json(rhs); // *NOPAD*
22222 }
22223
22224#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22225 // all operators that are computed as an odd number of inverses of others
22226 // need to be overloaded to emulate the legacy comparison behavior
22227
22231 bool operator<=(const_reference rhs) const noexcept
22232 {
22233 if (compares_unordered(rhs, true))
22234 {
22235 return false;
22236 }
22237 return !(rhs < *this);
22238 }
22239
22242 template<typename ScalarType>
22243 requires std::is_scalar_v<ScalarType>
22244 bool operator<=(ScalarType rhs) const noexcept
22245 {
22246 return *this <= basic_json(rhs);
22247 }
22248
22252 bool operator>=(const_reference rhs) const noexcept
22253 {
22254 if (compares_unordered(rhs, true))
22255 {
22256 return false;
22257 }
22258 return !(*this < rhs);
22259 }
22260
22263 template<typename ScalarType>
22264 requires std::is_scalar_v<ScalarType>
22265 bool operator>=(ScalarType rhs) const noexcept
22266 {
22267 return *this >= basic_json(rhs);
22268 }
22269#endif
22270#else
22273 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
22274 {
22275#ifdef __GNUC__
22276#pragma GCC diagnostic push
22277#pragma GCC diagnostic ignored "-Wfloat-equal"
22278#endif
22279 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
22280#ifdef __GNUC__
22281#pragma GCC diagnostic pop
22282#endif
22283 }
22284
22287 template<typename ScalarType, typename std::enable_if<
22288 std::is_scalar<ScalarType>::value, int>::type = 0>
22289 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
22290 {
22291 return lhs == basic_json(rhs);
22292 }
22293
22296 template<typename ScalarType, typename std::enable_if<
22297 std::is_scalar<ScalarType>::value, int>::type = 0>
22298 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
22299 {
22300 return basic_json(lhs) == rhs;
22301 }
22302
22305 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
22306 {
22307 if (compares_unordered(lhs, rhs, true))
22308 {
22309 return false;
22310 }
22311 return !(lhs == rhs);
22312 }
22313
22316 template<typename ScalarType, typename std::enable_if<
22317 std::is_scalar<ScalarType>::value, int>::type = 0>
22318 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
22319 {
22320 return lhs != basic_json(rhs);
22321 }
22322
22325 template<typename ScalarType, typename std::enable_if<
22326 std::is_scalar<ScalarType>::value, int>::type = 0>
22327 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
22328 {
22329 return basic_json(lhs) != rhs;
22330 }
22331
22334 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
22335 {
22336 // default_result is used if we cannot compare values. In that case,
22337 // we compare types. Note we have to call the operator explicitly,
22338 // because MSVC has problems otherwise.
22339 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
22340 }
22341
22344 template<typename ScalarType, typename std::enable_if<
22345 std::is_scalar<ScalarType>::value, int>::type = 0>
22346 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
22347 {
22348 return lhs < basic_json(rhs);
22349 }
22350
22353 template<typename ScalarType, typename std::enable_if<
22354 std::is_scalar<ScalarType>::value, int>::type = 0>
22355 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
22356 {
22357 return basic_json(lhs) < rhs;
22358 }
22359
22362 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
22363 {
22364 if (compares_unordered(lhs, rhs, true))
22365 {
22366 return false;
22367 }
22368 return !(rhs < lhs);
22369 }
22370
22373 template<typename ScalarType, typename std::enable_if<
22374 std::is_scalar<ScalarType>::value, int>::type = 0>
22375 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
22376 {
22377 return lhs <= basic_json(rhs);
22378 }
22379
22382 template<typename ScalarType, typename std::enable_if<
22383 std::is_scalar<ScalarType>::value, int>::type = 0>
22384 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
22385 {
22386 return basic_json(lhs) <= rhs;
22387 }
22388
22391 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
22392 {
22393 // double inverse
22394 if (compares_unordered(lhs, rhs))
22395 {
22396 return false;
22397 }
22398 return !(lhs <= rhs);
22399 }
22400
22403 template<typename ScalarType, typename std::enable_if<
22404 std::is_scalar<ScalarType>::value, int>::type = 0>
22405 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
22406 {
22407 return lhs > basic_json(rhs);
22408 }
22409
22412 template<typename ScalarType, typename std::enable_if<
22413 std::is_scalar<ScalarType>::value, int>::type = 0>
22414 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
22415 {
22416 return basic_json(lhs) > rhs;
22417 }
22418
22421 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
22422 {
22423 if (compares_unordered(lhs, rhs, true))
22424 {
22425 return false;
22426 }
22427 return !(lhs < rhs);
22428 }
22429
22432 template<typename ScalarType, typename std::enable_if<
22433 std::is_scalar<ScalarType>::value, int>::type = 0>
22434 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
22435 {
22436 return lhs >= basic_json(rhs);
22437 }
22438
22441 template<typename ScalarType, typename std::enable_if<
22442 std::is_scalar<ScalarType>::value, int>::type = 0>
22443 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
22444 {
22445 return basic_json(lhs) >= rhs;
22446 }
22447#endif
22448
22449#undef JSON_IMPLEMENT_OPERATOR
22450
22452
22454 // serialization //
22456
22459#ifndef JSON_NO_IO
22462 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
22463 {
22464 // read width member and use it as indentation parameter if nonzero
22465 const bool pretty_print = o.width() > 0;
22466 const auto indentation = pretty_print ? o.width() : 0;
22467
22468 // reset width to 0 for subsequent calls to this stream
22469 o.width(0);
22470
22471 // do the actual serialization
22472 serializer s(detail::output_adapter<char>(o), o.fill());
22473 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
22474 return o;
22475 }
22476
22483 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
22484 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
22485 {
22486 return o << j;
22487 }
22488#endif // JSON_NO_IO
22490
22491
22493 // deserialization //
22495
22498
22501 template<typename InputType>
22503 static basic_json parse(InputType&& i,
22504 const parser_callback_t cb = nullptr,
22505 const bool allow_exceptions = true,
22506 const bool ignore_comments = false)
22507 {
22508 basic_json result;
22509 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
22510 return result;
22511 }
22512
22515 template<typename IteratorType>
22517 static basic_json parse(IteratorType first,
22518 IteratorType last,
22519 const parser_callback_t cb = nullptr,
22520 const bool allow_exceptions = true,
22521 const bool ignore_comments = false)
22522 {
22523 basic_json result;
22524 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
22525 return result;
22526 }
22527
22529 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
22530 static basic_json parse(detail::span_input_adapter&& i,
22531 const parser_callback_t cb = nullptr,
22532 const bool allow_exceptions = true,
22533 const bool ignore_comments = false)
22534 {
22535 basic_json result;
22536 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
22537 return result;
22538 }
22539
22542 template<typename InputType>
22543 static bool accept(InputType&& i,
22544 const bool ignore_comments = false)
22545 {
22546 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
22547 }
22548
22551 template<typename IteratorType>
22552 static bool accept(IteratorType first, IteratorType last,
22553 const bool ignore_comments = false)
22554 {
22555 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
22556 }
22557
22559 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
22560 static bool accept(detail::span_input_adapter&& i,
22561 const bool ignore_comments = false)
22562 {
22563 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
22564 }
22565
22568 template <typename InputType, typename SAX>
22570 static bool sax_parse(InputType&& i, SAX* sax,
22571 input_format_t format = input_format_t::json,
22572 const bool strict = true,
22573 const bool ignore_comments = false)
22574 {
22575 auto ia = detail::input_adapter(std::forward<InputType>(i));
22576 return format == input_format_t::json
22577 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
22578 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
22579 }
22580
22583 template<class IteratorType, class SAX>
22585 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
22586 input_format_t format = input_format_t::json,
22587 const bool strict = true,
22588 const bool ignore_comments = false)
22589 {
22590 auto ia = detail::input_adapter(std::move(first), std::move(last));
22591 return format == input_format_t::json
22592 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
22593 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
22594 }
22595
22601 template <typename SAX>
22602 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
22604 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
22605 input_format_t format = input_format_t::json,
22606 const bool strict = true,
22607 const bool ignore_comments = false)
22608 {
22609 auto ia = i.get();
22610 return format == input_format_t::json
22611 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
22612 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
22613 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
22614 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
22615 }
22616#ifndef JSON_NO_IO
22623 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
22624 friend std::istream& operator<<(basic_json& j, std::istream& i)
22625 {
22626 return operator>>(i, j);
22627 }
22628
22631 friend std::istream& operator>>(std::istream& i, basic_json& j)
22632 {
22633 parser(detail::input_adapter(i)).parse(false, j);
22634 return i;
22635 }
22636#endif // JSON_NO_IO
22638
22640 // convenience functions //
22642
22646 const char* type_name() const noexcept
22647 {
22648 switch (m_type)
22649 {
22650 case value_t::null:
22651 return "null";
22652 case value_t::object:
22653 return "object";
22654 case value_t::array:
22655 return "array";
22656 case value_t::string:
22657 return "string";
22658 case value_t::boolean:
22659 return "boolean";
22660 case value_t::binary:
22661 return "binary";
22662 case value_t::discarded:
22663 return "discarded";
22664 case value_t::number_integer:
22665 case value_t::number_unsigned:
22666 case value_t::number_float:
22667 default:
22668 return "number";
22669 }
22670 }
22671
22672
22675 // member variables //
22677
22679 value_t m_type = value_t::null;
22680
22682 json_value m_value = {};
22683
22684#if JSON_DIAGNOSTICS
22686 basic_json* m_parent = nullptr;
22687#endif
22688
22690 // binary serialization/deserialization //
22692
22695
22696 public:
22699 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
22700 {
22701 std::vector<std::uint8_t> result;
22702 to_cbor(j, result);
22703 return result;
22704 }
22705
22708 static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
22709 {
22710 binary_writer<std::uint8_t>(o).write_cbor(j);
22711 }
22712
22715 static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
22716 {
22717 binary_writer<char>(o).write_cbor(j);
22718 }
22719
22722 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
22723 {
22724 std::vector<std::uint8_t> result;
22725 to_msgpack(j, result);
22726 return result;
22727 }
22728
22731 static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
22732 {
22733 binary_writer<std::uint8_t>(o).write_msgpack(j);
22734 }
22735
22738 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
22739 {
22740 binary_writer<char>(o).write_msgpack(j);
22741 }
22742
22745 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
22746 const bool use_size = false,
22747 const bool use_type = false)
22748 {
22749 std::vector<std::uint8_t> result;
22750 to_ubjson(j, result, use_size, use_type);
22751 return result;
22752 }
22753
22756 static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
22757 const bool use_size = false, const bool use_type = false)
22758 {
22759 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
22760 }
22761
22764 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
22765 const bool use_size = false, const bool use_type = false)
22766 {
22767 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
22768 }
22769
22772 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
22773 const bool use_size = false,
22774 const bool use_type = false)
22775 {
22776 std::vector<std::uint8_t> result;
22777 to_bjdata(j, result, use_size, use_type);
22778 return result;
22779 }
22780
22783 static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
22784 const bool use_size = false, const bool use_type = false)
22785 {
22786 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
22787 }
22788
22791 static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
22792 const bool use_size = false, const bool use_type = false)
22793 {
22794 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
22795 }
22796
22799 static std::vector<std::uint8_t> to_bson(const basic_json& j)
22800 {
22801 std::vector<std::uint8_t> result;
22802 to_bson(j, result);
22803 return result;
22804 }
22805
22808 static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
22809 {
22810 binary_writer<std::uint8_t>(o).write_bson(j);
22811 }
22812
22815 static void to_bson(const basic_json& j, detail::output_adapter<char> o)
22816 {
22817 binary_writer<char>(o).write_bson(j);
22818 }
22819
22822 template<typename InputType>
22824 static basic_json from_cbor(InputType&& i,
22825 const bool strict = true,
22826 const bool allow_exceptions = true,
22827 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
22828 {
22829 basic_json result;
22830 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22831 auto ia = detail::input_adapter(std::forward<InputType>(i));
22832 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
22833 return res ? result : basic_json(value_t::discarded);
22834 }
22835
22838 template<typename IteratorType>
22840 static basic_json from_cbor(IteratorType first, IteratorType last,
22841 const bool strict = true,
22842 const bool allow_exceptions = true,
22843 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
22844 {
22845 basic_json result;
22846 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22847 auto ia = detail::input_adapter(std::move(first), std::move(last));
22848 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
22849 return res ? result : basic_json(value_t::discarded);
22850 }
22851
22852 template<typename T>
22854 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
22855 static basic_json from_cbor(const T* ptr, std::size_t len,
22856 const bool strict = true,
22857 const bool allow_exceptions = true,
22858 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
22859 {
22860 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
22861 }
22862
22863
22865 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
22866 static basic_json from_cbor(detail::span_input_adapter&& i,
22867 const bool strict = true,
22868 const bool allow_exceptions = true,
22869 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
22870 {
22871 basic_json result;
22872 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22873 auto ia = i.get();
22874 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
22875 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
22876 return res ? result : basic_json(value_t::discarded);
22877 }
22878
22881 template<typename InputType>
22883 static basic_json from_msgpack(InputType&& i,
22884 const bool strict = true,
22885 const bool allow_exceptions = true)
22886 {
22887 basic_json result;
22888 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22889 auto ia = detail::input_adapter(std::forward<InputType>(i));
22890 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
22891 return res ? result : basic_json(value_t::discarded);
22892 }
22893
22896 template<typename IteratorType>
22898 static basic_json from_msgpack(IteratorType first, IteratorType last,
22899 const bool strict = true,
22900 const bool allow_exceptions = true)
22901 {
22902 basic_json result;
22903 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22904 auto ia = detail::input_adapter(std::move(first), std::move(last));
22905 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
22906 return res ? result : basic_json(value_t::discarded);
22907 }
22908
22909 template<typename T>
22911 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
22912 static basic_json from_msgpack(const T* ptr, std::size_t len,
22913 const bool strict = true,
22914 const bool allow_exceptions = true)
22915 {
22916 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
22917 }
22918
22920 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
22921 static basic_json from_msgpack(detail::span_input_adapter&& i,
22922 const bool strict = true,
22923 const bool allow_exceptions = true)
22924 {
22925 basic_json result;
22926 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22927 auto ia = i.get();
22928 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
22929 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
22930 return res ? result : basic_json(value_t::discarded);
22931 }
22932
22935 template<typename InputType>
22937 static basic_json from_ubjson(InputType&& i,
22938 const bool strict = true,
22939 const bool allow_exceptions = true)
22940 {
22941 basic_json result;
22942 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22943 auto ia = detail::input_adapter(std::forward<InputType>(i));
22944 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
22945 return res ? result : basic_json(value_t::discarded);
22946 }
22947
22950 template<typename IteratorType>
22952 static basic_json from_ubjson(IteratorType first, IteratorType last,
22953 const bool strict = true,
22954 const bool allow_exceptions = true)
22955 {
22956 basic_json result;
22957 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22958 auto ia = detail::input_adapter(std::move(first), std::move(last));
22959 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
22960 return res ? result : basic_json(value_t::discarded);
22961 }
22962
22963 template<typename T>
22965 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
22966 static basic_json from_ubjson(const T* ptr, std::size_t len,
22967 const bool strict = true,
22968 const bool allow_exceptions = true)
22969 {
22970 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
22971 }
22972
22974 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
22975 static basic_json from_ubjson(detail::span_input_adapter&& i,
22976 const bool strict = true,
22977 const bool allow_exceptions = true)
22978 {
22979 basic_json result;
22980 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22981 auto ia = i.get();
22982 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
22983 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
22984 return res ? result : basic_json(value_t::discarded);
22985 }
22986
22987
22990 template<typename InputType>
22992 static basic_json from_bjdata(InputType&& i,
22993 const bool strict = true,
22994 const bool allow_exceptions = true)
22995 {
22996 basic_json result;
22997 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22998 auto ia = detail::input_adapter(std::forward<InputType>(i));
22999 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23000 return res ? result : basic_json(value_t::discarded);
23001 }
23002
23005 template<typename IteratorType>
23007 static basic_json from_bjdata(IteratorType first, IteratorType last,
23008 const bool strict = true,
23009 const bool allow_exceptions = true)
23010 {
23011 basic_json result;
23012 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23013 auto ia = detail::input_adapter(std::move(first), std::move(last));
23014 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23015 return res ? result : basic_json(value_t::discarded);
23016 }
23017
23020 template<typename InputType>
23022 static basic_json from_bson(InputType&& i,
23023 const bool strict = true,
23024 const bool allow_exceptions = true)
23025 {
23026 basic_json result;
23027 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23028 auto ia = detail::input_adapter(std::forward<InputType>(i));
23029 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23030 return res ? result : basic_json(value_t::discarded);
23031 }
23032
23035 template<typename IteratorType>
23037 static basic_json from_bson(IteratorType first, IteratorType last,
23038 const bool strict = true,
23039 const bool allow_exceptions = true)
23040 {
23041 basic_json result;
23042 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23043 auto ia = detail::input_adapter(std::move(first), std::move(last));
23044 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23045 return res ? result : basic_json(value_t::discarded);
23046 }
23047
23048 template<typename T>
23050 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23051 static basic_json from_bson(const T* ptr, std::size_t len,
23052 const bool strict = true,
23053 const bool allow_exceptions = true)
23054 {
23055 return from_bson(ptr, ptr + len, strict, allow_exceptions);
23056 }
23057
23059 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23060 static basic_json from_bson(detail::span_input_adapter&& i,
23061 const bool strict = true,
23062 const bool allow_exceptions = true)
23063 {
23064 basic_json result;
23065 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23066 auto ia = i.get();
23067 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23068 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23069 return res ? result : basic_json(value_t::discarded);
23070 }
23072
23074 // JSON Pointer support //
23076
23079
23083 {
23084 return ptr.get_unchecked(this);
23085 }
23086
23087 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23089 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23090 {
23091 return ptr.get_unchecked(this);
23092 }
23093
23097 {
23098 return ptr.get_unchecked(this);
23099 }
23100
23101 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23103 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23104 {
23105 return ptr.get_unchecked(this);
23106 }
23107
23111 {
23112 return ptr.get_checked(this);
23113 }
23114
23115 template<typename BasicJsonType>
23117 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23118 {
23119 return ptr.get_checked(this);
23120 }
23121
23125 {
23126 return ptr.get_checked(this);
23127 }
23128
23129 template<typename BasicJsonType>
23131 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23132 {
23133 return ptr.get_checked(this);
23134 }
23135
23139 {
23140 basic_json result(value_t::object);
23141 json_pointer::flatten("", *this, result);
23142 return result;
23143 }
23144
23148 {
23149 return json_pointer::unflatten(*this);
23150 }
23151
23153
23155 // JSON Patch functions //
23157
23160
23163 basic_json patch(const basic_json& json_patch) const
23164 {
23165 // make a working copy to apply the patch to
23166 basic_json result = *this;
23167
23168 // the valid JSON Patch operations
23169 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
23170
23171 const auto get_op = [](const std::string & op)
23172 {
23173 if (op == "add")
23174 {
23175 return patch_operations::add;
23176 }
23177 if (op == "remove")
23178 {
23179 return patch_operations::remove;
23180 }
23181 if (op == "replace")
23182 {
23183 return patch_operations::replace;
23184 }
23185 if (op == "move")
23186 {
23187 return patch_operations::move;
23188 }
23189 if (op == "copy")
23190 {
23191 return patch_operations::copy;
23192 }
23193 if (op == "test")
23194 {
23195 return patch_operations::test;
23196 }
23197
23198 return patch_operations::invalid;
23199 };
23200
23201 // wrapper for "add" operation; add value at ptr
23202 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
23203 {
23204 // adding to the root of the target document means replacing it
23205 if (ptr.empty())
23206 {
23207 result = val;
23208 return;
23209 }
23210
23211 // make sure the top element of the pointer exists
23212 json_pointer top_pointer = ptr.top();
23213 if (top_pointer != ptr)
23214 {
23215 result.at(top_pointer);
23216 }
23217
23218 // get reference to parent of JSON pointer ptr
23219 const auto last_path = ptr.back();
23220 ptr.pop_back();
23221 basic_json& parent = result[ptr];
23222
23223 switch (parent.m_type)
23224 {
23225 case value_t::null:
23226 case value_t::object:
23227 {
23228 // use operator[] to add value
23229 parent[last_path] = val;
23230 break;
23231 }
23232
23233 case value_t::array:
23234 {
23235 if (last_path == "-")
23236 {
23237 // special case: append to back
23238 parent.push_back(val);
23239 }
23240 else
23241 {
23242 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
23243 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
23244 {
23245 // avoid undefined behavior
23246 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
23247 }
23248
23249 // default case: insert add offset
23250 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
23251 }
23252 break;
23253 }
23254
23255 // if there exists a parent it cannot be primitive
23256 case value_t::string: // LCOV_EXCL_LINE
23257 case value_t::boolean: // LCOV_EXCL_LINE
23258 case value_t::number_integer: // LCOV_EXCL_LINE
23259 case value_t::number_unsigned: // LCOV_EXCL_LINE
23260 case value_t::number_float: // LCOV_EXCL_LINE
23261 case value_t::binary: // LCOV_EXCL_LINE
23262 case value_t::discarded: // LCOV_EXCL_LINE
23263 default: // LCOV_EXCL_LINE
23264 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
23265 }
23266 };
23267
23268 // wrapper for "remove" operation; remove value at ptr
23269 const auto operation_remove = [this, &result](json_pointer & ptr)
23270 {
23271 // get reference to parent of JSON pointer ptr
23272 const auto last_path = ptr.back();
23273 ptr.pop_back();
23274 basic_json& parent = result.at(ptr);
23275
23276 // remove child
23277 if (parent.is_object())
23278 {
23279 // perform range check
23280 auto it = parent.find(last_path);
23281 if (JSON_HEDLEY_LIKELY(it != parent.end()))
23282 {
23283 parent.erase(it);
23284 }
23285 else
23286 {
23287 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
23288 }
23289 }
23290 else if (parent.is_array())
23291 {
23292 // note erase performs range check
23293 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
23294 }
23295 };
23296
23297 // type check: top level value must be an array
23298 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
23299 {
23300 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
23301 }
23302
23303 // iterate and apply the operations
23304 for (const auto& val : json_patch)
23305 {
23306 // wrapper to get a value for an operation
23307 const auto get_value = [&val](const std::string & op,
23308 const std::string & member,
23309 bool string_type) -> basic_json &
23310 {
23311 // find value
23312 auto it = val.m_value.object->find(member);
23313
23314 // context-sensitive error message
23315 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
23316
23317 // check if desired value is present
23318 if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
23319 {
23320 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
23321 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
23322 }
23323
23324 // check if result is of type string
23325 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
23326 {
23327 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
23328 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
23329 }
23330
23331 // no error: return value
23332 return it->second;
23333 };
23334
23335 // type check: every element of the array must be an object
23336 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
23337 {
23338 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
23339 }
23340
23341 // collect mandatory members
23342 const auto op = get_value("op", "op", true).template get<std::string>();
23343 const auto path = get_value(op, "path", true).template get<std::string>();
23344 json_pointer ptr(path);
23345
23346 switch (get_op(op))
23347 {
23348 case patch_operations::add:
23349 {
23350 operation_add(ptr, get_value("add", "value", false));
23351 break;
23352 }
23353
23354 case patch_operations::remove:
23355 {
23356 operation_remove(ptr);
23357 break;
23358 }
23359
23360 case patch_operations::replace:
23361 {
23362 // the "path" location must exist - use at()
23363 result.at(ptr) = get_value("replace", "value", false);
23364 break;
23365 }
23366
23367 case patch_operations::move:
23368 {
23369 const auto from_path = get_value("move", "from", true).template get<std::string>();
23370 json_pointer from_ptr(from_path);
23371
23372 // the "from" location must exist - use at()
23373 basic_json v = result.at(from_ptr);
23374
23375 // The move operation is functionally identical to a
23376 // "remove" operation on the "from" location, followed
23377 // immediately by an "add" operation at the target
23378 // location with the value that was just removed.
23379 operation_remove(from_ptr);
23380 operation_add(ptr, v);
23381 break;
23382 }
23383
23384 case patch_operations::copy:
23385 {
23386 const auto from_path = get_value("copy", "from", true).template get<std::string>();
23387 const json_pointer from_ptr(from_path);
23388
23389 // the "from" location must exist - use at()
23390 basic_json v = result.at(from_ptr);
23391
23392 // The copy is functionally identical to an "add"
23393 // operation at the target location using the value
23394 // specified in the "from" member.
23395 operation_add(ptr, v);
23396 break;
23397 }
23398
23399 case patch_operations::test:
23400 {
23401 bool success = false;
23402 JSON_TRY
23403 {
23404 // check if "value" matches the one at "path"
23405 // the "path" location must exist - use at()
23406 success = (result.at(ptr) == get_value("test", "value", false));
23407 }
23409 {
23410 // ignore out of range errors: success remains false
23411 }
23412
23413 // throw an exception if test fails
23414 if (JSON_HEDLEY_UNLIKELY(!success))
23415 {
23416 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
23417 }
23418
23419 break;
23420 }
23421
23422 case patch_operations::invalid:
23423 default:
23424 {
23425 // op must be "add", "remove", "replace", "move", "copy", or
23426 // "test"
23427 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
23428 }
23429 }
23430 }
23431
23432 return result;
23433 }
23434
23438 static basic_json diff(const basic_json& source, const basic_json& target,
23439 const std::string& path = "")
23440 {
23441 // the patch
23442 basic_json result(value_t::array);
23443
23444 // if the values are the same, return empty patch
23445 if (source == target)
23446 {
23447 return result;
23448 }
23449
23450 if (source.type() != target.type())
23451 {
23452 // different types: replace value
23453 result.push_back(
23454 {
23455 {"op", "replace"}, {"path", path}, {"value", target}
23456 });
23457 return result;
23458 }
23459
23460 switch (source.type())
23461 {
23462 case value_t::array:
23463 {
23464 // first pass: traverse common elements
23465 std::size_t i = 0;
23466 while (i < source.size() && i < target.size())
23467 {
23468 // recursive call to compare array values at index i
23469 auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
23470 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
23471 ++i;
23472 }
23473
23474 // We now reached the end of at least one array
23475 // in a second pass, traverse the remaining elements
23476
23477 // remove my remaining elements
23478 const auto end_index = static_cast<difference_type>(result.size());
23479 while (i < source.size())
23480 {
23481 // add operations in reverse order to avoid invalid
23482 // indices
23483 result.insert(result.begin() + end_index, object(
23484 {
23485 {"op", "remove"},
23486 {"path", detail::concat(path, '/', std::to_string(i))}
23487 }));
23488 ++i;
23489 }
23490
23491 // add other remaining elements
23492 while (i < target.size())
23493 {
23494 result.push_back(
23495 {
23496 {"op", "add"},
23497 {"path", detail::concat(path, "/-")},
23498 {"value", target[i]}
23499 });
23500 ++i;
23501 }
23502
23503 break;
23504 }
23505
23506 case value_t::object:
23507 {
23508 // first pass: traverse this object's elements
23509 for (auto it = source.cbegin(); it != source.cend(); ++it)
23510 {
23511 // escape the key name to be used in a JSON patch
23512 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
23513
23514 if (target.find(it.key()) != target.end())
23515 {
23516 // recursive call to compare object values at key it
23517 auto temp_diff = diff(it.value(), target[it.key()], path_key);
23518 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
23519 }
23520 else
23521 {
23522 // found a key that is not in o -> remove it
23523 result.push_back(object(
23524 {
23525 {"op", "remove"}, {"path", path_key}
23526 }));
23527 }
23528 }
23529
23530 // second pass: traverse other object's elements
23531 for (auto it = target.cbegin(); it != target.cend(); ++it)
23532 {
23533 if (source.find(it.key()) == source.end())
23534 {
23535 // found a key that is not in this -> add it
23536 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
23537 result.push_back(
23538 {
23539 {"op", "add"}, {"path", path_key},
23540 {"value", it.value()}
23541 });
23542 }
23543 }
23544
23545 break;
23546 }
23547
23548 case value_t::null:
23549 case value_t::string:
23550 case value_t::boolean:
23551 case value_t::number_integer:
23552 case value_t::number_unsigned:
23553 case value_t::number_float:
23554 case value_t::binary:
23555 case value_t::discarded:
23556 default:
23557 {
23558 // both primitive type: replace value
23559 result.push_back(
23560 {
23561 {"op", "replace"}, {"path", path}, {"value", target}
23562 });
23563 break;
23564 }
23565 }
23566
23567 return result;
23568 }
23569
23571
23573 // JSON Merge Patch functions //
23575
23578
23581 void merge_patch(const basic_json& apply_patch)
23582 {
23583 if (apply_patch.is_object())
23584 {
23585 if (!is_object())
23586 {
23587 *this = object();
23588 }
23589 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
23590 {
23591 if (it.value().is_null())
23592 {
23593 erase(it.key());
23594 }
23595 else
23596 {
23597 operator[](it.key()).merge_patch(it.value());
23598 }
23599 }
23600 }
23601 else
23602 {
23603 *this = apply_patch;
23604 }
23605 }
23606
23608};
23609
23613std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
23614{
23615 return j.dump();
23616}
23617
23618} // namespace nlohmann
23619
23621// nonmember support //
23623
23624namespace std // NOLINT(cert-dcl58-cpp)
23625{
23626
23631{
23632 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
23633 {
23634 return nlohmann::detail::hash(j);
23635 }
23636};
23637
23638// specialization for std::less<value_t>
23639template<>
23640struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
23641{
23647 ::nlohmann::detail::value_t rhs) const noexcept
23648 {
23649#if JSON_HAS_THREE_WAY_COMPARISON
23650 return std::is_lt(lhs <=> rhs); // *NOPAD*
23651#else
23652 return ::nlohmann::detail::operator<(lhs, rhs);
23653#endif
23654 }
23655};
23656
23657// C++20 prohibit function specialization in the std namespace.
23658#ifndef JSON_HAS_CPP_20
23659
23663inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name)
23664 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression)
23665 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
23666{
23667 j1.swap(j2);
23668}
23669
23670#endif
23671
23672} // namespace std
23673
23677inline nlohmann::json operator""_json(const char* s, std::size_t n)
23678{
23679 return nlohmann::json::parse(s, s + n);
23680}
23681
23685inline nlohmann::json::json_pointer operator""_json_pointer(const char* s, std::size_t n)
23686{
23687 return nlohmann::json::json_pointer(std::string(s, n));
23688}
23689
23690// #include <nlohmann/detail/macro_unscope.hpp>
23691
23692
23693// restore clang diagnostic settings
23694#if defined(__clang__)
23695 #pragma clang diagnostic pop
23696#endif
23697
23698// clean up
23699#undef JSON_ASSERT
23700#undef JSON_INTERNAL_CATCH
23701#undef JSON_THROW
23702#undef JSON_PRIVATE_UNLESS_TESTED
23703#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
23704#undef NLOHMANN_BASIC_JSON_TPL
23705#undef JSON_EXPLICIT
23706#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
23707#undef JSON_INLINE_VARIABLE
23708#undef JSON_NO_UNIQUE_ADDRESS
23709#undef JSON_DISABLE_ENUM_SERIALIZATION
23710
23711#ifndef JSON_TEST_KEEP_MACROS
23712 #undef JSON_CATCH
23713 #undef JSON_TRY
23714 #undef JSON_HAS_CPP_11
23715 #undef JSON_HAS_CPP_14
23716 #undef JSON_HAS_CPP_17
23717 #undef JSON_HAS_CPP_20
23718 #undef JSON_HAS_FILESYSTEM
23719 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
23720 #undef JSON_HAS_THREE_WAY_COMPARISON
23721 #undef JSON_HAS_RANGES
23722 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23723#endif
23724
23725// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
23726
23727
23728#undef JSON_HEDLEY_ALWAYS_INLINE
23729#undef JSON_HEDLEY_ARM_VERSION
23730#undef JSON_HEDLEY_ARM_VERSION_CHECK
23731#undef JSON_HEDLEY_ARRAY_PARAM
23732#undef JSON_HEDLEY_ASSUME
23733#undef JSON_HEDLEY_BEGIN_C_DECLS
23734#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
23735#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
23736#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
23737#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
23738#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
23739#undef JSON_HEDLEY_CLANG_HAS_FEATURE
23740#undef JSON_HEDLEY_CLANG_HAS_WARNING
23741#undef JSON_HEDLEY_COMPCERT_VERSION
23742#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
23743#undef JSON_HEDLEY_CONCAT
23744#undef JSON_HEDLEY_CONCAT3
23745#undef JSON_HEDLEY_CONCAT3_EX
23746#undef JSON_HEDLEY_CONCAT_EX
23747#undef JSON_HEDLEY_CONST
23748#undef JSON_HEDLEY_CONSTEXPR
23749#undef JSON_HEDLEY_CONST_CAST
23750#undef JSON_HEDLEY_CPP_CAST
23751#undef JSON_HEDLEY_CRAY_VERSION
23752#undef JSON_HEDLEY_CRAY_VERSION_CHECK
23753#undef JSON_HEDLEY_C_DECL
23754#undef JSON_HEDLEY_DEPRECATED
23755#undef JSON_HEDLEY_DEPRECATED_FOR
23756#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
23757#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
23758#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
23759#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
23760#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
23761#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
23762#undef JSON_HEDLEY_DIAGNOSTIC_POP
23763#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
23764#undef JSON_HEDLEY_DMC_VERSION
23765#undef JSON_HEDLEY_DMC_VERSION_CHECK
23766#undef JSON_HEDLEY_EMPTY_BASES
23767#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
23768#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
23769#undef JSON_HEDLEY_END_C_DECLS
23770#undef JSON_HEDLEY_FLAGS
23771#undef JSON_HEDLEY_FLAGS_CAST
23772#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
23773#undef JSON_HEDLEY_GCC_HAS_BUILTIN
23774#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
23775#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
23776#undef JSON_HEDLEY_GCC_HAS_EXTENSION
23777#undef JSON_HEDLEY_GCC_HAS_FEATURE
23778#undef JSON_HEDLEY_GCC_HAS_WARNING
23779#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
23780#undef JSON_HEDLEY_GCC_VERSION
23781#undef JSON_HEDLEY_GCC_VERSION_CHECK
23782#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
23783#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
23784#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
23785#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
23786#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
23787#undef JSON_HEDLEY_GNUC_HAS_FEATURE
23788#undef JSON_HEDLEY_GNUC_HAS_WARNING
23789#undef JSON_HEDLEY_GNUC_VERSION
23790#undef JSON_HEDLEY_GNUC_VERSION_CHECK
23791#undef JSON_HEDLEY_HAS_ATTRIBUTE
23792#undef JSON_HEDLEY_HAS_BUILTIN
23793#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
23794#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
23795#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
23796#undef JSON_HEDLEY_HAS_EXTENSION
23797#undef JSON_HEDLEY_HAS_FEATURE
23798#undef JSON_HEDLEY_HAS_WARNING
23799#undef JSON_HEDLEY_IAR_VERSION
23800#undef JSON_HEDLEY_IAR_VERSION_CHECK
23801#undef JSON_HEDLEY_IBM_VERSION
23802#undef JSON_HEDLEY_IBM_VERSION_CHECK
23803#undef JSON_HEDLEY_IMPORT
23804#undef JSON_HEDLEY_INLINE
23805#undef JSON_HEDLEY_INTEL_CL_VERSION
23806#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
23807#undef JSON_HEDLEY_INTEL_VERSION
23808#undef JSON_HEDLEY_INTEL_VERSION_CHECK
23809#undef JSON_HEDLEY_IS_CONSTANT
23810#undef JSON_HEDLEY_IS_CONSTEXPR_
23811#undef JSON_HEDLEY_LIKELY
23812#undef JSON_HEDLEY_MALLOC
23813#undef JSON_HEDLEY_MCST_LCC_VERSION
23814#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
23815#undef JSON_HEDLEY_MESSAGE
23816#undef JSON_HEDLEY_MSVC_VERSION
23817#undef JSON_HEDLEY_MSVC_VERSION_CHECK
23818#undef JSON_HEDLEY_NEVER_INLINE
23819#undef JSON_HEDLEY_NON_NULL
23820#undef JSON_HEDLEY_NO_ESCAPE
23821#undef JSON_HEDLEY_NO_RETURN
23822#undef JSON_HEDLEY_NO_THROW
23823#undef JSON_HEDLEY_NULL
23824#undef JSON_HEDLEY_PELLES_VERSION
23825#undef JSON_HEDLEY_PELLES_VERSION_CHECK
23826#undef JSON_HEDLEY_PGI_VERSION
23827#undef JSON_HEDLEY_PGI_VERSION_CHECK
23828#undef JSON_HEDLEY_PREDICT
23829#undef JSON_HEDLEY_PRINTF_FORMAT
23830#undef JSON_HEDLEY_PRIVATE
23831#undef JSON_HEDLEY_PUBLIC
23832#undef JSON_HEDLEY_PURE
23833#undef JSON_HEDLEY_REINTERPRET_CAST
23834#undef JSON_HEDLEY_REQUIRE
23835#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
23836#undef JSON_HEDLEY_REQUIRE_MSG
23837#undef JSON_HEDLEY_RESTRICT
23838#undef JSON_HEDLEY_RETURNS_NON_NULL
23839#undef JSON_HEDLEY_SENTINEL
23840#undef JSON_HEDLEY_STATIC_ASSERT
23841#undef JSON_HEDLEY_STATIC_CAST
23842#undef JSON_HEDLEY_STRINGIFY
23843#undef JSON_HEDLEY_STRINGIFY_EX
23844#undef JSON_HEDLEY_SUNPRO_VERSION
23845#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
23846#undef JSON_HEDLEY_TINYC_VERSION
23847#undef JSON_HEDLEY_TINYC_VERSION_CHECK
23848#undef JSON_HEDLEY_TI_ARMCL_VERSION
23849#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
23850#undef JSON_HEDLEY_TI_CL2000_VERSION
23851#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
23852#undef JSON_HEDLEY_TI_CL430_VERSION
23853#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
23854#undef JSON_HEDLEY_TI_CL6X_VERSION
23855#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
23856#undef JSON_HEDLEY_TI_CL7X_VERSION
23857#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
23858#undef JSON_HEDLEY_TI_CLPRU_VERSION
23859#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
23860#undef JSON_HEDLEY_TI_VERSION
23861#undef JSON_HEDLEY_TI_VERSION_CHECK
23862#undef JSON_HEDLEY_UNAVAILABLE
23863#undef JSON_HEDLEY_UNLIKELY
23864#undef JSON_HEDLEY_UNPREDICTABLE
23865#undef JSON_HEDLEY_UNREACHABLE
23866#undef JSON_HEDLEY_UNREACHABLE_RETURN
23867#undef JSON_HEDLEY_VERSION
23868#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
23869#undef JSON_HEDLEY_VERSION_DECODE_MINOR
23870#undef JSON_HEDLEY_VERSION_DECODE_REVISION
23871#undef JSON_HEDLEY_VERSION_ENCODE
23872#undef JSON_HEDLEY_WARNING
23873#undef JSON_HEDLEY_WARN_UNUSED_RESULT
23874#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
23875#undef JSON_HEDLEY_FALL_THROUGH
23876
23877
23878
23879#endif // INCLUDE_NLOHMANN_JSON_HPP_
a class to store JSON values
ValueType & get_to(ValueType &v) const
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
detail::parser_callback_t< basic_json > parser_callback_t
per-element parser callback type
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
const_reference operator[](T *key) const
NumberIntegerType number_integer_t
a type for a number (integer)
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
static std::vector< std::uint8_t > to_bjdata(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
::nlohmann::json_pointer< StringType > json_pointer
JSON Pointer, see nlohmann::json_pointer.
ReferenceType get_ref()
get a reference value (implicit)
reference emplace_back(Args &&... args)
add an object to an array
json_sax< basic_json > json_sax_t
SAX interface type, see nlohmann::json_sax.
basic_json(const value_t v)
create an empty value with a given type
size_type max_size() const noexcept
returns the maximum possible number of elements
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
iterator find(KeyType &&key)
find an element in a JSON object
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
value_type & reference
the type of an element reference
void erase(const size_type idx)
remove element from a JSON array given an index
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
iterator begin() noexcept
returns an iterator to the first element
binary_t & get_binary()
get a binary value
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
basic_json(const JsonRef &ref)
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
basic_json & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value)
copy assignment
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
const_iterator cend() const noexcept
returns an iterator to one past the last element
reference back()
access the last element
const binary_t & get_binary() const
get a binary value
static void to_bjdata(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
StringType string_t
a type for a string
size_type size() const noexcept
returns the number of elements
void push_back(const basic_json &val)
add an object to an array
reference at(KeyType &&key)
access specified object element with bounds checking
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
ObjectType< StringType, basic_json, default_object_comparator_t, AllocatorType< std::pair< const StringType, basic_json > > > object_t
a type for an object
std::size_t size_type
a type to represent container sizes
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
std::ptrdiff_t difference_type
a type to represent differences between iterators
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init)
explicitly create a binary array (without subtype)
reference operator+=(basic_json &&val)
add an object to an array
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
size_type count(const typename object_t::key_type &key) const
returns the number of occurrences of a key in a JSON object
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(InputType &&i, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
BooleanType boolean_t
a type for a boolean
void push_back(initializer_list_t init)
add an object to an object
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
reference operator[](typename object_t::key_type key)
access specified object element
std::decay< ValueType >::type value(KeyType &&key, ValueType &&default_value) const
access specified object element with default value
IteratorType erase(IteratorType pos)
remove element given an iterator
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
static void to_bson(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a BSON serialization of a given JSON value
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
constexpr bool is_structured() const noexcept
return whether type is structured
const_iterator begin() const noexcept
returns an iterator to the first element
void update(const_iterator first, const_iterator last, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
JSON_PRIVATE_UNLESS_TESTED const_reference bool static SAX bool sax_parse(InputType &&i, SAX *sax, input_format_t format=input_format_t::json, const bool strict=true, const bool ignore_comments=false)
reference at(size_type idx)
access specified array element with bounds checking
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
reference front()
access the first element
constexpr bool is_primitive() const noexcept
return whether type is primitive
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
static void to_cbor(const basic_json &j, detail::output_adapter< char > o)
create a CBOR serialization of a given JSON value
void swap(object_t &other)
exchanges the values
constexpr bool is_object() const noexcept
return whether value is an object
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
reference operator[](KeyType &&key)
access specified object element
const_reference front() const
access the first element
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
NumberFloatType number_float_t
a type for a number (floating-point)
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
bool empty() const noexcept
checks whether the container is empty.
basic_json(const basic_json &other)
copy constructor
~basic_json() noexcept
destructor
const_iterator find(KeyType &&key) const
find an element in a JSON object
static std::vector< std::uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
basic_json(basic_json &&other) noexcept
move constructor
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
static void to_ubjson(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
json_value m_value
the value of the current element
void swap(typename binary_t::container_type &other)
exchanges the values
void swap(array_t &other)
exchanges the values
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
static iteration_proxy< iterator > iterator_wrapper(reference ref) noexcept
wrapper to access iterator member functions in range-based for
std::less< StringType > default_object_comparator_t
default object key comparator type The actual object key comparator type (object_comparator_t) may be...
ReferenceType get_ref() const
get a reference value (implicit)
const_reference at(KeyType &&key) const
access specified object element with bounds checking
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
const_iterator end() const noexcept
returns an iterator to one past the last element
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Array get_to(T(&v)[N]) const noexcept(noexcept(JSONSerializer< Array >::from_json(std::declval< const basic_json_t & >(), v)))
const_reference operator[](KeyType &&key) const
access specified object element
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
constexpr bool is_boolean() const noexcept
return whether value is a boolean
iterator end() noexcept
returns an iterator to one past the last element
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
void clear() noexcept
clears the contents
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
constexpr bool is_binary() const noexcept
return whether value is a binary array
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
reference operator[](size_type idx)
access specified array element
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
create a BSON serialization of a given JSON value
std::decay< ValueType >::type value(const char *key, ValueType &&default_value) const
string_t value(KeyType &&key, const char *default_value) const
access specified object element with default value
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
void swap(binary_t &other)
exchanges the values
iter_impl< basic_json > iterator
an iterator for a basic_json container
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
static void to_ubjson(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
string_t value(const char *key, const char *default_value) const
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
void swap(string_t &other)
exchanges the values
const_reference back() const
access the last element
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
constexpr bool is_string() const noexcept
return whether value is a string
constexpr bool is_array() const noexcept
return whether value is an array
iterator insert_iterator(const_iterator pos, Args &&... args)
basic_json flatten() const
return flattened JSON value
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
return the type as string
const value_type & const_reference
the type of an element const reference
void push_back(basic_json &&val)
add an object to an array
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
reference operator[](T *key)
constexpr bool is_number() const noexcept
return whether value is a number
reference operator+=(initializer_list_t init)
add an object to an object
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
static void to_cbor(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a CBOR serialization of a given JSON value
detail::value_t value_t
size_type erase(KeyType &&key)
remove element from a JSON object given a key
friend class ::nlohmann::detail::parser
static void to_msgpack(const basic_json &j, detail::output_adapter< char > o)
create a MessagePack serialization of a given JSON value
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
detail::actual_object_comparator_t< basic_json > object_comparator_t
object key comparator type
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
const_reference operator[](size_type idx) const
access specified array element
AllocatorType< basic_json > allocator_type
the allocator type
nlohmann::byte_container_with_subtype< BinaryType > binary_t
a type for a packed binary type
JSONSerializer< T, SFINAE > json_serializer
void push_back(const typename object_t::value_type &val)
add an object to an object
JSON_PRIVATE_UNLESS_TESTED const_reference rhs
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
basic_json patch(const basic_json &json_patch) const
applies a JSON patch
string_t value(const typename object_t::key_type &key, const char *default_value) const
access specified object element with default value
basic_json(CompatibleType &&val) noexcept(noexcept(//NOLINT(bugprone-forwarding-reference-overload, bugprone-exception-escape) JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value from compatible types
basic_json unflatten() const
unflatten a previously flattened JSON value
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
iterator find(const typename object_t::key_type &key)
find an element in a JSON object
reference operator+=(const typename object_t::value_type &val)
add an object to an object
const_iterator cbegin() const noexcept
returns a const iterator to the first element
std::decay< ValueType >::type value(const KeyType &key, ValueType &&default_value) const
access specified object element with default value
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
basic_json(initializer_list_t init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
const_reference at(size_type idx) const
access specified array element with bounds checking
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
constexpr bool is_discarded() const noexcept
return whether value is discarded
constexpr bool is_null() const noexcept
return whether value is null
friend void swap(reference left, reference right) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
static void to_bjdata(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
JSON_PRIVATE_UNLESS_TESTED const_reference bool inverse
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
get a (pointer) value (explicit)
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
static void to_msgpack(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a MessagePack serialization of a given JSON value
reference operator+=(const basic_json &val)
add an object to an array
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
static allocator_type get_allocator()
returns the allocator associated with the container
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
an internal type for a backed binary type
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
bool operator!=(const byte_container_with_subtype &rhs) const
void clear_subtype() noexcept
clears the binary subtype
byte_container_with_subtype() noexcept(noexcept(container_type()))
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
constexpr subtype_type subtype() const noexcept
return the binary subtype
bool operator==(const byte_container_with_subtype &rhs) const
deserialization of CBOR, MessagePack, and UBJSON values
binary_reader & operator=(const binary_reader &)=delete
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
binary_reader & operator=(binary_reader &&)=default
binary_reader(const binary_reader &)=delete
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
binary_reader(binary_reader &&)=default
general exception of the basic_json class
const int id
the id of the exception
static std::string diagnostics(std::nullptr_t)
static std::string diagnostics(const BasicJsonType *leaf_element)
static std::string name(const std::string &ename, int id_)
const char * what() const noexcept override
returns the explanatory string
exception indicating errors with iterators
static invalid_iterator create(int id_, const std::string &what_arg, BasicJsonContext context)
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
bool operator<(const iter_impl &other) const
comparison: smaller
iter_impl operator-(difference_type i) const
subtract from iterator
bool operator!=(const IterImpl &other) const
comparison: not equal
void set_end() noexcept
set the iterator past the last value
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
iter_impl & operator--()
pre-decrement (–it)
difference_type operator-(const iter_impl &other) const
return difference
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
defines a reference to the type iterated over (value_type)
reference operator*() const
return a reference to the value pointed to by the iterator
iter_impl(iter_impl &&) noexcept=default
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
pointer operator->() const
dereference the iterator
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
the actual iterator of the associated instance
iter_impl operator+(difference_type i) const
add to iterator
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
const object_t::key_type & key() const
return the key of an object iterator
bool operator==(const IterImpl &other) const
comparison: equal
bool operator>(const iter_impl &other) const
comparison: greater than
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
reference value() const
return the value of an iterator
iter_impl & operator++()
pre-increment (++it)
reference operator[](difference_type n) const
access to successor
bool operator<=(const iter_impl &other) const
comparison: less than or equal
iter_impl operator++(int) &
post-increment (it++)
std::bidirectional_iterator_tag iterator_category
iter_impl operator--(int) &
post-decrement (it–)
iter_impl & operator+=(difference_type i)
add to iterator
iter_impl & operator-=(difference_type i)
subtract from iterator
json_ref(json_ref &&) noexcept=default
value_type const & operator*() const
json_ref(Args &&... args)
json_ref(const value_type &value)
value_type const * operator->() const
json_ref(std::initializer_list< json_ref > init)
json_ref(value_type &&value)
value_type moved_or_copied() const
a template for a reverse iterator class
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
typename Base::reference reference
the reference type for the pointed-to element
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
json_reverse_iterator & operator+=(difference_type i)
add to iterator
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
reference operator[](difference_type n) const
access to successor
json_reverse_iterator operator--(int) &
post-decrement (it–)
difference_type operator-(const json_reverse_iterator &other) const
return difference
json_reverse_iterator operator+(difference_type i) const
add to iterator
json_reverse_iterator operator++(int) &
post-increment (it++)
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
json_reverse_iterator & operator--()
pre-decrement (–it)
reference value() const
return the value of an iterator
json_reverse_iterator & operator++()
pre-increment (++it)
bool start_object(std::size_t=static_cast< std::size_t >(-1))
typename BasicJsonType::string_t string_t
typename BasicJsonType::number_integer_t number_integer_t
typename BasicJsonType::number_float_t number_float_t
typename BasicJsonType::binary_t binary_t
bool start_array(std::size_t=static_cast< std::size_t >(-1))
bool parse_error(std::size_t, const std::string &, const detail::exception &)
bool number_integer(number_integer_t)
bool number_unsigned(number_unsigned_t)
typename BasicJsonType::number_unsigned_t number_unsigned_t
bool number_float(number_float_t, const string_t &)
typename BasicJsonType::string_t string_t
json_sax_dom_callback_parser & operator=(const json_sax_dom_callback_parser &)=delete
typename BasicJsonType::number_unsigned_t number_unsigned_t
typename BasicJsonType::number_integer_t number_integer_t
typename BasicJsonType::parser_callback_t parser_callback_t
json_sax_dom_callback_parser(const json_sax_dom_callback_parser &)=delete
typename BasicJsonType::binary_t binary_t
typename BasicJsonType::number_float_t number_float_t
typename BasicJsonType::parse_event_t parse_event_t
bool number_unsigned(number_unsigned_t val)
json_sax_dom_callback_parser & operator=(json_sax_dom_callback_parser &&)=default
bool number_float(number_float_t val, const string_t &)
json_sax_dom_callback_parser(json_sax_dom_callback_parser &&)=default
bool parse_error(std::size_t, const std::string &, const Exception &ex)
json_sax_dom_callback_parser(BasicJsonType &r, const parser_callback_t cb, const bool allow_exceptions_=true)
SAX implementation to create a JSON value from SAX events.
json_sax_dom_parser(const json_sax_dom_parser &)=delete
typename BasicJsonType::binary_t binary_t
json_sax_dom_parser & operator=(json_sax_dom_parser &&)=default
bool number_unsigned(number_unsigned_t val)
typename BasicJsonType::number_integer_t number_integer_t
bool parse_error(std::size_t, const std::string &, const Exception &ex)
typename BasicJsonType::number_unsigned_t number_unsigned_t
constexpr bool is_errored() const
json_sax_dom_parser(json_sax_dom_parser &&)=default
typename BasicJsonType::number_float_t number_float_t
json_sax_dom_parser & operator=(const json_sax_dom_parser &)=delete
bool number_float(number_float_t val, const string_t &)
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true)
typename BasicJsonType::string_t string_t
bool number_integer(number_integer_t val)
JSON_HEDLEY_RETURNS_NON_NULL static JSON_HEDLEY_CONST const char * token_type_name(const token_type t) noexcept
return name of values of type token_type (only used for errors)
token_type
token types for the parser
@ value_float
an floating point number – use get_number_float() for actual value
@ begin_array
the character for array begin [
@ value_string
a string – use get_string() for actual value
@ end_array
the character for array end ]
@ uninitialized
indicating the scanner is uninitialized
@ parse_error
indicating a parse error
@ value_integer
a signed integer – use get_number_integer() for actual value
@ value_separator
the value separator ,
@ end_object
the character for object end }
@ begin_object
the character for object begin {
@ value_unsigned
an unsigned integer – use get_number_unsigned() for actual value
@ end_of_input
indicating the end of the input buffer
@ literal_or_value
a literal or the begin of a value (only for diagnostics)
lexical analysis
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
lexer & operator=(lexer &&)=default
bool skip_bom()
skip the UTF-8 byte order mark
lexer(InputAdapterType &&adapter, bool ignore_comments_=false) noexcept
constexpr position_t get_position() const noexcept
return position of last read token
constexpr number_integer_t get_number_integer() const noexcept
return integer value
typename lexer_base< BasicJsonType >::token_type token_type
lexer & operator=(lexer &)=delete
lexer(const lexer &)=delete
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
constexpr number_float_t get_number_float() const noexcept
return floating-point value
std::string get_token_string() const
lexer(lexer &&)=default
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
exception indicating other library errors
static other_error create(int id_, const std::string &what_arg, BasicJsonContext context)
exception indicating access out of the defined range
static out_of_range create(int id_, const std::string &what_arg, BasicJsonContext context)
exception indicating a parse error
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, BasicJsonContext context)
create a parse error exception
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg, BasicJsonContext context)
const std::size_t byte
byte index of the parse error
const error_handler_t error_handler
error_handler how to react on decoding errors
const std::lconv * loc
the locale
std::array< char, 64 > number_buffer
a (hopefully) large enough character buffer
serializer(serializer &&)=delete
serializer & operator=(serializer &&)=delete
const char decimal_point
the locale's decimal point character
const char thousands_sep
the locale's thousand separator character
serializer & operator=(const serializer &)=delete
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
const char indent_char
the indentation character
std::array< char, 512 > string_buffer
string buffer
JSON_PRIVATE_UNLESS_TESTED const bool ensure_ascii
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
serializer(const serializer &)=delete
string_t indent_string
the indentation string
exception indicating executing a member function with a wrong type
static type_error create(int id_, const std::string &what_arg, BasicJsonContext context)
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
friend json_pointer operator/(const json_pointer &lhs, string_t token)
create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
void pop_back()
remove last reference token
friend json_pointer operator/(const json_pointer &lhs, std::size_t array_idx)
create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
json_pointer parent_pointer() const
returns the parent of this JSON pointer
bool empty() const noexcept
return whether pointer points to the root document
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
typename string_t_helper< RefStringType >::type string_t
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
friend json_pointer operator/(const json_pointer &lhs, const json_pointer &rhs)
create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
friend class json_pointer
string_t to_string() const
return a string representation of the JSON pointer
friend bool operator==(json_pointer< RefStringTypeLhs > const &lhs, json_pointer< RefStringTypeRhs > const &rhs) noexcept
compares two JSON pointers for equality
const string_t & back() const
return last reference token
friend bool operator!=(json_pointer< RefStringTypeLhs > const &lhs, json_pointer< RefStringTypeRhs > const &rhs) noexcept
compares two JSON pointers for inequality
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
json_pointer(const string_t &s="")
create JSON pointer
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
decltype(get< N >(std::declval< ::nlohmann::detail::iteration_proxy_value< IteratorType > >())) type
int errno
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION
#define JSON_HEDLEY_CONST
#define JSON_HEDLEY_DIAGNOSTIC_PUSH
Definition indijson.hpp:893
#define JSON_INLINE_VARIABLE
#define JSON_HEDLEY_WARN_UNUSED_RESULT
#define JSON_PRIVATE_UNLESS_TESTED
#define NLOHMANN_JSON_VERSION_PATCH
Definition indijson.hpp:52
#define JSON_HEDLEY_LIKELY(expr)
#define JSON_HEDLEY_NON_NULL(...)
#define JSON_INTERNAL_CATCH(exception)
#define JSON_HEDLEY_RETURNS_NON_NULL
#define JSON_CATCH(exception)
#define JSON_ASSERT(x)
#define JSON_THROW(exception)
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#define NLOHMANN_JSON_VERSION_MAJOR
Definition indijson.hpp:50
#define NLOHMANN_BASIC_JSON_TPL
#define JSON_HEDLEY_UNLIKELY(expr)
#define JSON_TRY
#define JSON_NO_UNIQUE_ADDRESS
#define NLOHMANN_JSON_VERSION_MINOR
Definition indijson.hpp:51
#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)
#define JSON_HEDLEY_DIAGNOSTIC_POP
Definition indijson.hpp:894
#define JSON_EXPLICIT
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
#define JSON_HEDLEY_PURE
#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)
std::variant< std::monostate, bool, std::int64_t, std::uint64_t, double, std::string > Value
std::string to_string(Error error)
Definition httplib.h:9275
detail namespace with internal helper functions
std::integral_constant< bool, all_signed< Types... >::value||all_unsigned< Types... >::value > same_sign
typename std::enable_if< B, T >::type enable_if_t
typename T::reference reference_t
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().data(), std::declval< const Arg & >().size())) string_can_append_data
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
typename actual_object_comparator< BasicJsonType >::type actual_object_comparator_t
typename T::key_compare detect_key_compare
std::integral_constant< bool,(std::is_signed< OfType >::value &&(sizeof(T)< sizeof(OfType)))||(same_sign< OfType, T >::value &&sizeof(OfType)==sizeof(T)) > never_out_of_range
decltype(T::from_json(std::declval< Args >()...)) from_json_function
is_detected< string_can_append_iter, StringType, Arg > detect_string_can_append_iter
void to_json(BasicJsonType &j, T b) noexcept
value_type_t< iterator_traits< iterator_t< T > > > range_value_t
value_t
the JSON type enumeration
@ number_integer
number value (signed integer)
@ discarded
discarded by the parser callback function
@ binary
binary array (ordered collection of bytes)
@ object
object (unordered set of name/value pairs)
@ number_float
number value (floating-point)
@ number_unsigned
number value (unsigned integer)
@ array
array (ordered collection of values)
typename std::conditional< is_usable_as_key_type< typename BasicJsonType::object_comparator_t, typename BasicJsonType::object_t::key_type, KeyTypeCVRef, RequireTransparentComparator, ExcludeObjectKeyType >::value &&!is_json_iterator_of< BasicJsonType, KeyType >::value, std::true_type, std::false_type >::type is_usable_as_basic_json_key_type
make_index_sequence< sizeof...(Ts)> index_sequence_for
typename T::pointer pointer_t
is_detected< string_can_append, StringType, Arg > detect_string_can_append
typename T::difference_type difference_type_t
typename detector< nonesuch, void, Op, Args... >::type detected_t
integer_sequence< size_t, Ints... > index_sequence
void to_json_tuple_impl(BasicJsonType &j, const Tuple &t, index_sequence< Idx... >)
enable_if_t< is_range< R >::value, result_of_begin< decltype(std::declval< R & >())> > iterator_t
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
decltype(std::declval< StringType & >().append(std::declval< Arg && >())) string_can_append
cbor_tag_handler_t
how to treat CBOR tags
@ store
store tags as binary type
@ error
throw a parse_error exception in case of a tag
error_handler_t
how to treat decoding errors
@ strict
throw a type_error exception in case of invalid UTF-8
@ ignore
ignore invalid UTF-8 sequences
@ replace
replace invalid UTF-8 sequences with U+FFFD
typename std::conditional< is_detected< detect_erase_with_key_type, typename BasicJsonType::object_t, KeyType >::value, std::true_type, std::false_type >::type has_erase_with_key_type
typename T::key_type key_type_t
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
typename utility_internal::Gen< T, N >::type make_integer_sequence
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
typename std::conditional< is_comparable< Comparator, ObjectKeyType, KeyTypeCVRef >::value &&!(ExcludeObjectKeyType &&std::is_same< KeyType, ObjectKeyType >::value) &&(!RequireTransparentComparator||is_detected< detect_is_transparent, Comparator >::value) &&!is_json_pointer< KeyType >::value, std::true_type, std::false_type >::type is_usable_as_key_type
typename detected_or< Default, Op, Args... >::type detected_or_t
constexpr bool value_in_range_of(T val)
void concat_into(OutStringType &)
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
typename detector< nonesuch, void, Op, Args... >::value_t is_detected
is_detected< string_can_append_data, StringType, Arg > detect_string_can_append_data
typename make_void< Ts... >::type void_t
OutStringType concat(Args &&... args)
make_integer_sequence< size_t, N > make_index_sequence
typename T::mapped_type mapped_type_t
decltype(std::declval< T >().template get< U >()) get_template_function
decltype(std::declval< ObjectType & >().erase(std::declval< KeyType >())) detect_erase_with_key_type
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().begin(), std::declval< const Arg & >().end())) string_can_append_iter
typename T::is_transparent detect_is_transparent
typename T::iterator_category iterator_category_t
std::size_t concat_length()
is_detected< string_can_append_op, StringType, Arg > detect_string_can_append_op
decltype(std::declval< StringType & >()+=std::declval< Arg && >()) string_can_append_op
T conditional_static_cast(U value)
decltype(T::to_json(std::declval< Args >()...)) to_json_function
typename T::value_type value_type_t
namespace for Niels Lohmann
bool operator!=(json_pointer< RefStringTypeLhs > const &lhs, json_pointer< RefStringTypeRhs > const &rhs) noexcept
bool operator==(json_pointer< RefStringTypeLhs > const &lhs, json_pointer< RefStringTypeRhs > const &rhs) noexcept
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
uint16_t type
Definition pwc-ioctl.h:0
default JSONSerializer template argument
static auto from_json(BasicJsonType &&j, TargetType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), val), void())
convert a JSON value to any value type
static auto from_json(BasicJsonType &&j) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))
convert a JSON value to any value type
static auto to_json(BasicJsonType &j, TargetType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< TargetType >(val)))) -> decltype(::nlohmann::to_json(j, std::forward< TargetType >(val)), void())
convert any value type to a JSON value
typename BasicJsonType::default_object_comparator_t object_comparator_t
typename std::conditional< has_key_compare< object_t >::value, typename object_t::key_compare, object_comparator_t >::type type
typename BasicJsonType::object_t object_t
static void construct(BasicJsonType &j, const CompatibleArrayType &arr)
static void construct(BasicJsonType &j, const std::valarray< T > &arr)
static void construct(BasicJsonType &j, const std::vector< bool > &arr)
static void construct(BasicJsonType &j, typename BasicJsonType::array_t &&arr)
static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr)
static void construct(BasicJsonType &j, const typename BasicJsonType::binary_t &b)
static void construct(BasicJsonType &j, typename BasicJsonType::binary_t &&b)
static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept
static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept
static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept
static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept
static void construct(BasicJsonType &j, typename BasicJsonType::object_t &&obj)
static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj)
static void construct(BasicJsonType &j, const CompatibleObjectType &obj)
static void construct(BasicJsonType &j, typename BasicJsonType::string_t &&s)
static void construct(BasicJsonType &j, const CompatibleStringType &str)
static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s)
typename BasicJsonType::template json_serializer< T, void > serializer
static constexpr std::size_t size() noexcept
primitive_iterator_t primitive_iterator
generic iterator for all other types
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
static constexpr bool value
static one test(decltype(&C::capacity))
static constexpr bool value
nonesuch(nonesuch const &)=delete
void operator=(nonesuch &&)=delete
nonesuch(nonesuch const &&)=delete
void operator=(nonesuch const &)=delete
struct to capture the start position of the current token
std::size_t lines_read
the number of lines read
std::size_t chars_read_current_line
the number of characters read in the current line
std::size_t chars_read_total
the total number of characters read
auto operator()(BasicJsonType &j, T &&val) const noexcept(noexcept(to_json(j, std::forward< T >(val)))) -> decltype(to_json(j, std::forward< T >(val)), void())
typename Extend< typename Gen< T, N/2 >::type, N/2, N % 2 >::type type
a minimal map-like container that preserves insertion order
std::vector< std::pair< const Key, T >, Allocator > Container
const_iterator find(const key_type &key) const
iterator erase(iterator pos)
void insert(InputIt first, InputIt last)
T & at(KeyType &&key)
std::pair< iterator, bool > insert(value_type &&value)
size_type count(const key_type &key) const
T & operator[](KeyType &&key)
iterator erase(iterator first, iterator last)
const T & operator[](const key_type &key) const
const T & at(const key_type &key) const
std::pair< iterator, bool > emplace(KeyType &&key, T &&t)
iterator find(KeyType &&key)
typename Container::const_iterator const_iterator
T & at(const key_type &key)
typename std::enable_if< std::is_convertible< typename std::iterator_traits< InputIt >::iterator_category, std::input_iterator_tag >::value >::type require_input_iter
T & operator[](const key_type &key)
ordered_map(It first, It last, const Allocator &alloc=Allocator())
std::equal_to< Key > key_compare
ordered_map(const Allocator &alloc) noexcept(noexcept(Container(alloc)))
std::pair< iterator, bool > insert(const value_type &value)
const T & operator[](KeyType &&key) const
typename Container::size_type size_type
size_type erase(const key_type &key)
typename Container::value_type value_type
const T & at(KeyType &&key) const
iterator find(const key_type &key)
ordered_map(std::initializer_list< value_type > init, const Allocator &alloc=Allocator())
ordered_map() noexcept(noexcept(Container()))
size_type count(KeyType &&key) const
typename Container::iterator iterator
std::pair< iterator, bool > emplace(const key_type &key, T &&t)
size_type erase(KeyType &&key)
std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL &j) const
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
unsigned char byte
Definition stvdriver.h:175