1 /*
2 __ _____ _____ _____
3 __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 3.7.1
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 SPDX-License-Identifier: MIT
9 Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
10
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
28 */
29
30 #ifndef INCLUDE_NLOHMANN_JSON_HPP_
31 #define INCLUDE_NLOHMANN_JSON_HPP_
32
33 #define NLOHMANN_JSON_VERSION_MAJOR 3
34 #define NLOHMANN_JSON_VERSION_MINOR 7
35 #define NLOHMANN_JSON_VERSION_PATCH 1
36
37 #include <algorithm> // all_of, find, for_each
38 #include <cassert> // assert
39 #include <ciso646> // and, not, or
40 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
41 #include <functional> // hash, less
42 #include <initializer_list> // initializer_list
43 #include <iosfwd> // istream, ostream
44 #include <iterator> // random_access_iterator_tag
45 #include <memory> // unique_ptr
46 #include <numeric> // accumulate
47 #include <string> // string, stoi, to_string
48 #include <utility> // declval, forward, move, pair, swap
49 #include <vector> // vector
50
51 // #include <nlohmann/adl_serializer.hpp>
52
53
54 #include <utility>
55
56 // #include <nlohmann/detail/conversions/from_json.hpp>
57
58
59 #include <algorithm> // transform
60 #include <array> // array
61 #include <ciso646> // and, not
62 #include <forward_list> // forward_list
63 #include <iterator> // inserter, front_inserter, end
64 #include <map> // map
65 #include <string> // string
66 #include <tuple> // tuple, make_tuple
67 #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
68 #include <unordered_map> // unordered_map
69 #include <utility> // pair, declval
70 #include <valarray> // valarray
71
72 // #include <nlohmann/detail/exceptions.hpp>
73
74
75 #include <exception> // exception
76 #include <stdexcept> // runtime_error
77 #include <string> // to_string
78
79 // #include <nlohmann/detail/input/position_t.hpp>
80
81
82 #include <cstddef> // size_t
83
84 namespace nlohmann
85 {
86 namespace detail
87 {
88 /// struct to capture the start position of the current token
89 struct position_t
90 {
91 /// the total number of characters read
92 std::size_t chars_read_total = 0;
93 /// the number of characters read in the current line
94 std::size_t chars_read_current_line = 0;
95 /// the number of lines read
96 std::size_t lines_read = 0;
97
98 /// conversion to size_t to preserve SAX interface
operator size_tnlohmann::detail::position_t99 constexpr operator size_t() const
100 {
101 return chars_read_total;
102 }
103 };
104
105 } // namespace detail
106 } // namespace nlohmann
107
108 // #include <nlohmann/detail/macro_scope.hpp>
109
110
111 #include <utility> // pair
112 // #include <nlohmann/thirdparty/hedley/hedley.hpp>
113 /* Hedley - https://nemequ.github.io/hedley
114 * Created by Evan Nemerson <evan@nemerson.com>
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 < 11)
126 #if defined(JSON_HEDLEY_VERSION)
127 #undef JSON_HEDLEY_VERSION
128 #endif
129 #define JSON_HEDLEY_VERSION 11
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_VERSION_ENCODE)
152 #undef JSON_HEDLEY_VERSION_ENCODE
153 #endif
154 #define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
155
156 #if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
157 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
158 #endif
159 #define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
160
161 #if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
162 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
163 #endif
164 #define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
165
166 #if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
167 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
168 #endif
169 #define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
170
171 #if defined(JSON_HEDLEY_GNUC_VERSION)
172 #undef JSON_HEDLEY_GNUC_VERSION
173 #endif
174 #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
175 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
176 #elif defined(__GNUC__)
177 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
178 #endif
179
180 #if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
181 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
182 #endif
183 #if defined(JSON_HEDLEY_GNUC_VERSION)
184 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
185 #else
186 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
187 #endif
188
189 #if defined(JSON_HEDLEY_MSVC_VERSION)
190 #undef JSON_HEDLEY_MSVC_VERSION
191 #endif
192 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000)
193 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
194 #elif defined(_MSC_FULL_VER)
195 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
196 #elif defined(_MSC_VER)
197 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
198 #endif
199
200 #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
201 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
202 #endif
203 #if !defined(_MSC_VER)
204 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
205 #elif defined(_MSC_VER) && (_MSC_VER >= 1400)
206 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
207 #elif defined(_MSC_VER) && (_MSC_VER >= 1200)
208 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
209 #else
210 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
211 #endif
212
213 #if defined(JSON_HEDLEY_INTEL_VERSION)
214 #undef JSON_HEDLEY_INTEL_VERSION
215 #endif
216 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE)
217 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
218 #elif defined(__INTEL_COMPILER)
219 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
220 #endif
221
222 #if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
223 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
224 #endif
225 #if defined(JSON_HEDLEY_INTEL_VERSION)
226 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
227 #else
228 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
229 #endif
230
231 #if defined(JSON_HEDLEY_PGI_VERSION)
232 #undef JSON_HEDLEY_PGI_VERSION
233 #endif
234 #if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
235 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
236 #endif
237
238 #if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
239 #undef JSON_HEDLEY_PGI_VERSION_CHECK
240 #endif
241 #if defined(JSON_HEDLEY_PGI_VERSION)
242 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
243 #else
244 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
245 #endif
246
247 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
248 #undef JSON_HEDLEY_SUNPRO_VERSION
249 #endif
250 #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
251 #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)
252 #elif defined(__SUNPRO_C)
253 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
254 #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
255 #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)
256 #elif defined(__SUNPRO_CC)
257 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
258 #endif
259
260 #if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
261 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
262 #endif
263 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
264 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
265 #else
266 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
267 #endif
268
269 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
270 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
271 #endif
272 #if defined(__EMSCRIPTEN__)
273 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
274 #endif
275
276 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
277 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
278 #endif
279 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
280 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
281 #else
282 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
283 #endif
284
285 #if defined(JSON_HEDLEY_ARM_VERSION)
286 #undef JSON_HEDLEY_ARM_VERSION
287 #endif
288 #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
289 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
290 #elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
291 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
292 #endif
293
294 #if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
295 #undef JSON_HEDLEY_ARM_VERSION_CHECK
296 #endif
297 #if defined(JSON_HEDLEY_ARM_VERSION)
298 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
299 #else
300 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
301 #endif
302
303 #if defined(JSON_HEDLEY_IBM_VERSION)
304 #undef JSON_HEDLEY_IBM_VERSION
305 #endif
306 #if defined(__ibmxl__)
307 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
308 #elif defined(__xlC__) && defined(__xlC_ver__)
309 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
310 #elif defined(__xlC__)
311 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
312 #endif
313
314 #if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
315 #undef JSON_HEDLEY_IBM_VERSION_CHECK
316 #endif
317 #if defined(JSON_HEDLEY_IBM_VERSION)
318 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
319 #else
320 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
321 #endif
322
323 #if defined(JSON_HEDLEY_TI_VERSION)
324 #undef JSON_HEDLEY_TI_VERSION
325 #endif
326 #if defined(__TI_COMPILER_VERSION__)
327 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
328 #endif
329
330 #if defined(JSON_HEDLEY_TI_VERSION_CHECK)
331 #undef JSON_HEDLEY_TI_VERSION_CHECK
332 #endif
333 #if defined(JSON_HEDLEY_TI_VERSION)
334 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
335 #else
336 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
337 #endif
338
339 #if defined(JSON_HEDLEY_CRAY_VERSION)
340 #undef JSON_HEDLEY_CRAY_VERSION
341 #endif
342 #if defined(_CRAYC)
343 #if defined(_RELEASE_PATCHLEVEL)
344 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
345 #else
346 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
347 #endif
348 #endif
349
350 #if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
351 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
352 #endif
353 #if defined(JSON_HEDLEY_CRAY_VERSION)
354 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
355 #else
356 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
357 #endif
358
359 #if defined(JSON_HEDLEY_IAR_VERSION)
360 #undef JSON_HEDLEY_IAR_VERSION
361 #endif
362 #if defined(__IAR_SYSTEMS_ICC__)
363 #if __VER__ > 1000
364 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
365 #else
366 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(VER / 100, __VER__ % 100, 0)
367 #endif
368 #endif
369
370 #if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
371 #undef JSON_HEDLEY_IAR_VERSION_CHECK
372 #endif
373 #if defined(JSON_HEDLEY_IAR_VERSION)
374 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
375 #else
376 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
377 #endif
378
379 #if defined(JSON_HEDLEY_TINYC_VERSION)
380 #undef JSON_HEDLEY_TINYC_VERSION
381 #endif
382 #if defined(__TINYC__)
383 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
384 #endif
385
386 #if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
387 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
388 #endif
389 #if defined(JSON_HEDLEY_TINYC_VERSION)
390 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
391 #else
392 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
393 #endif
394
395 #if defined(JSON_HEDLEY_DMC_VERSION)
396 #undef JSON_HEDLEY_DMC_VERSION
397 #endif
398 #if defined(__DMC__)
399 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
400 #endif
401
402 #if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
403 #undef JSON_HEDLEY_DMC_VERSION_CHECK
404 #endif
405 #if defined(JSON_HEDLEY_DMC_VERSION)
406 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
407 #else
408 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
409 #endif
410
411 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
412 #undef JSON_HEDLEY_COMPCERT_VERSION
413 #endif
414 #if defined(__COMPCERT_VERSION__)
415 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
416 #endif
417
418 #if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
419 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
420 #endif
421 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
422 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
423 #else
424 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
425 #endif
426
427 #if defined(JSON_HEDLEY_PELLES_VERSION)
428 #undef JSON_HEDLEY_PELLES_VERSION
429 #endif
430 #if defined(__POCC__)
431 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
432 #endif
433
434 #if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
435 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
436 #endif
437 #if defined(JSON_HEDLEY_PELLES_VERSION)
438 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
439 #else
440 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
441 #endif
442
443 #if defined(JSON_HEDLEY_GCC_VERSION)
444 #undef JSON_HEDLEY_GCC_VERSION
445 #endif
446 #if \
447 defined(JSON_HEDLEY_GNUC_VERSION) && \
448 !defined(__clang__) && \
449 !defined(JSON_HEDLEY_INTEL_VERSION) && \
450 !defined(JSON_HEDLEY_PGI_VERSION) && \
451 !defined(JSON_HEDLEY_ARM_VERSION) && \
452 !defined(JSON_HEDLEY_TI_VERSION) && \
453 !defined(__COMPCERT__)
454 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
455 #endif
456
457 #if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
458 #undef JSON_HEDLEY_GCC_VERSION_CHECK
459 #endif
460 #if defined(JSON_HEDLEY_GCC_VERSION)
461 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
462 #else
463 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
464 #endif
465
466 #if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
467 #undef JSON_HEDLEY_HAS_ATTRIBUTE
468 #endif
469 #if defined(__has_attribute)
470 #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
471 #else
472 #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
473 #endif
474
475 #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
476 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
477 #endif
478 #if defined(__has_attribute)
479 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute)
480 #else
481 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
482 #endif
483
484 #if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
485 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
486 #endif
487 #if defined(__has_attribute)
488 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute)
489 #else
490 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
491 #endif
492
493 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
494 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
495 #endif
496 #if \
497 defined(__has_cpp_attribute) && \
498 defined(__cplusplus) && \
499 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
500 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
501 #else
502 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
503 #endif
504
505 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
506 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
507 #endif
508 #if !defined(__cplusplus) || !defined(__has_cpp_attribute)
509 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
510 #elif \
511 !defined(JSON_HEDLEY_PGI_VERSION) && \
512 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
513 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
514 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
515 #else
516 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
517 #endif
518
519 #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
520 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
521 #endif
522 #if defined(__has_cpp_attribute) && defined(__cplusplus)
523 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
524 #else
525 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
526 #endif
527
528 #if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
529 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
530 #endif
531 #if defined(__has_cpp_attribute) && defined(__cplusplus)
532 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
533 #else
534 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
535 #endif
536
537 #if defined(JSON_HEDLEY_HAS_BUILTIN)
538 #undef JSON_HEDLEY_HAS_BUILTIN
539 #endif
540 #if defined(__has_builtin)
541 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
542 #else
543 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
544 #endif
545
546 #if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
547 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
548 #endif
549 #if defined(__has_builtin)
550 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
551 #else
552 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
553 #endif
554
555 #if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
556 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
557 #endif
558 #if defined(__has_builtin)
559 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
560 #else
561 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
562 #endif
563
564 #if defined(JSON_HEDLEY_HAS_FEATURE)
565 #undef JSON_HEDLEY_HAS_FEATURE
566 #endif
567 #if defined(__has_feature)
568 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
569 #else
570 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
571 #endif
572
573 #if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
574 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
575 #endif
576 #if defined(__has_feature)
577 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
578 #else
579 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
580 #endif
581
582 #if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
583 #undef JSON_HEDLEY_GCC_HAS_FEATURE
584 #endif
585 #if defined(__has_feature)
586 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
587 #else
588 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
589 #endif
590
591 #if defined(JSON_HEDLEY_HAS_EXTENSION)
592 #undef JSON_HEDLEY_HAS_EXTENSION
593 #endif
594 #if defined(__has_extension)
595 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
596 #else
597 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
598 #endif
599
600 #if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
601 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
602 #endif
603 #if defined(__has_extension)
604 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
605 #else
606 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
607 #endif
608
609 #if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
610 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
611 #endif
612 #if defined(__has_extension)
613 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
614 #else
615 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
616 #endif
617
618 #if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
619 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
620 #endif
621 #if defined(__has_declspec_attribute)
622 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
623 #else
624 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
625 #endif
626
627 #if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
628 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
629 #endif
630 #if defined(__has_declspec_attribute)
631 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
632 #else
633 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
634 #endif
635
636 #if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
637 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
638 #endif
639 #if defined(__has_declspec_attribute)
640 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
641 #else
642 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
643 #endif
644
645 #if defined(JSON_HEDLEY_HAS_WARNING)
646 #undef JSON_HEDLEY_HAS_WARNING
647 #endif
648 #if defined(__has_warning)
649 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
650 #else
651 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
652 #endif
653
654 #if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
655 #undef JSON_HEDLEY_GNUC_HAS_WARNING
656 #endif
657 #if defined(__has_warning)
658 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
659 #else
660 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
661 #endif
662
663 #if defined(JSON_HEDLEY_GCC_HAS_WARNING)
664 #undef JSON_HEDLEY_GCC_HAS_WARNING
665 #endif
666 #if defined(__has_warning)
667 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
668 #else
669 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
670 #endif
671
672 /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
673 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
674 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
675 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
676 #endif
677 #if defined(__cplusplus) && JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
678 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
679 JSON_HEDLEY_DIAGNOSTIC_PUSH \
680 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
681 xpr \
682 JSON_HEDLEY_DIAGNOSTIC_POP
683 #else
684 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
685 #endif
686
687 #if \
688 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
689 defined(__clang__) || \
690 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
691 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
692 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
693 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
694 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
695 JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) || \
696 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
697 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
698 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
699 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
700 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
701 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
702 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
703 #else
704 #define JSON_HEDLEY_PRAGMA(value)
705 #endif
706
707 #if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
708 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
709 #endif
710 #if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
711 #undef JSON_HEDLEY_DIAGNOSTIC_POP
712 #endif
713 #if defined(__clang__)
714 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
715 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
716 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
717 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
718 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
719 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
720 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
721 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
722 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
723 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
724 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
725 #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
726 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
727 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
728 #elif JSON_HEDLEY_TI_VERSION_CHECK(8,1,0)
729 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
730 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
731 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
732 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
733 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
734 #else
735 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
736 #define JSON_HEDLEY_DIAGNOSTIC_POP
737 #endif
738
739 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
740 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
741 #endif
742 #if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
743 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
744 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
745 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
746 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
747 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
748 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
749 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
750 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
751 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
752 #elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0)
753 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
754 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
755 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
756 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
757 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
758 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
759 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
760 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
761 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
762 #else
763 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
764 #endif
765
766 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
767 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
768 #endif
769 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
770 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
771 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
772 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
773 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
774 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
775 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
776 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
777 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
778 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
779 #elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0)
780 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
781 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
782 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
783 #else
784 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
785 #endif
786
787 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
788 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
789 #endif
790 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
791 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
792 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
793 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
794 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
795 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
796 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
797 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
798 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
799 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
800 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
801 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
802 #elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0)
803 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
804 #else
805 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
806 #endif
807
808 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
809 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
810 #endif
811 #if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
812 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
813 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
814 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
815 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
816 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
817 #else
818 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
819 #endif
820
821 #if defined(JSON_HEDLEY_DEPRECATED)
822 #undef JSON_HEDLEY_DEPRECATED
823 #endif
824 #if defined(JSON_HEDLEY_DEPRECATED_FOR)
825 #undef JSON_HEDLEY_DEPRECATED_FOR
826 #endif
827 #if defined(__cplusplus) && (__cplusplus >= 201402L)
828 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
829 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
830 #elif \
831 JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || \
832 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
833 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
834 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
835 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
836 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
837 JSON_HEDLEY_TI_VERSION_CHECK(8,3,0)
838 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
839 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
840 #elif \
841 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
842 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
843 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
844 JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
845 (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
846 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
847 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
848 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0)
849 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
850 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
851 #elif \
852 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
853 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0)
854 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
855 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
856 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
857 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
858 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
859 #else
860 #define JSON_HEDLEY_DEPRECATED(since)
861 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
862 #endif
863
864 #if defined(JSON_HEDLEY_UNAVAILABLE)
865 #undef JSON_HEDLEY_UNAVAILABLE
866 #endif
867 #if \
868 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
869 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
870 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
871 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
872 #else
873 #define JSON_HEDLEY_UNAVAILABLE(available_since)
874 #endif
875
876 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
877 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
878 #endif
879 #if defined(__cplusplus) && (__cplusplus >= 201703L)
880 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
881 #elif \
882 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
883 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
884 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
885 JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
886 (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
887 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
888 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
889 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
890 #elif defined(_Check_return_) /* SAL */
891 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
892 #else
893 #define JSON_HEDLEY_WARN_UNUSED_RESULT
894 #endif
895
896 #if defined(JSON_HEDLEY_SENTINEL)
897 #undef JSON_HEDLEY_SENTINEL
898 #endif
899 #if \
900 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
901 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
902 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
903 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0)
904 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
905 #else
906 #define JSON_HEDLEY_SENTINEL(position)
907 #endif
908
909 #if defined(JSON_HEDLEY_NO_RETURN)
910 #undef JSON_HEDLEY_NO_RETURN
911 #endif
912 #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
913 #define JSON_HEDLEY_NO_RETURN __noreturn
914 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
915 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
916 #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
917 #define JSON_HEDLEY_NO_RETURN _Noreturn
918 #elif defined(__cplusplus) && (__cplusplus >= 201103L)
919 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
920 #elif \
921 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
922 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
923 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
924 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
925 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
926 JSON_HEDLEY_TI_VERSION_CHECK(18,0,0) || \
927 (JSON_HEDLEY_TI_VERSION_CHECK(17,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
928 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
929 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
930 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
931 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0)
932 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
933 #elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus)
934 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
935 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
936 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
937 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
938 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
939 #else
940 #define JSON_HEDLEY_NO_RETURN
941 #endif
942
943 #if defined(JSON_HEDLEY_NO_ESCAPE)
944 #undef JSON_HEDLEY_NO_ESCAPE
945 #endif
946 #if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
947 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
948 #else
949 #define JSON_HEDLEY_NO_ESCAPE
950 #endif
951
952 #if defined(JSON_HEDLEY_UNREACHABLE)
953 #undef JSON_HEDLEY_UNREACHABLE
954 #endif
955 #if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
956 #undef JSON_HEDLEY_UNREACHABLE_RETURN
957 #endif
958 #if \
959 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
960 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
961 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
962 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5)
963 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
964 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0)
965 #define JSON_HEDLEY_UNREACHABLE() __assume(0)
966 #elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0)
967 #if defined(__cplusplus)
968 #define JSON_HEDLEY_UNREACHABLE() std::_nassert(0)
969 #else
970 #define JSON_HEDLEY_UNREACHABLE() _nassert(0)
971 #endif
972 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return value
973 #elif defined(EXIT_FAILURE)
974 #define JSON_HEDLEY_UNREACHABLE() abort()
975 #else
976 #define JSON_HEDLEY_UNREACHABLE()
977 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return value
978 #endif
979 #if !defined(JSON_HEDLEY_UNREACHABLE_RETURN)
980 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
981 #endif
982
983 #if defined(JSON_HEDLEY_ASSUME)
984 #undef JSON_HEDLEY_ASSUME
985 #endif
986 #if \
987 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
988 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
989 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
990 #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
991 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
992 #elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0)
993 #if defined(__cplusplus)
994 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
995 #else
996 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
997 #endif
998 #elif \
999 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && !defined(JSON_HEDLEY_ARM_VERSION)) || \
1000 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1001 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1002 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5)
1003 #define JSON_HEDLEY_ASSUME(expr) ((void) ((expr) ? 1 : (__builtin_unreachable(), 1)))
1004 #else
1005 #define JSON_HEDLEY_ASSUME(expr) ((void) (expr))
1006 #endif
1007
1008 JSON_HEDLEY_DIAGNOSTIC_PUSH
1009 #if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1010 #pragma clang diagnostic ignored "-Wpedantic"
1011 #endif
1012 #if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1013 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1014 #endif
1015 #if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1016 #if defined(__clang__)
1017 #pragma clang diagnostic ignored "-Wvariadic-macros"
1018 #elif defined(JSON_HEDLEY_GCC_VERSION)
1019 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1020 #endif
1021 #endif
1022 #if defined(JSON_HEDLEY_NON_NULL)
1023 #undef JSON_HEDLEY_NON_NULL
1024 #endif
1025 #if \
1026 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1027 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1028 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1029 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1030 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1031 #else
1032 #define JSON_HEDLEY_NON_NULL(...)
1033 #endif
1034 JSON_HEDLEY_DIAGNOSTIC_POP
1035
1036 #if defined(JSON_HEDLEY_PRINTF_FORMAT)
1037 #undef JSON_HEDLEY_PRINTF_FORMAT
1038 #endif
1039 #if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1040 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1041 #elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1042 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1043 #elif \
1044 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1045 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1046 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1047 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1048 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1049 JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
1050 (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
1051 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1052 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1053 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1054 #else
1055 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1056 #endif
1057
1058 #if defined(JSON_HEDLEY_CONSTEXPR)
1059 #undef JSON_HEDLEY_CONSTEXPR
1060 #endif
1061 #if defined(__cplusplus)
1062 #if __cplusplus >= 201103L
1063 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1064 #endif
1065 #endif
1066 #if !defined(JSON_HEDLEY_CONSTEXPR)
1067 #define JSON_HEDLEY_CONSTEXPR
1068 #endif
1069
1070 #if defined(JSON_HEDLEY_PREDICT)
1071 #undef JSON_HEDLEY_PREDICT
1072 #endif
1073 #if defined(JSON_HEDLEY_LIKELY)
1074 #undef JSON_HEDLEY_LIKELY
1075 #endif
1076 #if defined(JSON_HEDLEY_UNLIKELY)
1077 #undef JSON_HEDLEY_UNLIKELY
1078 #endif
1079 #if defined(JSON_HEDLEY_UNPREDICTABLE)
1080 #undef JSON_HEDLEY_UNPREDICTABLE
1081 #endif
1082 #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1083 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable(!!(expr))
1084 #endif
1085 #if \
1086 JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) || \
1087 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0)
1088 # define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability(expr, value, probability)
1089 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1, probability)
1090 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0, probability)
1091 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1092 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1093 #if !defined(JSON_HEDLEY_BUILTIN_UNPREDICTABLE)
1094 #define JSON_HEDLEY_BUILTIN_UNPREDICTABLE(expr) __builtin_expect_with_probability(!!(expr), 1, 0.5)
1095 #endif
1096 #elif \
1097 JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) || \
1098 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1099 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1100 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1101 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1102 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1103 JSON_HEDLEY_TI_VERSION_CHECK(6,1,0) || \
1104 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27)
1105 # define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1106 (((probability) >= 0.9) ? __builtin_expect(!!(expr), (expected)) : (((void) (expected)), !!(expr)))
1107 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1108 (__extension__ ({ \
1109 JSON_HEDLEY_CONSTEXPR double hedley_probability_ = (probability); \
1110 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1111 }))
1112 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1113 (__extension__ ({ \
1114 JSON_HEDLEY_CONSTEXPR double hedley_probability_ = (probability); \
1115 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1116 }))
1117 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1118 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1119 #else
1120 # define JSON_HEDLEY_PREDICT(expr, expected, probability) (((void) (expected)), !!(expr))
1121 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1122 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1123 # define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1124 # define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1125 #endif
1126 #if !defined(JSON_HEDLEY_UNPREDICTABLE)
1127 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1128 #endif
1129
1130 #if defined(JSON_HEDLEY_MALLOC)
1131 #undef JSON_HEDLEY_MALLOC
1132 #endif
1133 #if \
1134 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1135 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1136 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1137 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1138 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1139 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1140 JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
1141 (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
1142 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1143 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1144 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1145 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0)
1146 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1147 #else
1148 #define JSON_HEDLEY_MALLOC
1149 #endif
1150
1151 #if defined(JSON_HEDLEY_PURE)
1152 #undef JSON_HEDLEY_PURE
1153 #endif
1154 #if \
1155 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1156 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1157 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1158 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1159 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1160 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1161 JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
1162 (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1163 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1164 #define JSON_HEDLEY_PURE __attribute__((__pure__))
1165 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1166 #define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1167 #elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1168 #define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1169 #else
1170 #define JSON_HEDLEY_PURE
1171 #endif
1172
1173 #if defined(JSON_HEDLEY_CONST)
1174 #undef JSON_HEDLEY_CONST
1175 #endif
1176 #if \
1177 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1178 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1179 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1180 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1181 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1182 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1183 JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
1184 (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1185 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1186 #define JSON_HEDLEY_CONST __attribute__((__const__))
1187 #elif \
1188 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1189 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1190 #else
1191 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1192 #endif
1193
1194 #if defined(JSON_HEDLEY_RESTRICT)
1195 #undef JSON_HEDLEY_RESTRICT
1196 #endif
1197 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1198 #define JSON_HEDLEY_RESTRICT restrict
1199 #elif \
1200 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1201 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1202 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1203 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1204 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1205 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1206 JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
1207 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1208 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1209 defined(__clang__)
1210 #define JSON_HEDLEY_RESTRICT __restrict
1211 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1212 #define JSON_HEDLEY_RESTRICT _Restrict
1213 #else
1214 #define JSON_HEDLEY_RESTRICT
1215 #endif
1216
1217 #if defined(JSON_HEDLEY_INLINE)
1218 #undef JSON_HEDLEY_INLINE
1219 #endif
1220 #if \
1221 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1222 (defined(__cplusplus) && (__cplusplus >= 199711L))
1223 #define JSON_HEDLEY_INLINE inline
1224 #elif \
1225 defined(JSON_HEDLEY_GCC_VERSION) || \
1226 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1227 #define JSON_HEDLEY_INLINE __inline__
1228 #elif \
1229 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1230 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1231 JSON_HEDLEY_TI_VERSION_CHECK(8,0,0)
1232 #define JSON_HEDLEY_INLINE __inline
1233 #else
1234 #define JSON_HEDLEY_INLINE
1235 #endif
1236
1237 #if defined(JSON_HEDLEY_ALWAYS_INLINE)
1238 #undef JSON_HEDLEY_ALWAYS_INLINE
1239 #endif
1240 #if \
1241 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1242 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1243 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1244 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1245 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1246 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1247 JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
1248 (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
1249 #define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1250 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0)
1251 #define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1252 #elif JSON_HEDLEY_TI_VERSION_CHECK(7,0,0) && defined(__cplusplus)
1253 #define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1254 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1255 #define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1256 #else
1257 #define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1258 #endif
1259
1260 #if defined(JSON_HEDLEY_NEVER_INLINE)
1261 #undef JSON_HEDLEY_NEVER_INLINE
1262 #endif
1263 #if \
1264 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1265 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1266 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1267 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1268 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1269 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1270 JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
1271 (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
1272 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1273 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0)
1274 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1275 #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1276 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1277 #elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1278 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1279 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1280 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1281 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1282 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1283 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1284 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1285 #else
1286 #define JSON_HEDLEY_NEVER_INLINE
1287 #endif
1288
1289 #if defined(JSON_HEDLEY_PRIVATE)
1290 #undef JSON_HEDLEY_PRIVATE
1291 #endif
1292 #if defined(JSON_HEDLEY_PUBLIC)
1293 #undef JSON_HEDLEY_PUBLIC
1294 #endif
1295 #if defined(JSON_HEDLEY_IMPORT)
1296 #undef JSON_HEDLEY_IMPORT
1297 #endif
1298 #if defined(_WIN32) || defined(__CYGWIN__)
1299 #define JSON_HEDLEY_PRIVATE
1300 #define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1301 #define JSON_HEDLEY_IMPORT __declspec(dllimport)
1302 #else
1303 #if \
1304 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1305 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1306 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1307 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1308 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1309 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1310 JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
1311 (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_EABI__) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
1312 #define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1313 #define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1314 #else
1315 #define JSON_HEDLEY_PRIVATE
1316 #define JSON_HEDLEY_PUBLIC
1317 #endif
1318 #define JSON_HEDLEY_IMPORT extern
1319 #endif
1320
1321 #if defined(JSON_HEDLEY_NO_THROW)
1322 #undef JSON_HEDLEY_NO_THROW
1323 #endif
1324 #if \
1325 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
1326 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1327 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1328 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
1329 #elif \
1330 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
1331 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1332 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
1333 #else
1334 #define JSON_HEDLEY_NO_THROW
1335 #endif
1336
1337 #if defined(JSON_HEDLEY_FALL_THROUGH)
1338 #undef JSON_HEDLEY_FALL_THROUGH
1339 #endif
1340 #if JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(fallthrough,7,0,0) && !defined(JSON_HEDLEY_PGI_VERSION)
1341 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
1342 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
1343 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
1344 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
1345 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
1346 #elif defined(__fallthrough) /* SAL */
1347 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
1348 #else
1349 #define JSON_HEDLEY_FALL_THROUGH
1350 #endif
1351
1352 #if defined(JSON_HEDLEY_RETURNS_NON_NULL)
1353 #undef JSON_HEDLEY_RETURNS_NON_NULL
1354 #endif
1355 #if \
1356 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
1357 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
1358 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
1359 #elif defined(_Ret_notnull_) /* SAL */
1360 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
1361 #else
1362 #define JSON_HEDLEY_RETURNS_NON_NULL
1363 #endif
1364
1365 #if defined(JSON_HEDLEY_ARRAY_PARAM)
1366 #undef JSON_HEDLEY_ARRAY_PARAM
1367 #endif
1368 #if \
1369 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
1370 !defined(__STDC_NO_VLA__) && \
1371 !defined(__cplusplus) && \
1372 !defined(JSON_HEDLEY_PGI_VERSION) && \
1373 !defined(JSON_HEDLEY_TINYC_VERSION)
1374 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
1375 #else
1376 #define JSON_HEDLEY_ARRAY_PARAM(name)
1377 #endif
1378
1379 #if defined(JSON_HEDLEY_IS_CONSTANT)
1380 #undef JSON_HEDLEY_IS_CONSTANT
1381 #endif
1382 #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
1383 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
1384 #endif
1385 /* JSON_HEDLEY_IS_CONSTEXPR_ is for
1386 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1387 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1388 #undef JSON_HEDLEY_IS_CONSTEXPR_
1389 #endif
1390 #if \
1391 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
1392 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1393 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1394 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
1395 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1396 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1397 JSON_HEDLEY_TI_VERSION_CHECK(6,1,0) || \
1398 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
1399 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0)
1400 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
1401 #endif
1402 #if !defined(__cplusplus)
1403 # if \
1404 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
1405 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1406 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1407 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1408 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1409 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1410 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
1411 #if defined(__INTPTR_TYPE__)
1412 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
1413 #else
1414 #include <stdint.h>
1415 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
1416 #endif
1417 # elif \
1418 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(JSON_HEDLEY_SUNPRO_VERSION) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1419 JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) || \
1420 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
1421 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
1422 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1423 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
1424 #if defined(__INTPTR_TYPE__)
1425 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
1426 #else
1427 #include <stdint.h>
1428 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
1429 #endif
1430 # elif \
1431 defined(JSON_HEDLEY_GCC_VERSION) || \
1432 defined(JSON_HEDLEY_INTEL_VERSION) || \
1433 defined(JSON_HEDLEY_TINYC_VERSION) || \
1434 defined(JSON_HEDLEY_TI_VERSION) || \
1435 defined(__clang__)
1436 # define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
1437 sizeof(void) != \
1438 sizeof(*( \
1439 1 ? \
1440 ((void*) ((expr) * 0L) ) : \
1441 ((struct { char v[sizeof(void) * 2]; } *) 1) \
1442 ) \
1443 ) \
1444 )
1445 # endif
1446 #endif
1447 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1448 #if !defined(JSON_HEDLEY_IS_CONSTANT)
1449 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
1450 #endif
1451 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
1452 #else
1453 #if !defined(JSON_HEDLEY_IS_CONSTANT)
1454 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
1455 #endif
1456 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
1457 #endif
1458
1459 #if defined(JSON_HEDLEY_BEGIN_C_DECLS)
1460 #undef JSON_HEDLEY_BEGIN_C_DECLS
1461 #endif
1462 #if defined(JSON_HEDLEY_END_C_DECLS)
1463 #undef JSON_HEDLEY_END_C_DECLS
1464 #endif
1465 #if defined(JSON_HEDLEY_C_DECL)
1466 #undef JSON_HEDLEY_C_DECL
1467 #endif
1468 #if defined(__cplusplus)
1469 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
1470 #define JSON_HEDLEY_END_C_DECLS }
1471 #define JSON_HEDLEY_C_DECL extern "C"
1472 #else
1473 #define JSON_HEDLEY_BEGIN_C_DECLS
1474 #define JSON_HEDLEY_END_C_DECLS
1475 #define JSON_HEDLEY_C_DECL
1476 #endif
1477
1478 #if defined(JSON_HEDLEY_STATIC_ASSERT)
1479 #undef JSON_HEDLEY_STATIC_ASSERT
1480 #endif
1481 #if \
1482 !defined(__cplusplus) && ( \
1483 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
1484 JSON_HEDLEY_HAS_FEATURE(c_static_assert) || \
1485 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
1486 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1487 defined(_Static_assert) \
1488 )
1489 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
1490 #elif \
1491 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
1492 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
1493 (defined(__cplusplus) && JSON_HEDLEY_TI_VERSION_CHECK(8,3,0))
1494 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
1495 #else
1496 # define JSON_HEDLEY_STATIC_ASSERT(expr, message)
1497 #endif
1498
1499 #if defined(JSON_HEDLEY_CONST_CAST)
1500 #undef JSON_HEDLEY_CONST_CAST
1501 #endif
1502 #if defined(__cplusplus)
1503 # define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1504 #elif \
1505 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1506 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1507 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1508 # define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1509 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1510 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1511 ((T) (expr)); \
1512 JSON_HEDLEY_DIAGNOSTIC_POP \
1513 }))
1514 #else
1515 # define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1516 #endif
1517
1518 #if defined(JSON_HEDLEY_REINTERPRET_CAST)
1519 #undef JSON_HEDLEY_REINTERPRET_CAST
1520 #endif
1521 #if defined(__cplusplus)
1522 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1523 #else
1524 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (*((T*) &(expr)))
1525 #endif
1526
1527 #if defined(JSON_HEDLEY_STATIC_CAST)
1528 #undef JSON_HEDLEY_STATIC_CAST
1529 #endif
1530 #if defined(__cplusplus)
1531 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1532 #else
1533 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1534 #endif
1535
1536 #if defined(JSON_HEDLEY_CPP_CAST)
1537 #undef JSON_HEDLEY_CPP_CAST
1538 #endif
1539 #if defined(__cplusplus)
1540 #define JSON_HEDLEY_CPP_CAST(T, expr) static_cast<T>(expr)
1541 #else
1542 #define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1543 #endif
1544
1545 #if defined(JSON_HEDLEY_NULL)
1546 #undef JSON_HEDLEY_NULL
1547 #endif
1548 #if defined(__cplusplus)
1549 #if __cplusplus >= 201103L
1550 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
1551 #elif defined(NULL)
1552 #define JSON_HEDLEY_NULL NULL
1553 #else
1554 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
1555 #endif
1556 #elif defined(NULL)
1557 #define JSON_HEDLEY_NULL NULL
1558 #else
1559 #define JSON_HEDLEY_NULL ((void*) 0)
1560 #endif
1561
1562 #if defined(JSON_HEDLEY_MESSAGE)
1563 #undef JSON_HEDLEY_MESSAGE
1564 #endif
1565 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1566 # define JSON_HEDLEY_MESSAGE(msg) \
1567 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1568 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
1569 JSON_HEDLEY_PRAGMA(message msg) \
1570 JSON_HEDLEY_DIAGNOSTIC_POP
1571 #elif \
1572 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
1573 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1574 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
1575 #elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
1576 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
1577 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1578 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
1579 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
1580 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
1581 #else
1582 # define JSON_HEDLEY_MESSAGE(msg)
1583 #endif
1584
1585 #if defined(JSON_HEDLEY_WARNING)
1586 #undef JSON_HEDLEY_WARNING
1587 #endif
1588 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1589 # define JSON_HEDLEY_WARNING(msg) \
1590 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1591 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
1592 JSON_HEDLEY_PRAGMA(clang warning msg) \
1593 JSON_HEDLEY_DIAGNOSTIC_POP
1594 #elif \
1595 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
1596 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0)
1597 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
1598 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1599 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
1600 #else
1601 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
1602 #endif
1603
1604 #if defined(JSON_HEDLEY_REQUIRE)
1605 #undef JSON_HEDLEY_REQUIRE
1606 #endif
1607 #if defined(JSON_HEDLEY_REQUIRE_MSG)
1608 #undef JSON_HEDLEY_REQUIRE_MSG
1609 #endif
1610 #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
1611 # if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
1612 # define JSON_HEDLEY_REQUIRE(expr) \
1613 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1614 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
1615 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
1616 JSON_HEDLEY_DIAGNOSTIC_POP
1617 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
1618 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1619 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
1620 __attribute__((diagnose_if(!(expr), msg, "error"))) \
1621 JSON_HEDLEY_DIAGNOSTIC_POP
1622 # else
1623 # define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
1624 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
1625 # endif
1626 #else
1627 # define JSON_HEDLEY_REQUIRE(expr)
1628 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
1629 #endif
1630
1631 #if defined(JSON_HEDLEY_FLAGS)
1632 #undef JSON_HEDLEY_FLAGS
1633 #endif
1634 #if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum)
1635 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
1636 #endif
1637
1638 #if defined(JSON_HEDLEY_FLAGS_CAST)
1639 #undef JSON_HEDLEY_FLAGS_CAST
1640 #endif
1641 #if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
1642 # define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
1643 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1644 _Pragma("warning(disable:188)") \
1645 ((T) (expr)); \
1646 JSON_HEDLEY_DIAGNOSTIC_POP \
1647 }))
1648 #else
1649 # define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
1650 #endif
1651
1652 #if defined(JSON_HEDLEY_EMPTY_BASES)
1653 #undef JSON_HEDLEY_EMPTY_BASES
1654 #endif
1655 #if JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)
1656 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
1657 #else
1658 #define JSON_HEDLEY_EMPTY_BASES
1659 #endif
1660
1661 /* Remaining macros are deprecated. */
1662
1663 #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
1664 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
1665 #endif
1666 #if defined(__clang__)
1667 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
1668 #else
1669 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1670 #endif
1671
1672 #if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
1673 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
1674 #endif
1675 #define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
1676
1677 #if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
1678 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
1679 #endif
1680 #define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
1681
1682 #if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
1683 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
1684 #endif
1685 #define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
1686
1687 #if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
1688 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
1689 #endif
1690 #define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
1691
1692 #if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
1693 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
1694 #endif
1695 #define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
1696
1697 #if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
1698 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
1699 #endif
1700 #define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
1701
1702 #if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
1703 #undef JSON_HEDLEY_CLANG_HAS_WARNING
1704 #endif
1705 #define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
1706
1707 #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
1708
1709
1710 // This file contains all internal macro definitions
1711 // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
1712
1713 // exclude unsupported compilers
1714 #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
1715 #if defined(__clang__)
1716 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
1717 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
1718 #endif
1719 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
1720 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
1721 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
1722 #endif
1723 #endif
1724 #endif
1725
1726 // C++ language standard detection
1727 #if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
1728 #define JSON_HAS_CPP_17
1729 #define JSON_HAS_CPP_14
1730 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
1731 #define JSON_HAS_CPP_14
1732 #endif
1733
1734 // disable float-equal warnings on GCC/clang
1735 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
1736 #pragma GCC diagnostic push
1737 #pragma GCC diagnostic ignored "-Wfloat-equal"
1738 #endif
1739
1740 // disable documentation warnings on clang
1741 #if defined(__clang__)
1742 #pragma GCC diagnostic push
1743 #pragma GCC diagnostic ignored "-Wdocumentation"
1744 #endif
1745
1746 // allow to disable exceptions
1747 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
1748 #define JSON_THROW(exception) throw exception
1749 #define JSON_TRY try
1750 #define JSON_CATCH(exception) catch(exception)
1751 #define JSON_INTERNAL_CATCH(exception) catch(exception)
1752 #else
1753 #include <cstdlib>
1754 #define JSON_THROW(exception) std::abort()
1755 #define JSON_TRY if(true)
1756 #define JSON_CATCH(exception) if(false)
1757 #define JSON_INTERNAL_CATCH(exception) if(false)
1758 #endif
1759
1760 // override exception macros
1761 #if defined(JSON_THROW_USER)
1762 #undef JSON_THROW
1763 #define JSON_THROW JSON_THROW_USER
1764 #endif
1765 #if defined(JSON_TRY_USER)
1766 #undef JSON_TRY
1767 #define JSON_TRY JSON_TRY_USER
1768 #endif
1769 #if defined(JSON_CATCH_USER)
1770 #undef JSON_CATCH
1771 #define JSON_CATCH JSON_CATCH_USER
1772 #undef JSON_INTERNAL_CATCH
1773 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
1774 #endif
1775 #if defined(JSON_INTERNAL_CATCH_USER)
1776 #undef JSON_INTERNAL_CATCH
1777 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
1778 #endif
1779
1780 /*!
1781 @brief macro to briefly define a mapping between an enum and JSON
1782 @def NLOHMANN_JSON_SERIALIZE_ENUM
1783 @since version 3.4.0
1784 */
1785 #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
1786 template<typename BasicJsonType> \
1787 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
1788 { \
1789 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
1790 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
1791 auto it = std::find_if(std::begin(m), std::end(m), \
1792 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
1793 { \
1794 return ej_pair.first == e; \
1795 }); \
1796 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
1797 } \
1798 template<typename BasicJsonType> \
1799 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
1800 { \
1801 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
1802 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
1803 auto it = std::find_if(std::begin(m), std::end(m), \
1804 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
1805 { \
1806 return ej_pair.second == j; \
1807 }); \
1808 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
1809 }
1810
1811 // Ugly macros to avoid uglier copy-paste when specializing basic_json. They
1812 // may be removed in the future once the class is split.
1813
1814 #define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
1815 template<template<typename, typename, typename...> class ObjectType, \
1816 template<typename, typename...> class ArrayType, \
1817 class StringType, class BooleanType, class NumberIntegerType, \
1818 class NumberUnsignedType, class NumberFloatType, \
1819 template<typename> class AllocatorType, \
1820 template<typename, typename = void> class JSONSerializer>
1821
1822 #define NLOHMANN_BASIC_JSON_TPL \
1823 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
1824 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
1825 AllocatorType, JSONSerializer>
1826
1827
1828 namespace nlohmann
1829 {
1830 namespace detail
1831 {
1832 ////////////////
1833 // exceptions //
1834 ////////////////
1835
1836 /*!
1837 @brief general exception of the @ref basic_json class
1838
1839 This class is an extension of `std::exception` objects with a member @a id for
1840 exception ids. It is used as the base class for all exceptions thrown by the
1841 @ref basic_json class. This class can hence be used as "wildcard" to catch
1842 exceptions.
1843
1844 Subclasses:
1845 - @ref parse_error for exceptions indicating a parse error
1846 - @ref invalid_iterator for exceptions indicating errors with iterators
1847 - @ref type_error for exceptions indicating executing a member function with
1848 a wrong type
1849 - @ref out_of_range for exceptions indicating access out of the defined range
1850 - @ref other_error for exceptions indicating other library errors
1851
1852 @internal
1853 @note To have nothrow-copy-constructible exceptions, we internally use
1854 `std::runtime_error` which can cope with arbitrary-length error messages.
1855 Intermediate strings are built with static functions and then passed to
1856 the actual constructor.
1857 @endinternal
1858
1859 @liveexample{The following code shows how arbitrary library exceptions can be
1860 caught.,exception}
1861
1862 @since version 3.0.0
1863 */
1864 class exception : public std::exception
1865 {
1866 public:
1867 /// returns the explanatory string
1868 JSON_HEDLEY_RETURNS_NON_NULL
what() const1869 const char* what() const noexcept override
1870 {
1871 return m.what();
1872 }
1873
1874 /// the id of the exception
1875 const int id;
1876
1877 protected:
1878 JSON_HEDLEY_NON_NULL(3)
exception(int id_,const char * what_arg)1879 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
1880
name(const std::string & ename,int id_)1881 static std::string name(const std::string& ename, int id_)
1882 {
1883 return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
1884 }
1885
1886 private:
1887 /// an exception object as storage for error messages
1888 std::runtime_error m;
1889 };
1890
1891 /*!
1892 @brief exception indicating a parse error
1893
1894 This exception is thrown by the library when a parse error occurs. Parse errors
1895 can occur during the deserialization of JSON text, CBOR, MessagePack, as well
1896 as when using JSON Patch.
1897
1898 Member @a byte holds the byte index of the last read character in the input
1899 file.
1900
1901 Exceptions have ids 1xx.
1902
1903 name / id | example message | description
1904 ------------------------------ | --------------- | -------------------------
1905 json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.
1906 json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.
1907 json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.
1908 json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects.
1909 json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors.
1910 json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`.
1911 json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.
1912 json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
1913 json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.
1914 json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.
1915 json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
1916 json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
1917 json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet).
1918
1919 @note For an input with n bytes, 1 is the index of the first character and n+1
1920 is the index of the terminating null byte or the end of file. This also
1921 holds true when reading a byte vector (CBOR or MessagePack).
1922
1923 @liveexample{The following code shows how a `parse_error` exception can be
1924 caught.,parse_error}
1925
1926 @sa - @ref exception for the base class of the library exceptions
1927 @sa - @ref invalid_iterator for exceptions indicating errors with iterators
1928 @sa - @ref type_error for exceptions indicating executing a member function with
1929 a wrong type
1930 @sa - @ref out_of_range for exceptions indicating access out of the defined range
1931 @sa - @ref other_error for exceptions indicating other library errors
1932
1933 @since version 3.0.0
1934 */
1935 class parse_error : public exception
1936 {
1937 public:
1938 /*!
1939 @brief create a parse error exception
1940 @param[in] id_ the id of the exception
1941 @param[in] pos the position where the error occurred (or with
1942 chars_read_total=0 if the position cannot be
1943 determined)
1944 @param[in] what_arg the explanatory string
1945 @return parse_error object
1946 */
create(int id_,const position_t & pos,const std::string & what_arg)1947 static parse_error create(int id_, const position_t& pos, const std::string& what_arg)
1948 {
1949 std::string w = exception::name("parse_error", id_) + "parse error" +
1950 position_string(pos) + ": " + what_arg;
1951 return parse_error(id_, pos.chars_read_total, w.c_str());
1952 }
1953
create(int id_,std::size_t byte_,const std::string & what_arg)1954 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)
1955 {
1956 std::string w = exception::name("parse_error", id_) + "parse error" +
1957 (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
1958 ": " + what_arg;
1959 return parse_error(id_, byte_, w.c_str());
1960 }
1961
1962 /*!
1963 @brief byte index of the parse error
1964
1965 The byte index of the last read character in the input file.
1966
1967 @note For an input with n bytes, 1 is the index of the first character and
1968 n+1 is the index of the terminating null byte or the end of file.
1969 This also holds true when reading a byte vector (CBOR or MessagePack).
1970 */
1971 const std::size_t byte;
1972
1973 private:
parse_error(int id_,std::size_t byte_,const char * what_arg)1974 parse_error(int id_, std::size_t byte_, const char* what_arg)
1975 : exception(id_, what_arg), byte(byte_) {}
1976
position_string(const position_t & pos)1977 static std::string position_string(const position_t& pos)
1978 {
1979 return " at line " + std::to_string(pos.lines_read + 1) +
1980 ", column " + std::to_string(pos.chars_read_current_line);
1981 }
1982 };
1983
1984 /*!
1985 @brief exception indicating errors with iterators
1986
1987 This exception is thrown if iterators passed to a library function do not match
1988 the expected semantics.
1989
1990 Exceptions have ids 2xx.
1991
1992 name / id | example message | description
1993 ----------------------------------- | --------------- | -------------------------
1994 json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
1995 json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
1996 json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.
1997 json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.
1998 json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.
1999 json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.
2000 json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.
2001 json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
2002 json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
2003 json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
2004 json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to.
2005 json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container.
2006 json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered.
2007 json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().
2008
2009 @liveexample{The following code shows how an `invalid_iterator` exception can be
2010 caught.,invalid_iterator}
2011
2012 @sa - @ref exception for the base class of the library exceptions
2013 @sa - @ref parse_error for exceptions indicating a parse error
2014 @sa - @ref type_error for exceptions indicating executing a member function with
2015 a wrong type
2016 @sa - @ref out_of_range for exceptions indicating access out of the defined range
2017 @sa - @ref other_error for exceptions indicating other library errors
2018
2019 @since version 3.0.0
2020 */
2021 class invalid_iterator : public exception
2022 {
2023 public:
create(int id_,const std::string & what_arg)2024 static invalid_iterator create(int id_, const std::string& what_arg)
2025 {
2026 std::string w = exception::name("invalid_iterator", id_) + what_arg;
2027 return invalid_iterator(id_, w.c_str());
2028 }
2029
2030 private:
2031 JSON_HEDLEY_NON_NULL(3)
invalid_iterator(int id_,const char * what_arg)2032 invalid_iterator(int id_, const char* what_arg)
2033 : exception(id_, what_arg) {}
2034 };
2035
2036 /*!
2037 @brief exception indicating executing a member function with a wrong type
2038
2039 This exception is thrown in case of a type error; that is, a library function is
2040 executed on a JSON value whose type does not match the expected semantics.
2041
2042 Exceptions have ids 3xx.
2043
2044 name / id | example message | description
2045 ----------------------------- | --------------- | -------------------------
2046 json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
2047 json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
2048 json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &.
2049 json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
2050 json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
2051 json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
2052 json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.
2053 json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.
2054 json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.
2055 json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.
2056 json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types.
2057 json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.
2058 json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.
2059 json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.
2060 json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.
2061 json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. |
2062 json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) |
2063
2064 @liveexample{The following code shows how a `type_error` exception can be
2065 caught.,type_error}
2066
2067 @sa - @ref exception for the base class of the library exceptions
2068 @sa - @ref parse_error for exceptions indicating a parse error
2069 @sa - @ref invalid_iterator for exceptions indicating errors with iterators
2070 @sa - @ref out_of_range for exceptions indicating access out of the defined range
2071 @sa - @ref other_error for exceptions indicating other library errors
2072
2073 @since version 3.0.0
2074 */
2075 class type_error : public exception
2076 {
2077 public:
create(int id_,const std::string & what_arg)2078 static type_error create(int id_, const std::string& what_arg)
2079 {
2080 std::string w = exception::name("type_error", id_) + what_arg;
2081 return type_error(id_, w.c_str());
2082 }
2083
2084 private:
2085 JSON_HEDLEY_NON_NULL(3)
type_error(int id_,const char * what_arg)2086 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
2087 };
2088
2089 /*!
2090 @brief exception indicating access out of the defined range
2091
2092 This exception is thrown in case a library function is called on an input
2093 parameter that exceeds the expected range, for instance in case of array
2094 indices or nonexisting object keys.
2095
2096 Exceptions have ids 4xx.
2097
2098 name / id | example message | description
2099 ------------------------------- | --------------- | -------------------------
2100 json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.
2101 json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.
2102 json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.
2103 json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
2104 json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
2105 json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
2106 json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. |
2107 json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
2108 json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |
2109
2110 @liveexample{The following code shows how an `out_of_range` exception can be
2111 caught.,out_of_range}
2112
2113 @sa - @ref exception for the base class of the library exceptions
2114 @sa - @ref parse_error for exceptions indicating a parse error
2115 @sa - @ref invalid_iterator for exceptions indicating errors with iterators
2116 @sa - @ref type_error for exceptions indicating executing a member function with
2117 a wrong type
2118 @sa - @ref other_error for exceptions indicating other library errors
2119
2120 @since version 3.0.0
2121 */
2122 class out_of_range : public exception
2123 {
2124 public:
create(int id_,const std::string & what_arg)2125 static out_of_range create(int id_, const std::string& what_arg)
2126 {
2127 std::string w = exception::name("out_of_range", id_) + what_arg;
2128 return out_of_range(id_, w.c_str());
2129 }
2130
2131 private:
2132 JSON_HEDLEY_NON_NULL(3)
out_of_range(int id_,const char * what_arg)2133 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
2134 };
2135
2136 /*!
2137 @brief exception indicating other library errors
2138
2139 This exception is thrown in case of errors that cannot be classified with the
2140 other exception types.
2141
2142 Exceptions have ids 5xx.
2143
2144 name / id | example message | description
2145 ------------------------------ | --------------- | -------------------------
2146 json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
2147
2148 @sa - @ref exception for the base class of the library exceptions
2149 @sa - @ref parse_error for exceptions indicating a parse error
2150 @sa - @ref invalid_iterator for exceptions indicating errors with iterators
2151 @sa - @ref type_error for exceptions indicating executing a member function with
2152 a wrong type
2153 @sa - @ref out_of_range for exceptions indicating access out of the defined range
2154
2155 @liveexample{The following code shows how an `other_error` exception can be
2156 caught.,other_error}
2157
2158 @since version 3.0.0
2159 */
2160 class other_error : public exception
2161 {
2162 public:
create(int id_,const std::string & what_arg)2163 static other_error create(int id_, const std::string& what_arg)
2164 {
2165 std::string w = exception::name("other_error", id_) + what_arg;
2166 return other_error(id_, w.c_str());
2167 }
2168
2169 private:
2170 JSON_HEDLEY_NON_NULL(3)
other_error(int id_,const char * what_arg)2171 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
2172 };
2173 } // namespace detail
2174 } // namespace nlohmann
2175
2176 // #include <nlohmann/detail/macro_scope.hpp>
2177
2178 // #include <nlohmann/detail/meta/cpp_future.hpp>
2179
2180
2181 #include <ciso646> // not
2182 #include <cstddef> // size_t
2183 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
2184
2185 namespace nlohmann
2186 {
2187 namespace detail
2188 {
2189 // alias templates to reduce boilerplate
2190 template<bool B, typename T = void>
2191 using enable_if_t = typename std::enable_if<B, T>::type;
2192
2193 template<typename T>
2194 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
2195
2196 // implementation of C++14 index_sequence and affiliates
2197 // source: https://stackoverflow.com/a/32223343
2198 template<std::size_t... Ints>
2199 struct index_sequence
2200 {
2201 using type = index_sequence;
2202 using value_type = std::size_t;
sizenlohmann::detail::index_sequence2203 static constexpr std::size_t size() noexcept
2204 {
2205 return sizeof...(Ints);
2206 }
2207 };
2208
2209 template<class Sequence1, class Sequence2>
2210 struct merge_and_renumber;
2211
2212 template<std::size_t... I1, std::size_t... I2>
2213 struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
2214 : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
2215
2216 template<std::size_t N>
2217 struct make_index_sequence
2218 : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
2219 typename make_index_sequence < N - N / 2 >::type > {};
2220
2221 template<> struct make_index_sequence<0> : index_sequence<> {};
2222 template<> struct make_index_sequence<1> : index_sequence<0> {};
2223
2224 template<typename... Ts>
2225 using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
2226
2227 // dispatch utility (taken from ranges-v3)
2228 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
2229 template<> struct priority_tag<0> {};
2230
2231 // taken from ranges-v3
2232 template<typename T>
2233 struct static_const
2234 {
2235 static constexpr T value{};
2236 };
2237
2238 template<typename T>
2239 constexpr T static_const<T>::value;
2240 } // namespace detail
2241 } // namespace nlohmann
2242
2243 // #include <nlohmann/detail/meta/type_traits.hpp>
2244
2245
2246 #include <ciso646> // not
2247 #include <limits> // numeric_limits
2248 #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
2249 #include <utility> // declval
2250
2251 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
2252
2253
2254 #include <iterator> // random_access_iterator_tag
2255
2256 // #include <nlohmann/detail/meta/void_t.hpp>
2257
2258
2259 namespace nlohmann
2260 {
2261 namespace detail
2262 {
2263 template <typename ...Ts> struct make_void
2264 {
2265 using type = void;
2266 };
2267 template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
2268 } // namespace detail
2269 } // namespace nlohmann
2270
2271 // #include <nlohmann/detail/meta/cpp_future.hpp>
2272
2273
2274 namespace nlohmann
2275 {
2276 namespace detail
2277 {
2278 template <typename It, typename = void>
2279 struct iterator_types {};
2280
2281 template <typename It>
2282 struct iterator_types <
2283 It,
2284 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
2285 typename It::reference, typename It::iterator_category >>
2286 {
2287 using difference_type = typename It::difference_type;
2288 using value_type = typename It::value_type;
2289 using pointer = typename It::pointer;
2290 using reference = typename It::reference;
2291 using iterator_category = typename It::iterator_category;
2292 };
2293
2294 // This is required as some compilers implement std::iterator_traits in a way that
2295 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
2296 template <typename T, typename = void>
2297 struct iterator_traits
2298 {
2299 };
2300
2301 template <typename T>
2302 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
2303 : iterator_types<T>
2304 {
2305 };
2306
2307 template <typename T>
2308 struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
2309 {
2310 using iterator_category = std::random_access_iterator_tag;
2311 using value_type = T;
2312 using difference_type = ptrdiff_t;
2313 using pointer = T*;
2314 using reference = T&;
2315 };
2316 } // namespace detail
2317 } // namespace nlohmann
2318
2319 // #include <nlohmann/detail/macro_scope.hpp>
2320
2321 // #include <nlohmann/detail/meta/cpp_future.hpp>
2322
2323 // #include <nlohmann/detail/meta/detected.hpp>
2324
2325
2326 #include <type_traits>
2327
2328 // #include <nlohmann/detail/meta/void_t.hpp>
2329
2330
2331 // http://en.cppreference.com/w/cpp/experimental/is_detected
2332 namespace nlohmann
2333 {
2334 namespace detail
2335 {
2336 struct nonesuch
2337 {
2338 nonesuch() = delete;
2339 ~nonesuch() = delete;
2340 nonesuch(nonesuch const&) = delete;
2341 nonesuch(nonesuch const&&) = delete;
2342 void operator=(nonesuch const&) = delete;
2343 void operator=(nonesuch&&) = delete;
2344 };
2345
2346 template <class Default,
2347 class AlwaysVoid,
2348 template <class...> class Op,
2349 class... Args>
2350 struct detector
2351 {
2352 using value_t = std::false_type;
2353 using type = Default;
2354 };
2355
2356 template <class Default, template <class...> class Op, class... Args>
2357 struct detector<Default, void_t<Op<Args...>>, Op, Args...>
2358 {
2359 using value_t = std::true_type;
2360 using type = Op<Args...>;
2361 };
2362
2363 template <template <class...> class Op, class... Args>
2364 using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
2365
2366 template <template <class...> class Op, class... Args>
2367 using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
2368
2369 template <class Default, template <class...> class Op, class... Args>
2370 using detected_or = detector<Default, void, Op, Args...>;
2371
2372 template <class Default, template <class...> class Op, class... Args>
2373 using detected_or_t = typename detected_or<Default, Op, Args...>::type;
2374
2375 template <class Expected, template <class...> class Op, class... Args>
2376 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
2377
2378 template <class To, template <class...> class Op, class... Args>
2379 using is_detected_convertible =
2380 std::is_convertible<detected_t<Op, Args...>, To>;
2381 } // namespace detail
2382 } // namespace nlohmann
2383
2384 // #include <nlohmann/json_fwd.hpp>
2385 #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
2386 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
2387
2388 #include <cstdint> // int64_t, uint64_t
2389 #include <map> // map
2390 #include <memory> // allocator
2391 #include <string> // string
2392 #include <vector> // vector
2393
2394 /*!
2395 @brief namespace for Niels Lohmann
2396 @see https://github.com/nlohmann
2397 @since version 1.0.0
2398 */
2399 namespace nlohmann
2400 {
2401 /*!
2402 @brief default JSONSerializer template argument
2403
2404 This serializer ignores the template arguments and uses ADL
2405 ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
2406 for serialization.
2407 */
2408 template<typename T = void, typename SFINAE = void>
2409 struct adl_serializer;
2410
2411 template<template<typename U, typename V, typename... Args> class ObjectType =
2412 std::map,
2413 template<typename U, typename... Args> class ArrayType = std::vector,
2414 class StringType = std::string, class BooleanType = bool,
2415 class NumberIntegerType = std::int64_t,
2416 class NumberUnsignedType = std::uint64_t,
2417 class NumberFloatType = double,
2418 template<typename U> class AllocatorType = std::allocator,
2419 template<typename T, typename SFINAE = void> class JSONSerializer =
2420 adl_serializer>
2421 class basic_json;
2422
2423 /*!
2424 @brief JSON Pointer
2425
2426 A JSON pointer defines a string syntax for identifying a specific value
2427 within a JSON document. It can be used with functions `at` and
2428 `operator[]`. Furthermore, JSON pointers are the base for JSON patches.
2429
2430 @sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
2431
2432 @since version 2.0.0
2433 */
2434 template<typename BasicJsonType>
2435 class json_pointer;
2436
2437 /*!
2438 @brief default JSON class
2439
2440 This type is the default specialization of the @ref basic_json class which
2441 uses the standard template types.
2442
2443 @since version 1.0.0
2444 */
2445 using json = basic_json<>;
2446 } // namespace nlohmann
2447
2448 #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
2449
2450
2451 namespace nlohmann
2452 {
2453 /*!
2454 @brief detail namespace with internal helper functions
2455
2456 This namespace collects functions that should not be exposed,
2457 implementations of some @ref basic_json methods, and meta-programming helpers.
2458
2459 @since version 2.1.0
2460 */
2461 namespace detail
2462 {
2463 /////////////
2464 // helpers //
2465 /////////////
2466
2467 // Note to maintainers:
2468 //
2469 // Every trait in this file expects a non CV-qualified type.
2470 // The only exceptions are in the 'aliases for detected' section
2471 // (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
2472 //
2473 // In this case, T has to be properly CV-qualified to constraint the function arguments
2474 // (e.g. to_json(BasicJsonType&, const T&))
2475
2476 template<typename> struct is_basic_json : std::false_type {};
2477
2478 NLOHMANN_BASIC_JSON_TPL_DECLARATION
2479 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
2480
2481 //////////////////////////
2482 // aliases for detected //
2483 //////////////////////////
2484
2485 template <typename T>
2486 using mapped_type_t = typename T::mapped_type;
2487
2488 template <typename T>
2489 using key_type_t = typename T::key_type;
2490
2491 template <typename T>
2492 using value_type_t = typename T::value_type;
2493
2494 template <typename T>
2495 using difference_type_t = typename T::difference_type;
2496
2497 template <typename T>
2498 using pointer_t = typename T::pointer;
2499
2500 template <typename T>
2501 using reference_t = typename T::reference;
2502
2503 template <typename T>
2504 using iterator_category_t = typename T::iterator_category;
2505
2506 template <typename T>
2507 using iterator_t = typename T::iterator;
2508
2509 template <typename T, typename... Args>
2510 using to_json_function = decltype(T::to_json(std::declval<Args>()...));
2511
2512 template <typename T, typename... Args>
2513 using from_json_function = decltype(T::from_json(std::declval<Args>()...));
2514
2515 template <typename T, typename U>
2516 using get_template_function = decltype(std::declval<T>().template get<U>());
2517
2518 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
2519 template <typename BasicJsonType, typename T, typename = void>
2520 struct has_from_json : std::false_type {};
2521
2522 template <typename BasicJsonType, typename T>
2523 struct has_from_json<BasicJsonType, T,
2524 enable_if_t<not is_basic_json<T>::value>>
2525 {
2526 using serializer = typename BasicJsonType::template json_serializer<T, void>;
2527
2528 static constexpr bool value =
2529 is_detected_exact<void, from_json_function, serializer,
2530 const BasicJsonType&, T&>::value;
2531 };
2532
2533 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
2534 // this overload is used for non-default-constructible user-defined-types
2535 template <typename BasicJsonType, typename T, typename = void>
2536 struct has_non_default_from_json : std::false_type {};
2537
2538 template<typename BasicJsonType, typename T>
2539 struct has_non_default_from_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
2540 {
2541 using serializer = typename BasicJsonType::template json_serializer<T, void>;
2542
2543 static constexpr bool value =
2544 is_detected_exact<T, from_json_function, serializer,
2545 const BasicJsonType&>::value;
2546 };
2547
2548 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
2549 // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
2550 template <typename BasicJsonType, typename T, typename = void>
2551 struct has_to_json : std::false_type {};
2552
2553 template <typename BasicJsonType, typename T>
2554 struct has_to_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
2555 {
2556 using serializer = typename BasicJsonType::template json_serializer<T, void>;
2557
2558 static constexpr bool value =
2559 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
2560 T>::value;
2561 };
2562
2563
2564 ///////////////////
2565 // is_ functions //
2566 ///////////////////
2567
2568 template <typename T, typename = void>
2569 struct is_iterator_traits : std::false_type {};
2570
2571 template <typename T>
2572 struct is_iterator_traits<iterator_traits<T>>
2573 {
2574 private:
2575 using traits = iterator_traits<T>;
2576
2577 public:
2578 static constexpr auto value =
2579 is_detected<value_type_t, traits>::value &&
2580 is_detected<difference_type_t, traits>::value &&
2581 is_detected<pointer_t, traits>::value &&
2582 is_detected<iterator_category_t, traits>::value &&
2583 is_detected<reference_t, traits>::value;
2584 };
2585
2586 // source: https://stackoverflow.com/a/37193089/4116453
2587
2588 template <typename T, typename = void>
2589 struct is_complete_type : std::false_type {};
2590
2591 template <typename T>
2592 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
2593
2594 template <typename BasicJsonType, typename CompatibleObjectType,
2595 typename = void>
2596 struct is_compatible_object_type_impl : std::false_type {};
2597
2598 template <typename BasicJsonType, typename CompatibleObjectType>
2599 struct is_compatible_object_type_impl <
2600 BasicJsonType, CompatibleObjectType,
2601 enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value and
2602 is_detected<key_type_t, CompatibleObjectType>::value >>
2603 {
2604
2605 using object_t = typename BasicJsonType::object_t;
2606
2607 // macOS's is_constructible does not play well with nonesuch...
2608 static constexpr bool value =
2609 std::is_constructible<typename object_t::key_type,
2610 typename CompatibleObjectType::key_type>::value and
2611 std::is_constructible<typename object_t::mapped_type,
2612 typename CompatibleObjectType::mapped_type>::value;
2613 };
2614
2615 template <typename BasicJsonType, typename CompatibleObjectType>
2616 struct is_compatible_object_type
2617 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
2618
2619 template <typename BasicJsonType, typename ConstructibleObjectType,
2620 typename = void>
2621 struct is_constructible_object_type_impl : std::false_type {};
2622
2623 template <typename BasicJsonType, typename ConstructibleObjectType>
2624 struct is_constructible_object_type_impl <
2625 BasicJsonType, ConstructibleObjectType,
2626 enable_if_t<is_detected<mapped_type_t, ConstructibleObjectType>::value and
2627 is_detected<key_type_t, ConstructibleObjectType>::value >>
2628 {
2629 using object_t = typename BasicJsonType::object_t;
2630
2631 static constexpr bool value =
2632 (std::is_default_constructible<ConstructibleObjectType>::value and
2633 (std::is_move_assignable<ConstructibleObjectType>::value or
2634 std::is_copy_assignable<ConstructibleObjectType>::value) and
2635 (std::is_constructible<typename ConstructibleObjectType::key_type,
2636 typename object_t::key_type>::value and
2637 std::is_same <
2638 typename object_t::mapped_type,
2639 typename ConstructibleObjectType::mapped_type >::value)) or
2640 (has_from_json<BasicJsonType,
2641 typename ConstructibleObjectType::mapped_type>::value or
2642 has_non_default_from_json <
2643 BasicJsonType,
2644 typename ConstructibleObjectType::mapped_type >::value);
2645 };
2646
2647 template <typename BasicJsonType, typename ConstructibleObjectType>
2648 struct is_constructible_object_type
2649 : is_constructible_object_type_impl<BasicJsonType,
2650 ConstructibleObjectType> {};
2651
2652 template <typename BasicJsonType, typename CompatibleStringType,
2653 typename = void>
2654 struct is_compatible_string_type_impl : std::false_type {};
2655
2656 template <typename BasicJsonType, typename CompatibleStringType>
2657 struct is_compatible_string_type_impl <
2658 BasicJsonType, CompatibleStringType,
2659 enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
2660 value_type_t, CompatibleStringType>::value >>
2661 {
2662 static constexpr auto value =
2663 std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
2664 };
2665
2666 template <typename BasicJsonType, typename ConstructibleStringType>
2667 struct is_compatible_string_type
2668 : is_compatible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
2669
2670 template <typename BasicJsonType, typename ConstructibleStringType,
2671 typename = void>
2672 struct is_constructible_string_type_impl : std::false_type {};
2673
2674 template <typename BasicJsonType, typename ConstructibleStringType>
2675 struct is_constructible_string_type_impl <
2676 BasicJsonType, ConstructibleStringType,
2677 enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
2678 value_type_t, ConstructibleStringType>::value >>
2679 {
2680 static constexpr auto value =
2681 std::is_constructible<ConstructibleStringType,
2682 typename BasicJsonType::string_t>::value;
2683 };
2684
2685 template <typename BasicJsonType, typename ConstructibleStringType>
2686 struct is_constructible_string_type
2687 : is_constructible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
2688
2689 template <typename BasicJsonType, typename CompatibleArrayType, typename = void>
2690 struct is_compatible_array_type_impl : std::false_type {};
2691
2692 template <typename BasicJsonType, typename CompatibleArrayType>
2693 struct is_compatible_array_type_impl <
2694 BasicJsonType, CompatibleArrayType,
2695 enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and
2696 is_detected<iterator_t, CompatibleArrayType>::value and
2697 // This is needed because json_reverse_iterator has a ::iterator type...
2698 // Therefore it is detected as a CompatibleArrayType.
2699 // The real fix would be to have an Iterable concept.
2700 not is_iterator_traits<
2701 iterator_traits<CompatibleArrayType>>::value >>
2702 {
2703 static constexpr bool value =
2704 std::is_constructible<BasicJsonType,
2705 typename CompatibleArrayType::value_type>::value;
2706 };
2707
2708 template <typename BasicJsonType, typename CompatibleArrayType>
2709 struct is_compatible_array_type
2710 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
2711
2712 template <typename BasicJsonType, typename ConstructibleArrayType, typename = void>
2713 struct is_constructible_array_type_impl : std::false_type {};
2714
2715 template <typename BasicJsonType, typename ConstructibleArrayType>
2716 struct is_constructible_array_type_impl <
2717 BasicJsonType, ConstructibleArrayType,
2718 enable_if_t<std::is_same<ConstructibleArrayType,
2719 typename BasicJsonType::value_type>::value >>
2720 : std::true_type {};
2721
2722 template <typename BasicJsonType, typename ConstructibleArrayType>
2723 struct is_constructible_array_type_impl <
2724 BasicJsonType, ConstructibleArrayType,
2725 enable_if_t<not std::is_same<ConstructibleArrayType,
2726 typename BasicJsonType::value_type>::value and
2727 std::is_default_constructible<ConstructibleArrayType>::value and
2728 (std::is_move_assignable<ConstructibleArrayType>::value or
2729 std::is_copy_assignable<ConstructibleArrayType>::value) and
2730 is_detected<value_type_t, ConstructibleArrayType>::value and
2731 is_detected<iterator_t, ConstructibleArrayType>::value and
2732 is_complete_type<
2733 detected_t<value_type_t, ConstructibleArrayType>>::value >>
2734 {
2735 static constexpr bool value =
2736 // This is needed because json_reverse_iterator has a ::iterator type,
2737 // furthermore, std::back_insert_iterator (and other iterators) have a
2738 // base class `iterator`... Therefore it is detected as a
2739 // ConstructibleArrayType. The real fix would be to have an Iterable
2740 // concept.
2741 not is_iterator_traits<iterator_traits<ConstructibleArrayType>>::value and
2742
2743 (std::is_same<typename ConstructibleArrayType::value_type,
2744 typename BasicJsonType::array_t::value_type>::value or
2745 has_from_json<BasicJsonType,
2746 typename ConstructibleArrayType::value_type>::value or
2747 has_non_default_from_json <
2748 BasicJsonType, typename ConstructibleArrayType::value_type >::value);
2749 };
2750
2751 template <typename BasicJsonType, typename ConstructibleArrayType>
2752 struct is_constructible_array_type
2753 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
2754
2755 template <typename RealIntegerType, typename CompatibleNumberIntegerType,
2756 typename = void>
2757 struct is_compatible_integer_type_impl : std::false_type {};
2758
2759 template <typename RealIntegerType, typename CompatibleNumberIntegerType>
2760 struct is_compatible_integer_type_impl <
2761 RealIntegerType, CompatibleNumberIntegerType,
2762 enable_if_t<std::is_integral<RealIntegerType>::value and
2763 std::is_integral<CompatibleNumberIntegerType>::value and
2764 not std::is_same<bool, CompatibleNumberIntegerType>::value >>
2765 {
2766 // is there an assert somewhere on overflows?
2767 using RealLimits = std::numeric_limits<RealIntegerType>;
2768 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
2769
2770 static constexpr auto value =
2771 std::is_constructible<RealIntegerType,
2772 CompatibleNumberIntegerType>::value and
2773 CompatibleLimits::is_integer and
2774 RealLimits::is_signed == CompatibleLimits::is_signed;
2775 };
2776
2777 template <typename RealIntegerType, typename CompatibleNumberIntegerType>
2778 struct is_compatible_integer_type
2779 : is_compatible_integer_type_impl<RealIntegerType,
2780 CompatibleNumberIntegerType> {};
2781
2782 template <typename BasicJsonType, typename CompatibleType, typename = void>
2783 struct is_compatible_type_impl: std::false_type {};
2784
2785 template <typename BasicJsonType, typename CompatibleType>
2786 struct is_compatible_type_impl <
2787 BasicJsonType, CompatibleType,
2788 enable_if_t<is_complete_type<CompatibleType>::value >>
2789 {
2790 static constexpr bool value =
2791 has_to_json<BasicJsonType, CompatibleType>::value;
2792 };
2793
2794 template <typename BasicJsonType, typename CompatibleType>
2795 struct is_compatible_type
2796 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
2797
2798 // https://en.cppreference.com/w/cpp/types/conjunction
2799 template<class...> struct conjunction : std::true_type { };
2800 template<class B1> struct conjunction<B1> : B1 { };
2801 template<class B1, class... Bn>
2802 struct conjunction<B1, Bn...>
2803 : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
2804
2805 template <typename T1, typename T2>
2806 struct is_constructible_tuple : std::false_type {};
2807
2808 template <typename T1, typename... Args>
2809 struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<std::is_constructible<T1, Args>...> {};
2810 } // namespace detail
2811 } // namespace nlohmann
2812
2813 // #include <nlohmann/detail/value_t.hpp>
2814
2815
2816 #include <array> // array
2817 #include <ciso646> // and
2818 #include <cstddef> // size_t
2819 #include <cstdint> // uint8_t
2820 #include <string> // string
2821
2822 namespace nlohmann
2823 {
2824 namespace detail
2825 {
2826 ///////////////////////////
2827 // JSON type enumeration //
2828 ///////////////////////////
2829
2830 /*!
2831 @brief the JSON type enumeration
2832
2833 This enumeration collects the different JSON types. It is internally used to
2834 distinguish the stored values, and the functions @ref basic_json::is_null(),
2835 @ref basic_json::is_object(), @ref basic_json::is_array(),
2836 @ref basic_json::is_string(), @ref basic_json::is_boolean(),
2837 @ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
2838 @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
2839 @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
2840 @ref basic_json::is_structured() rely on it.
2841
2842 @note There are three enumeration entries (number_integer, number_unsigned, and
2843 number_float), because the library distinguishes these three types for numbers:
2844 @ref basic_json::number_unsigned_t is used for unsigned integers,
2845 @ref basic_json::number_integer_t is used for signed integers, and
2846 @ref basic_json::number_float_t is used for floating-point numbers or to
2847 approximate integers which do not fit in the limits of their respective type.
2848
2849 @sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON
2850 value with the default value for a given type
2851
2852 @since version 1.0.0
2853 */
2854 enum class value_t : std::uint8_t
2855 {
2856 null, ///< null value
2857 object, ///< object (unordered set of name/value pairs)
2858 array, ///< array (ordered collection of values)
2859 string, ///< string value
2860 boolean, ///< boolean value
2861 number_integer, ///< number value (signed integer)
2862 number_unsigned, ///< number value (unsigned integer)
2863 number_float, ///< number value (floating-point)
2864 discarded ///< discarded by the the parser callback function
2865 };
2866
2867 /*!
2868 @brief comparison operator for JSON types
2869
2870 Returns an ordering that is similar to Python:
2871 - order: null < boolean < number < object < array < string
2872 - furthermore, each type is not smaller than itself
2873 - discarded values are not comparable
2874
2875 @since version 1.0.0
2876 */
operator <(const value_t lhs,const value_t rhs)2877 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2878 {
2879 static constexpr std::array<std::uint8_t, 8> order = {{
2880 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
2881 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */
2882 }
2883 };
2884
2885 const auto l_index = static_cast<std::size_t>(lhs);
2886 const auto r_index = static_cast<std::size_t>(rhs);
2887 return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];
2888 }
2889 } // namespace detail
2890 } // namespace nlohmann
2891
2892
2893 namespace nlohmann
2894 {
2895 namespace detail
2896 {
2897 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename std::nullptr_t & n)2898 void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
2899 {
2900 if (JSON_HEDLEY_UNLIKELY(not j.is_null()))
2901 {
2902 JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
2903 }
2904 n = nullptr;
2905 }
2906
2907 // overloads for basic_json template parameters
2908 template<typename BasicJsonType, typename ArithmeticType,
2909 enable_if_t<std::is_arithmetic<ArithmeticType>::value and
2910 not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
2911 int> = 0>
get_arithmetic_value(const BasicJsonType & j,ArithmeticType & val)2912 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
2913 {
2914 switch (static_cast<value_t>(j))
2915 {
2916 case value_t::number_unsigned:
2917 {
2918 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
2919 break;
2920 }
2921 case value_t::number_integer:
2922 {
2923 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
2924 break;
2925 }
2926 case value_t::number_float:
2927 {
2928 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
2929 break;
2930 }
2931
2932 default:
2933 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
2934 }
2935 }
2936
2937 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::boolean_t & b)2938 void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
2939 {
2940 if (JSON_HEDLEY_UNLIKELY(not j.is_boolean()))
2941 {
2942 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
2943 }
2944 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
2945 }
2946
2947 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::string_t & s)2948 void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
2949 {
2950 if (JSON_HEDLEY_UNLIKELY(not j.is_string()))
2951 {
2952 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
2953 }
2954 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
2955 }
2956
2957 template <
2958 typename BasicJsonType, typename ConstructibleStringType,
2959 enable_if_t <
2960 is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value and
2961 not std::is_same<typename BasicJsonType::string_t,
2962 ConstructibleStringType>::value,
2963 int > = 0 >
from_json(const BasicJsonType & j,ConstructibleStringType & s)2964 void from_json(const BasicJsonType& j, ConstructibleStringType& s)
2965 {
2966 if (JSON_HEDLEY_UNLIKELY(not j.is_string()))
2967 {
2968 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
2969 }
2970
2971 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
2972 }
2973
2974 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::number_float_t & val)2975 void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
2976 {
2977 get_arithmetic_value(j, val);
2978 }
2979
2980 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::number_unsigned_t & val)2981 void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
2982 {
2983 get_arithmetic_value(j, val);
2984 }
2985
2986 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::number_integer_t & val)2987 void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
2988 {
2989 get_arithmetic_value(j, val);
2990 }
2991
2992 template<typename BasicJsonType, typename EnumType,
2993 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
from_json(const BasicJsonType & j,EnumType & e)2994 void from_json(const BasicJsonType& j, EnumType& e)
2995 {
2996 typename std::underlying_type<EnumType>::type val;
2997 get_arithmetic_value(j, val);
2998 e = static_cast<EnumType>(val);
2999 }
3000
3001 // forward_list doesn't have an insert method
3002 template<typename BasicJsonType, typename T, typename Allocator,
3003 enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
from_json(const BasicJsonType & j,std::forward_list<T,Allocator> & l)3004 void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
3005 {
3006 if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
3007 {
3008 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
3009 }
3010 l.clear();
3011 std::transform(j.rbegin(), j.rend(),
3012 std::front_inserter(l), [](const BasicJsonType & i)
3013 {
3014 return i.template get<T>();
3015 });
3016 }
3017
3018 // valarray doesn't have an insert method
3019 template<typename BasicJsonType, typename T,
3020 enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
from_json(const BasicJsonType & j,std::valarray<T> & l)3021 void from_json(const BasicJsonType& j, std::valarray<T>& l)
3022 {
3023 if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
3024 {
3025 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
3026 }
3027 l.resize(j.size());
3028 std::copy(j.begin(), j.end(), std::begin(l));
3029 }
3030
3031 template <typename BasicJsonType, typename T, std::size_t N>
from_json(const BasicJsonType & j,T (& arr)[N])3032 auto from_json(const BasicJsonType& j, T (&arr)[N])
3033 -> decltype(j.template get<T>(), void())
3034 {
3035 for (std::size_t i = 0; i < N; ++i)
3036 {
3037 arr[i] = j.at(i).template get<T>();
3038 }
3039 }
3040
3041 template<typename BasicJsonType>
from_json_array_impl(const BasicJsonType & j,typename BasicJsonType::array_t & arr,priority_tag<3>)3042 void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
3043 {
3044 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
3045 }
3046
3047 template <typename BasicJsonType, typename T, std::size_t N>
from_json_array_impl(const BasicJsonType & j,std::array<T,N> & arr,priority_tag<2>)3048 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
3049 priority_tag<2> /*unused*/)
3050 -> decltype(j.template get<T>(), void())
3051 {
3052 for (std::size_t i = 0; i < N; ++i)
3053 {
3054 arr[i] = j.at(i).template get<T>();
3055 }
3056 }
3057
3058 template<typename BasicJsonType, typename ConstructibleArrayType>
from_json_array_impl(const BasicJsonType & j,ConstructibleArrayType & arr,priority_tag<1>)3059 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
3060 -> decltype(
3061 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
3062 j.template get<typename ConstructibleArrayType::value_type>(),
3063 void())
3064 {
3065 using std::end;
3066
3067 ConstructibleArrayType ret;
3068 ret.reserve(j.size());
3069 std::transform(j.begin(), j.end(),
3070 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
3071 {
3072 // get<BasicJsonType>() returns *this, this won't call a from_json
3073 // method when value_type is BasicJsonType
3074 return i.template get<typename ConstructibleArrayType::value_type>();
3075 });
3076 arr = std::move(ret);
3077 }
3078
3079 template <typename BasicJsonType, typename ConstructibleArrayType>
from_json_array_impl(const BasicJsonType & j,ConstructibleArrayType & arr,priority_tag<0>)3080 void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
3081 priority_tag<0> /*unused*/)
3082 {
3083 using std::end;
3084
3085 ConstructibleArrayType ret;
3086 std::transform(
3087 j.begin(), j.end(), std::inserter(ret, end(ret)),
3088 [](const BasicJsonType & i)
3089 {
3090 // get<BasicJsonType>() returns *this, this won't call a from_json
3091 // method when value_type is BasicJsonType
3092 return i.template get<typename ConstructibleArrayType::value_type>();
3093 });
3094 arr = std::move(ret);
3095 }
3096
3097 template <typename BasicJsonType, typename ConstructibleArrayType,
3098 enable_if_t <
3099 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value and
3100 not is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value and
3101 not is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value and
3102 not is_basic_json<ConstructibleArrayType>::value,
3103 int > = 0 >
3104
from_json(const BasicJsonType & j,ConstructibleArrayType & arr)3105 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
3106 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
3107 j.template get<typename ConstructibleArrayType::value_type>(),
3108 void())
3109 {
3110 if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
3111 {
3112 JSON_THROW(type_error::create(302, "type must be array, but is " +
3113 std::string(j.type_name())));
3114 }
3115
3116 from_json_array_impl(j, arr, priority_tag<3> {});
3117 }
3118
3119 template<typename BasicJsonType, typename ConstructibleObjectType,
3120 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
from_json(const BasicJsonType & j,ConstructibleObjectType & obj)3121 void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
3122 {
3123 if (JSON_HEDLEY_UNLIKELY(not j.is_object()))
3124 {
3125 JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
3126 }
3127
3128 ConstructibleObjectType ret;
3129 auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
3130 using value_type = typename ConstructibleObjectType::value_type;
3131 std::transform(
3132 inner_object->begin(), inner_object->end(),
3133 std::inserter(ret, ret.begin()),
3134 [](typename BasicJsonType::object_t::value_type const & p)
3135 {
3136 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
3137 });
3138 obj = std::move(ret);
3139 }
3140
3141 // overload for arithmetic types, not chosen for basic_json template arguments
3142 // (BooleanType, etc..); note: Is it really necessary to provide explicit
3143 // overloads for boolean_t etc. in case of a custom BooleanType which is not
3144 // an arithmetic type?
3145 template<typename BasicJsonType, typename ArithmeticType,
3146 enable_if_t <
3147 std::is_arithmetic<ArithmeticType>::value and
3148 not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
3149 not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
3150 not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
3151 not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
3152 int> = 0>
from_json(const BasicJsonType & j,ArithmeticType & val)3153 void from_json(const BasicJsonType& j, ArithmeticType& val)
3154 {
3155 switch (static_cast<value_t>(j))
3156 {
3157 case value_t::number_unsigned:
3158 {
3159 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
3160 break;
3161 }
3162 case value_t::number_integer:
3163 {
3164 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
3165 break;
3166 }
3167 case value_t::number_float:
3168 {
3169 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
3170 break;
3171 }
3172 case value_t::boolean:
3173 {
3174 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
3175 break;
3176 }
3177
3178 default:
3179 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
3180 }
3181 }
3182
3183 template<typename BasicJsonType, typename A1, typename A2>
from_json(const BasicJsonType & j,std::pair<A1,A2> & p)3184 void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
3185 {
3186 p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
3187 }
3188
3189 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
from_json_tuple_impl(const BasicJsonType & j,Tuple & t,index_sequence<Idx...>)3190 void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...> /*unused*/)
3191 {
3192 t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
3193 }
3194
3195 template<typename BasicJsonType, typename... Args>
from_json(const BasicJsonType & j,std::tuple<Args...> & t)3196 void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
3197 {
3198 from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
3199 }
3200
3201 template <typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
3202 typename = enable_if_t<not std::is_constructible<
3203 typename BasicJsonType::string_t, Key>::value>>
from_json(const BasicJsonType & j,std::map<Key,Value,Compare,Allocator> & m)3204 void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
3205 {
3206 if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
3207 {
3208 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
3209 }
3210 m.clear();
3211 for (const auto& p : j)
3212 {
3213 if (JSON_HEDLEY_UNLIKELY(not p.is_array()))
3214 {
3215 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
3216 }
3217 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
3218 }
3219 }
3220
3221 template <typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
3222 typename = enable_if_t<not std::is_constructible<
3223 typename BasicJsonType::string_t, Key>::value>>
from_json(const BasicJsonType & j,std::unordered_map<Key,Value,Hash,KeyEqual,Allocator> & m)3224 void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
3225 {
3226 if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
3227 {
3228 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
3229 }
3230 m.clear();
3231 for (const auto& p : j)
3232 {
3233 if (JSON_HEDLEY_UNLIKELY(not p.is_array()))
3234 {
3235 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
3236 }
3237 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
3238 }
3239 }
3240
3241 struct from_json_fn
3242 {
3243 template<typename BasicJsonType, typename T>
operator ()nlohmann::detail::from_json_fn3244 auto operator()(const BasicJsonType& j, T& val) const
3245 noexcept(noexcept(from_json(j, val)))
3246 -> decltype(from_json(j, val), void())
3247 {
3248 return from_json(j, val);
3249 }
3250 };
3251 } // namespace detail
3252
3253 /// namespace to hold default `from_json` function
3254 /// to see why this is required:
3255 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
3256 namespace
3257 {
3258 constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
3259 } // namespace
3260 } // namespace nlohmann
3261
3262 // #include <nlohmann/detail/conversions/to_json.hpp>
3263
3264
3265 #include <algorithm> // copy
3266 #include <ciso646> // or, and, not
3267 #include <iterator> // begin, end
3268 #include <string> // string
3269 #include <tuple> // tuple, get
3270 #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
3271 #include <utility> // move, forward, declval, pair
3272 #include <valarray> // valarray
3273 #include <vector> // vector
3274
3275 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
3276
3277
3278 #include <cstddef> // size_t
3279 #include <iterator> // input_iterator_tag
3280 #include <string> // string, to_string
3281 #include <tuple> // tuple_size, get, tuple_element
3282
3283 // #include <nlohmann/detail/meta/type_traits.hpp>
3284
3285 // #include <nlohmann/detail/value_t.hpp>
3286
3287
3288 namespace nlohmann
3289 {
3290 namespace detail
3291 {
3292 template<typename string_type>
int_to_string(string_type & target,std::size_t value)3293 void int_to_string( string_type& target, std::size_t value )
3294 {
3295 target = std::to_string(value);
3296 }
3297 template <typename IteratorType> class iteration_proxy_value
3298 {
3299 public:
3300 using difference_type = std::ptrdiff_t;
3301 using value_type = iteration_proxy_value;
3302 using pointer = value_type * ;
3303 using reference = value_type & ;
3304 using iterator_category = std::input_iterator_tag;
3305 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
3306
3307 private:
3308 /// the iterator
3309 IteratorType anchor;
3310 /// an index for arrays (used to create key names)
3311 std::size_t array_index = 0;
3312 /// last stringified array index
3313 mutable std::size_t array_index_last = 0;
3314 /// a string representation of the array index
3315 mutable string_type array_index_str = "0";
3316 /// an empty string (to return a reference for primitive values)
3317 const string_type empty_str = "";
3318
3319 public:
iteration_proxy_value(IteratorType it)3320 explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {}
3321
3322 /// dereference operator (needed for range-based for)
operator *()3323 iteration_proxy_value& operator*()
3324 {
3325 return *this;
3326 }
3327
3328 /// increment operator (needed for range-based for)
operator ++()3329 iteration_proxy_value& operator++()
3330 {
3331 ++anchor;
3332 ++array_index;
3333
3334 return *this;
3335 }
3336
3337 /// equality operator (needed for InputIterator)
operator ==(const iteration_proxy_value & o) const3338 bool operator==(const iteration_proxy_value& o) const
3339 {
3340 return anchor == o.anchor;
3341 }
3342
3343 /// inequality operator (needed for range-based for)
operator !=(const iteration_proxy_value & o) const3344 bool operator!=(const iteration_proxy_value& o) const
3345 {
3346 return anchor != o.anchor;
3347 }
3348
3349 /// return key of the iterator
key() const3350 const string_type& key() const
3351 {
3352 assert(anchor.m_object != nullptr);
3353
3354 switch (anchor.m_object->type())
3355 {
3356 // use integer array index as key
3357 case value_t::array:
3358 {
3359 if (array_index != array_index_last)
3360 {
3361 int_to_string( array_index_str, array_index );
3362 array_index_last = array_index;
3363 }
3364 return array_index_str;
3365 }
3366
3367 // use key from the object
3368 case value_t::object:
3369 return anchor.key();
3370
3371 // use an empty key for all primitive types
3372 default:
3373 return empty_str;
3374 }
3375 }
3376
3377 /// return value of the iterator
value() const3378 typename IteratorType::reference value() const
3379 {
3380 return anchor.value();
3381 }
3382 };
3383
3384 /// proxy class for the items() function
3385 template<typename IteratorType> class iteration_proxy
3386 {
3387 private:
3388 /// the container to iterate
3389 typename IteratorType::reference container;
3390
3391 public:
3392 /// construct iteration proxy from a container
iteration_proxy(typename IteratorType::reference cont)3393 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
3394 : container(cont) {}
3395
3396 /// return iterator begin (needed for range-based for)
begin()3397 iteration_proxy_value<IteratorType> begin() noexcept
3398 {
3399 return iteration_proxy_value<IteratorType>(container.begin());
3400 }
3401
3402 /// return iterator end (needed for range-based for)
end()3403 iteration_proxy_value<IteratorType> end() noexcept
3404 {
3405 return iteration_proxy_value<IteratorType>(container.end());
3406 }
3407 };
3408 // Structured Bindings Support
3409 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
3410 // And see https://github.com/nlohmann/json/pull/1391
3411 template <std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
get(const nlohmann::detail::iteration_proxy_value<IteratorType> & i)3412 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
3413 {
3414 return i.key();
3415 }
3416 // Structured Bindings Support
3417 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
3418 // And see https://github.com/nlohmann/json/pull/1391
3419 template <std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
get(const nlohmann::detail::iteration_proxy_value<IteratorType> & i)3420 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
3421 {
3422 return i.value();
3423 }
3424 } // namespace detail
3425 } // namespace nlohmann
3426
3427 // The Addition to the STD Namespace is required to add
3428 // Structured Bindings Support to the iteration_proxy_value class
3429 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
3430 // And see https://github.com/nlohmann/json/pull/1391
3431 namespace std
3432 {
3433 #if defined(__clang__)
3434 // Fix: https://github.com/nlohmann/json/issues/1401
3435 #pragma clang diagnostic push
3436 #pragma clang diagnostic ignored "-Wmismatched-tags"
3437 #endif
3438 template <typename IteratorType>
3439 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
3440 : public std::integral_constant<std::size_t, 2> {};
3441
3442 template <std::size_t N, typename IteratorType>
3443 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
3444 {
3445 public:
3446 using type = decltype(
3447 get<N>(std::declval <
3448 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
3449 };
3450 #if defined(__clang__)
3451 #pragma clang diagnostic pop
3452 #endif
3453 } // namespace std
3454
3455 // #include <nlohmann/detail/meta/cpp_future.hpp>
3456
3457 // #include <nlohmann/detail/meta/type_traits.hpp>
3458
3459 // #include <nlohmann/detail/value_t.hpp>
3460
3461
3462 namespace nlohmann
3463 {
3464 namespace detail
3465 {
3466 //////////////////
3467 // constructors //
3468 //////////////////
3469
3470 template<value_t> struct external_constructor;
3471
3472 template<>
3473 struct external_constructor<value_t::boolean>
3474 {
3475 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor3476 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
3477 {
3478 j.m_type = value_t::boolean;
3479 j.m_value = b;
3480 j.assert_invariant();
3481 }
3482 };
3483
3484 template<>
3485 struct external_constructor<value_t::string>
3486 {
3487 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor3488 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
3489 {
3490 j.m_type = value_t::string;
3491 j.m_value = s;
3492 j.assert_invariant();
3493 }
3494
3495 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor3496 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
3497 {
3498 j.m_type = value_t::string;
3499 j.m_value = std::move(s);
3500 j.assert_invariant();
3501 }
3502
3503 template<typename BasicJsonType, typename CompatibleStringType,
3504 enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
3505 int> = 0>
constructnlohmann::detail::external_constructor3506 static void construct(BasicJsonType& j, const CompatibleStringType& str)
3507 {
3508 j.m_type = value_t::string;
3509 j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
3510 j.assert_invariant();
3511 }
3512 };
3513
3514 template<>
3515 struct external_constructor<value_t::number_float>
3516 {
3517 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor3518 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
3519 {
3520 j.m_type = value_t::number_float;
3521 j.m_value = val;
3522 j.assert_invariant();
3523 }
3524 };
3525
3526 template<>
3527 struct external_constructor<value_t::number_unsigned>
3528 {
3529 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor3530 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
3531 {
3532 j.m_type = value_t::number_unsigned;
3533 j.m_value = val;
3534 j.assert_invariant();
3535 }
3536 };
3537
3538 template<>
3539 struct external_constructor<value_t::number_integer>
3540 {
3541 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor3542 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
3543 {
3544 j.m_type = value_t::number_integer;
3545 j.m_value = val;
3546 j.assert_invariant();
3547 }
3548 };
3549
3550 template<>
3551 struct external_constructor<value_t::array>
3552 {
3553 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor3554 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
3555 {
3556 j.m_type = value_t::array;
3557 j.m_value = arr;
3558 j.assert_invariant();
3559 }
3560
3561 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor3562 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
3563 {
3564 j.m_type = value_t::array;
3565 j.m_value = std::move(arr);
3566 j.assert_invariant();
3567 }
3568
3569 template<typename BasicJsonType, typename CompatibleArrayType,
3570 enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
3571 int> = 0>
constructnlohmann::detail::external_constructor3572 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
3573 {
3574 using std::begin;
3575 using std::end;
3576 j.m_type = value_t::array;
3577 j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
3578 j.assert_invariant();
3579 }
3580
3581 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor3582 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
3583 {
3584 j.m_type = value_t::array;
3585 j.m_value = value_t::array;
3586 j.m_value.array->reserve(arr.size());
3587 for (const bool x : arr)
3588 {
3589 j.m_value.array->push_back(x);
3590 }
3591 j.assert_invariant();
3592 }
3593
3594 template<typename BasicJsonType, typename T,
3595 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
constructnlohmann::detail::external_constructor3596 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
3597 {
3598 j.m_type = value_t::array;
3599 j.m_value = value_t::array;
3600 j.m_value.array->resize(arr.size());
3601 if (arr.size() > 0)
3602 {
3603 std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
3604 }
3605 j.assert_invariant();
3606 }
3607 };
3608
3609 template<>
3610 struct external_constructor<value_t::object>
3611 {
3612 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor3613 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
3614 {
3615 j.m_type = value_t::object;
3616 j.m_value = obj;
3617 j.assert_invariant();
3618 }
3619
3620 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor3621 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
3622 {
3623 j.m_type = value_t::object;
3624 j.m_value = std::move(obj);
3625 j.assert_invariant();
3626 }
3627
3628 template<typename BasicJsonType, typename CompatibleObjectType,
3629 enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
constructnlohmann::detail::external_constructor3630 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
3631 {
3632 using std::begin;
3633 using std::end;
3634
3635 j.m_type = value_t::object;
3636 j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
3637 j.assert_invariant();
3638 }
3639 };
3640
3641 /////////////
3642 // to_json //
3643 /////////////
3644
3645 template<typename BasicJsonType, typename T,
3646 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
to_json(BasicJsonType & j,T b)3647 void to_json(BasicJsonType& j, T b) noexcept
3648 {
3649 external_constructor<value_t::boolean>::construct(j, b);
3650 }
3651
3652 template<typename BasicJsonType, typename CompatibleString,
3653 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
to_json(BasicJsonType & j,const CompatibleString & s)3654 void to_json(BasicJsonType& j, const CompatibleString& s)
3655 {
3656 external_constructor<value_t::string>::construct(j, s);
3657 }
3658
3659 template<typename BasicJsonType>
to_json(BasicJsonType & j,typename BasicJsonType::string_t && s)3660 void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
3661 {
3662 external_constructor<value_t::string>::construct(j, std::move(s));
3663 }
3664
3665 template<typename BasicJsonType, typename FloatType,
3666 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
to_json(BasicJsonType & j,FloatType val)3667 void to_json(BasicJsonType& j, FloatType val) noexcept
3668 {
3669 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
3670 }
3671
3672 template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
3673 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
to_json(BasicJsonType & j,CompatibleNumberUnsignedType val)3674 void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
3675 {
3676 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
3677 }
3678
3679 template<typename BasicJsonType, typename CompatibleNumberIntegerType,
3680 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
to_json(BasicJsonType & j,CompatibleNumberIntegerType val)3681 void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
3682 {
3683 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
3684 }
3685
3686 template<typename BasicJsonType, typename EnumType,
3687 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
to_json(BasicJsonType & j,EnumType e)3688 void to_json(BasicJsonType& j, EnumType e) noexcept
3689 {
3690 using underlying_type = typename std::underlying_type<EnumType>::type;
3691 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
3692 }
3693
3694 template<typename BasicJsonType>
to_json(BasicJsonType & j,const std::vector<bool> & e)3695 void to_json(BasicJsonType& j, const std::vector<bool>& e)
3696 {
3697 external_constructor<value_t::array>::construct(j, e);
3698 }
3699
3700 template <typename BasicJsonType, typename CompatibleArrayType,
3701 enable_if_t<is_compatible_array_type<BasicJsonType,
3702 CompatibleArrayType>::value and
3703 not is_compatible_object_type<
3704 BasicJsonType, CompatibleArrayType>::value and
3705 not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
3706 not is_basic_json<CompatibleArrayType>::value,
3707 int> = 0>
to_json(BasicJsonType & j,const CompatibleArrayType & arr)3708 void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
3709 {
3710 external_constructor<value_t::array>::construct(j, arr);
3711 }
3712
3713 template<typename BasicJsonType, typename T,
3714 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
to_json(BasicJsonType & j,const std::valarray<T> & arr)3715 void to_json(BasicJsonType& j, const std::valarray<T>& arr)
3716 {
3717 external_constructor<value_t::array>::construct(j, std::move(arr));
3718 }
3719
3720 template<typename BasicJsonType>
to_json(BasicJsonType & j,typename BasicJsonType::array_t && arr)3721 void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
3722 {
3723 external_constructor<value_t::array>::construct(j, std::move(arr));
3724 }
3725
3726 template<typename BasicJsonType, typename CompatibleObjectType,
3727 enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0>
to_json(BasicJsonType & j,const CompatibleObjectType & obj)3728 void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
3729 {
3730 external_constructor<value_t::object>::construct(j, obj);
3731 }
3732
3733 template<typename BasicJsonType>
to_json(BasicJsonType & j,typename BasicJsonType::object_t && obj)3734 void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
3735 {
3736 external_constructor<value_t::object>::construct(j, std::move(obj));
3737 }
3738
3739 template <
3740 typename BasicJsonType, typename T, std::size_t N,
3741 enable_if_t<not std::is_constructible<typename BasicJsonType::string_t,
3742 const T(&)[N]>::value,
3743 int> = 0 >
to_json(BasicJsonType & j,const T (& arr)[N])3744 void to_json(BasicJsonType& j, const T(&arr)[N])
3745 {
3746 external_constructor<value_t::array>::construct(j, arr);
3747 }
3748
3749 template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
to_json(BasicJsonType & j,const std::pair<T1,T2> & p)3750 void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
3751 {
3752 j = { p.first, p.second };
3753 }
3754
3755 // for https://github.com/nlohmann/json/pull/1134
3756 template < typename BasicJsonType, typename T,
3757 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
to_json(BasicJsonType & j,const T & b)3758 void to_json(BasicJsonType& j, const T& b)
3759 {
3760 j = { {b.key(), b.value()} };
3761 }
3762
3763 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
to_json_tuple_impl(BasicJsonType & j,const Tuple & t,index_sequence<Idx...>)3764 void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
3765 {
3766 j = { std::get<Idx>(t)... };
3767 }
3768
3769 template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
to_json(BasicJsonType & j,const T & t)3770 void to_json(BasicJsonType& j, const T& t)
3771 {
3772 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
3773 }
3774
3775 struct to_json_fn
3776 {
3777 template<typename BasicJsonType, typename T>
operator ()nlohmann::detail::to_json_fn3778 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
3779 -> decltype(to_json(j, std::forward<T>(val)), void())
3780 {
3781 return to_json(j, std::forward<T>(val));
3782 }
3783 };
3784 } // namespace detail
3785
3786 /// namespace to hold default `to_json` function
3787 namespace
3788 {
3789 constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
3790 } // namespace
3791 } // namespace nlohmann
3792
3793
3794 namespace nlohmann
3795 {
3796
3797 template<typename, typename>
3798 struct adl_serializer
3799 {
3800 /*!
3801 @brief convert a JSON value to any value type
3802
3803 This function is usually called by the `get()` function of the
3804 @ref basic_json class (either explicit or via conversion operators).
3805
3806 @param[in] j JSON value to read from
3807 @param[in,out] val value to write to
3808 */
3809 template<typename BasicJsonType, typename ValueType>
from_jsonnlohmann::adl_serializer3810 static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(
3811 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
3812 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
3813 {
3814 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
3815 }
3816
3817 /*!
3818 @brief convert any value type to a JSON value
3819
3820 This function is usually called by the constructors of the @ref basic_json
3821 class.
3822
3823 @param[in,out] j JSON value to write to
3824 @param[in] val value to read from
3825 */
3826 template <typename BasicJsonType, typename ValueType>
to_jsonnlohmann::adl_serializer3827 static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
3828 noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
3829 -> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)), void())
3830 {
3831 ::nlohmann::to_json(j, std::forward<ValueType>(val));
3832 }
3833 };
3834
3835 } // namespace nlohmann
3836
3837 // #include <nlohmann/detail/conversions/from_json.hpp>
3838
3839 // #include <nlohmann/detail/conversions/to_json.hpp>
3840
3841 // #include <nlohmann/detail/exceptions.hpp>
3842
3843 // #include <nlohmann/detail/input/binary_reader.hpp>
3844
3845
3846 #include <algorithm> // generate_n
3847 #include <array> // array
3848 #include <cassert> // assert
3849 #include <cmath> // ldexp
3850 #include <cstddef> // size_t
3851 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
3852 #include <cstdio> // snprintf
3853 #include <cstring> // memcpy
3854 #include <iterator> // back_inserter
3855 #include <limits> // numeric_limits
3856 #include <string> // char_traits, string
3857 #include <utility> // make_pair, move
3858
3859 // #include <nlohmann/detail/exceptions.hpp>
3860
3861 // #include <nlohmann/detail/input/input_adapters.hpp>
3862
3863
3864 #include <array> // array
3865 #include <cassert> // assert
3866 #include <cstddef> // size_t
3867 #include <cstdio> //FILE *
3868 #include <cstring> // strlen
3869 #include <istream> // istream
3870 #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
3871 #include <memory> // shared_ptr, make_shared, addressof
3872 #include <numeric> // accumulate
3873 #include <string> // string, char_traits
3874 #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
3875 #include <utility> // pair, declval
3876
3877 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
3878
3879 // #include <nlohmann/detail/macro_scope.hpp>
3880
3881
3882 namespace nlohmann
3883 {
3884 namespace detail
3885 {
3886 /// the supported input formats
3887 enum class input_format_t { json, cbor, msgpack, ubjson, bson };
3888
3889 ////////////////////
3890 // input adapters //
3891 ////////////////////
3892
3893 /*!
3894 @brief abstract input adapter interface
3895
3896 Produces a stream of std::char_traits<char>::int_type characters from a
3897 std::istream, a buffer, or some other input type. Accepts the return of
3898 exactly one non-EOF character for future input. The int_type characters
3899 returned consist of all valid char values as positive values (typically
3900 unsigned char), plus an EOF value outside that range, specified by the value
3901 of the function std::char_traits<char>::eof(). This value is typically -1, but
3902 could be any arbitrary value which is not a valid char value.
3903 */
3904 struct input_adapter_protocol
3905 {
3906 /// get a character [0,255] or std::char_traits<char>::eof().
3907 virtual std::char_traits<char>::int_type get_character() = 0;
3908 virtual ~input_adapter_protocol() = default;
3909 };
3910
3911 /// a type to simplify interfaces
3912 using input_adapter_t = std::shared_ptr<input_adapter_protocol>;
3913
3914 /*!
3915 Input adapter for stdio file access. This adapter read only 1 byte and do not use any
3916 buffer. This adapter is a very low level adapter.
3917 */
3918 class file_input_adapter : public input_adapter_protocol
3919 {
3920 public:
3921 JSON_HEDLEY_NON_NULL(2)
file_input_adapter(std::FILE * f)3922 explicit file_input_adapter(std::FILE* f) noexcept
3923 : m_file(f)
3924 {}
3925
3926 // make class move-only
3927 file_input_adapter(const file_input_adapter&) = delete;
3928 file_input_adapter(file_input_adapter&&) = default;
3929 file_input_adapter& operator=(const file_input_adapter&) = delete;
3930 file_input_adapter& operator=(file_input_adapter&&) = default;
3931 ~file_input_adapter() override = default;
3932
get_character()3933 std::char_traits<char>::int_type get_character() noexcept override
3934 {
3935 return std::fgetc(m_file);
3936 }
3937
3938 private:
3939 /// the file pointer to read from
3940 std::FILE* m_file;
3941 };
3942
3943
3944 /*!
3945 Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
3946 beginning of input. Does not support changing the underlying std::streambuf
3947 in mid-input. Maintains underlying std::istream and std::streambuf to support
3948 subsequent use of standard std::istream operations to process any input
3949 characters following those used in parsing the JSON input. Clears the
3950 std::istream flags; any input errors (e.g., EOF) will be detected by the first
3951 subsequent call for input from the std::istream.
3952 */
3953 class input_stream_adapter : public input_adapter_protocol
3954 {
3955 public:
~input_stream_adapter()3956 ~input_stream_adapter() override
3957 {
3958 // clear stream flags; we use underlying streambuf I/O, do not
3959 // maintain ifstream flags, except eof
3960 is.clear(is.rdstate() & std::ios::eofbit);
3961 }
3962
input_stream_adapter(std::istream & i)3963 explicit input_stream_adapter(std::istream& i)
3964 : is(i), sb(*i.rdbuf())
3965 {}
3966
3967 // delete because of pointer members
3968 input_stream_adapter(const input_stream_adapter&) = delete;
3969 input_stream_adapter& operator=(input_stream_adapter&) = delete;
3970 input_stream_adapter(input_stream_adapter&&) = delete;
3971 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
3972
3973 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
3974 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
3975 // end up as the same value, eg. 0xFFFFFFFF.
get_character()3976 std::char_traits<char>::int_type get_character() override
3977 {
3978 auto res = sb.sbumpc();
3979 // set eof manually, as we don't use the istream interface.
3980 if (res == EOF)
3981 {
3982 is.clear(is.rdstate() | std::ios::eofbit);
3983 }
3984 return res;
3985 }
3986
3987 private:
3988 /// the associated input stream
3989 std::istream& is;
3990 std::streambuf& sb;
3991 };
3992
3993 /// input adapter for buffer input
3994 class input_buffer_adapter : public input_adapter_protocol
3995 {
3996 public:
input_buffer_adapter(const char * b,const std::size_t l)3997 input_buffer_adapter(const char* b, const std::size_t l) noexcept
3998 : cursor(b), limit(b == nullptr ? nullptr : (b + l))
3999 {}
4000
4001 // delete because of pointer members
4002 input_buffer_adapter(const input_buffer_adapter&) = delete;
4003 input_buffer_adapter& operator=(input_buffer_adapter&) = delete;
4004 input_buffer_adapter(input_buffer_adapter&&) = delete;
4005 input_buffer_adapter& operator=(input_buffer_adapter&&) = delete;
4006 ~input_buffer_adapter() override = default;
4007
get_character()4008 std::char_traits<char>::int_type get_character() noexcept override
4009 {
4010 if (JSON_HEDLEY_LIKELY(cursor < limit))
4011 {
4012 assert(cursor != nullptr and limit != nullptr);
4013 return std::char_traits<char>::to_int_type(*(cursor++));
4014 }
4015
4016 return std::char_traits<char>::eof();
4017 }
4018
4019 private:
4020 /// pointer to the current character
4021 const char* cursor;
4022 /// pointer past the last character
4023 const char* const limit;
4024 };
4025
4026 template<typename WideStringType, size_t T>
4027 struct wide_string_input_helper
4028 {
4029 // UTF-32
fill_buffernlohmann::detail::wide_string_input_helper4030 static void fill_buffer(const WideStringType& str,
4031 size_t& current_wchar,
4032 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
4033 size_t& utf8_bytes_index,
4034 size_t& utf8_bytes_filled)
4035 {
4036 utf8_bytes_index = 0;
4037
4038 if (current_wchar == str.size())
4039 {
4040 utf8_bytes[0] = std::char_traits<char>::eof();
4041 utf8_bytes_filled = 1;
4042 }
4043 else
4044 {
4045 // get the current character
4046 const auto wc = static_cast<unsigned int>(str[current_wchar++]);
4047
4048 // UTF-32 to UTF-8 encoding
4049 if (wc < 0x80)
4050 {
4051 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
4052 utf8_bytes_filled = 1;
4053 }
4054 else if (wc <= 0x7FF)
4055 {
4056 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u) & 0x1Fu));
4057 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
4058 utf8_bytes_filled = 2;
4059 }
4060 else if (wc <= 0xFFFF)
4061 {
4062 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u) & 0x0Fu));
4063 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
4064 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
4065 utf8_bytes_filled = 3;
4066 }
4067 else if (wc <= 0x10FFFF)
4068 {
4069 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((wc >> 18u) & 0x07u));
4070 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 12u) & 0x3Fu));
4071 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
4072 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
4073 utf8_bytes_filled = 4;
4074 }
4075 else
4076 {
4077 // unknown character
4078 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
4079 utf8_bytes_filled = 1;
4080 }
4081 }
4082 }
4083 };
4084
4085 template<typename WideStringType>
4086 struct wide_string_input_helper<WideStringType, 2>
4087 {
4088 // UTF-16
fill_buffernlohmann::detail::wide_string_input_helper4089 static void fill_buffer(const WideStringType& str,
4090 size_t& current_wchar,
4091 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
4092 size_t& utf8_bytes_index,
4093 size_t& utf8_bytes_filled)
4094 {
4095 utf8_bytes_index = 0;
4096
4097 if (current_wchar == str.size())
4098 {
4099 utf8_bytes[0] = std::char_traits<char>::eof();
4100 utf8_bytes_filled = 1;
4101 }
4102 else
4103 {
4104 // get the current character
4105 const auto wc = static_cast<unsigned int>(str[current_wchar++]);
4106
4107 // UTF-16 to UTF-8 encoding
4108 if (wc < 0x80)
4109 {
4110 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
4111 utf8_bytes_filled = 1;
4112 }
4113 else if (wc <= 0x7FF)
4114 {
4115 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u)));
4116 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
4117 utf8_bytes_filled = 2;
4118 }
4119 else if (0xD800 > wc or wc >= 0xE000)
4120 {
4121 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u)));
4122 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
4123 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
4124 utf8_bytes_filled = 3;
4125 }
4126 else
4127 {
4128 if (current_wchar < str.size())
4129 {
4130 const auto wc2 = static_cast<unsigned int>(str[current_wchar++]);
4131 const auto charcode = 0x10000u + (((wc & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
4132 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
4133 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
4134 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
4135 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
4136 utf8_bytes_filled = 4;
4137 }
4138 else
4139 {
4140 // unknown character
4141 ++current_wchar;
4142 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
4143 utf8_bytes_filled = 1;
4144 }
4145 }
4146 }
4147 }
4148 };
4149
4150 template<typename WideStringType>
4151 class wide_string_input_adapter : public input_adapter_protocol
4152 {
4153 public:
wide_string_input_adapter(const WideStringType & w)4154 explicit wide_string_input_adapter(const WideStringType& w) noexcept
4155 : str(w)
4156 {}
4157
get_character()4158 std::char_traits<char>::int_type get_character() noexcept override
4159 {
4160 // check if buffer needs to be filled
4161 if (utf8_bytes_index == utf8_bytes_filled)
4162 {
4163 fill_buffer<sizeof(typename WideStringType::value_type)>();
4164
4165 assert(utf8_bytes_filled > 0);
4166 assert(utf8_bytes_index == 0);
4167 }
4168
4169 // use buffer
4170 assert(utf8_bytes_filled > 0);
4171 assert(utf8_bytes_index < utf8_bytes_filled);
4172 return utf8_bytes[utf8_bytes_index++];
4173 }
4174
4175 private:
4176 template<size_t T>
fill_buffer()4177 void fill_buffer()
4178 {
4179 wide_string_input_helper<WideStringType, T>::fill_buffer(str, current_wchar, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
4180 }
4181
4182 /// the wstring to process
4183 const WideStringType& str;
4184
4185 /// index of the current wchar in str
4186 std::size_t current_wchar = 0;
4187
4188 /// a buffer for UTF-8 bytes
4189 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
4190
4191 /// index to the utf8_codes array for the next valid byte
4192 std::size_t utf8_bytes_index = 0;
4193 /// number of valid bytes in the utf8_codes array
4194 std::size_t utf8_bytes_filled = 0;
4195 };
4196
4197 class input_adapter
4198 {
4199 public:
4200 // native support
4201 JSON_HEDLEY_NON_NULL(2)
input_adapter(std::FILE * file)4202 input_adapter(std::FILE* file)
4203 : ia(std::make_shared<file_input_adapter>(file)) {}
4204 /// input adapter for input stream
input_adapter(std::istream & i)4205 input_adapter(std::istream& i)
4206 : ia(std::make_shared<input_stream_adapter>(i)) {}
4207
4208 /// input adapter for input stream
input_adapter(std::istream && i)4209 input_adapter(std::istream&& i)
4210 : ia(std::make_shared<input_stream_adapter>(i)) {}
4211
input_adapter(const std::wstring & ws)4212 input_adapter(const std::wstring& ws)
4213 : ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {}
4214
input_adapter(const std::u16string & ws)4215 input_adapter(const std::u16string& ws)
4216 : ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {}
4217
input_adapter(const std::u32string & ws)4218 input_adapter(const std::u32string& ws)
4219 : ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {}
4220
4221 /// input adapter for buffer
4222 template<typename CharT,
4223 typename std::enable_if<
4224 std::is_pointer<CharT>::value and
4225 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
4226 sizeof(typename std::remove_pointer<CharT>::type) == 1,
4227 int>::type = 0>
input_adapter(CharT b,std::size_t l)4228 input_adapter(CharT b, std::size_t l)
4229 : ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l)) {}
4230
4231 // derived support
4232
4233 /// input adapter for string literal
4234 template<typename CharT,
4235 typename std::enable_if<
4236 std::is_pointer<CharT>::value and
4237 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
4238 sizeof(typename std::remove_pointer<CharT>::type) == 1,
4239 int>::type = 0>
input_adapter(CharT b)4240 input_adapter(CharT b)
4241 : input_adapter(reinterpret_cast<const char*>(b),
4242 std::strlen(reinterpret_cast<const char*>(b))) {}
4243
4244 /// input adapter for iterator range with contiguous storage
4245 template<class IteratorType,
4246 typename std::enable_if<
4247 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
4248 int>::type = 0>
input_adapter(IteratorType first,IteratorType last)4249 input_adapter(IteratorType first, IteratorType last)
4250 {
4251 #ifndef NDEBUG
4252 // assertion to check that the iterator range is indeed contiguous,
4253 // see http://stackoverflow.com/a/35008842/266378 for more discussion
4254 const auto is_contiguous = std::accumulate(
4255 first, last, std::pair<bool, int>(true, 0),
4256 [&first](std::pair<bool, int> res, decltype(*first) val)
4257 {
4258 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
4259 return res;
4260 }).first;
4261 assert(is_contiguous);
4262 #endif
4263
4264 // assertion to check that each element is 1 byte long
4265 static_assert(
4266 sizeof(typename iterator_traits<IteratorType>::value_type) == 1,
4267 "each element in the iterator range must have the size of 1 byte");
4268
4269 const auto len = static_cast<size_t>(std::distance(first, last));
4270 if (JSON_HEDLEY_LIKELY(len > 0))
4271 {
4272 // there is at least one element: use the address of first
4273 ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
4274 }
4275 else
4276 {
4277 // the address of first cannot be used: use nullptr
4278 ia = std::make_shared<input_buffer_adapter>(nullptr, len);
4279 }
4280 }
4281
4282 /// input adapter for array
4283 template<class T, std::size_t N>
input_adapter(T (& array)[N])4284 input_adapter(T (&array)[N])
4285 : input_adapter(std::begin(array), std::end(array)) {}
4286
4287 /// input adapter for contiguous container
4288 template<class ContiguousContainer, typename
4289 std::enable_if<not std::is_pointer<ContiguousContainer>::value and
4290 std::is_base_of<std::random_access_iterator_tag, typename iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
4291 int>::type = 0>
input_adapter(const ContiguousContainer & c)4292 input_adapter(const ContiguousContainer& c)
4293 : input_adapter(std::begin(c), std::end(c)) {}
4294
operator input_adapter_t()4295 operator input_adapter_t()
4296 {
4297 return ia;
4298 }
4299
4300 private:
4301 /// the actual adapter
4302 input_adapter_t ia = nullptr;
4303 };
4304 } // namespace detail
4305 } // namespace nlohmann
4306
4307 // #include <nlohmann/detail/input/json_sax.hpp>
4308
4309
4310 #include <cassert> // assert
4311 #include <cstddef>
4312 #include <string> // string
4313 #include <utility> // move
4314 #include <vector> // vector
4315
4316 // #include <nlohmann/detail/exceptions.hpp>
4317
4318 // #include <nlohmann/detail/macro_scope.hpp>
4319
4320
4321 namespace nlohmann
4322 {
4323
4324 /*!
4325 @brief SAX interface
4326
4327 This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
4328 Each function is called in different situations while the input is parsed. The
4329 boolean return value informs the parser whether to continue processing the
4330 input.
4331 */
4332 template<typename BasicJsonType>
4333 struct json_sax
4334 {
4335 /// type for (signed) integers
4336 using number_integer_t = typename BasicJsonType::number_integer_t;
4337 /// type for unsigned integers
4338 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4339 /// type for floating-point numbers
4340 using number_float_t = typename BasicJsonType::number_float_t;
4341 /// type for strings
4342 using string_t = typename BasicJsonType::string_t;
4343
4344 /*!
4345 @brief a null value was read
4346 @return whether parsing should proceed
4347 */
4348 virtual bool null() = 0;
4349
4350 /*!
4351 @brief a boolean value was read
4352 @param[in] val boolean value
4353 @return whether parsing should proceed
4354 */
4355 virtual bool boolean(bool val) = 0;
4356
4357 /*!
4358 @brief an integer number was read
4359 @param[in] val integer value
4360 @return whether parsing should proceed
4361 */
4362 virtual bool number_integer(number_integer_t val) = 0;
4363
4364 /*!
4365 @brief an unsigned integer number was read
4366 @param[in] val unsigned integer value
4367 @return whether parsing should proceed
4368 */
4369 virtual bool number_unsigned(number_unsigned_t val) = 0;
4370
4371 /*!
4372 @brief an floating-point number was read
4373 @param[in] val floating-point value
4374 @param[in] s raw token value
4375 @return whether parsing should proceed
4376 */
4377 virtual bool number_float(number_float_t val, const string_t& s) = 0;
4378
4379 /*!
4380 @brief a string was read
4381 @param[in] val string value
4382 @return whether parsing should proceed
4383 @note It is safe to move the passed string.
4384 */
4385 virtual bool string(string_t& val) = 0;
4386
4387 /*!
4388 @brief the beginning of an object was read
4389 @param[in] elements number of object elements or -1 if unknown
4390 @return whether parsing should proceed
4391 @note binary formats may report the number of elements
4392 */
4393 virtual bool start_object(std::size_t elements) = 0;
4394
4395 /*!
4396 @brief an object key was read
4397 @param[in] val object key
4398 @return whether parsing should proceed
4399 @note It is safe to move the passed string.
4400 */
4401 virtual bool key(string_t& val) = 0;
4402
4403 /*!
4404 @brief the end of an object was read
4405 @return whether parsing should proceed
4406 */
4407 virtual bool end_object() = 0;
4408
4409 /*!
4410 @brief the beginning of an array was read
4411 @param[in] elements number of array elements or -1 if unknown
4412 @return whether parsing should proceed
4413 @note binary formats may report the number of elements
4414 */
4415 virtual bool start_array(std::size_t elements) = 0;
4416
4417 /*!
4418 @brief the end of an array was read
4419 @return whether parsing should proceed
4420 */
4421 virtual bool end_array() = 0;
4422
4423 /*!
4424 @brief a parse error occurred
4425 @param[in] position the position in the input where the error occurs
4426 @param[in] last_token the last read token
4427 @param[in] ex an exception object describing the error
4428 @return whether parsing should proceed (must return false)
4429 */
4430 virtual bool parse_error(std::size_t position,
4431 const std::string& last_token,
4432 const detail::exception& ex) = 0;
4433
4434 virtual ~json_sax() = default;
4435 };
4436
4437
4438 namespace detail
4439 {
4440 /*!
4441 @brief SAX implementation to create a JSON value from SAX events
4442
4443 This class implements the @ref json_sax interface and processes the SAX events
4444 to create a JSON value which makes it basically a DOM parser. The structure or
4445 hierarchy of the JSON value is managed by the stack `ref_stack` which contains
4446 a pointer to the respective array or object for each recursion depth.
4447
4448 After successful parsing, the value that is passed by reference to the
4449 constructor contains the parsed value.
4450
4451 @tparam BasicJsonType the JSON type
4452 */
4453 template<typename BasicJsonType>
4454 class json_sax_dom_parser
4455 {
4456 public:
4457 using number_integer_t = typename BasicJsonType::number_integer_t;
4458 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4459 using number_float_t = typename BasicJsonType::number_float_t;
4460 using string_t = typename BasicJsonType::string_t;
4461
4462 /*!
4463 @param[in, out] r reference to a JSON value that is manipulated while
4464 parsing
4465 @param[in] allow_exceptions_ whether parse errors yield exceptions
4466 */
json_sax_dom_parser(BasicJsonType & r,const bool allow_exceptions_=true)4467 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
4468 : root(r), allow_exceptions(allow_exceptions_)
4469 {}
4470
4471 // make class move-only
4472 json_sax_dom_parser(const json_sax_dom_parser&) = delete;
4473 json_sax_dom_parser(json_sax_dom_parser&&) = default;
4474 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
4475 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default;
4476 ~json_sax_dom_parser() = default;
4477
null()4478 bool null()
4479 {
4480 handle_value(nullptr);
4481 return true;
4482 }
4483
boolean(bool val)4484 bool boolean(bool val)
4485 {
4486 handle_value(val);
4487 return true;
4488 }
4489
number_integer(number_integer_t val)4490 bool number_integer(number_integer_t val)
4491 {
4492 handle_value(val);
4493 return true;
4494 }
4495
number_unsigned(number_unsigned_t val)4496 bool number_unsigned(number_unsigned_t val)
4497 {
4498 handle_value(val);
4499 return true;
4500 }
4501
number_float(number_float_t val,const string_t &)4502 bool number_float(number_float_t val, const string_t& /*unused*/)
4503 {
4504 handle_value(val);
4505 return true;
4506 }
4507
string(string_t & val)4508 bool string(string_t& val)
4509 {
4510 handle_value(val);
4511 return true;
4512 }
4513
start_object(std::size_t len)4514 bool start_object(std::size_t len)
4515 {
4516 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
4517
4518 if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4519 {
4520 JSON_THROW(out_of_range::create(408,
4521 "excessive object size: " + std::to_string(len)));
4522 }
4523
4524 return true;
4525 }
4526
key(string_t & val)4527 bool key(string_t& val)
4528 {
4529 // add null at given key and store the reference for later
4530 object_element = &(ref_stack.back()->m_value.object->operator[](val));
4531 return true;
4532 }
4533
end_object()4534 bool end_object()
4535 {
4536 ref_stack.pop_back();
4537 return true;
4538 }
4539
start_array(std::size_t len)4540 bool start_array(std::size_t len)
4541 {
4542 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
4543
4544 if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4545 {
4546 JSON_THROW(out_of_range::create(408,
4547 "excessive array size: " + std::to_string(len)));
4548 }
4549
4550 return true;
4551 }
4552
end_array()4553 bool end_array()
4554 {
4555 ref_stack.pop_back();
4556 return true;
4557 }
4558
parse_error(std::size_t,const std::string &,const detail::exception & ex)4559 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
4560 const detail::exception& ex)
4561 {
4562 errored = true;
4563 if (allow_exceptions)
4564 {
4565 // determine the proper exception type from the id
4566 switch ((ex.id / 100) % 100)
4567 {
4568 case 1:
4569 JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
4570 case 4:
4571 JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
4572 // LCOV_EXCL_START
4573 case 2:
4574 JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
4575 case 3:
4576 JSON_THROW(*static_cast<const detail::type_error*>(&ex));
4577 case 5:
4578 JSON_THROW(*static_cast<const detail::other_error*>(&ex));
4579 default:
4580 assert(false);
4581 // LCOV_EXCL_STOP
4582 }
4583 }
4584 return false;
4585 }
4586
is_errored() const4587 constexpr bool is_errored() const
4588 {
4589 return errored;
4590 }
4591
4592 private:
4593 /*!
4594 @invariant If the ref stack is empty, then the passed value will be the new
4595 root.
4596 @invariant If the ref stack contains a value, then it is an array or an
4597 object to which we can add elements
4598 */
4599 template<typename Value>
4600 JSON_HEDLEY_RETURNS_NON_NULL
handle_value(Value && v)4601 BasicJsonType* handle_value(Value&& v)
4602 {
4603 if (ref_stack.empty())
4604 {
4605 root = BasicJsonType(std::forward<Value>(v));
4606 return &root;
4607 }
4608
4609 assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4610
4611 if (ref_stack.back()->is_array())
4612 {
4613 ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4614 return &(ref_stack.back()->m_value.array->back());
4615 }
4616
4617 assert(ref_stack.back()->is_object());
4618 assert(object_element);
4619 *object_element = BasicJsonType(std::forward<Value>(v));
4620 return object_element;
4621 }
4622
4623 /// the parsed JSON value
4624 BasicJsonType& root;
4625 /// stack to model hierarchy of values
4626 std::vector<BasicJsonType*> ref_stack {};
4627 /// helper to hold the reference for the next object element
4628 BasicJsonType* object_element = nullptr;
4629 /// whether a syntax error occurred
4630 bool errored = false;
4631 /// whether to throw exceptions in case of errors
4632 const bool allow_exceptions = true;
4633 };
4634
4635 template<typename BasicJsonType>
4636 class json_sax_dom_callback_parser
4637 {
4638 public:
4639 using number_integer_t = typename BasicJsonType::number_integer_t;
4640 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4641 using number_float_t = typename BasicJsonType::number_float_t;
4642 using string_t = typename BasicJsonType::string_t;
4643 using parser_callback_t = typename BasicJsonType::parser_callback_t;
4644 using parse_event_t = typename BasicJsonType::parse_event_t;
4645
json_sax_dom_callback_parser(BasicJsonType & r,const parser_callback_t cb,const bool allow_exceptions_=true)4646 json_sax_dom_callback_parser(BasicJsonType& r,
4647 const parser_callback_t cb,
4648 const bool allow_exceptions_ = true)
4649 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
4650 {
4651 keep_stack.push_back(true);
4652 }
4653
4654 // make class move-only
4655 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
4656 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default;
4657 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
4658 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default;
4659 ~json_sax_dom_callback_parser() = default;
4660
null()4661 bool null()
4662 {
4663 handle_value(nullptr);
4664 return true;
4665 }
4666
boolean(bool val)4667 bool boolean(bool val)
4668 {
4669 handle_value(val);
4670 return true;
4671 }
4672
number_integer(number_integer_t val)4673 bool number_integer(number_integer_t val)
4674 {
4675 handle_value(val);
4676 return true;
4677 }
4678
number_unsigned(number_unsigned_t val)4679 bool number_unsigned(number_unsigned_t val)
4680 {
4681 handle_value(val);
4682 return true;
4683 }
4684
number_float(number_float_t val,const string_t &)4685 bool number_float(number_float_t val, const string_t& /*unused*/)
4686 {
4687 handle_value(val);
4688 return true;
4689 }
4690
string(string_t & val)4691 bool string(string_t& val)
4692 {
4693 handle_value(val);
4694 return true;
4695 }
4696
start_object(std::size_t len)4697 bool start_object(std::size_t len)
4698 {
4699 // check callback for object start
4700 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
4701 keep_stack.push_back(keep);
4702
4703 auto val = handle_value(BasicJsonType::value_t::object, true);
4704 ref_stack.push_back(val.second);
4705
4706 // check object limit
4707 if (ref_stack.back() and JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4708 {
4709 JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len)));
4710 }
4711
4712 return true;
4713 }
4714
key(string_t & val)4715 bool key(string_t& val)
4716 {
4717 BasicJsonType k = BasicJsonType(val);
4718
4719 // check callback for key
4720 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
4721 key_keep_stack.push_back(keep);
4722
4723 // add discarded value at given key and store the reference for later
4724 if (keep and ref_stack.back())
4725 {
4726 object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
4727 }
4728
4729 return true;
4730 }
4731
end_object()4732 bool end_object()
4733 {
4734 if (ref_stack.back() and not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
4735 {
4736 // discard object
4737 *ref_stack.back() = discarded;
4738 }
4739
4740 assert(not ref_stack.empty());
4741 assert(not keep_stack.empty());
4742 ref_stack.pop_back();
4743 keep_stack.pop_back();
4744
4745 if (not ref_stack.empty() and ref_stack.back() and ref_stack.back()->is_object())
4746 {
4747 // remove discarded value
4748 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
4749 {
4750 if (it->is_discarded())
4751 {
4752 ref_stack.back()->erase(it);
4753 break;
4754 }
4755 }
4756 }
4757
4758 return true;
4759 }
4760
start_array(std::size_t len)4761 bool start_array(std::size_t len)
4762 {
4763 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
4764 keep_stack.push_back(keep);
4765
4766 auto val = handle_value(BasicJsonType::value_t::array, true);
4767 ref_stack.push_back(val.second);
4768
4769 // check array limit
4770 if (ref_stack.back() and JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4771 {
4772 JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len)));
4773 }
4774
4775 return true;
4776 }
4777
end_array()4778 bool end_array()
4779 {
4780 bool keep = true;
4781
4782 if (ref_stack.back())
4783 {
4784 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
4785 if (not keep)
4786 {
4787 // discard array
4788 *ref_stack.back() = discarded;
4789 }
4790 }
4791
4792 assert(not ref_stack.empty());
4793 assert(not keep_stack.empty());
4794 ref_stack.pop_back();
4795 keep_stack.pop_back();
4796
4797 // remove discarded value
4798 if (not keep and not ref_stack.empty() and ref_stack.back()->is_array())
4799 {
4800 ref_stack.back()->m_value.array->pop_back();
4801 }
4802
4803 return true;
4804 }
4805
parse_error(std::size_t,const std::string &,const detail::exception & ex)4806 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
4807 const detail::exception& ex)
4808 {
4809 errored = true;
4810 if (allow_exceptions)
4811 {
4812 // determine the proper exception type from the id
4813 switch ((ex.id / 100) % 100)
4814 {
4815 case 1:
4816 JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
4817 case 4:
4818 JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
4819 // LCOV_EXCL_START
4820 case 2:
4821 JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
4822 case 3:
4823 JSON_THROW(*static_cast<const detail::type_error*>(&ex));
4824 case 5:
4825 JSON_THROW(*static_cast<const detail::other_error*>(&ex));
4826 default:
4827 assert(false);
4828 // LCOV_EXCL_STOP
4829 }
4830 }
4831 return false;
4832 }
4833
is_errored() const4834 constexpr bool is_errored() const
4835 {
4836 return errored;
4837 }
4838
4839 private:
4840 /*!
4841 @param[in] v value to add to the JSON value we build during parsing
4842 @param[in] skip_callback whether we should skip calling the callback
4843 function; this is required after start_array() and
4844 start_object() SAX events, because otherwise we would call the
4845 callback function with an empty array or object, respectively.
4846
4847 @invariant If the ref stack is empty, then the passed value will be the new
4848 root.
4849 @invariant If the ref stack contains a value, then it is an array or an
4850 object to which we can add elements
4851
4852 @return pair of boolean (whether value should be kept) and pointer (to the
4853 passed value in the ref_stack hierarchy; nullptr if not kept)
4854 */
4855 template<typename Value>
handle_value(Value && v,const bool skip_callback=false)4856 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
4857 {
4858 assert(not keep_stack.empty());
4859
4860 // do not handle this value if we know it would be added to a discarded
4861 // container
4862 if (not keep_stack.back())
4863 {
4864 return {false, nullptr};
4865 }
4866
4867 // create value
4868 auto value = BasicJsonType(std::forward<Value>(v));
4869
4870 // check callback
4871 const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
4872
4873 // do not handle this value if we just learnt it shall be discarded
4874 if (not keep)
4875 {
4876 return {false, nullptr};
4877 }
4878
4879 if (ref_stack.empty())
4880 {
4881 root = std::move(value);
4882 return {true, &root};
4883 }
4884
4885 // skip this value if we already decided to skip the parent
4886 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
4887 if (not ref_stack.back())
4888 {
4889 return {false, nullptr};
4890 }
4891
4892 // we now only expect arrays and objects
4893 assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4894
4895 // array
4896 if (ref_stack.back()->is_array())
4897 {
4898 ref_stack.back()->m_value.array->push_back(std::move(value));
4899 return {true, &(ref_stack.back()->m_value.array->back())};
4900 }
4901
4902 // object
4903 assert(ref_stack.back()->is_object());
4904 // check if we should store an element for the current key
4905 assert(not key_keep_stack.empty());
4906 const bool store_element = key_keep_stack.back();
4907 key_keep_stack.pop_back();
4908
4909 if (not store_element)
4910 {
4911 return {false, nullptr};
4912 }
4913
4914 assert(object_element);
4915 *object_element = std::move(value);
4916 return {true, object_element};
4917 }
4918
4919 /// the parsed JSON value
4920 BasicJsonType& root;
4921 /// stack to model hierarchy of values
4922 std::vector<BasicJsonType*> ref_stack {};
4923 /// stack to manage which values to keep
4924 std::vector<bool> keep_stack {};
4925 /// stack to manage which object keys to keep
4926 std::vector<bool> key_keep_stack {};
4927 /// helper to hold the reference for the next object element
4928 BasicJsonType* object_element = nullptr;
4929 /// whether a syntax error occurred
4930 bool errored = false;
4931 /// callback function
4932 const parser_callback_t callback = nullptr;
4933 /// whether to throw exceptions in case of errors
4934 const bool allow_exceptions = true;
4935 /// a discarded value for the callback
4936 BasicJsonType discarded = BasicJsonType::value_t::discarded;
4937 };
4938
4939 template<typename BasicJsonType>
4940 class json_sax_acceptor
4941 {
4942 public:
4943 using number_integer_t = typename BasicJsonType::number_integer_t;
4944 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4945 using number_float_t = typename BasicJsonType::number_float_t;
4946 using string_t = typename BasicJsonType::string_t;
4947
null()4948 bool null()
4949 {
4950 return true;
4951 }
4952
boolean(bool)4953 bool boolean(bool /*unused*/)
4954 {
4955 return true;
4956 }
4957
number_integer(number_integer_t)4958 bool number_integer(number_integer_t /*unused*/)
4959 {
4960 return true;
4961 }
4962
number_unsigned(number_unsigned_t)4963 bool number_unsigned(number_unsigned_t /*unused*/)
4964 {
4965 return true;
4966 }
4967
number_float(number_float_t,const string_t &)4968 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
4969 {
4970 return true;
4971 }
4972
string(string_t &)4973 bool string(string_t& /*unused*/)
4974 {
4975 return true;
4976 }
4977
start_object(std::size_t=std::size_t (-1))4978 bool start_object(std::size_t /*unused*/ = std::size_t(-1))
4979 {
4980 return true;
4981 }
4982
key(string_t &)4983 bool key(string_t& /*unused*/)
4984 {
4985 return true;
4986 }
4987
end_object()4988 bool end_object()
4989 {
4990 return true;
4991 }
4992
start_array(std::size_t=std::size_t (-1))4993 bool start_array(std::size_t /*unused*/ = std::size_t(-1))
4994 {
4995 return true;
4996 }
4997
end_array()4998 bool end_array()
4999 {
5000 return true;
5001 }
5002
parse_error(std::size_t,const std::string &,const detail::exception &)5003 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
5004 {
5005 return false;
5006 }
5007 };
5008 } // namespace detail
5009
5010 } // namespace nlohmann
5011
5012 // #include <nlohmann/detail/macro_scope.hpp>
5013
5014 // #include <nlohmann/detail/meta/is_sax.hpp>
5015
5016
5017 #include <cstdint> // size_t
5018 #include <utility> // declval
5019 #include <string> // string
5020
5021 // #include <nlohmann/detail/meta/detected.hpp>
5022
5023 // #include <nlohmann/detail/meta/type_traits.hpp>
5024
5025
5026 namespace nlohmann
5027 {
5028 namespace detail
5029 {
5030 template <typename T>
5031 using null_function_t = decltype(std::declval<T&>().null());
5032
5033 template <typename T>
5034 using boolean_function_t =
5035 decltype(std::declval<T&>().boolean(std::declval<bool>()));
5036
5037 template <typename T, typename Integer>
5038 using number_integer_function_t =
5039 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
5040
5041 template <typename T, typename Unsigned>
5042 using number_unsigned_function_t =
5043 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
5044
5045 template <typename T, typename Float, typename String>
5046 using number_float_function_t = decltype(std::declval<T&>().number_float(
5047 std::declval<Float>(), std::declval<const String&>()));
5048
5049 template <typename T, typename String>
5050 using string_function_t =
5051 decltype(std::declval<T&>().string(std::declval<String&>()));
5052
5053 template <typename T>
5054 using start_object_function_t =
5055 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
5056
5057 template <typename T, typename String>
5058 using key_function_t =
5059 decltype(std::declval<T&>().key(std::declval<String&>()));
5060
5061 template <typename T>
5062 using end_object_function_t = decltype(std::declval<T&>().end_object());
5063
5064 template <typename T>
5065 using start_array_function_t =
5066 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
5067
5068 template <typename T>
5069 using end_array_function_t = decltype(std::declval<T&>().end_array());
5070
5071 template <typename T, typename Exception>
5072 using parse_error_function_t = decltype(std::declval<T&>().parse_error(
5073 std::declval<std::size_t>(), std::declval<const std::string&>(),
5074 std::declval<const Exception&>()));
5075
5076 template <typename SAX, typename BasicJsonType>
5077 struct is_sax
5078 {
5079 private:
5080 static_assert(is_basic_json<BasicJsonType>::value,
5081 "BasicJsonType must be of type basic_json<...>");
5082
5083 using number_integer_t = typename BasicJsonType::number_integer_t;
5084 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5085 using number_float_t = typename BasicJsonType::number_float_t;
5086 using string_t = typename BasicJsonType::string_t;
5087 using exception_t = typename BasicJsonType::exception;
5088
5089 public:
5090 static constexpr bool value =
5091 is_detected_exact<bool, null_function_t, SAX>::value &&
5092 is_detected_exact<bool, boolean_function_t, SAX>::value &&
5093 is_detected_exact<bool, number_integer_function_t, SAX,
5094 number_integer_t>::value &&
5095 is_detected_exact<bool, number_unsigned_function_t, SAX,
5096 number_unsigned_t>::value &&
5097 is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
5098 string_t>::value &&
5099 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
5100 is_detected_exact<bool, start_object_function_t, SAX>::value &&
5101 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
5102 is_detected_exact<bool, end_object_function_t, SAX>::value &&
5103 is_detected_exact<bool, start_array_function_t, SAX>::value &&
5104 is_detected_exact<bool, end_array_function_t, SAX>::value &&
5105 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
5106 };
5107
5108 template <typename SAX, typename BasicJsonType>
5109 struct is_sax_static_asserts
5110 {
5111 private:
5112 static_assert(is_basic_json<BasicJsonType>::value,
5113 "BasicJsonType must be of type basic_json<...>");
5114
5115 using number_integer_t = typename BasicJsonType::number_integer_t;
5116 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5117 using number_float_t = typename BasicJsonType::number_float_t;
5118 using string_t = typename BasicJsonType::string_t;
5119 using exception_t = typename BasicJsonType::exception;
5120
5121 public:
5122 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
5123 "Missing/invalid function: bool null()");
5124 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
5125 "Missing/invalid function: bool boolean(bool)");
5126 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
5127 "Missing/invalid function: bool boolean(bool)");
5128 static_assert(
5129 is_detected_exact<bool, number_integer_function_t, SAX,
5130 number_integer_t>::value,
5131 "Missing/invalid function: bool number_integer(number_integer_t)");
5132 static_assert(
5133 is_detected_exact<bool, number_unsigned_function_t, SAX,
5134 number_unsigned_t>::value,
5135 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
5136 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
5137 number_float_t, string_t>::value,
5138 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
5139 static_assert(
5140 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
5141 "Missing/invalid function: bool string(string_t&)");
5142 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
5143 "Missing/invalid function: bool start_object(std::size_t)");
5144 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
5145 "Missing/invalid function: bool key(string_t&)");
5146 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
5147 "Missing/invalid function: bool end_object()");
5148 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
5149 "Missing/invalid function: bool start_array(std::size_t)");
5150 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
5151 "Missing/invalid function: bool end_array()");
5152 static_assert(
5153 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
5154 "Missing/invalid function: bool parse_error(std::size_t, const "
5155 "std::string&, const exception&)");
5156 };
5157 } // namespace detail
5158 } // namespace nlohmann
5159
5160 // #include <nlohmann/detail/value_t.hpp>
5161
5162
5163 namespace nlohmann
5164 {
5165 namespace detail
5166 {
5167 ///////////////////
5168 // binary reader //
5169 ///////////////////
5170
5171 /*!
5172 @brief deserialization of CBOR, MessagePack, and UBJSON values
5173 */
5174 template<typename BasicJsonType, typename SAX = json_sax_dom_parser<BasicJsonType>>
5175 class binary_reader
5176 {
5177 using number_integer_t = typename BasicJsonType::number_integer_t;
5178 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5179 using number_float_t = typename BasicJsonType::number_float_t;
5180 using string_t = typename BasicJsonType::string_t;
5181 using json_sax_t = SAX;
5182
5183 public:
5184 /*!
5185 @brief create a binary reader
5186
5187 @param[in] adapter input adapter to read from
5188 */
binary_reader(input_adapter_t adapter)5189 explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
5190 {
5191 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
5192 assert(ia);
5193 }
5194
5195 // make class move-only
5196 binary_reader(const binary_reader&) = delete;
5197 binary_reader(binary_reader&&) = default;
5198 binary_reader& operator=(const binary_reader&) = delete;
5199 binary_reader& operator=(binary_reader&&) = default;
5200 ~binary_reader() = default;
5201
5202 /*!
5203 @param[in] format the binary format to parse
5204 @param[in] sax_ a SAX event processor
5205 @param[in] strict whether to expect the input to be consumed completed
5206
5207 @return
5208 */
5209 JSON_HEDLEY_NON_NULL(3)
sax_parse(const input_format_t format,json_sax_t * sax_,const bool strict=true)5210 bool sax_parse(const input_format_t format,
5211 json_sax_t* sax_,
5212 const bool strict = true)
5213 {
5214 sax = sax_;
5215 bool result = false;
5216
5217 switch (format)
5218 {
5219 case input_format_t::bson:
5220 result = parse_bson_internal();
5221 break;
5222
5223 case input_format_t::cbor:
5224 result = parse_cbor_internal();
5225 break;
5226
5227 case input_format_t::msgpack:
5228 result = parse_msgpack_internal();
5229 break;
5230
5231 case input_format_t::ubjson:
5232 result = parse_ubjson_internal();
5233 break;
5234
5235 default: // LCOV_EXCL_LINE
5236 assert(false); // LCOV_EXCL_LINE
5237 }
5238
5239 // strict mode: next byte must be EOF
5240 if (result and strict)
5241 {
5242 if (format == input_format_t::ubjson)
5243 {
5244 get_ignore_noop();
5245 }
5246 else
5247 {
5248 get();
5249 }
5250
5251 if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char>::eof()))
5252 {
5253 return sax->parse_error(chars_read, get_token_string(),
5254 parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value")));
5255 }
5256 }
5257
5258 return result;
5259 }
5260
5261 /*!
5262 @brief determine system byte order
5263
5264 @return true if and only if system's byte order is little endian
5265
5266 @note from http://stackoverflow.com/a/1001328/266378
5267 */
little_endianess(int num=1)5268 static constexpr bool little_endianess(int num = 1) noexcept
5269 {
5270 return *reinterpret_cast<char*>(&num) == 1;
5271 }
5272
5273 private:
5274 //////////
5275 // BSON //
5276 //////////
5277
5278 /*!
5279 @brief Reads in a BSON-object and passes it to the SAX-parser.
5280 @return whether a valid BSON-value was passed to the SAX parser
5281 */
parse_bson_internal()5282 bool parse_bson_internal()
5283 {
5284 std::int32_t document_size;
5285 get_number<std::int32_t, true>(input_format_t::bson, document_size);
5286
5287 if (JSON_HEDLEY_UNLIKELY(not sax->start_object(std::size_t(-1))))
5288 {
5289 return false;
5290 }
5291
5292 if (JSON_HEDLEY_UNLIKELY(not parse_bson_element_list(/*is_array*/false)))
5293 {
5294 return false;
5295 }
5296
5297 return sax->end_object();
5298 }
5299
5300 /*!
5301 @brief Parses a C-style string from the BSON input.
5302 @param[in, out] result A reference to the string variable where the read
5303 string is to be stored.
5304 @return `true` if the \x00-byte indicating the end of the string was
5305 encountered before the EOF; false` indicates an unexpected EOF.
5306 */
get_bson_cstr(string_t & result)5307 bool get_bson_cstr(string_t& result)
5308 {
5309 auto out = std::back_inserter(result);
5310 while (true)
5311 {
5312 get();
5313 if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::bson, "cstring")))
5314 {
5315 return false;
5316 }
5317 if (current == 0x00)
5318 {
5319 return true;
5320 }
5321 *out++ = static_cast<char>(current);
5322 }
5323
5324 return true;
5325 }
5326
5327 /*!
5328 @brief Parses a zero-terminated string of length @a len from the BSON
5329 input.
5330 @param[in] len The length (including the zero-byte at the end) of the
5331 string to be read.
5332 @param[in, out] result A reference to the string variable where the read
5333 string is to be stored.
5334 @tparam NumberType The type of the length @a len
5335 @pre len >= 1
5336 @return `true` if the string was successfully parsed
5337 */
5338 template<typename NumberType>
get_bson_string(const NumberType len,string_t & result)5339 bool get_bson_string(const NumberType len, string_t& result)
5340 {
5341 if (JSON_HEDLEY_UNLIKELY(len < 1))
5342 {
5343 auto last_token = get_token_string();
5344 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string")));
5345 }
5346
5347 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) and get() != std::char_traits<char>::eof();
5348 }
5349
5350 /*!
5351 @brief Read a BSON document element of the given @a element_type.
5352 @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
5353 @param[in] element_type_parse_position The position in the input stream,
5354 where the `element_type` was read.
5355 @warning Not all BSON element types are supported yet. An unsupported
5356 @a element_type will give rise to a parse_error.114:
5357 Unsupported BSON record type 0x...
5358 @return whether a valid BSON-object/array was passed to the SAX parser
5359 */
parse_bson_element_internal(const int element_type,const std::size_t element_type_parse_position)5360 bool parse_bson_element_internal(const int element_type,
5361 const std::size_t element_type_parse_position)
5362 {
5363 switch (element_type)
5364 {
5365 case 0x01: // double
5366 {
5367 double number;
5368 return get_number<double, true>(input_format_t::bson, number) and sax->number_float(static_cast<number_float_t>(number), "");
5369 }
5370
5371 case 0x02: // string
5372 {
5373 std::int32_t len;
5374 string_t value;
5375 return get_number<std::int32_t, true>(input_format_t::bson, len) and get_bson_string(len, value) and sax->string(value);
5376 }
5377
5378 case 0x03: // object
5379 {
5380 return parse_bson_internal();
5381 }
5382
5383 case 0x04: // array
5384 {
5385 return parse_bson_array();
5386 }
5387
5388 case 0x08: // boolean
5389 {
5390 return sax->boolean(get() != 0);
5391 }
5392
5393 case 0x0A: // null
5394 {
5395 return sax->null();
5396 }
5397
5398 case 0x10: // int32
5399 {
5400 std::int32_t value;
5401 return get_number<std::int32_t, true>(input_format_t::bson, value) and sax->number_integer(value);
5402 }
5403
5404 case 0x12: // int64
5405 {
5406 std::int64_t value;
5407 return get_number<std::int64_t, true>(input_format_t::bson, value) and sax->number_integer(value);
5408 }
5409
5410 default: // anything else not supported (yet)
5411 {
5412 std::array<char, 3> cr{{}};
5413 (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type));
5414 return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data())));
5415 }
5416 }
5417 }
5418
5419 /*!
5420 @brief Read a BSON element list (as specified in the BSON-spec)
5421
5422 The same binary layout is used for objects and arrays, hence it must be
5423 indicated with the argument @a is_array which one is expected
5424 (true --> array, false --> object).
5425
5426 @param[in] is_array Determines if the element list being read is to be
5427 treated as an object (@a is_array == false), or as an
5428 array (@a is_array == true).
5429 @return whether a valid BSON-object/array was passed to the SAX parser
5430 */
parse_bson_element_list(const bool is_array)5431 bool parse_bson_element_list(const bool is_array)
5432 {
5433 string_t key;
5434 while (int element_type = get())
5435 {
5436 if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::bson, "element list")))
5437 {
5438 return false;
5439 }
5440
5441 const std::size_t element_type_parse_position = chars_read;
5442 if (JSON_HEDLEY_UNLIKELY(not get_bson_cstr(key)))
5443 {
5444 return false;
5445 }
5446
5447 if (not is_array and not sax->key(key))
5448 {
5449 return false;
5450 }
5451
5452 if (JSON_HEDLEY_UNLIKELY(not parse_bson_element_internal(element_type, element_type_parse_position)))
5453 {
5454 return false;
5455 }
5456
5457 // get_bson_cstr only appends
5458 key.clear();
5459 }
5460
5461 return true;
5462 }
5463
5464 /*!
5465 @brief Reads an array from the BSON input and passes it to the SAX-parser.
5466 @return whether a valid BSON-array was passed to the SAX parser
5467 */
parse_bson_array()5468 bool parse_bson_array()
5469 {
5470 std::int32_t document_size;
5471 get_number<std::int32_t, true>(input_format_t::bson, document_size);
5472
5473 if (JSON_HEDLEY_UNLIKELY(not sax->start_array(std::size_t(-1))))
5474 {
5475 return false;
5476 }
5477
5478 if (JSON_HEDLEY_UNLIKELY(not parse_bson_element_list(/*is_array*/true)))
5479 {
5480 return false;
5481 }
5482
5483 return sax->end_array();
5484 }
5485
5486 //////////
5487 // CBOR //
5488 //////////
5489
5490 /*!
5491 @param[in] get_char whether a new character should be retrieved from the
5492 input (true, default) or whether the last read
5493 character should be considered instead
5494
5495 @return whether a valid CBOR value was passed to the SAX parser
5496 */
parse_cbor_internal(const bool get_char=true)5497 bool parse_cbor_internal(const bool get_char = true)
5498 {
5499 switch (get_char ? get() : current)
5500 {
5501 // EOF
5502 case std::char_traits<char>::eof():
5503 return unexpect_eof(input_format_t::cbor, "value");
5504
5505 // Integer 0x00..0x17 (0..23)
5506 case 0x00:
5507 case 0x01:
5508 case 0x02:
5509 case 0x03:
5510 case 0x04:
5511 case 0x05:
5512 case 0x06:
5513 case 0x07:
5514 case 0x08:
5515 case 0x09:
5516 case 0x0A:
5517 case 0x0B:
5518 case 0x0C:
5519 case 0x0D:
5520 case 0x0E:
5521 case 0x0F:
5522 case 0x10:
5523 case 0x11:
5524 case 0x12:
5525 case 0x13:
5526 case 0x14:
5527 case 0x15:
5528 case 0x16:
5529 case 0x17:
5530 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
5531
5532 case 0x18: // Unsigned integer (one-byte uint8_t follows)
5533 {
5534 std::uint8_t number;
5535 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
5536 }
5537
5538 case 0x19: // Unsigned integer (two-byte uint16_t follows)
5539 {
5540 std::uint16_t number;
5541 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
5542 }
5543
5544 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
5545 {
5546 std::uint32_t number;
5547 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
5548 }
5549
5550 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
5551 {
5552 std::uint64_t number;
5553 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
5554 }
5555
5556 // Negative integer -1-0x00..-1-0x17 (-1..-24)
5557 case 0x20:
5558 case 0x21:
5559 case 0x22:
5560 case 0x23:
5561 case 0x24:
5562 case 0x25:
5563 case 0x26:
5564 case 0x27:
5565 case 0x28:
5566 case 0x29:
5567 case 0x2A:
5568 case 0x2B:
5569 case 0x2C:
5570 case 0x2D:
5571 case 0x2E:
5572 case 0x2F:
5573 case 0x30:
5574 case 0x31:
5575 case 0x32:
5576 case 0x33:
5577 case 0x34:
5578 case 0x35:
5579 case 0x36:
5580 case 0x37:
5581 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
5582
5583 case 0x38: // Negative integer (one-byte uint8_t follows)
5584 {
5585 std::uint8_t number;
5586 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
5587 }
5588
5589 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
5590 {
5591 std::uint16_t number;
5592 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
5593 }
5594
5595 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
5596 {
5597 std::uint32_t number;
5598 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
5599 }
5600
5601 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
5602 {
5603 std::uint64_t number;
5604 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1)
5605 - static_cast<number_integer_t>(number));
5606 }
5607
5608 // UTF-8 string (0x00..0x17 bytes follow)
5609 case 0x60:
5610 case 0x61:
5611 case 0x62:
5612 case 0x63:
5613 case 0x64:
5614 case 0x65:
5615 case 0x66:
5616 case 0x67:
5617 case 0x68:
5618 case 0x69:
5619 case 0x6A:
5620 case 0x6B:
5621 case 0x6C:
5622 case 0x6D:
5623 case 0x6E:
5624 case 0x6F:
5625 case 0x70:
5626 case 0x71:
5627 case 0x72:
5628 case 0x73:
5629 case 0x74:
5630 case 0x75:
5631 case 0x76:
5632 case 0x77:
5633 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
5634 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
5635 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
5636 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
5637 case 0x7F: // UTF-8 string (indefinite length)
5638 {
5639 string_t s;
5640 return get_cbor_string(s) and sax->string(s);
5641 }
5642
5643 // array (0x00..0x17 data items follow)
5644 case 0x80:
5645 case 0x81:
5646 case 0x82:
5647 case 0x83:
5648 case 0x84:
5649 case 0x85:
5650 case 0x86:
5651 case 0x87:
5652 case 0x88:
5653 case 0x89:
5654 case 0x8A:
5655 case 0x8B:
5656 case 0x8C:
5657 case 0x8D:
5658 case 0x8E:
5659 case 0x8F:
5660 case 0x90:
5661 case 0x91:
5662 case 0x92:
5663 case 0x93:
5664 case 0x94:
5665 case 0x95:
5666 case 0x96:
5667 case 0x97:
5668 return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
5669
5670 case 0x98: // array (one-byte uint8_t for n follows)
5671 {
5672 std::uint8_t len;
5673 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
5674 }
5675
5676 case 0x99: // array (two-byte uint16_t for n follow)
5677 {
5678 std::uint16_t len;
5679 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
5680 }
5681
5682 case 0x9A: // array (four-byte uint32_t for n follow)
5683 {
5684 std::uint32_t len;
5685 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
5686 }
5687
5688 case 0x9B: // array (eight-byte uint64_t for n follow)
5689 {
5690 std::uint64_t len;
5691 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
5692 }
5693
5694 case 0x9F: // array (indefinite length)
5695 return get_cbor_array(std::size_t(-1));
5696
5697 // map (0x00..0x17 pairs of data items follow)
5698 case 0xA0:
5699 case 0xA1:
5700 case 0xA2:
5701 case 0xA3:
5702 case 0xA4:
5703 case 0xA5:
5704 case 0xA6:
5705 case 0xA7:
5706 case 0xA8:
5707 case 0xA9:
5708 case 0xAA:
5709 case 0xAB:
5710 case 0xAC:
5711 case 0xAD:
5712 case 0xAE:
5713 case 0xAF:
5714 case 0xB0:
5715 case 0xB1:
5716 case 0xB2:
5717 case 0xB3:
5718 case 0xB4:
5719 case 0xB5:
5720 case 0xB6:
5721 case 0xB7:
5722 return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
5723
5724 case 0xB8: // map (one-byte uint8_t for n follows)
5725 {
5726 std::uint8_t len;
5727 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
5728 }
5729
5730 case 0xB9: // map (two-byte uint16_t for n follow)
5731 {
5732 std::uint16_t len;
5733 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
5734 }
5735
5736 case 0xBA: // map (four-byte uint32_t for n follow)
5737 {
5738 std::uint32_t len;
5739 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
5740 }
5741
5742 case 0xBB: // map (eight-byte uint64_t for n follow)
5743 {
5744 std::uint64_t len;
5745 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
5746 }
5747
5748 case 0xBF: // map (indefinite length)
5749 return get_cbor_object(std::size_t(-1));
5750
5751 case 0xF4: // false
5752 return sax->boolean(false);
5753
5754 case 0xF5: // true
5755 return sax->boolean(true);
5756
5757 case 0xF6: // null
5758 return sax->null();
5759
5760 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
5761 {
5762 const int byte1_raw = get();
5763 if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number")))
5764 {
5765 return false;
5766 }
5767 const int byte2_raw = get();
5768 if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number")))
5769 {
5770 return false;
5771 }
5772
5773 const auto byte1 = static_cast<unsigned char>(byte1_raw);
5774 const auto byte2 = static_cast<unsigned char>(byte2_raw);
5775
5776 // code from RFC 7049, Appendix D, Figure 3:
5777 // As half-precision floating-point numbers were only added
5778 // to IEEE 754 in 2008, today's programming platforms often
5779 // still only have limited support for them. It is very
5780 // easy to include at least decoding support for them even
5781 // without such support. An example of a small decoder for
5782 // half-precision floating-point numbers in the C language
5783 // is shown in Fig. 3.
5784 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
5785 const double val = [&half]
5786 {
5787 const int exp = (half >> 10u) & 0x1Fu;
5788 const unsigned int mant = half & 0x3FFu;
5789 assert(0 <= exp and exp <= 32);
5790 assert(mant <= 1024);
5791 switch (exp)
5792 {
5793 case 0:
5794 return std::ldexp(mant, -24);
5795 case 31:
5796 return (mant == 0)
5797 ? std::numeric_limits<double>::infinity()
5798 : std::numeric_limits<double>::quiet_NaN();
5799 default:
5800 return std::ldexp(mant + 1024, exp - 25);
5801 }
5802 }();
5803 return sax->number_float((half & 0x8000u) != 0
5804 ? static_cast<number_float_t>(-val)
5805 : static_cast<number_float_t>(val), "");
5806 }
5807
5808 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
5809 {
5810 float number;
5811 return get_number(input_format_t::cbor, number) and sax->number_float(static_cast<number_float_t>(number), "");
5812 }
5813
5814 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
5815 {
5816 double number;
5817 return get_number(input_format_t::cbor, number) and sax->number_float(static_cast<number_float_t>(number), "");
5818 }
5819
5820 default: // anything else (0xFF is handled inside the other types)
5821 {
5822 auto last_token = get_token_string();
5823 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value")));
5824 }
5825 }
5826 }
5827
5828 /*!
5829 @brief reads a CBOR string
5830
5831 This function first reads starting bytes to determine the expected
5832 string length and then copies this number of bytes into a string.
5833 Additionally, CBOR's strings with indefinite lengths are supported.
5834
5835 @param[out] result created string
5836
5837 @return whether string creation completed
5838 */
get_cbor_string(string_t & result)5839 bool get_cbor_string(string_t& result)
5840 {
5841 if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::cbor, "string")))
5842 {
5843 return false;
5844 }
5845
5846 switch (current)
5847 {
5848 // UTF-8 string (0x00..0x17 bytes follow)
5849 case 0x60:
5850 case 0x61:
5851 case 0x62:
5852 case 0x63:
5853 case 0x64:
5854 case 0x65:
5855 case 0x66:
5856 case 0x67:
5857 case 0x68:
5858 case 0x69:
5859 case 0x6A:
5860 case 0x6B:
5861 case 0x6C:
5862 case 0x6D:
5863 case 0x6E:
5864 case 0x6F:
5865 case 0x70:
5866 case 0x71:
5867 case 0x72:
5868 case 0x73:
5869 case 0x74:
5870 case 0x75:
5871 case 0x76:
5872 case 0x77:
5873 {
5874 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
5875 }
5876
5877 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
5878 {
5879 std::uint8_t len;
5880 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
5881 }
5882
5883 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
5884 {
5885 std::uint16_t len;
5886 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
5887 }
5888
5889 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
5890 {
5891 std::uint32_t len;
5892 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
5893 }
5894
5895 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
5896 {
5897 std::uint64_t len;
5898 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
5899 }
5900
5901 case 0x7F: // UTF-8 string (indefinite length)
5902 {
5903 while (get() != 0xFF)
5904 {
5905 string_t chunk;
5906 if (not get_cbor_string(chunk))
5907 {
5908 return false;
5909 }
5910 result.append(chunk);
5911 }
5912 return true;
5913 }
5914
5915 default:
5916 {
5917 auto last_token = get_token_string();
5918 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string")));
5919 }
5920 }
5921 }
5922
5923 /*!
5924 @param[in] len the length of the array or std::size_t(-1) for an
5925 array of indefinite size
5926 @return whether array creation completed
5927 */
get_cbor_array(const std::size_t len)5928 bool get_cbor_array(const std::size_t len)
5929 {
5930 if (JSON_HEDLEY_UNLIKELY(not sax->start_array(len)))
5931 {
5932 return false;
5933 }
5934
5935 if (len != std::size_t(-1))
5936 {
5937 for (std::size_t i = 0; i < len; ++i)
5938 {
5939 if (JSON_HEDLEY_UNLIKELY(not parse_cbor_internal()))
5940 {
5941 return false;
5942 }
5943 }
5944 }
5945 else
5946 {
5947 while (get() != 0xFF)
5948 {
5949 if (JSON_HEDLEY_UNLIKELY(not parse_cbor_internal(false)))
5950 {
5951 return false;
5952 }
5953 }
5954 }
5955
5956 return sax->end_array();
5957 }
5958
5959 /*!
5960 @param[in] len the length of the object or std::size_t(-1) for an
5961 object of indefinite size
5962 @return whether object creation completed
5963 */
get_cbor_object(const std::size_t len)5964 bool get_cbor_object(const std::size_t len)
5965 {
5966 if (JSON_HEDLEY_UNLIKELY(not sax->start_object(len)))
5967 {
5968 return false;
5969 }
5970
5971 string_t key;
5972 if (len != std::size_t(-1))
5973 {
5974 for (std::size_t i = 0; i < len; ++i)
5975 {
5976 get();
5977 if (JSON_HEDLEY_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
5978 {
5979 return false;
5980 }
5981
5982 if (JSON_HEDLEY_UNLIKELY(not parse_cbor_internal()))
5983 {
5984 return false;
5985 }
5986 key.clear();
5987 }
5988 }
5989 else
5990 {
5991 while (get() != 0xFF)
5992 {
5993 if (JSON_HEDLEY_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
5994 {
5995 return false;
5996 }
5997
5998 if (JSON_HEDLEY_UNLIKELY(not parse_cbor_internal()))
5999 {
6000 return false;
6001 }
6002 key.clear();
6003 }
6004 }
6005
6006 return sax->end_object();
6007 }
6008
6009 /////////////
6010 // MsgPack //
6011 /////////////
6012
6013 /*!
6014 @return whether a valid MessagePack value was passed to the SAX parser
6015 */
parse_msgpack_internal()6016 bool parse_msgpack_internal()
6017 {
6018 switch (get())
6019 {
6020 // EOF
6021 case std::char_traits<char>::eof():
6022 return unexpect_eof(input_format_t::msgpack, "value");
6023
6024 // positive fixint
6025 case 0x00:
6026 case 0x01:
6027 case 0x02:
6028 case 0x03:
6029 case 0x04:
6030 case 0x05:
6031 case 0x06:
6032 case 0x07:
6033 case 0x08:
6034 case 0x09:
6035 case 0x0A:
6036 case 0x0B:
6037 case 0x0C:
6038 case 0x0D:
6039 case 0x0E:
6040 case 0x0F:
6041 case 0x10:
6042 case 0x11:
6043 case 0x12:
6044 case 0x13:
6045 case 0x14:
6046 case 0x15:
6047 case 0x16:
6048 case 0x17:
6049 case 0x18:
6050 case 0x19:
6051 case 0x1A:
6052 case 0x1B:
6053 case 0x1C:
6054 case 0x1D:
6055 case 0x1E:
6056 case 0x1F:
6057 case 0x20:
6058 case 0x21:
6059 case 0x22:
6060 case 0x23:
6061 case 0x24:
6062 case 0x25:
6063 case 0x26:
6064 case 0x27:
6065 case 0x28:
6066 case 0x29:
6067 case 0x2A:
6068 case 0x2B:
6069 case 0x2C:
6070 case 0x2D:
6071 case 0x2E:
6072 case 0x2F:
6073 case 0x30:
6074 case 0x31:
6075 case 0x32:
6076 case 0x33:
6077 case 0x34:
6078 case 0x35:
6079 case 0x36:
6080 case 0x37:
6081 case 0x38:
6082 case 0x39:
6083 case 0x3A:
6084 case 0x3B:
6085 case 0x3C:
6086 case 0x3D:
6087 case 0x3E:
6088 case 0x3F:
6089 case 0x40:
6090 case 0x41:
6091 case 0x42:
6092 case 0x43:
6093 case 0x44:
6094 case 0x45:
6095 case 0x46:
6096 case 0x47:
6097 case 0x48:
6098 case 0x49:
6099 case 0x4A:
6100 case 0x4B:
6101 case 0x4C:
6102 case 0x4D:
6103 case 0x4E:
6104 case 0x4F:
6105 case 0x50:
6106 case 0x51:
6107 case 0x52:
6108 case 0x53:
6109 case 0x54:
6110 case 0x55:
6111 case 0x56:
6112 case 0x57:
6113 case 0x58:
6114 case 0x59:
6115 case 0x5A:
6116 case 0x5B:
6117 case 0x5C:
6118 case 0x5D:
6119 case 0x5E:
6120 case 0x5F:
6121 case 0x60:
6122 case 0x61:
6123 case 0x62:
6124 case 0x63:
6125 case 0x64:
6126 case 0x65:
6127 case 0x66:
6128 case 0x67:
6129 case 0x68:
6130 case 0x69:
6131 case 0x6A:
6132 case 0x6B:
6133 case 0x6C:
6134 case 0x6D:
6135 case 0x6E:
6136 case 0x6F:
6137 case 0x70:
6138 case 0x71:
6139 case 0x72:
6140 case 0x73:
6141 case 0x74:
6142 case 0x75:
6143 case 0x76:
6144 case 0x77:
6145 case 0x78:
6146 case 0x79:
6147 case 0x7A:
6148 case 0x7B:
6149 case 0x7C:
6150 case 0x7D:
6151 case 0x7E:
6152 case 0x7F:
6153 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
6154
6155 // fixmap
6156 case 0x80:
6157 case 0x81:
6158 case 0x82:
6159 case 0x83:
6160 case 0x84:
6161 case 0x85:
6162 case 0x86:
6163 case 0x87:
6164 case 0x88:
6165 case 0x89:
6166 case 0x8A:
6167 case 0x8B:
6168 case 0x8C:
6169 case 0x8D:
6170 case 0x8E:
6171 case 0x8F:
6172 return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
6173
6174 // fixarray
6175 case 0x90:
6176 case 0x91:
6177 case 0x92:
6178 case 0x93:
6179 case 0x94:
6180 case 0x95:
6181 case 0x96:
6182 case 0x97:
6183 case 0x98:
6184 case 0x99:
6185 case 0x9A:
6186 case 0x9B:
6187 case 0x9C:
6188 case 0x9D:
6189 case 0x9E:
6190 case 0x9F:
6191 return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
6192
6193 // fixstr
6194 case 0xA0:
6195 case 0xA1:
6196 case 0xA2:
6197 case 0xA3:
6198 case 0xA4:
6199 case 0xA5:
6200 case 0xA6:
6201 case 0xA7:
6202 case 0xA8:
6203 case 0xA9:
6204 case 0xAA:
6205 case 0xAB:
6206 case 0xAC:
6207 case 0xAD:
6208 case 0xAE:
6209 case 0xAF:
6210 case 0xB0:
6211 case 0xB1:
6212 case 0xB2:
6213 case 0xB3:
6214 case 0xB4:
6215 case 0xB5:
6216 case 0xB6:
6217 case 0xB7:
6218 case 0xB8:
6219 case 0xB9:
6220 case 0xBA:
6221 case 0xBB:
6222 case 0xBC:
6223 case 0xBD:
6224 case 0xBE:
6225 case 0xBF:
6226 case 0xD9: // str 8
6227 case 0xDA: // str 16
6228 case 0xDB: // str 32
6229 {
6230 string_t s;
6231 return get_msgpack_string(s) and sax->string(s);
6232 }
6233
6234 case 0xC0: // nil
6235 return sax->null();
6236
6237 case 0xC2: // false
6238 return sax->boolean(false);
6239
6240 case 0xC3: // true
6241 return sax->boolean(true);
6242
6243 case 0xCA: // float 32
6244 {
6245 float number;
6246 return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast<number_float_t>(number), "");
6247 }
6248
6249 case 0xCB: // float 64
6250 {
6251 double number;
6252 return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast<number_float_t>(number), "");
6253 }
6254
6255 case 0xCC: // uint 8
6256 {
6257 std::uint8_t number;
6258 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
6259 }
6260
6261 case 0xCD: // uint 16
6262 {
6263 std::uint16_t number;
6264 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
6265 }
6266
6267 case 0xCE: // uint 32
6268 {
6269 std::uint32_t number;
6270 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
6271 }
6272
6273 case 0xCF: // uint 64
6274 {
6275 std::uint64_t number;
6276 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
6277 }
6278
6279 case 0xD0: // int 8
6280 {
6281 std::int8_t number;
6282 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
6283 }
6284
6285 case 0xD1: // int 16
6286 {
6287 std::int16_t number;
6288 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
6289 }
6290
6291 case 0xD2: // int 32
6292 {
6293 std::int32_t number;
6294 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
6295 }
6296
6297 case 0xD3: // int 64
6298 {
6299 std::int64_t number;
6300 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
6301 }
6302
6303 case 0xDC: // array 16
6304 {
6305 std::uint16_t len;
6306 return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
6307 }
6308
6309 case 0xDD: // array 32
6310 {
6311 std::uint32_t len;
6312 return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
6313 }
6314
6315 case 0xDE: // map 16
6316 {
6317 std::uint16_t len;
6318 return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
6319 }
6320
6321 case 0xDF: // map 32
6322 {
6323 std::uint32_t len;
6324 return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
6325 }
6326
6327 // negative fixint
6328 case 0xE0:
6329 case 0xE1:
6330 case 0xE2:
6331 case 0xE3:
6332 case 0xE4:
6333 case 0xE5:
6334 case 0xE6:
6335 case 0xE7:
6336 case 0xE8:
6337 case 0xE9:
6338 case 0xEA:
6339 case 0xEB:
6340 case 0xEC:
6341 case 0xED:
6342 case 0xEE:
6343 case 0xEF:
6344 case 0xF0:
6345 case 0xF1:
6346 case 0xF2:
6347 case 0xF3:
6348 case 0xF4:
6349 case 0xF5:
6350 case 0xF6:
6351 case 0xF7:
6352 case 0xF8:
6353 case 0xF9:
6354 case 0xFA:
6355 case 0xFB:
6356 case 0xFC:
6357 case 0xFD:
6358 case 0xFE:
6359 case 0xFF:
6360 return sax->number_integer(static_cast<std::int8_t>(current));
6361
6362 default: // anything else
6363 {
6364 auto last_token = get_token_string();
6365 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value")));
6366 }
6367 }
6368 }
6369
6370 /*!
6371 @brief reads a MessagePack string
6372
6373 This function first reads starting bytes to determine the expected
6374 string length and then copies this number of bytes into a string.
6375
6376 @param[out] result created string
6377
6378 @return whether string creation completed
6379 */
get_msgpack_string(string_t & result)6380 bool get_msgpack_string(string_t& result)
6381 {
6382 if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::msgpack, "string")))
6383 {
6384 return false;
6385 }
6386
6387 switch (current)
6388 {
6389 // fixstr
6390 case 0xA0:
6391 case 0xA1:
6392 case 0xA2:
6393 case 0xA3:
6394 case 0xA4:
6395 case 0xA5:
6396 case 0xA6:
6397 case 0xA7:
6398 case 0xA8:
6399 case 0xA9:
6400 case 0xAA:
6401 case 0xAB:
6402 case 0xAC:
6403 case 0xAD:
6404 case 0xAE:
6405 case 0xAF:
6406 case 0xB0:
6407 case 0xB1:
6408 case 0xB2:
6409 case 0xB3:
6410 case 0xB4:
6411 case 0xB5:
6412 case 0xB6:
6413 case 0xB7:
6414 case 0xB8:
6415 case 0xB9:
6416 case 0xBA:
6417 case 0xBB:
6418 case 0xBC:
6419 case 0xBD:
6420 case 0xBE:
6421 case 0xBF:
6422 {
6423 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
6424 }
6425
6426 case 0xD9: // str 8
6427 {
6428 std::uint8_t len;
6429 return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
6430 }
6431
6432 case 0xDA: // str 16
6433 {
6434 std::uint16_t len;
6435 return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
6436 }
6437
6438 case 0xDB: // str 32
6439 {
6440 std::uint32_t len;
6441 return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
6442 }
6443
6444 default:
6445 {
6446 auto last_token = get_token_string();
6447 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string")));
6448 }
6449 }
6450 }
6451
6452 /*!
6453 @param[in] len the length of the array
6454 @return whether array creation completed
6455 */
get_msgpack_array(const std::size_t len)6456 bool get_msgpack_array(const std::size_t len)
6457 {
6458 if (JSON_HEDLEY_UNLIKELY(not sax->start_array(len)))
6459 {
6460 return false;
6461 }
6462
6463 for (std::size_t i = 0; i < len; ++i)
6464 {
6465 if (JSON_HEDLEY_UNLIKELY(not parse_msgpack_internal()))
6466 {
6467 return false;
6468 }
6469 }
6470
6471 return sax->end_array();
6472 }
6473
6474 /*!
6475 @param[in] len the length of the object
6476 @return whether object creation completed
6477 */
get_msgpack_object(const std::size_t len)6478 bool get_msgpack_object(const std::size_t len)
6479 {
6480 if (JSON_HEDLEY_UNLIKELY(not sax->start_object(len)))
6481 {
6482 return false;
6483 }
6484
6485 string_t key;
6486 for (std::size_t i = 0; i < len; ++i)
6487 {
6488 get();
6489 if (JSON_HEDLEY_UNLIKELY(not get_msgpack_string(key) or not sax->key(key)))
6490 {
6491 return false;
6492 }
6493
6494 if (JSON_HEDLEY_UNLIKELY(not parse_msgpack_internal()))
6495 {
6496 return false;
6497 }
6498 key.clear();
6499 }
6500
6501 return sax->end_object();
6502 }
6503
6504 ////////////
6505 // UBJSON //
6506 ////////////
6507
6508 /*!
6509 @param[in] get_char whether a new character should be retrieved from the
6510 input (true, default) or whether the last read
6511 character should be considered instead
6512
6513 @return whether a valid UBJSON value was passed to the SAX parser
6514 */
parse_ubjson_internal(const bool get_char=true)6515 bool parse_ubjson_internal(const bool get_char = true)
6516 {
6517 return get_ubjson_value(get_char ? get_ignore_noop() : current);
6518 }
6519
6520 /*!
6521 @brief reads a UBJSON string
6522
6523 This function is either called after reading the 'S' byte explicitly
6524 indicating a string, or in case of an object key where the 'S' byte can be
6525 left out.
6526
6527 @param[out] result created string
6528 @param[in] get_char whether a new character should be retrieved from the
6529 input (true, default) or whether the last read
6530 character should be considered instead
6531
6532 @return whether string creation completed
6533 */
get_ubjson_string(string_t & result,const bool get_char=true)6534 bool get_ubjson_string(string_t& result, const bool get_char = true)
6535 {
6536 if (get_char)
6537 {
6538 get(); // TODO(niels): may we ignore N here?
6539 }
6540
6541 if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
6542 {
6543 return false;
6544 }
6545
6546 switch (current)
6547 {
6548 case 'U':
6549 {
6550 std::uint8_t len;
6551 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
6552 }
6553
6554 case 'i':
6555 {
6556 std::int8_t len;
6557 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
6558 }
6559
6560 case 'I':
6561 {
6562 std::int16_t len;
6563 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
6564 }
6565
6566 case 'l':
6567 {
6568 std::int32_t len;
6569 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
6570 }
6571
6572 case 'L':
6573 {
6574 std::int64_t len;
6575 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
6576 }
6577
6578 default:
6579 auto last_token = get_token_string();
6580 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string")));
6581 }
6582 }
6583
6584 /*!
6585 @param[out] result determined size
6586 @return whether size determination completed
6587 */
get_ubjson_size_value(std::size_t & result)6588 bool get_ubjson_size_value(std::size_t& result)
6589 {
6590 switch (get_ignore_noop())
6591 {
6592 case 'U':
6593 {
6594 std::uint8_t number;
6595 if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number)))
6596 {
6597 return false;
6598 }
6599 result = static_cast<std::size_t>(number);
6600 return true;
6601 }
6602
6603 case 'i':
6604 {
6605 std::int8_t number;
6606 if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number)))
6607 {
6608 return false;
6609 }
6610 result = static_cast<std::size_t>(number);
6611 return true;
6612 }
6613
6614 case 'I':
6615 {
6616 std::int16_t number;
6617 if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number)))
6618 {
6619 return false;
6620 }
6621 result = static_cast<std::size_t>(number);
6622 return true;
6623 }
6624
6625 case 'l':
6626 {
6627 std::int32_t number;
6628 if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number)))
6629 {
6630 return false;
6631 }
6632 result = static_cast<std::size_t>(number);
6633 return true;
6634 }
6635
6636 case 'L':
6637 {
6638 std::int64_t number;
6639 if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number)))
6640 {
6641 return false;
6642 }
6643 result = static_cast<std::size_t>(number);
6644 return true;
6645 }
6646
6647 default:
6648 {
6649 auto last_token = get_token_string();
6650 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size")));
6651 }
6652 }
6653 }
6654
6655 /*!
6656 @brief determine the type and size for a container
6657
6658 In the optimized UBJSON format, a type and a size can be provided to allow
6659 for a more compact representation.
6660
6661 @param[out] result pair of the size and the type
6662
6663 @return whether pair creation completed
6664 */
get_ubjson_size_type(std::pair<std::size_t,int> & result)6665 bool get_ubjson_size_type(std::pair<std::size_t, int>& result)
6666 {
6667 result.first = string_t::npos; // size
6668 result.second = 0; // type
6669
6670 get_ignore_noop();
6671
6672 if (current == '$')
6673 {
6674 result.second = get(); // must not ignore 'N', because 'N' maybe the type
6675 if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "type")))
6676 {
6677 return false;
6678 }
6679
6680 get_ignore_noop();
6681 if (JSON_HEDLEY_UNLIKELY(current != '#'))
6682 {
6683 if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
6684 {
6685 return false;
6686 }
6687 auto last_token = get_token_string();
6688 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size")));
6689 }
6690
6691 return get_ubjson_size_value(result.first);
6692 }
6693
6694 if (current == '#')
6695 {
6696 return get_ubjson_size_value(result.first);
6697 }
6698
6699 return true;
6700 }
6701
6702 /*!
6703 @param prefix the previously read or set type prefix
6704 @return whether value creation completed
6705 */
get_ubjson_value(const int prefix)6706 bool get_ubjson_value(const int prefix)
6707 {
6708 switch (prefix)
6709 {
6710 case std::char_traits<char>::eof(): // EOF
6711 return unexpect_eof(input_format_t::ubjson, "value");
6712
6713 case 'T': // true
6714 return sax->boolean(true);
6715 case 'F': // false
6716 return sax->boolean(false);
6717
6718 case 'Z': // null
6719 return sax->null();
6720
6721 case 'U':
6722 {
6723 std::uint8_t number;
6724 return get_number(input_format_t::ubjson, number) and sax->number_unsigned(number);
6725 }
6726
6727 case 'i':
6728 {
6729 std::int8_t number;
6730 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
6731 }
6732
6733 case 'I':
6734 {
6735 std::int16_t number;
6736 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
6737 }
6738
6739 case 'l':
6740 {
6741 std::int32_t number;
6742 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
6743 }
6744
6745 case 'L':
6746 {
6747 std::int64_t number;
6748 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
6749 }
6750
6751 case 'd':
6752 {
6753 float number;
6754 return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast<number_float_t>(number), "");
6755 }
6756
6757 case 'D':
6758 {
6759 double number;
6760 return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast<number_float_t>(number), "");
6761 }
6762
6763 case 'C': // char
6764 {
6765 get();
6766 if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "char")))
6767 {
6768 return false;
6769 }
6770 if (JSON_HEDLEY_UNLIKELY(current > 127))
6771 {
6772 auto last_token = get_token_string();
6773 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char")));
6774 }
6775 string_t s(1, static_cast<char>(current));
6776 return sax->string(s);
6777 }
6778
6779 case 'S': // string
6780 {
6781 string_t s;
6782 return get_ubjson_string(s) and sax->string(s);
6783 }
6784
6785 case '[': // array
6786 return get_ubjson_array();
6787
6788 case '{': // object
6789 return get_ubjson_object();
6790
6791 default: // anything else
6792 {
6793 auto last_token = get_token_string();
6794 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value")));
6795 }
6796 }
6797 }
6798
6799 /*!
6800 @return whether array creation completed
6801 */
get_ubjson_array()6802 bool get_ubjson_array()
6803 {
6804 std::pair<std::size_t, int> size_and_type;
6805 if (JSON_HEDLEY_UNLIKELY(not get_ubjson_size_type(size_and_type)))
6806 {
6807 return false;
6808 }
6809
6810 if (size_and_type.first != string_t::npos)
6811 {
6812 if (JSON_HEDLEY_UNLIKELY(not sax->start_array(size_and_type.first)))
6813 {
6814 return false;
6815 }
6816
6817 if (size_and_type.second != 0)
6818 {
6819 if (size_and_type.second != 'N')
6820 {
6821 for (std::size_t i = 0; i < size_and_type.first; ++i)
6822 {
6823 if (JSON_HEDLEY_UNLIKELY(not get_ubjson_value(size_and_type.second)))
6824 {
6825 return false;
6826 }
6827 }
6828 }
6829 }
6830 else
6831 {
6832 for (std::size_t i = 0; i < size_and_type.first; ++i)
6833 {
6834 if (JSON_HEDLEY_UNLIKELY(not parse_ubjson_internal()))
6835 {
6836 return false;
6837 }
6838 }
6839 }
6840 }
6841 else
6842 {
6843 if (JSON_HEDLEY_UNLIKELY(not sax->start_array(std::size_t(-1))))
6844 {
6845 return false;
6846 }
6847
6848 while (current != ']')
6849 {
6850 if (JSON_HEDLEY_UNLIKELY(not parse_ubjson_internal(false)))
6851 {
6852 return false;
6853 }
6854 get_ignore_noop();
6855 }
6856 }
6857
6858 return sax->end_array();
6859 }
6860
6861 /*!
6862 @return whether object creation completed
6863 */
get_ubjson_object()6864 bool get_ubjson_object()
6865 {
6866 std::pair<std::size_t, int> size_and_type;
6867 if (JSON_HEDLEY_UNLIKELY(not get_ubjson_size_type(size_and_type)))
6868 {
6869 return false;
6870 }
6871
6872 string_t key;
6873 if (size_and_type.first != string_t::npos)
6874 {
6875 if (JSON_HEDLEY_UNLIKELY(not sax->start_object(size_and_type.first)))
6876 {
6877 return false;
6878 }
6879
6880 if (size_and_type.second != 0)
6881 {
6882 for (std::size_t i = 0; i < size_and_type.first; ++i)
6883 {
6884 if (JSON_HEDLEY_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
6885 {
6886 return false;
6887 }
6888 if (JSON_HEDLEY_UNLIKELY(not get_ubjson_value(size_and_type.second)))
6889 {
6890 return false;
6891 }
6892 key.clear();
6893 }
6894 }
6895 else
6896 {
6897 for (std::size_t i = 0; i < size_and_type.first; ++i)
6898 {
6899 if (JSON_HEDLEY_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
6900 {
6901 return false;
6902 }
6903 if (JSON_HEDLEY_UNLIKELY(not parse_ubjson_internal()))
6904 {
6905 return false;
6906 }
6907 key.clear();
6908 }
6909 }
6910 }
6911 else
6912 {
6913 if (JSON_HEDLEY_UNLIKELY(not sax->start_object(std::size_t(-1))))
6914 {
6915 return false;
6916 }
6917
6918 while (current != '}')
6919 {
6920 if (JSON_HEDLEY_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key)))
6921 {
6922 return false;
6923 }
6924 if (JSON_HEDLEY_UNLIKELY(not parse_ubjson_internal()))
6925 {
6926 return false;
6927 }
6928 get_ignore_noop();
6929 key.clear();
6930 }
6931 }
6932
6933 return sax->end_object();
6934 }
6935
6936 ///////////////////////
6937 // Utility functions //
6938 ///////////////////////
6939
6940 /*!
6941 @brief get next character from the input
6942
6943 This function provides the interface to the used input adapter. It does
6944 not throw in case the input reached EOF, but returns a -'ve valued
6945 `std::char_traits<char>::eof()` in that case.
6946
6947 @return character read from the input
6948 */
get()6949 int get()
6950 {
6951 ++chars_read;
6952 return current = ia->get_character();
6953 }
6954
6955 /*!
6956 @return character read from the input after ignoring all 'N' entries
6957 */
get_ignore_noop()6958 int get_ignore_noop()
6959 {
6960 do
6961 {
6962 get();
6963 }
6964 while (current == 'N');
6965
6966 return current;
6967 }
6968
6969 /*
6970 @brief read a number from the input
6971
6972 @tparam NumberType the type of the number
6973 @param[in] format the current format (for diagnostics)
6974 @param[out] result number of type @a NumberType
6975
6976 @return whether conversion completed
6977
6978 @note This function needs to respect the system's endianess, because
6979 bytes in CBOR, MessagePack, and UBJSON are stored in network order
6980 (big endian) and therefore need reordering on little endian systems.
6981 */
6982 template<typename NumberType, bool InputIsLittleEndian = false>
get_number(const input_format_t format,NumberType & result)6983 bool get_number(const input_format_t format, NumberType& result)
6984 {
6985 // step 1: read input into array with system's byte order
6986 std::array<std::uint8_t, sizeof(NumberType)> vec;
6987 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
6988 {
6989 get();
6990 if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(format, "number")))
6991 {
6992 return false;
6993 }
6994
6995 // reverse byte order prior to conversion if necessary
6996 if (is_little_endian != InputIsLittleEndian)
6997 {
6998 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
6999 }
7000 else
7001 {
7002 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
7003 }
7004 }
7005
7006 // step 2: convert array into number of type T and return
7007 std::memcpy(&result, vec.data(), sizeof(NumberType));
7008 return true;
7009 }
7010
7011 /*!
7012 @brief create a string by reading characters from the input
7013
7014 @tparam NumberType the type of the number
7015 @param[in] format the current format (for diagnostics)
7016 @param[in] len number of characters to read
7017 @param[out] result string created by reading @a len bytes
7018
7019 @return whether string creation completed
7020
7021 @note We can not reserve @a len bytes for the result, because @a len
7022 may be too large. Usually, @ref unexpect_eof() detects the end of
7023 the input before we run out of string memory.
7024 */
7025 template<typename NumberType>
get_string(const input_format_t format,const NumberType len,string_t & result)7026 bool get_string(const input_format_t format,
7027 const NumberType len,
7028 string_t& result)
7029 {
7030 bool success = true;
7031 std::generate_n(std::back_inserter(result), len, [this, &success, &format]()
7032 {
7033 get();
7034 if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(format, "string")))
7035 {
7036 success = false;
7037 }
7038 return static_cast<char>(current);
7039 });
7040 return success;
7041 }
7042
7043 /*!
7044 @param[in] format the current format (for diagnostics)
7045 @param[in] context further context information (for diagnostics)
7046 @return whether the last read character is not EOF
7047 */
7048 JSON_HEDLEY_NON_NULL(3)
unexpect_eof(const input_format_t format,const char * context) const7049 bool unexpect_eof(const input_format_t format, const char* context) const
7050 {
7051 if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char>::eof()))
7052 {
7053 return sax->parse_error(chars_read, "<end of file>",
7054 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context)));
7055 }
7056 return true;
7057 }
7058
7059 /*!
7060 @return a string representation of the last read byte
7061 */
get_token_string() const7062 std::string get_token_string() const
7063 {
7064 std::array<char, 3> cr{{}};
7065 (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current));
7066 return std::string{cr.data()};
7067 }
7068
7069 /*!
7070 @param[in] format the current format
7071 @param[in] detail a detailed error message
7072 @param[in] context further context information
7073 @return a message string to use in the parse_error exceptions
7074 */
exception_message(const input_format_t format,const std::string & detail,const std::string & context) const7075 std::string exception_message(const input_format_t format,
7076 const std::string& detail,
7077 const std::string& context) const
7078 {
7079 std::string error_msg = "syntax error while parsing ";
7080
7081 switch (format)
7082 {
7083 case input_format_t::cbor:
7084 error_msg += "CBOR";
7085 break;
7086
7087 case input_format_t::msgpack:
7088 error_msg += "MessagePack";
7089 break;
7090
7091 case input_format_t::ubjson:
7092 error_msg += "UBJSON";
7093 break;
7094
7095 case input_format_t::bson:
7096 error_msg += "BSON";
7097 break;
7098
7099 default: // LCOV_EXCL_LINE
7100 assert(false); // LCOV_EXCL_LINE
7101 }
7102
7103 return error_msg + " " + context + ": " + detail;
7104 }
7105
7106 private:
7107 /// input adapter
7108 input_adapter_t ia = nullptr;
7109
7110 /// the current character
7111 int current = std::char_traits<char>::eof();
7112
7113 /// the number of characters read
7114 std::size_t chars_read = 0;
7115
7116 /// whether we can assume little endianess
7117 const bool is_little_endian = little_endianess();
7118
7119 /// the SAX parser
7120 json_sax_t* sax = nullptr;
7121 };
7122 } // namespace detail
7123 } // namespace nlohmann
7124
7125 // #include <nlohmann/detail/input/input_adapters.hpp>
7126
7127 // #include <nlohmann/detail/input/lexer.hpp>
7128
7129
7130 #include <array> // array
7131 #include <clocale> // localeconv
7132 #include <cstddef> // size_t
7133 #include <cstdio> // snprintf
7134 #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7135 #include <initializer_list> // initializer_list
7136 #include <string> // char_traits, string
7137 #include <utility> // move
7138 #include <vector> // vector
7139
7140 // #include <nlohmann/detail/input/input_adapters.hpp>
7141
7142 // #include <nlohmann/detail/input/position_t.hpp>
7143
7144 // #include <nlohmann/detail/macro_scope.hpp>
7145
7146
7147 namespace nlohmann
7148 {
7149 namespace detail
7150 {
7151 ///////////
7152 // lexer //
7153 ///////////
7154
7155 /*!
7156 @brief lexical analysis
7157
7158 This class organizes the lexical analysis during JSON deserialization.
7159 */
7160 template<typename BasicJsonType>
7161 class lexer
7162 {
7163 using number_integer_t = typename BasicJsonType::number_integer_t;
7164 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7165 using number_float_t = typename BasicJsonType::number_float_t;
7166 using string_t = typename BasicJsonType::string_t;
7167
7168 public:
7169 /// token types for the parser
7170 enum class token_type
7171 {
7172 uninitialized, ///< indicating the scanner is uninitialized
7173 literal_true, ///< the `true` literal
7174 literal_false, ///< the `false` literal
7175 literal_null, ///< the `null` literal
7176 value_string, ///< a string -- use get_string() for actual value
7177 value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
7178 value_integer, ///< a signed integer -- use get_number_integer() for actual value
7179 value_float, ///< an floating point number -- use get_number_float() for actual value
7180 begin_array, ///< the character for array begin `[`
7181 begin_object, ///< the character for object begin `{`
7182 end_array, ///< the character for array end `]`
7183 end_object, ///< the character for object end `}`
7184 name_separator, ///< the name separator `:`
7185 value_separator, ///< the value separator `,`
7186 parse_error, ///< indicating a parse error
7187 end_of_input, ///< indicating the end of the input buffer
7188 literal_or_value ///< a literal or the begin of a value (only for diagnostics)
7189 };
7190
7191 /// return name of values of type token_type (only used for errors)
7192 JSON_HEDLEY_RETURNS_NON_NULL
7193 JSON_HEDLEY_CONST
token_type_name(const token_type t)7194 static const char* token_type_name(const token_type t) noexcept
7195 {
7196 switch (t)
7197 {
7198 case token_type::uninitialized:
7199 return "<uninitialized>";
7200 case token_type::literal_true:
7201 return "true literal";
7202 case token_type::literal_false:
7203 return "false literal";
7204 case token_type::literal_null:
7205 return "null literal";
7206 case token_type::value_string:
7207 return "string literal";
7208 case lexer::token_type::value_unsigned:
7209 case lexer::token_type::value_integer:
7210 case lexer::token_type::value_float:
7211 return "number literal";
7212 case token_type::begin_array:
7213 return "'['";
7214 case token_type::begin_object:
7215 return "'{'";
7216 case token_type::end_array:
7217 return "']'";
7218 case token_type::end_object:
7219 return "'}'";
7220 case token_type::name_separator:
7221 return "':'";
7222 case token_type::value_separator:
7223 return "','";
7224 case token_type::parse_error:
7225 return "<parse error>";
7226 case token_type::end_of_input:
7227 return "end of input";
7228 case token_type::literal_or_value:
7229 return "'[', '{', or a literal";
7230 // LCOV_EXCL_START
7231 default: // catch non-enum values
7232 return "unknown token";
7233 // LCOV_EXCL_STOP
7234 }
7235 }
7236
lexer(detail::input_adapter_t && adapter)7237 explicit lexer(detail::input_adapter_t&& adapter)
7238 : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
7239
7240 // delete because of pointer members
7241 lexer(const lexer&) = delete;
7242 lexer(lexer&&) = delete;
7243 lexer& operator=(lexer&) = delete;
7244 lexer& operator=(lexer&&) = delete;
7245 ~lexer() = default;
7246
7247 private:
7248 /////////////////////
7249 // locales
7250 /////////////////////
7251
7252 /// return the locale-dependent decimal point
7253 JSON_HEDLEY_PURE
get_decimal_point()7254 static char get_decimal_point() noexcept
7255 {
7256 const auto loc = localeconv();
7257 assert(loc != nullptr);
7258 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7259 }
7260
7261 /////////////////////
7262 // scan functions
7263 /////////////////////
7264
7265 /*!
7266 @brief get codepoint from 4 hex characters following `\u`
7267
7268 For input "\u c1 c2 c3 c4" the codepoint is:
7269 (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
7270 = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
7271
7272 Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
7273 must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
7274 conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
7275 between the ASCII value of the character and the desired integer value.
7276
7277 @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
7278 non-hex character)
7279 */
get_codepoint()7280 int get_codepoint()
7281 {
7282 // this function only makes sense after reading `\u`
7283 assert(current == 'u');
7284 int codepoint = 0;
7285
7286 const auto factors = { 12u, 8u, 4u, 0u };
7287 for (const auto factor : factors)
7288 {
7289 get();
7290
7291 if (current >= '0' and current <= '9')
7292 {
7293 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7294 }
7295 else if (current >= 'A' and current <= 'F')
7296 {
7297 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7298 }
7299 else if (current >= 'a' and current <= 'f')
7300 {
7301 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7302 }
7303 else
7304 {
7305 return -1;
7306 }
7307 }
7308
7309 assert(0x0000 <= codepoint and codepoint <= 0xFFFF);
7310 return codepoint;
7311 }
7312
7313 /*!
7314 @brief check if the next byte(s) are inside a given range
7315
7316 Adds the current byte and, for each passed range, reads a new byte and
7317 checks if it is inside the range. If a violation was detected, set up an
7318 error message and return false. Otherwise, return true.
7319
7320 @param[in] ranges list of integers; interpreted as list of pairs of
7321 inclusive lower and upper bound, respectively
7322
7323 @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
7324 1, 2, or 3 pairs. This precondition is enforced by an assertion.
7325
7326 @return true if and only if no range violation was detected
7327 */
next_byte_in_range(std::initializer_list<int> ranges)7328 bool next_byte_in_range(std::initializer_list<int> ranges)
7329 {
7330 assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6);
7331 add(current);
7332
7333 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7334 {
7335 get();
7336 if (JSON_HEDLEY_LIKELY(*range <= current and current <= *(++range)))
7337 {
7338 add(current);
7339 }
7340 else
7341 {
7342 error_message = "invalid string: ill-formed UTF-8 byte";
7343 return false;
7344 }
7345 }
7346
7347 return true;
7348 }
7349
7350 /*!
7351 @brief scan a string literal
7352
7353 This function scans a string according to Sect. 7 of RFC 7159. While
7354 scanning, bytes are escaped and copied into buffer token_buffer. Then the
7355 function returns successfully, token_buffer is *not* null-terminated (as it
7356 may contain \0 bytes), and token_buffer.size() is the number of bytes in the
7357 string.
7358
7359 @return token_type::value_string if string could be successfully scanned,
7360 token_type::parse_error otherwise
7361
7362 @note In case of errors, variable error_message contains a textual
7363 description.
7364 */
scan_string()7365 token_type scan_string()
7366 {
7367 // reset token_buffer (ignore opening quote)
7368 reset();
7369
7370 // we entered the function by reading an open quote
7371 assert(current == '\"');
7372
7373 while (true)
7374 {
7375 // get next character
7376 switch (get())
7377 {
7378 // end of file while parsing string
7379 case std::char_traits<char>::eof():
7380 {
7381 error_message = "invalid string: missing closing quote";
7382 return token_type::parse_error;
7383 }
7384
7385 // closing quote
7386 case '\"':
7387 {
7388 return token_type::value_string;
7389 }
7390
7391 // escapes
7392 case '\\':
7393 {
7394 switch (get())
7395 {
7396 // quotation mark
7397 case '\"':
7398 add('\"');
7399 break;
7400 // reverse solidus
7401 case '\\':
7402 add('\\');
7403 break;
7404 // solidus
7405 case '/':
7406 add('/');
7407 break;
7408 // backspace
7409 case 'b':
7410 add('\b');
7411 break;
7412 // form feed
7413 case 'f':
7414 add('\f');
7415 break;
7416 // line feed
7417 case 'n':
7418 add('\n');
7419 break;
7420 // carriage return
7421 case 'r':
7422 add('\r');
7423 break;
7424 // tab
7425 case 't':
7426 add('\t');
7427 break;
7428
7429 // unicode escapes
7430 case 'u':
7431 {
7432 const int codepoint1 = get_codepoint();
7433 int codepoint = codepoint1; // start with codepoint1
7434
7435 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7436 {
7437 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7438 return token_type::parse_error;
7439 }
7440
7441 // check if code point is a high surrogate
7442 if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)
7443 {
7444 // expect next \uxxxx entry
7445 if (JSON_HEDLEY_LIKELY(get() == '\\' and get() == 'u'))
7446 {
7447 const int codepoint2 = get_codepoint();
7448
7449 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7450 {
7451 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7452 return token_type::parse_error;
7453 }
7454
7455 // check if codepoint2 is a low surrogate
7456 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
7457 {
7458 // overwrite codepoint
7459 codepoint = static_cast<int>(
7460 // high surrogate occupies the most significant 22 bits
7461 (static_cast<unsigned int>(codepoint1) << 10u)
7462 // low surrogate occupies the least significant 15 bits
7463 + static_cast<unsigned int>(codepoint2)
7464 // there is still the 0xD800, 0xDC00 and 0x10000 noise
7465 // in the result so we have to subtract with:
7466 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7467 - 0x35FDC00u);
7468 }
7469 else
7470 {
7471 error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
7472 return token_type::parse_error;
7473 }
7474 }
7475 else
7476 {
7477 error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
7478 return token_type::parse_error;
7479 }
7480 }
7481 else
7482 {
7483 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))
7484 {
7485 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7486 return token_type::parse_error;
7487 }
7488 }
7489
7490 // result of the above calculation yields a proper codepoint
7491 assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
7492
7493 // translate codepoint into bytes
7494 if (codepoint < 0x80)
7495 {
7496 // 1-byte characters: 0xxxxxxx (ASCII)
7497 add(codepoint);
7498 }
7499 else if (codepoint <= 0x7FF)
7500 {
7501 // 2-byte characters: 110xxxxx 10xxxxxx
7502 add(static_cast<int>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7503 add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7504 }
7505 else if (codepoint <= 0xFFFF)
7506 {
7507 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7508 add(static_cast<int>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7509 add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7510 add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7511 }
7512 else
7513 {
7514 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7515 add(static_cast<int>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7516 add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7517 add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7518 add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7519 }
7520
7521 break;
7522 }
7523
7524 // other characters after escape
7525 default:
7526 error_message = "invalid string: forbidden character after backslash";
7527 return token_type::parse_error;
7528 }
7529
7530 break;
7531 }
7532
7533 // invalid control characters
7534 case 0x00:
7535 {
7536 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7537 return token_type::parse_error;
7538 }
7539
7540 case 0x01:
7541 {
7542 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7543 return token_type::parse_error;
7544 }
7545
7546 case 0x02:
7547 {
7548 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7549 return token_type::parse_error;
7550 }
7551
7552 case 0x03:
7553 {
7554 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7555 return token_type::parse_error;
7556 }
7557
7558 case 0x04:
7559 {
7560 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7561 return token_type::parse_error;
7562 }
7563
7564 case 0x05:
7565 {
7566 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7567 return token_type::parse_error;
7568 }
7569
7570 case 0x06:
7571 {
7572 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7573 return token_type::parse_error;
7574 }
7575
7576 case 0x07:
7577 {
7578 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7579 return token_type::parse_error;
7580 }
7581
7582 case 0x08:
7583 {
7584 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7585 return token_type::parse_error;
7586 }
7587
7588 case 0x09:
7589 {
7590 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7591 return token_type::parse_error;
7592 }
7593
7594 case 0x0A:
7595 {
7596 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7597 return token_type::parse_error;
7598 }
7599
7600 case 0x0B:
7601 {
7602 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7603 return token_type::parse_error;
7604 }
7605
7606 case 0x0C:
7607 {
7608 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7609 return token_type::parse_error;
7610 }
7611
7612 case 0x0D:
7613 {
7614 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7615 return token_type::parse_error;
7616 }
7617
7618 case 0x0E:
7619 {
7620 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7621 return token_type::parse_error;
7622 }
7623
7624 case 0x0F:
7625 {
7626 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7627 return token_type::parse_error;
7628 }
7629
7630 case 0x10:
7631 {
7632 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7633 return token_type::parse_error;
7634 }
7635
7636 case 0x11:
7637 {
7638 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7639 return token_type::parse_error;
7640 }
7641
7642 case 0x12:
7643 {
7644 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7645 return token_type::parse_error;
7646 }
7647
7648 case 0x13:
7649 {
7650 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7651 return token_type::parse_error;
7652 }
7653
7654 case 0x14:
7655 {
7656 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7657 return token_type::parse_error;
7658 }
7659
7660 case 0x15:
7661 {
7662 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7663 return token_type::parse_error;
7664 }
7665
7666 case 0x16:
7667 {
7668 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7669 return token_type::parse_error;
7670 }
7671
7672 case 0x17:
7673 {
7674 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7675 return token_type::parse_error;
7676 }
7677
7678 case 0x18:
7679 {
7680 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7681 return token_type::parse_error;
7682 }
7683
7684 case 0x19:
7685 {
7686 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7687 return token_type::parse_error;
7688 }
7689
7690 case 0x1A:
7691 {
7692 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7693 return token_type::parse_error;
7694 }
7695
7696 case 0x1B:
7697 {
7698 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7699 return token_type::parse_error;
7700 }
7701
7702 case 0x1C:
7703 {
7704 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7705 return token_type::parse_error;
7706 }
7707
7708 case 0x1D:
7709 {
7710 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7711 return token_type::parse_error;
7712 }
7713
7714 case 0x1E:
7715 {
7716 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7717 return token_type::parse_error;
7718 }
7719
7720 case 0x1F:
7721 {
7722 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7723 return token_type::parse_error;
7724 }
7725
7726 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7727 case 0x20:
7728 case 0x21:
7729 case 0x23:
7730 case 0x24:
7731 case 0x25:
7732 case 0x26:
7733 case 0x27:
7734 case 0x28:
7735 case 0x29:
7736 case 0x2A:
7737 case 0x2B:
7738 case 0x2C:
7739 case 0x2D:
7740 case 0x2E:
7741 case 0x2F:
7742 case 0x30:
7743 case 0x31:
7744 case 0x32:
7745 case 0x33:
7746 case 0x34:
7747 case 0x35:
7748 case 0x36:
7749 case 0x37:
7750 case 0x38:
7751 case 0x39:
7752 case 0x3A:
7753 case 0x3B:
7754 case 0x3C:
7755 case 0x3D:
7756 case 0x3E:
7757 case 0x3F:
7758 case 0x40:
7759 case 0x41:
7760 case 0x42:
7761 case 0x43:
7762 case 0x44:
7763 case 0x45:
7764 case 0x46:
7765 case 0x47:
7766 case 0x48:
7767 case 0x49:
7768 case 0x4A:
7769 case 0x4B:
7770 case 0x4C:
7771 case 0x4D:
7772 case 0x4E:
7773 case 0x4F:
7774 case 0x50:
7775 case 0x51:
7776 case 0x52:
7777 case 0x53:
7778 case 0x54:
7779 case 0x55:
7780 case 0x56:
7781 case 0x57:
7782 case 0x58:
7783 case 0x59:
7784 case 0x5A:
7785 case 0x5B:
7786 case 0x5D:
7787 case 0x5E:
7788 case 0x5F:
7789 case 0x60:
7790 case 0x61:
7791 case 0x62:
7792 case 0x63:
7793 case 0x64:
7794 case 0x65:
7795 case 0x66:
7796 case 0x67:
7797 case 0x68:
7798 case 0x69:
7799 case 0x6A:
7800 case 0x6B:
7801 case 0x6C:
7802 case 0x6D:
7803 case 0x6E:
7804 case 0x6F:
7805 case 0x70:
7806 case 0x71:
7807 case 0x72:
7808 case 0x73:
7809 case 0x74:
7810 case 0x75:
7811 case 0x76:
7812 case 0x77:
7813 case 0x78:
7814 case 0x79:
7815 case 0x7A:
7816 case 0x7B:
7817 case 0x7C:
7818 case 0x7D:
7819 case 0x7E:
7820 case 0x7F:
7821 {
7822 add(current);
7823 break;
7824 }
7825
7826 // U+0080..U+07FF: bytes C2..DF 80..BF
7827 case 0xC2:
7828 case 0xC3:
7829 case 0xC4:
7830 case 0xC5:
7831 case 0xC6:
7832 case 0xC7:
7833 case 0xC8:
7834 case 0xC9:
7835 case 0xCA:
7836 case 0xCB:
7837 case 0xCC:
7838 case 0xCD:
7839 case 0xCE:
7840 case 0xCF:
7841 case 0xD0:
7842 case 0xD1:
7843 case 0xD2:
7844 case 0xD3:
7845 case 0xD4:
7846 case 0xD5:
7847 case 0xD6:
7848 case 0xD7:
7849 case 0xD8:
7850 case 0xD9:
7851 case 0xDA:
7852 case 0xDB:
7853 case 0xDC:
7854 case 0xDD:
7855 case 0xDE:
7856 case 0xDF:
7857 {
7858 if (JSON_HEDLEY_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))
7859 {
7860 return token_type::parse_error;
7861 }
7862 break;
7863 }
7864
7865 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7866 case 0xE0:
7867 {
7868 if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7869 {
7870 return token_type::parse_error;
7871 }
7872 break;
7873 }
7874
7875 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7876 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7877 case 0xE1:
7878 case 0xE2:
7879 case 0xE3:
7880 case 0xE4:
7881 case 0xE5:
7882 case 0xE6:
7883 case 0xE7:
7884 case 0xE8:
7885 case 0xE9:
7886 case 0xEA:
7887 case 0xEB:
7888 case 0xEC:
7889 case 0xEE:
7890 case 0xEF:
7891 {
7892 if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7893 {
7894 return token_type::parse_error;
7895 }
7896 break;
7897 }
7898
7899 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7900 case 0xED:
7901 {
7902 if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7903 {
7904 return token_type::parse_error;
7905 }
7906 break;
7907 }
7908
7909 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7910 case 0xF0:
7911 {
7912 if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7913 {
7914 return token_type::parse_error;
7915 }
7916 break;
7917 }
7918
7919 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7920 case 0xF1:
7921 case 0xF2:
7922 case 0xF3:
7923 {
7924 if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7925 {
7926 return token_type::parse_error;
7927 }
7928 break;
7929 }
7930
7931 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7932 case 0xF4:
7933 {
7934 if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
7935 {
7936 return token_type::parse_error;
7937 }
7938 break;
7939 }
7940
7941 // remaining bytes (80..C1 and F5..FF) are ill-formed
7942 default:
7943 {
7944 error_message = "invalid string: ill-formed UTF-8 byte";
7945 return token_type::parse_error;
7946 }
7947 }
7948 }
7949 }
7950
7951 JSON_HEDLEY_NON_NULL(2)
strtof(float & f,const char * str,char ** endptr)7952 static void strtof(float& f, const char* str, char** endptr) noexcept
7953 {
7954 f = std::strtof(str, endptr);
7955 }
7956
7957 JSON_HEDLEY_NON_NULL(2)
strtof(double & f,const char * str,char ** endptr)7958 static void strtof(double& f, const char* str, char** endptr) noexcept
7959 {
7960 f = std::strtod(str, endptr);
7961 }
7962
7963 JSON_HEDLEY_NON_NULL(2)
strtof(long double & f,const char * str,char ** endptr)7964 static void strtof(long double& f, const char* str, char** endptr) noexcept
7965 {
7966 f = std::strtold(str, endptr);
7967 }
7968
7969 /*!
7970 @brief scan a number literal
7971
7972 This function scans a string according to Sect. 6 of RFC 7159.
7973
7974 The function is realized with a deterministic finite state machine derived
7975 from the grammar described in RFC 7159. Starting in state "init", the
7976 input is read and used to determined the next state. Only state "done"
7977 accepts the number. State "error" is a trap state to model errors. In the
7978 table below, "anything" means any character but the ones listed before.
7979
7980 state | 0 | 1-9 | e E | + | - | . | anything
7981 ---------|----------|----------|----------|---------|---------|----------|-----------
7982 init | zero | any1 | [error] | [error] | minus | [error] | [error]
7983 minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
7984 zero | done | done | exponent | done | done | decimal1 | done
7985 any1 | any1 | any1 | exponent | done | done | decimal1 | done
7986 decimal1 | decimal2 | [error] | [error] | [error] | [error] | [error] | [error]
7987 decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
7988 exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
7989 sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
7990 any2 | any2 | any2 | done | done | done | done | done
7991
7992 The state machine is realized with one label per state (prefixed with
7993 "scan_number_") and `goto` statements between them. The state machine
7994 contains cycles, but any cycle can be left when EOF is read. Therefore,
7995 the function is guaranteed to terminate.
7996
7997 During scanning, the read bytes are stored in token_buffer. This string is
7998 then converted to a signed integer, an unsigned integer, or a
7999 floating-point number.
8000
8001 @return token_type::value_unsigned, token_type::value_integer, or
8002 token_type::value_float if number could be successfully scanned,
8003 token_type::parse_error otherwise
8004
8005 @note The scanner is independent of the current locale. Internally, the
8006 locale's decimal point is used instead of `.` to work with the
8007 locale-dependent converters.
8008 */
scan_number()8009 token_type scan_number() // lgtm [cpp/use-of-goto]
8010 {
8011 // reset token_buffer to store the number's bytes
8012 reset();
8013
8014 // the type of the parsed number; initially set to unsigned; will be
8015 // changed if minus sign, decimal point or exponent is read
8016 token_type number_type = token_type::value_unsigned;
8017
8018 // state (init): we just found out we need to scan a number
8019 switch (current)
8020 {
8021 case '-':
8022 {
8023 add(current);
8024 goto scan_number_minus;
8025 }
8026
8027 case '0':
8028 {
8029 add(current);
8030 goto scan_number_zero;
8031 }
8032
8033 case '1':
8034 case '2':
8035 case '3':
8036 case '4':
8037 case '5':
8038 case '6':
8039 case '7':
8040 case '8':
8041 case '9':
8042 {
8043 add(current);
8044 goto scan_number_any1;
8045 }
8046
8047 // all other characters are rejected outside scan_number()
8048 default: // LCOV_EXCL_LINE
8049 assert(false); // LCOV_EXCL_LINE
8050 }
8051
8052 scan_number_minus:
8053 // state: we just parsed a leading minus sign
8054 number_type = token_type::value_integer;
8055 switch (get())
8056 {
8057 case '0':
8058 {
8059 add(current);
8060 goto scan_number_zero;
8061 }
8062
8063 case '1':
8064 case '2':
8065 case '3':
8066 case '4':
8067 case '5':
8068 case '6':
8069 case '7':
8070 case '8':
8071 case '9':
8072 {
8073 add(current);
8074 goto scan_number_any1;
8075 }
8076
8077 default:
8078 {
8079 error_message = "invalid number; expected digit after '-'";
8080 return token_type::parse_error;
8081 }
8082 }
8083
8084 scan_number_zero:
8085 // state: we just parse a zero (maybe with a leading minus sign)
8086 switch (get())
8087 {
8088 case '.':
8089 {
8090 add(decimal_point_char);
8091 goto scan_number_decimal1;
8092 }
8093
8094 case 'e':
8095 case 'E':
8096 {
8097 add(current);
8098 goto scan_number_exponent;
8099 }
8100
8101 default:
8102 goto scan_number_done;
8103 }
8104
8105 scan_number_any1:
8106 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8107 switch (get())
8108 {
8109 case '0':
8110 case '1':
8111 case '2':
8112 case '3':
8113 case '4':
8114 case '5':
8115 case '6':
8116 case '7':
8117 case '8':
8118 case '9':
8119 {
8120 add(current);
8121 goto scan_number_any1;
8122 }
8123
8124 case '.':
8125 {
8126 add(decimal_point_char);
8127 goto scan_number_decimal1;
8128 }
8129
8130 case 'e':
8131 case 'E':
8132 {
8133 add(current);
8134 goto scan_number_exponent;
8135 }
8136
8137 default:
8138 goto scan_number_done;
8139 }
8140
8141 scan_number_decimal1:
8142 // state: we just parsed a decimal point
8143 number_type = token_type::value_float;
8144 switch (get())
8145 {
8146 case '0':
8147 case '1':
8148 case '2':
8149 case '3':
8150 case '4':
8151 case '5':
8152 case '6':
8153 case '7':
8154 case '8':
8155 case '9':
8156 {
8157 add(current);
8158 goto scan_number_decimal2;
8159 }
8160
8161 default:
8162 {
8163 error_message = "invalid number; expected digit after '.'";
8164 return token_type::parse_error;
8165 }
8166 }
8167
8168 scan_number_decimal2:
8169 // we just parsed at least one number after a decimal point
8170 switch (get())
8171 {
8172 case '0':
8173 case '1':
8174 case '2':
8175 case '3':
8176 case '4':
8177 case '5':
8178 case '6':
8179 case '7':
8180 case '8':
8181 case '9':
8182 {
8183 add(current);
8184 goto scan_number_decimal2;
8185 }
8186
8187 case 'e':
8188 case 'E':
8189 {
8190 add(current);
8191 goto scan_number_exponent;
8192 }
8193
8194 default:
8195 goto scan_number_done;
8196 }
8197
8198 scan_number_exponent:
8199 // we just parsed an exponent
8200 number_type = token_type::value_float;
8201 switch (get())
8202 {
8203 case '+':
8204 case '-':
8205 {
8206 add(current);
8207 goto scan_number_sign;
8208 }
8209
8210 case '0':
8211 case '1':
8212 case '2':
8213 case '3':
8214 case '4':
8215 case '5':
8216 case '6':
8217 case '7':
8218 case '8':
8219 case '9':
8220 {
8221 add(current);
8222 goto scan_number_any2;
8223 }
8224
8225 default:
8226 {
8227 error_message =
8228 "invalid number; expected '+', '-', or digit after exponent";
8229 return token_type::parse_error;
8230 }
8231 }
8232
8233 scan_number_sign:
8234 // we just parsed an exponent sign
8235 switch (get())
8236 {
8237 case '0':
8238 case '1':
8239 case '2':
8240 case '3':
8241 case '4':
8242 case '5':
8243 case '6':
8244 case '7':
8245 case '8':
8246 case '9':
8247 {
8248 add(current);
8249 goto scan_number_any2;
8250 }
8251
8252 default:
8253 {
8254 error_message = "invalid number; expected digit after exponent sign";
8255 return token_type::parse_error;
8256 }
8257 }
8258
8259 scan_number_any2:
8260 // we just parsed a number after the exponent or exponent sign
8261 switch (get())
8262 {
8263 case '0':
8264 case '1':
8265 case '2':
8266 case '3':
8267 case '4':
8268 case '5':
8269 case '6':
8270 case '7':
8271 case '8':
8272 case '9':
8273 {
8274 add(current);
8275 goto scan_number_any2;
8276 }
8277
8278 default:
8279 goto scan_number_done;
8280 }
8281
8282 scan_number_done:
8283 // unget the character after the number (we only read it to know that
8284 // we are done scanning a number)
8285 unget();
8286
8287 char* endptr = nullptr;
8288 errno = 0;
8289
8290 // try to parse integers first and fall back to floats
8291 if (number_type == token_type::value_unsigned)
8292 {
8293 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8294
8295 // we checked the number format before
8296 assert(endptr == token_buffer.data() + token_buffer.size());
8297
8298 if (errno == 0)
8299 {
8300 value_unsigned = static_cast<number_unsigned_t>(x);
8301 if (value_unsigned == x)
8302 {
8303 return token_type::value_unsigned;
8304 }
8305 }
8306 }
8307 else if (number_type == token_type::value_integer)
8308 {
8309 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8310
8311 // we checked the number format before
8312 assert(endptr == token_buffer.data() + token_buffer.size());
8313
8314 if (errno == 0)
8315 {
8316 value_integer = static_cast<number_integer_t>(x);
8317 if (value_integer == x)
8318 {
8319 return token_type::value_integer;
8320 }
8321 }
8322 }
8323
8324 // this code is reached if we parse a floating-point number or if an
8325 // integer conversion above failed
8326 strtof(value_float, token_buffer.data(), &endptr);
8327
8328 // we checked the number format before
8329 assert(endptr == token_buffer.data() + token_buffer.size());
8330
8331 return token_type::value_float;
8332 }
8333
8334 /*!
8335 @param[in] literal_text the literal text to expect
8336 @param[in] length the length of the passed literal text
8337 @param[in] return_type the token type to return on success
8338 */
8339 JSON_HEDLEY_NON_NULL(2)
scan_literal(const char * literal_text,const std::size_t length,token_type return_type)8340 token_type scan_literal(const char* literal_text, const std::size_t length,
8341 token_type return_type)
8342 {
8343 assert(current == literal_text[0]);
8344 for (std::size_t i = 1; i < length; ++i)
8345 {
8346 if (JSON_HEDLEY_UNLIKELY(get() != literal_text[i]))
8347 {
8348 error_message = "invalid literal";
8349 return token_type::parse_error;
8350 }
8351 }
8352 return return_type;
8353 }
8354
8355 /////////////////////
8356 // input management
8357 /////////////////////
8358
8359 /// reset token_buffer; current character is beginning of token
reset()8360 void reset() noexcept
8361 {
8362 token_buffer.clear();
8363 token_string.clear();
8364 token_string.push_back(std::char_traits<char>::to_char_type(current));
8365 }
8366
8367 /*
8368 @brief get next character from the input
8369
8370 This function provides the interface to the used input adapter. It does
8371 not throw in case the input reached EOF, but returns a
8372 `std::char_traits<char>::eof()` in that case. Stores the scanned characters
8373 for use in error messages.
8374
8375 @return character read from the input
8376 */
get()8377 std::char_traits<char>::int_type get()
8378 {
8379 ++position.chars_read_total;
8380 ++position.chars_read_current_line;
8381
8382 if (next_unget)
8383 {
8384 // just reset the next_unget variable and work with current
8385 next_unget = false;
8386 }
8387 else
8388 {
8389 current = ia->get_character();
8390 }
8391
8392 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char>::eof()))
8393 {
8394 token_string.push_back(std::char_traits<char>::to_char_type(current));
8395 }
8396
8397 if (current == '\n')
8398 {
8399 ++position.lines_read;
8400 position.chars_read_current_line = 0;
8401 }
8402
8403 return current;
8404 }
8405
8406 /*!
8407 @brief unget current character (read it again on next get)
8408
8409 We implement unget by setting variable next_unget to true. The input is not
8410 changed - we just simulate ungetting by modifying chars_read_total,
8411 chars_read_current_line, and token_string. The next call to get() will
8412 behave as if the unget character is read again.
8413 */
unget()8414 void unget()
8415 {
8416 next_unget = true;
8417
8418 --position.chars_read_total;
8419
8420 // in case we "unget" a newline, we have to also decrement the lines_read
8421 if (position.chars_read_current_line == 0)
8422 {
8423 if (position.lines_read > 0)
8424 {
8425 --position.lines_read;
8426 }
8427 }
8428 else
8429 {
8430 --position.chars_read_current_line;
8431 }
8432
8433 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char>::eof()))
8434 {
8435 assert(not token_string.empty());
8436 token_string.pop_back();
8437 }
8438 }
8439
8440 /// add a character to token_buffer
add(int c)8441 void add(int c)
8442 {
8443 token_buffer.push_back(std::char_traits<char>::to_char_type(c));
8444 }
8445
8446 public:
8447 /////////////////////
8448 // value getters
8449 /////////////////////
8450
8451 /// return integer value
get_number_integer() const8452 constexpr number_integer_t get_number_integer() const noexcept
8453 {
8454 return value_integer;
8455 }
8456
8457 /// return unsigned integer value
get_number_unsigned() const8458 constexpr number_unsigned_t get_number_unsigned() const noexcept
8459 {
8460 return value_unsigned;
8461 }
8462
8463 /// return floating-point value
get_number_float() const8464 constexpr number_float_t get_number_float() const noexcept
8465 {
8466 return value_float;
8467 }
8468
8469 /// return current string value (implicitly resets the token; useful only once)
get_string()8470 string_t& get_string()
8471 {
8472 return token_buffer;
8473 }
8474
8475 /////////////////////
8476 // diagnostics
8477 /////////////////////
8478
8479 /// return position of last read token
get_position() const8480 constexpr position_t get_position() const noexcept
8481 {
8482 return position;
8483 }
8484
8485 /// return the last read token (for errors only). Will never contain EOF
8486 /// (an arbitrary value that is not a valid char value, often -1), because
8487 /// 255 may legitimately occur. May contain NUL, which should be escaped.
get_token_string() const8488 std::string get_token_string() const
8489 {
8490 // escape control characters
8491 std::string result;
8492 for (const auto c : token_string)
8493 {
8494 if ('\x00' <= c and c <= '\x1F')
8495 {
8496 // escape control characters
8497 std::array<char, 9> cs{{}};
8498 (std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c));
8499 result += cs.data();
8500 }
8501 else
8502 {
8503 // add character as is
8504 result.push_back(c);
8505 }
8506 }
8507
8508 return result;
8509 }
8510
8511 /// return syntax error message
8512 JSON_HEDLEY_RETURNS_NON_NULL
get_error_message() const8513 constexpr const char* get_error_message() const noexcept
8514 {
8515 return error_message;
8516 }
8517
8518 /////////////////////
8519 // actual scanner
8520 /////////////////////
8521
8522 /*!
8523 @brief skip the UTF-8 byte order mark
8524 @return true iff there is no BOM or the correct BOM has been skipped
8525 */
skip_bom()8526 bool skip_bom()
8527 {
8528 if (get() == 0xEF)
8529 {
8530 // check if we completely parse the BOM
8531 return get() == 0xBB and get() == 0xBF;
8532 }
8533
8534 // the first character is not the beginning of the BOM; unget it to
8535 // process is later
8536 unget();
8537 return true;
8538 }
8539
scan()8540 token_type scan()
8541 {
8542 // initially, skip the BOM
8543 if (position.chars_read_total == 0 and not skip_bom())
8544 {
8545 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8546 return token_type::parse_error;
8547 }
8548
8549 // read next character and ignore whitespace
8550 do
8551 {
8552 get();
8553 }
8554 while (current == ' ' or current == '\t' or current == '\n' or current == '\r');
8555
8556 switch (current)
8557 {
8558 // structural characters
8559 case '[':
8560 return token_type::begin_array;
8561 case ']':
8562 return token_type::end_array;
8563 case '{':
8564 return token_type::begin_object;
8565 case '}':
8566 return token_type::end_object;
8567 case ':':
8568 return token_type::name_separator;
8569 case ',':
8570 return token_type::value_separator;
8571
8572 // literals
8573 case 't':
8574 return scan_literal("true", 4, token_type::literal_true);
8575 case 'f':
8576 return scan_literal("false", 5, token_type::literal_false);
8577 case 'n':
8578 return scan_literal("null", 4, token_type::literal_null);
8579
8580 // string
8581 case '\"':
8582 return scan_string();
8583
8584 // number
8585 case '-':
8586 case '0':
8587 case '1':
8588 case '2':
8589 case '3':
8590 case '4':
8591 case '5':
8592 case '6':
8593 case '7':
8594 case '8':
8595 case '9':
8596 return scan_number();
8597
8598 // end of input (the null byte is needed when parsing from
8599 // string literals)
8600 case '\0':
8601 case std::char_traits<char>::eof():
8602 return token_type::end_of_input;
8603
8604 // error
8605 default:
8606 error_message = "invalid literal";
8607 return token_type::parse_error;
8608 }
8609 }
8610
8611 private:
8612 /// input adapter
8613 detail::input_adapter_t ia = nullptr;
8614
8615 /// the current character
8616 std::char_traits<char>::int_type current = std::char_traits<char>::eof();
8617
8618 /// whether the next get() call should just return current
8619 bool next_unget = false;
8620
8621 /// the start position of the current token
8622 position_t position {};
8623
8624 /// raw input token string (for error messages)
8625 std::vector<char> token_string {};
8626
8627 /// buffer for variable-length tokens (numbers, strings)
8628 string_t token_buffer {};
8629
8630 /// a description of occurred lexer errors
8631 const char* error_message = "";
8632
8633 // number values
8634 number_integer_t value_integer = 0;
8635 number_unsigned_t value_unsigned = 0;
8636 number_float_t value_float = 0;
8637
8638 /// the decimal point
8639 const char decimal_point_char = '.';
8640 };
8641 } // namespace detail
8642 } // namespace nlohmann
8643
8644 // #include <nlohmann/detail/input/parser.hpp>
8645
8646
8647 #include <cassert> // assert
8648 #include <cmath> // isfinite
8649 #include <cstdint> // uint8_t
8650 #include <functional> // function
8651 #include <string> // string
8652 #include <utility> // move
8653 #include <vector> // vector
8654
8655 // #include <nlohmann/detail/exceptions.hpp>
8656
8657 // #include <nlohmann/detail/input/input_adapters.hpp>
8658
8659 // #include <nlohmann/detail/input/json_sax.hpp>
8660
8661 // #include <nlohmann/detail/input/lexer.hpp>
8662
8663 // #include <nlohmann/detail/macro_scope.hpp>
8664
8665 // #include <nlohmann/detail/meta/is_sax.hpp>
8666
8667 // #include <nlohmann/detail/value_t.hpp>
8668
8669
8670 namespace nlohmann
8671 {
8672 namespace detail
8673 {
8674 ////////////
8675 // parser //
8676 ////////////
8677
8678 /*!
8679 @brief syntax analysis
8680
8681 This class implements a recursive decent parser.
8682 */
8683 template<typename BasicJsonType>
8684 class parser
8685 {
8686 using number_integer_t = typename BasicJsonType::number_integer_t;
8687 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8688 using number_float_t = typename BasicJsonType::number_float_t;
8689 using string_t = typename BasicJsonType::string_t;
8690 using lexer_t = lexer<BasicJsonType>;
8691 using token_type = typename lexer_t::token_type;
8692
8693 public:
8694 enum class parse_event_t : uint8_t
8695 {
8696 /// the parser read `{` and started to process a JSON object
8697 object_start,
8698 /// the parser read `}` and finished processing a JSON object
8699 object_end,
8700 /// the parser read `[` and started to process a JSON array
8701 array_start,
8702 /// the parser read `]` and finished processing a JSON array
8703 array_end,
8704 /// the parser read a key of a value in an object
8705 key,
8706 /// the parser finished reading a JSON value
8707 value
8708 };
8709
8710 using parser_callback_t =
8711 std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
8712
8713 /// a parser reading from an input adapter
parser(detail::input_adapter_t && adapter,const parser_callback_t cb=nullptr,const bool allow_exceptions_=true)8714 explicit parser(detail::input_adapter_t&& adapter,
8715 const parser_callback_t cb = nullptr,
8716 const bool allow_exceptions_ = true)
8717 : callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
8718 {
8719 // read first token
8720 get_token();
8721 }
8722
8723 /*!
8724 @brief public parser interface
8725
8726 @param[in] strict whether to expect the last token to be EOF
8727 @param[in,out] result parsed JSON value
8728
8729 @throw parse_error.101 in case of an unexpected token
8730 @throw parse_error.102 if to_unicode fails or surrogate error
8731 @throw parse_error.103 if to_unicode fails
8732 */
parse(const bool strict,BasicJsonType & result)8733 void parse(const bool strict, BasicJsonType& result)
8734 {
8735 if (callback)
8736 {
8737 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
8738 sax_parse_internal(&sdp);
8739 result.assert_invariant();
8740
8741 // in strict mode, input must be completely read
8742 if (strict and (get_token() != token_type::end_of_input))
8743 {
8744 sdp.parse_error(m_lexer.get_position(),
8745 m_lexer.get_token_string(),
8746 parse_error::create(101, m_lexer.get_position(),
8747 exception_message(token_type::end_of_input, "value")));
8748 }
8749
8750 // in case of an error, return discarded value
8751 if (sdp.is_errored())
8752 {
8753 result = value_t::discarded;
8754 return;
8755 }
8756
8757 // set top-level value to null if it was discarded by the callback
8758 // function
8759 if (result.is_discarded())
8760 {
8761 result = nullptr;
8762 }
8763 }
8764 else
8765 {
8766 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
8767 sax_parse_internal(&sdp);
8768 result.assert_invariant();
8769
8770 // in strict mode, input must be completely read
8771 if (strict and (get_token() != token_type::end_of_input))
8772 {
8773 sdp.parse_error(m_lexer.get_position(),
8774 m_lexer.get_token_string(),
8775 parse_error::create(101, m_lexer.get_position(),
8776 exception_message(token_type::end_of_input, "value")));
8777 }
8778
8779 // in case of an error, return discarded value
8780 if (sdp.is_errored())
8781 {
8782 result = value_t::discarded;
8783 return;
8784 }
8785 }
8786 }
8787
8788 /*!
8789 @brief public accept interface
8790
8791 @param[in] strict whether to expect the last token to be EOF
8792 @return whether the input is a proper JSON text
8793 */
accept(const bool strict=true)8794 bool accept(const bool strict = true)
8795 {
8796 json_sax_acceptor<BasicJsonType> sax_acceptor;
8797 return sax_parse(&sax_acceptor, strict);
8798 }
8799
8800 template <typename SAX>
8801 JSON_HEDLEY_NON_NULL(2)
sax_parse(SAX * sax,const bool strict=true)8802 bool sax_parse(SAX* sax, const bool strict = true)
8803 {
8804 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
8805 const bool result = sax_parse_internal(sax);
8806
8807 // strict mode: next byte must be EOF
8808 if (result and strict and (get_token() != token_type::end_of_input))
8809 {
8810 return sax->parse_error(m_lexer.get_position(),
8811 m_lexer.get_token_string(),
8812 parse_error::create(101, m_lexer.get_position(),
8813 exception_message(token_type::end_of_input, "value")));
8814 }
8815
8816 return result;
8817 }
8818
8819 private:
8820 template <typename SAX>
8821 JSON_HEDLEY_NON_NULL(2)
sax_parse_internal(SAX * sax)8822 bool sax_parse_internal(SAX* sax)
8823 {
8824 // stack to remember the hierarchy of structured values we are parsing
8825 // true = array; false = object
8826 std::vector<bool> states;
8827 // value to avoid a goto (see comment where set to true)
8828 bool skip_to_state_evaluation = false;
8829
8830 while (true)
8831 {
8832 if (not skip_to_state_evaluation)
8833 {
8834 // invariant: get_token() was called before each iteration
8835 switch (last_token)
8836 {
8837 case token_type::begin_object:
8838 {
8839 if (JSON_HEDLEY_UNLIKELY(not sax->start_object(std::size_t(-1))))
8840 {
8841 return false;
8842 }
8843
8844 // closing } -> we are done
8845 if (get_token() == token_type::end_object)
8846 {
8847 if (JSON_HEDLEY_UNLIKELY(not sax->end_object()))
8848 {
8849 return false;
8850 }
8851 break;
8852 }
8853
8854 // parse key
8855 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
8856 {
8857 return sax->parse_error(m_lexer.get_position(),
8858 m_lexer.get_token_string(),
8859 parse_error::create(101, m_lexer.get_position(),
8860 exception_message(token_type::value_string, "object key")));
8861 }
8862 if (JSON_HEDLEY_UNLIKELY(not sax->key(m_lexer.get_string())))
8863 {
8864 return false;
8865 }
8866
8867 // parse separator (:)
8868 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
8869 {
8870 return sax->parse_error(m_lexer.get_position(),
8871 m_lexer.get_token_string(),
8872 parse_error::create(101, m_lexer.get_position(),
8873 exception_message(token_type::name_separator, "object separator")));
8874 }
8875
8876 // remember we are now inside an object
8877 states.push_back(false);
8878
8879 // parse values
8880 get_token();
8881 continue;
8882 }
8883
8884 case token_type::begin_array:
8885 {
8886 if (JSON_HEDLEY_UNLIKELY(not sax->start_array(std::size_t(-1))))
8887 {
8888 return false;
8889 }
8890
8891 // closing ] -> we are done
8892 if (get_token() == token_type::end_array)
8893 {
8894 if (JSON_HEDLEY_UNLIKELY(not sax->end_array()))
8895 {
8896 return false;
8897 }
8898 break;
8899 }
8900
8901 // remember we are now inside an array
8902 states.push_back(true);
8903
8904 // parse values (no need to call get_token)
8905 continue;
8906 }
8907
8908 case token_type::value_float:
8909 {
8910 const auto res = m_lexer.get_number_float();
8911
8912 if (JSON_HEDLEY_UNLIKELY(not std::isfinite(res)))
8913 {
8914 return sax->parse_error(m_lexer.get_position(),
8915 m_lexer.get_token_string(),
8916 out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
8917 }
8918
8919 if (JSON_HEDLEY_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
8920 {
8921 return false;
8922 }
8923
8924 break;
8925 }
8926
8927 case token_type::literal_false:
8928 {
8929 if (JSON_HEDLEY_UNLIKELY(not sax->boolean(false)))
8930 {
8931 return false;
8932 }
8933 break;
8934 }
8935
8936 case token_type::literal_null:
8937 {
8938 if (JSON_HEDLEY_UNLIKELY(not sax->null()))
8939 {
8940 return false;
8941 }
8942 break;
8943 }
8944
8945 case token_type::literal_true:
8946 {
8947 if (JSON_HEDLEY_UNLIKELY(not sax->boolean(true)))
8948 {
8949 return false;
8950 }
8951 break;
8952 }
8953
8954 case token_type::value_integer:
8955 {
8956 if (JSON_HEDLEY_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
8957 {
8958 return false;
8959 }
8960 break;
8961 }
8962
8963 case token_type::value_string:
8964 {
8965 if (JSON_HEDLEY_UNLIKELY(not sax->string(m_lexer.get_string())))
8966 {
8967 return false;
8968 }
8969 break;
8970 }
8971
8972 case token_type::value_unsigned:
8973 {
8974 if (JSON_HEDLEY_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
8975 {
8976 return false;
8977 }
8978 break;
8979 }
8980
8981 case token_type::parse_error:
8982 {
8983 // using "uninitialized" to avoid "expected" message
8984 return sax->parse_error(m_lexer.get_position(),
8985 m_lexer.get_token_string(),
8986 parse_error::create(101, m_lexer.get_position(),
8987 exception_message(token_type::uninitialized, "value")));
8988 }
8989
8990 default: // the last token was unexpected
8991 {
8992 return sax->parse_error(m_lexer.get_position(),
8993 m_lexer.get_token_string(),
8994 parse_error::create(101, m_lexer.get_position(),
8995 exception_message(token_type::literal_or_value, "value")));
8996 }
8997 }
8998 }
8999 else
9000 {
9001 skip_to_state_evaluation = false;
9002 }
9003
9004 // we reached this line after we successfully parsed a value
9005 if (states.empty())
9006 {
9007 // empty stack: we reached the end of the hierarchy: done
9008 return true;
9009 }
9010
9011 if (states.back()) // array
9012 {
9013 // comma -> next value
9014 if (get_token() == token_type::value_separator)
9015 {
9016 // parse a new value
9017 get_token();
9018 continue;
9019 }
9020
9021 // closing ]
9022 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
9023 {
9024 if (JSON_HEDLEY_UNLIKELY(not sax->end_array()))
9025 {
9026 return false;
9027 }
9028
9029 // We are done with this array. Before we can parse a
9030 // new value, we need to evaluate the new state first.
9031 // By setting skip_to_state_evaluation to false, we
9032 // are effectively jumping to the beginning of this if.
9033 assert(not states.empty());
9034 states.pop_back();
9035 skip_to_state_evaluation = true;
9036 continue;
9037 }
9038
9039 return sax->parse_error(m_lexer.get_position(),
9040 m_lexer.get_token_string(),
9041 parse_error::create(101, m_lexer.get_position(),
9042 exception_message(token_type::end_array, "array")));
9043 }
9044 else // object
9045 {
9046 // comma -> next value
9047 if (get_token() == token_type::value_separator)
9048 {
9049 // parse key
9050 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
9051 {
9052 return sax->parse_error(m_lexer.get_position(),
9053 m_lexer.get_token_string(),
9054 parse_error::create(101, m_lexer.get_position(),
9055 exception_message(token_type::value_string, "object key")));
9056 }
9057
9058 if (JSON_HEDLEY_UNLIKELY(not sax->key(m_lexer.get_string())))
9059 {
9060 return false;
9061 }
9062
9063 // parse separator (:)
9064 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
9065 {
9066 return sax->parse_error(m_lexer.get_position(),
9067 m_lexer.get_token_string(),
9068 parse_error::create(101, m_lexer.get_position(),
9069 exception_message(token_type::name_separator, "object separator")));
9070 }
9071
9072 // parse values
9073 get_token();
9074 continue;
9075 }
9076
9077 // closing }
9078 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
9079 {
9080 if (JSON_HEDLEY_UNLIKELY(not sax->end_object()))
9081 {
9082 return false;
9083 }
9084
9085 // We are done with this object. Before we can parse a
9086 // new value, we need to evaluate the new state first.
9087 // By setting skip_to_state_evaluation to false, we
9088 // are effectively jumping to the beginning of this if.
9089 assert(not states.empty());
9090 states.pop_back();
9091 skip_to_state_evaluation = true;
9092 continue;
9093 }
9094
9095 return sax->parse_error(m_lexer.get_position(),
9096 m_lexer.get_token_string(),
9097 parse_error::create(101, m_lexer.get_position(),
9098 exception_message(token_type::end_object, "object")));
9099 }
9100 }
9101 }
9102
9103 /// get next token from lexer
get_token()9104 token_type get_token()
9105 {
9106 return last_token = m_lexer.scan();
9107 }
9108
exception_message(const token_type expected,const std::string & context)9109 std::string exception_message(const token_type expected, const std::string& context)
9110 {
9111 std::string error_msg = "syntax error ";
9112
9113 if (not context.empty())
9114 {
9115 error_msg += "while parsing " + context + " ";
9116 }
9117
9118 error_msg += "- ";
9119
9120 if (last_token == token_type::parse_error)
9121 {
9122 error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
9123 m_lexer.get_token_string() + "'";
9124 }
9125 else
9126 {
9127 error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
9128 }
9129
9130 if (expected != token_type::uninitialized)
9131 {
9132 error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
9133 }
9134
9135 return error_msg;
9136 }
9137
9138 private:
9139 /// callback function
9140 const parser_callback_t callback = nullptr;
9141 /// the type of the last read token
9142 token_type last_token = token_type::uninitialized;
9143 /// the lexer
9144 lexer_t m_lexer;
9145 /// whether to throw exceptions in case of errors
9146 const bool allow_exceptions = true;
9147 };
9148 } // namespace detail
9149 } // namespace nlohmann
9150
9151 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
9152
9153
9154 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
9155
9156
9157 #include <cstddef> // ptrdiff_t
9158 #include <limits> // numeric_limits
9159
9160 namespace nlohmann
9161 {
9162 namespace detail
9163 {
9164 /*
9165 @brief an iterator for primitive JSON types
9166
9167 This class models an iterator for primitive JSON types (boolean, number,
9168 string). It's only purpose is to allow the iterator/const_iterator classes
9169 to "iterate" over primitive values. Internally, the iterator is modeled by
9170 a `difference_type` variable. Value begin_value (`0`) models the begin,
9171 end_value (`1`) models past the end.
9172 */
9173 class primitive_iterator_t
9174 {
9175 private:
9176 using difference_type = std::ptrdiff_t;
9177 static constexpr difference_type begin_value = 0;
9178 static constexpr difference_type end_value = begin_value + 1;
9179
9180 /// iterator as signed integer type
9181 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
9182
9183 public:
get_value() const9184 constexpr difference_type get_value() const noexcept
9185 {
9186 return m_it;
9187 }
9188
9189 /// set iterator to a defined beginning
set_begin()9190 void set_begin() noexcept
9191 {
9192 m_it = begin_value;
9193 }
9194
9195 /// set iterator to a defined past the end
set_end()9196 void set_end() noexcept
9197 {
9198 m_it = end_value;
9199 }
9200
9201 /// return whether the iterator can be dereferenced
is_begin() const9202 constexpr bool is_begin() const noexcept
9203 {
9204 return m_it == begin_value;
9205 }
9206
9207 /// return whether the iterator is at end
is_end() const9208 constexpr bool is_end() const noexcept
9209 {
9210 return m_it == end_value;
9211 }
9212
operator ==(primitive_iterator_t lhs,primitive_iterator_t rhs)9213 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
9214 {
9215 return lhs.m_it == rhs.m_it;
9216 }
9217
operator <(primitive_iterator_t lhs,primitive_iterator_t rhs)9218 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
9219 {
9220 return lhs.m_it < rhs.m_it;
9221 }
9222
operator +(difference_type n)9223 primitive_iterator_t operator+(difference_type n) noexcept
9224 {
9225 auto result = *this;
9226 result += n;
9227 return result;
9228 }
9229
operator -(primitive_iterator_t lhs,primitive_iterator_t rhs)9230 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
9231 {
9232 return lhs.m_it - rhs.m_it;
9233 }
9234
operator ++()9235 primitive_iterator_t& operator++() noexcept
9236 {
9237 ++m_it;
9238 return *this;
9239 }
9240
operator ++(int)9241 primitive_iterator_t const operator++(int) noexcept
9242 {
9243 auto result = *this;
9244 ++m_it;
9245 return result;
9246 }
9247
operator --()9248 primitive_iterator_t& operator--() noexcept
9249 {
9250 --m_it;
9251 return *this;
9252 }
9253
operator --(int)9254 primitive_iterator_t const operator--(int) noexcept
9255 {
9256 auto result = *this;
9257 --m_it;
9258 return result;
9259 }
9260
operator +=(difference_type n)9261 primitive_iterator_t& operator+=(difference_type n) noexcept
9262 {
9263 m_it += n;
9264 return *this;
9265 }
9266
operator -=(difference_type n)9267 primitive_iterator_t& operator-=(difference_type n) noexcept
9268 {
9269 m_it -= n;
9270 return *this;
9271 }
9272 };
9273 } // namespace detail
9274 } // namespace nlohmann
9275
9276
9277 namespace nlohmann
9278 {
9279 namespace detail
9280 {
9281 /*!
9282 @brief an iterator value
9283
9284 @note This structure could easily be a union, but MSVC currently does not allow
9285 unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
9286 */
9287 template<typename BasicJsonType> struct internal_iterator
9288 {
9289 /// iterator for JSON objects
9290 typename BasicJsonType::object_t::iterator object_iterator {};
9291 /// iterator for JSON arrays
9292 typename BasicJsonType::array_t::iterator array_iterator {};
9293 /// generic iterator for all other types
9294 primitive_iterator_t primitive_iterator {};
9295 };
9296 } // namespace detail
9297 } // namespace nlohmann
9298
9299 // #include <nlohmann/detail/iterators/iter_impl.hpp>
9300
9301
9302 #include <ciso646> // not
9303 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
9304 #include <type_traits> // conditional, is_const, remove_const
9305
9306 // #include <nlohmann/detail/exceptions.hpp>
9307
9308 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
9309
9310 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
9311
9312 // #include <nlohmann/detail/macro_scope.hpp>
9313
9314 // #include <nlohmann/detail/meta/cpp_future.hpp>
9315
9316 // #include <nlohmann/detail/meta/type_traits.hpp>
9317
9318 // #include <nlohmann/detail/value_t.hpp>
9319
9320
9321 namespace nlohmann
9322 {
9323 namespace detail
9324 {
9325 // forward declare, to be able to friend it later on
9326 template<typename IteratorType> class iteration_proxy;
9327 template<typename IteratorType> class iteration_proxy_value;
9328
9329 /*!
9330 @brief a template for a bidirectional iterator for the @ref basic_json class
9331 This class implements a both iterators (iterator and const_iterator) for the
9332 @ref basic_json class.
9333 @note An iterator is called *initialized* when a pointer to a JSON value has
9334 been set (e.g., by a constructor or a copy assignment). If the iterator is
9335 default-constructed, it is *uninitialized* and most methods are undefined.
9336 **The library uses assertions to detect calls on uninitialized iterators.**
9337 @requirement The class satisfies the following concept requirements:
9338 -
9339 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
9340 The iterator that can be moved can be moved in both directions (i.e.
9341 incremented and decremented).
9342 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional
9343 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
9344 */
9345 template<typename BasicJsonType>
9346 class iter_impl
9347 {
9348 /// allow basic_json to access private members
9349 friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
9350 friend BasicJsonType;
9351 friend iteration_proxy<iter_impl>;
9352 friend iteration_proxy_value<iter_impl>;
9353
9354 using object_t = typename BasicJsonType::object_t;
9355 using array_t = typename BasicJsonType::array_t;
9356 // make sure BasicJsonType is basic_json or const basic_json
9357 static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
9358 "iter_impl only accepts (const) basic_json");
9359
9360 public:
9361
9362 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
9363 /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
9364 /// A user-defined iterator should provide publicly accessible typedefs named
9365 /// iterator_category, value_type, difference_type, pointer, and reference.
9366 /// Note that value_type is required to be non-const, even for constant iterators.
9367 using iterator_category = std::bidirectional_iterator_tag;
9368
9369 /// the type of the values when the iterator is dereferenced
9370 using value_type = typename BasicJsonType::value_type;
9371 /// a type to represent differences between iterators
9372 using difference_type = typename BasicJsonType::difference_type;
9373 /// defines a pointer to the type iterated over (value_type)
9374 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
9375 typename BasicJsonType::const_pointer,
9376 typename BasicJsonType::pointer>::type;
9377 /// defines a reference to the type iterated over (value_type)
9378 using reference =
9379 typename std::conditional<std::is_const<BasicJsonType>::value,
9380 typename BasicJsonType::const_reference,
9381 typename BasicJsonType::reference>::type;
9382
9383 /// default constructor
9384 iter_impl() = default;
9385
9386 /*!
9387 @brief constructor for a given JSON instance
9388 @param[in] object pointer to a JSON object for this iterator
9389 @pre object != nullptr
9390 @post The iterator is initialized; i.e. `m_object != nullptr`.
9391 */
iter_impl(pointer object)9392 explicit iter_impl(pointer object) noexcept : m_object(object)
9393 {
9394 assert(m_object != nullptr);
9395
9396 switch (m_object->m_type)
9397 {
9398 case value_t::object:
9399 {
9400 m_it.object_iterator = typename object_t::iterator();
9401 break;
9402 }
9403
9404 case value_t::array:
9405 {
9406 m_it.array_iterator = typename array_t::iterator();
9407 break;
9408 }
9409
9410 default:
9411 {
9412 m_it.primitive_iterator = primitive_iterator_t();
9413 break;
9414 }
9415 }
9416 }
9417
9418 /*!
9419 @note The conventional copy constructor and copy assignment are implicitly
9420 defined. Combined with the following converting constructor and
9421 assignment, they support: (1) copy from iterator to iterator, (2)
9422 copy from const iterator to const iterator, and (3) conversion from
9423 iterator to const iterator. However conversion from const iterator
9424 to iterator is not defined.
9425 */
9426
9427 /*!
9428 @brief const copy constructor
9429 @param[in] other const iterator to copy from
9430 @note This copy constructor had to be defined explicitly to circumvent a bug
9431 occurring on msvc v19.0 compiler (VS 2015) debug build. For more
9432 information refer to: https://github.com/nlohmann/json/issues/1608
9433 */
iter_impl(const iter_impl<const BasicJsonType> & other)9434 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
9435 : m_object(other.m_object), m_it(other.m_it)
9436 {}
9437
9438 /*!
9439 @brief converting assignment
9440 @param[in] other const iterator to copy from
9441 @return const/non-const iterator
9442 @note It is not checked whether @a other is initialized.
9443 */
operator =(const iter_impl<const BasicJsonType> & other)9444 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
9445 {
9446 m_object = other.m_object;
9447 m_it = other.m_it;
9448 return *this;
9449 }
9450
9451 /*!
9452 @brief converting constructor
9453 @param[in] other non-const iterator to copy from
9454 @note It is not checked whether @a other is initialized.
9455 */
iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type> & other)9456 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
9457 : m_object(other.m_object), m_it(other.m_it)
9458 {}
9459
9460 /*!
9461 @brief converting assignment
9462 @param[in] other non-const iterator to copy from
9463 @return const/non-const iterator
9464 @note It is not checked whether @a other is initialized.
9465 */
operator =(const iter_impl<typename std::remove_const<BasicJsonType>::type> & other)9466 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
9467 {
9468 m_object = other.m_object;
9469 m_it = other.m_it;
9470 return *this;
9471 }
9472
9473 private:
9474 /*!
9475 @brief set the iterator to the first value
9476 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9477 */
set_begin()9478 void set_begin() noexcept
9479 {
9480 assert(m_object != nullptr);
9481
9482 switch (m_object->m_type)
9483 {
9484 case value_t::object:
9485 {
9486 m_it.object_iterator = m_object->m_value.object->begin();
9487 break;
9488 }
9489
9490 case value_t::array:
9491 {
9492 m_it.array_iterator = m_object->m_value.array->begin();
9493 break;
9494 }
9495
9496 case value_t::null:
9497 {
9498 // set to end so begin()==end() is true: null is empty
9499 m_it.primitive_iterator.set_end();
9500 break;
9501 }
9502
9503 default:
9504 {
9505 m_it.primitive_iterator.set_begin();
9506 break;
9507 }
9508 }
9509 }
9510
9511 /*!
9512 @brief set the iterator past the last value
9513 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9514 */
set_end()9515 void set_end() noexcept
9516 {
9517 assert(m_object != nullptr);
9518
9519 switch (m_object->m_type)
9520 {
9521 case value_t::object:
9522 {
9523 m_it.object_iterator = m_object->m_value.object->end();
9524 break;
9525 }
9526
9527 case value_t::array:
9528 {
9529 m_it.array_iterator = m_object->m_value.array->end();
9530 break;
9531 }
9532
9533 default:
9534 {
9535 m_it.primitive_iterator.set_end();
9536 break;
9537 }
9538 }
9539 }
9540
9541 public:
9542 /*!
9543 @brief return a reference to the value pointed to by the iterator
9544 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9545 */
operator *() const9546 reference operator*() const
9547 {
9548 assert(m_object != nullptr);
9549
9550 switch (m_object->m_type)
9551 {
9552 case value_t::object:
9553 {
9554 assert(m_it.object_iterator != m_object->m_value.object->end());
9555 return m_it.object_iterator->second;
9556 }
9557
9558 case value_t::array:
9559 {
9560 assert(m_it.array_iterator != m_object->m_value.array->end());
9561 return *m_it.array_iterator;
9562 }
9563
9564 case value_t::null:
9565 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
9566
9567 default:
9568 {
9569 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
9570 {
9571 return *m_object;
9572 }
9573
9574 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
9575 }
9576 }
9577 }
9578
9579 /*!
9580 @brief dereference the iterator
9581 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9582 */
operator ->() const9583 pointer operator->() const
9584 {
9585 assert(m_object != nullptr);
9586
9587 switch (m_object->m_type)
9588 {
9589 case value_t::object:
9590 {
9591 assert(m_it.object_iterator != m_object->m_value.object->end());
9592 return &(m_it.object_iterator->second);
9593 }
9594
9595 case value_t::array:
9596 {
9597 assert(m_it.array_iterator != m_object->m_value.array->end());
9598 return &*m_it.array_iterator;
9599 }
9600
9601 default:
9602 {
9603 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
9604 {
9605 return m_object;
9606 }
9607
9608 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
9609 }
9610 }
9611 }
9612
9613 /*!
9614 @brief post-increment (it++)
9615 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9616 */
operator ++(int)9617 iter_impl const operator++(int)
9618 {
9619 auto result = *this;
9620 ++(*this);
9621 return result;
9622 }
9623
9624 /*!
9625 @brief pre-increment (++it)
9626 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9627 */
operator ++()9628 iter_impl& operator++()
9629 {
9630 assert(m_object != nullptr);
9631
9632 switch (m_object->m_type)
9633 {
9634 case value_t::object:
9635 {
9636 std::advance(m_it.object_iterator, 1);
9637 break;
9638 }
9639
9640 case value_t::array:
9641 {
9642 std::advance(m_it.array_iterator, 1);
9643 break;
9644 }
9645
9646 default:
9647 {
9648 ++m_it.primitive_iterator;
9649 break;
9650 }
9651 }
9652
9653 return *this;
9654 }
9655
9656 /*!
9657 @brief post-decrement (it--)
9658 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9659 */
operator --(int)9660 iter_impl const operator--(int)
9661 {
9662 auto result = *this;
9663 --(*this);
9664 return result;
9665 }
9666
9667 /*!
9668 @brief pre-decrement (--it)
9669 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9670 */
operator --()9671 iter_impl& operator--()
9672 {
9673 assert(m_object != nullptr);
9674
9675 switch (m_object->m_type)
9676 {
9677 case value_t::object:
9678 {
9679 std::advance(m_it.object_iterator, -1);
9680 break;
9681 }
9682
9683 case value_t::array:
9684 {
9685 std::advance(m_it.array_iterator, -1);
9686 break;
9687 }
9688
9689 default:
9690 {
9691 --m_it.primitive_iterator;
9692 break;
9693 }
9694 }
9695
9696 return *this;
9697 }
9698
9699 /*!
9700 @brief comparison: equal
9701 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9702 */
operator ==(const iter_impl & other) const9703 bool operator==(const iter_impl& other) const
9704 {
9705 // if objects are not the same, the comparison is undefined
9706 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
9707 {
9708 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
9709 }
9710
9711 assert(m_object != nullptr);
9712
9713 switch (m_object->m_type)
9714 {
9715 case value_t::object:
9716 return (m_it.object_iterator == other.m_it.object_iterator);
9717
9718 case value_t::array:
9719 return (m_it.array_iterator == other.m_it.array_iterator);
9720
9721 default:
9722 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
9723 }
9724 }
9725
9726 /*!
9727 @brief comparison: not equal
9728 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9729 */
operator !=(const iter_impl & other) const9730 bool operator!=(const iter_impl& other) const
9731 {
9732 return not operator==(other);
9733 }
9734
9735 /*!
9736 @brief comparison: smaller
9737 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9738 */
operator <(const iter_impl & other) const9739 bool operator<(const iter_impl& other) const
9740 {
9741 // if objects are not the same, the comparison is undefined
9742 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
9743 {
9744 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
9745 }
9746
9747 assert(m_object != nullptr);
9748
9749 switch (m_object->m_type)
9750 {
9751 case value_t::object:
9752 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
9753
9754 case value_t::array:
9755 return (m_it.array_iterator < other.m_it.array_iterator);
9756
9757 default:
9758 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
9759 }
9760 }
9761
9762 /*!
9763 @brief comparison: less than or equal
9764 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9765 */
operator <=(const iter_impl & other) const9766 bool operator<=(const iter_impl& other) const
9767 {
9768 return not other.operator < (*this);
9769 }
9770
9771 /*!
9772 @brief comparison: greater than
9773 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9774 */
operator >(const iter_impl & other) const9775 bool operator>(const iter_impl& other) const
9776 {
9777 return not operator<=(other);
9778 }
9779
9780 /*!
9781 @brief comparison: greater than or equal
9782 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9783 */
operator >=(const iter_impl & other) const9784 bool operator>=(const iter_impl& other) const
9785 {
9786 return not operator<(other);
9787 }
9788
9789 /*!
9790 @brief add to iterator
9791 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9792 */
operator +=(difference_type i)9793 iter_impl& operator+=(difference_type i)
9794 {
9795 assert(m_object != nullptr);
9796
9797 switch (m_object->m_type)
9798 {
9799 case value_t::object:
9800 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
9801
9802 case value_t::array:
9803 {
9804 std::advance(m_it.array_iterator, i);
9805 break;
9806 }
9807
9808 default:
9809 {
9810 m_it.primitive_iterator += i;
9811 break;
9812 }
9813 }
9814
9815 return *this;
9816 }
9817
9818 /*!
9819 @brief subtract from iterator
9820 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9821 */
operator -=(difference_type i)9822 iter_impl& operator-=(difference_type i)
9823 {
9824 return operator+=(-i);
9825 }
9826
9827 /*!
9828 @brief add to iterator
9829 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9830 */
operator +(difference_type i) const9831 iter_impl operator+(difference_type i) const
9832 {
9833 auto result = *this;
9834 result += i;
9835 return result;
9836 }
9837
9838 /*!
9839 @brief addition of distance and iterator
9840 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9841 */
operator +(difference_type i,const iter_impl & it)9842 friend iter_impl operator+(difference_type i, const iter_impl& it)
9843 {
9844 auto result = it;
9845 result += i;
9846 return result;
9847 }
9848
9849 /*!
9850 @brief subtract from iterator
9851 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9852 */
operator -(difference_type i) const9853 iter_impl operator-(difference_type i) const
9854 {
9855 auto result = *this;
9856 result -= i;
9857 return result;
9858 }
9859
9860 /*!
9861 @brief return difference
9862 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9863 */
operator -(const iter_impl & other) const9864 difference_type operator-(const iter_impl& other) const
9865 {
9866 assert(m_object != nullptr);
9867
9868 switch (m_object->m_type)
9869 {
9870 case value_t::object:
9871 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
9872
9873 case value_t::array:
9874 return m_it.array_iterator - other.m_it.array_iterator;
9875
9876 default:
9877 return m_it.primitive_iterator - other.m_it.primitive_iterator;
9878 }
9879 }
9880
9881 /*!
9882 @brief access to successor
9883 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9884 */
operator [](difference_type n) const9885 reference operator[](difference_type n) const
9886 {
9887 assert(m_object != nullptr);
9888
9889 switch (m_object->m_type)
9890 {
9891 case value_t::object:
9892 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
9893
9894 case value_t::array:
9895 return *std::next(m_it.array_iterator, n);
9896
9897 case value_t::null:
9898 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
9899
9900 default:
9901 {
9902 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
9903 {
9904 return *m_object;
9905 }
9906
9907 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
9908 }
9909 }
9910 }
9911
9912 /*!
9913 @brief return the key of an object iterator
9914 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9915 */
key() const9916 const typename object_t::key_type& key() const
9917 {
9918 assert(m_object != nullptr);
9919
9920 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
9921 {
9922 return m_it.object_iterator->first;
9923 }
9924
9925 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
9926 }
9927
9928 /*!
9929 @brief return the value of an iterator
9930 @pre The iterator is initialized; i.e. `m_object != nullptr`.
9931 */
value() const9932 reference value() const
9933 {
9934 return operator*();
9935 }
9936
9937 private:
9938 /// associated JSON instance
9939 pointer m_object = nullptr;
9940 /// the actual iterator of the associated instance
9941 internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
9942 };
9943 } // namespace detail
9944 } // namespace nlohmann
9945
9946 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
9947
9948 // #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
9949
9950
9951 #include <cstddef> // ptrdiff_t
9952 #include <iterator> // reverse_iterator
9953 #include <utility> // declval
9954
9955 namespace nlohmann
9956 {
9957 namespace detail
9958 {
9959 //////////////////////
9960 // reverse_iterator //
9961 //////////////////////
9962
9963 /*!
9964 @brief a template for a reverse iterator class
9965
9966 @tparam Base the base iterator type to reverse. Valid types are @ref
9967 iterator (to create @ref reverse_iterator) and @ref const_iterator (to
9968 create @ref const_reverse_iterator).
9969
9970 @requirement The class satisfies the following concept requirements:
9971 -
9972 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
9973 The iterator that can be moved can be moved in both directions (i.e.
9974 incremented and decremented).
9975 - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
9976 It is possible to write to the pointed-to element (only if @a Base is
9977 @ref iterator).
9978
9979 @since version 1.0.0
9980 */
9981 template<typename Base>
9982 class json_reverse_iterator : public std::reverse_iterator<Base>
9983 {
9984 public:
9985 using difference_type = std::ptrdiff_t;
9986 /// shortcut to the reverse iterator adapter
9987 using base_iterator = std::reverse_iterator<Base>;
9988 /// the reference type for the pointed-to element
9989 using reference = typename Base::reference;
9990
9991 /// create reverse iterator from iterator
json_reverse_iterator(const typename base_iterator::iterator_type & it)9992 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
9993 : base_iterator(it) {}
9994
9995 /// create reverse iterator from base class
json_reverse_iterator(const base_iterator & it)9996 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
9997
9998 /// post-increment (it++)
operator ++(int)9999 json_reverse_iterator const operator++(int)
10000 {
10001 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
10002 }
10003
10004 /// pre-increment (++it)
operator ++()10005 json_reverse_iterator& operator++()
10006 {
10007 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
10008 }
10009
10010 /// post-decrement (it--)
operator --(int)10011 json_reverse_iterator const operator--(int)
10012 {
10013 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
10014 }
10015
10016 /// pre-decrement (--it)
operator --()10017 json_reverse_iterator& operator--()
10018 {
10019 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
10020 }
10021
10022 /// add to iterator
operator +=(difference_type i)10023 json_reverse_iterator& operator+=(difference_type i)
10024 {
10025 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
10026 }
10027
10028 /// add to iterator
operator +(difference_type i) const10029 json_reverse_iterator operator+(difference_type i) const
10030 {
10031 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
10032 }
10033
10034 /// subtract from iterator
operator -(difference_type i) const10035 json_reverse_iterator operator-(difference_type i) const
10036 {
10037 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
10038 }
10039
10040 /// return difference
operator -(const json_reverse_iterator & other) const10041 difference_type operator-(const json_reverse_iterator& other) const
10042 {
10043 return base_iterator(*this) - base_iterator(other);
10044 }
10045
10046 /// access to successor
operator [](difference_type n) const10047 reference operator[](difference_type n) const
10048 {
10049 return *(this->operator+(n));
10050 }
10051
10052 /// return the key of an object iterator
key() const10053 auto key() const -> decltype(std::declval<Base>().key())
10054 {
10055 auto it = --this->base();
10056 return it.key();
10057 }
10058
10059 /// return the value of an iterator
value() const10060 reference value() const
10061 {
10062 auto it = --this->base();
10063 return it.operator * ();
10064 }
10065 };
10066 } // namespace detail
10067 } // namespace nlohmann
10068
10069 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
10070
10071 // #include <nlohmann/detail/json_pointer.hpp>
10072
10073
10074 #include <algorithm> // all_of
10075 #include <cassert> // assert
10076 #include <cctype> // isdigit
10077 #include <numeric> // accumulate
10078 #include <string> // string
10079 #include <utility> // move
10080 #include <vector> // vector
10081
10082 // #include <nlohmann/detail/exceptions.hpp>
10083
10084 // #include <nlohmann/detail/macro_scope.hpp>
10085
10086 // #include <nlohmann/detail/value_t.hpp>
10087
10088
10089 namespace nlohmann
10090 {
10091 template<typename BasicJsonType>
10092 class json_pointer
10093 {
10094 // allow basic_json to access private members
10095 NLOHMANN_BASIC_JSON_TPL_DECLARATION
10096 friend class basic_json;
10097
10098 public:
10099 /*!
10100 @brief create JSON pointer
10101
10102 Create a JSON pointer according to the syntax described in
10103 [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).
10104
10105 @param[in] s string representing the JSON pointer; if omitted, the empty
10106 string is assumed which references the whole JSON value
10107
10108 @throw parse_error.107 if the given JSON pointer @a s is nonempty and does
10109 not begin with a slash (`/`); see example below
10110
10111 @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is
10112 not followed by `0` (representing `~`) or `1` (representing `/`); see
10113 example below
10114
10115 @liveexample{The example shows the construction several valid JSON pointers
10116 as well as the exceptional behavior.,json_pointer}
10117
10118 @since version 2.0.0
10119 */
json_pointer(const std::string & s="")10120 explicit json_pointer(const std::string& s = "")
10121 : reference_tokens(split(s))
10122 {}
10123
10124 /*!
10125 @brief return a string representation of the JSON pointer
10126
10127 @invariant For each JSON pointer `ptr`, it holds:
10128 @code {.cpp}
10129 ptr == json_pointer(ptr.to_string());
10130 @endcode
10131
10132 @return a string representation of the JSON pointer
10133
10134 @liveexample{The example shows the result of `to_string`.,json_pointer__to_string}
10135
10136 @since version 2.0.0
10137 */
to_string() const10138 std::string to_string() const
10139 {
10140 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
10141 std::string{},
10142 [](const std::string & a, const std::string & b)
10143 {
10144 return a + "/" + escape(b);
10145 });
10146 }
10147
10148 /// @copydoc to_string()
operator std::string() const10149 operator std::string() const
10150 {
10151 return to_string();
10152 }
10153
10154 /*!
10155 @brief append another JSON pointer at the end of this JSON pointer
10156
10157 @param[in] ptr JSON pointer to append
10158 @return JSON pointer with @a ptr appended
10159
10160 @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
10161
10162 @complexity Linear in the length of @a ptr.
10163
10164 @sa @ref operator/=(std::string) to append a reference token
10165 @sa @ref operator/=(std::size_t) to append an array index
10166 @sa @ref operator/(const json_pointer&, const json_pointer&) for a binary operator
10167
10168 @since version 3.6.0
10169 */
operator /=(const json_pointer & ptr)10170 json_pointer& operator/=(const json_pointer& ptr)
10171 {
10172 reference_tokens.insert(reference_tokens.end(),
10173 ptr.reference_tokens.begin(),
10174 ptr.reference_tokens.end());
10175 return *this;
10176 }
10177
10178 /*!
10179 @brief append an unescaped reference token at the end of this JSON pointer
10180
10181 @param[in] token reference token to append
10182 @return JSON pointer with @a token appended without escaping @a token
10183
10184 @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
10185
10186 @complexity Amortized constant.
10187
10188 @sa @ref operator/=(const json_pointer&) to append a JSON pointer
10189 @sa @ref operator/=(std::size_t) to append an array index
10190 @sa @ref operator/(const json_pointer&, std::size_t) for a binary operator
10191
10192 @since version 3.6.0
10193 */
operator /=(std::string token)10194 json_pointer& operator/=(std::string token)
10195 {
10196 push_back(std::move(token));
10197 return *this;
10198 }
10199
10200 /*!
10201 @brief append an array index at the end of this JSON pointer
10202
10203 @param[in] array_index array index to append
10204 @return JSON pointer with @a array_index appended
10205
10206 @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
10207
10208 @complexity Amortized constant.
10209
10210 @sa @ref operator/=(const json_pointer&) to append a JSON pointer
10211 @sa @ref operator/=(std::string) to append a reference token
10212 @sa @ref operator/(const json_pointer&, std::string) for a binary operator
10213
10214 @since version 3.6.0
10215 */
operator /=(std::size_t array_index)10216 json_pointer& operator/=(std::size_t array_index)
10217 {
10218 return *this /= std::to_string(array_index);
10219 }
10220
10221 /*!
10222 @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
10223
10224 @param[in] lhs JSON pointer
10225 @param[in] rhs JSON pointer
10226 @return a new JSON pointer with @a rhs appended to @a lhs
10227
10228 @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
10229
10230 @complexity Linear in the length of @a lhs and @a rhs.
10231
10232 @sa @ref operator/=(const json_pointer&) to append a JSON pointer
10233
10234 @since version 3.6.0
10235 */
operator /(const json_pointer & lhs,const json_pointer & rhs)10236 friend json_pointer operator/(const json_pointer& lhs,
10237 const json_pointer& rhs)
10238 {
10239 return json_pointer(lhs) /= rhs;
10240 }
10241
10242 /*!
10243 @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
10244
10245 @param[in] ptr JSON pointer
10246 @param[in] token reference token
10247 @return a new JSON pointer with unescaped @a token appended to @a ptr
10248
10249 @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
10250
10251 @complexity Linear in the length of @a ptr.
10252
10253 @sa @ref operator/=(std::string) to append a reference token
10254
10255 @since version 3.6.0
10256 */
operator /(const json_pointer & ptr,std::string token)10257 friend json_pointer operator/(const json_pointer& ptr, std::string token)
10258 {
10259 return json_pointer(ptr) /= std::move(token);
10260 }
10261
10262 /*!
10263 @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
10264
10265 @param[in] ptr JSON pointer
10266 @param[in] array_index array index
10267 @return a new JSON pointer with @a array_index appended to @a ptr
10268
10269 @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
10270
10271 @complexity Linear in the length of @a ptr.
10272
10273 @sa @ref operator/=(std::size_t) to append an array index
10274
10275 @since version 3.6.0
10276 */
operator /(const json_pointer & ptr,std::size_t array_index)10277 friend json_pointer operator/(const json_pointer& ptr, std::size_t array_index)
10278 {
10279 return json_pointer(ptr) /= array_index;
10280 }
10281
10282 /*!
10283 @brief returns the parent of this JSON pointer
10284
10285 @return parent of this JSON pointer; in case this JSON pointer is the root,
10286 the root itself is returned
10287
10288 @complexity Linear in the length of the JSON pointer.
10289
10290 @liveexample{The example shows the result of `parent_pointer` for different
10291 JSON Pointers.,json_pointer__parent_pointer}
10292
10293 @since version 3.6.0
10294 */
parent_pointer() const10295 json_pointer parent_pointer() const
10296 {
10297 if (empty())
10298 {
10299 return *this;
10300 }
10301
10302 json_pointer res = *this;
10303 res.pop_back();
10304 return res;
10305 }
10306
10307 /*!
10308 @brief remove last reference token
10309
10310 @pre not `empty()`
10311
10312 @liveexample{The example shows the usage of `pop_back`.,json_pointer__pop_back}
10313
10314 @complexity Constant.
10315
10316 @throw out_of_range.405 if JSON pointer has no parent
10317
10318 @since version 3.6.0
10319 */
pop_back()10320 void pop_back()
10321 {
10322 if (JSON_HEDLEY_UNLIKELY(empty()))
10323 {
10324 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
10325 }
10326
10327 reference_tokens.pop_back();
10328 }
10329
10330 /*!
10331 @brief return last reference token
10332
10333 @pre not `empty()`
10334 @return last reference token
10335
10336 @liveexample{The example shows the usage of `back`.,json_pointer__back}
10337
10338 @complexity Constant.
10339
10340 @throw out_of_range.405 if JSON pointer has no parent
10341
10342 @since version 3.6.0
10343 */
back() const10344 const std::string& back() const
10345 {
10346 if (JSON_HEDLEY_UNLIKELY(empty()))
10347 {
10348 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
10349 }
10350
10351 return reference_tokens.back();
10352 }
10353
10354 /*!
10355 @brief append an unescaped token at the end of the reference pointer
10356
10357 @param[in] token token to add
10358
10359 @complexity Amortized constant.
10360
10361 @liveexample{The example shows the result of `push_back` for different
10362 JSON Pointers.,json_pointer__push_back}
10363
10364 @since version 3.6.0
10365 */
push_back(const std::string & token)10366 void push_back(const std::string& token)
10367 {
10368 reference_tokens.push_back(token);
10369 }
10370
10371 /// @copydoc push_back(const std::string&)
push_back(std::string && token)10372 void push_back(std::string&& token)
10373 {
10374 reference_tokens.push_back(std::move(token));
10375 }
10376
10377 /*!
10378 @brief return whether pointer points to the root document
10379
10380 @return true iff the JSON pointer points to the root document
10381
10382 @complexity Constant.
10383
10384 @exceptionsafety No-throw guarantee: this function never throws exceptions.
10385
10386 @liveexample{The example shows the result of `empty` for different JSON
10387 Pointers.,json_pointer__empty}
10388
10389 @since version 3.6.0
10390 */
empty() const10391 bool empty() const noexcept
10392 {
10393 return reference_tokens.empty();
10394 }
10395
10396 private:
10397 /*!
10398 @param[in] s reference token to be converted into an array index
10399
10400 @return integer representation of @a s
10401
10402 @throw out_of_range.404 if string @a s could not be converted to an integer
10403 */
array_index(const std::string & s)10404 static int array_index(const std::string& s)
10405 {
10406 std::size_t processed_chars = 0;
10407 const int res = std::stoi(s, &processed_chars);
10408
10409 // check if the string was completely read
10410 if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
10411 {
10412 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
10413 }
10414
10415 return res;
10416 }
10417
top() const10418 json_pointer top() const
10419 {
10420 if (JSON_HEDLEY_UNLIKELY(empty()))
10421 {
10422 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
10423 }
10424
10425 json_pointer result = *this;
10426 result.reference_tokens = {reference_tokens[0]};
10427 return result;
10428 }
10429
10430 /*!
10431 @brief create and return a reference to the pointed to value
10432
10433 @complexity Linear in the number of reference tokens.
10434
10435 @throw parse_error.109 if array index is not a number
10436 @throw type_error.313 if value cannot be unflattened
10437 */
get_and_create(BasicJsonType & j) const10438 BasicJsonType& get_and_create(BasicJsonType& j) const
10439 {
10440 using size_type = typename BasicJsonType::size_type;
10441 auto result = &j;
10442
10443 // in case no reference tokens exist, return a reference to the JSON value
10444 // j which will be overwritten by a primitive value
10445 for (const auto& reference_token : reference_tokens)
10446 {
10447 switch (result->type())
10448 {
10449 case detail::value_t::null:
10450 {
10451 if (reference_token == "0")
10452 {
10453 // start a new array if reference token is 0
10454 result = &result->operator[](0);
10455 }
10456 else
10457 {
10458 // start a new object otherwise
10459 result = &result->operator[](reference_token);
10460 }
10461 break;
10462 }
10463
10464 case detail::value_t::object:
10465 {
10466 // create an entry in the object
10467 result = &result->operator[](reference_token);
10468 break;
10469 }
10470
10471 case detail::value_t::array:
10472 {
10473 // create an entry in the array
10474 JSON_TRY
10475 {
10476 result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
10477 }
10478 JSON_CATCH(std::invalid_argument&)
10479 {
10480 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10481 }
10482 break;
10483 }
10484
10485 /*
10486 The following code is only reached if there exists a reference
10487 token _and_ the current value is primitive. In this case, we have
10488 an error situation, because primitive values may only occur as
10489 single value; that is, with an empty list of reference tokens.
10490 */
10491 default:
10492 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
10493 }
10494 }
10495
10496 return *result;
10497 }
10498
10499 /*!
10500 @brief return a reference to the pointed to value
10501
10502 @note This version does not throw if a value is not present, but tries to
10503 create nested values instead. For instance, calling this function
10504 with pointer `"/this/that"` on a null value is equivalent to calling
10505 `operator[]("this").operator[]("that")` on that value, effectively
10506 changing the null value to an object.
10507
10508 @param[in] ptr a JSON value
10509
10510 @return reference to the JSON value pointed to by the JSON pointer
10511
10512 @complexity Linear in the length of the JSON pointer.
10513
10514 @throw parse_error.106 if an array index begins with '0'
10515 @throw parse_error.109 if an array index was not a number
10516 @throw out_of_range.404 if the JSON pointer can not be resolved
10517 */
get_unchecked(BasicJsonType * ptr) const10518 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
10519 {
10520 using size_type = typename BasicJsonType::size_type;
10521 for (const auto& reference_token : reference_tokens)
10522 {
10523 // convert null values to arrays or objects before continuing
10524 if (ptr->is_null())
10525 {
10526 // check if reference token is a number
10527 const bool nums =
10528 std::all_of(reference_token.begin(), reference_token.end(),
10529 [](const unsigned char x)
10530 {
10531 return std::isdigit(x);
10532 });
10533
10534 // change value to array for numbers or "-" or to object otherwise
10535 *ptr = (nums or reference_token == "-")
10536 ? detail::value_t::array
10537 : detail::value_t::object;
10538 }
10539
10540 switch (ptr->type())
10541 {
10542 case detail::value_t::object:
10543 {
10544 // use unchecked object access
10545 ptr = &ptr->operator[](reference_token);
10546 break;
10547 }
10548
10549 case detail::value_t::array:
10550 {
10551 // error condition (cf. RFC 6901, Sect. 4)
10552 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10553 {
10554 JSON_THROW(detail::parse_error::create(106, 0,
10555 "array index '" + reference_token +
10556 "' must not begin with '0'"));
10557 }
10558
10559 if (reference_token == "-")
10560 {
10561 // explicitly treat "-" as index beyond the end
10562 ptr = &ptr->operator[](ptr->m_value.array->size());
10563 }
10564 else
10565 {
10566 // convert array index to number; unchecked access
10567 JSON_TRY
10568 {
10569 ptr = &ptr->operator[](
10570 static_cast<size_type>(array_index(reference_token)));
10571 }
10572 JSON_CATCH(std::invalid_argument&)
10573 {
10574 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10575 }
10576 }
10577 break;
10578 }
10579
10580 default:
10581 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
10582 }
10583 }
10584
10585 return *ptr;
10586 }
10587
10588 /*!
10589 @throw parse_error.106 if an array index begins with '0'
10590 @throw parse_error.109 if an array index was not a number
10591 @throw out_of_range.402 if the array index '-' is used
10592 @throw out_of_range.404 if the JSON pointer can not be resolved
10593 */
get_checked(BasicJsonType * ptr) const10594 BasicJsonType& get_checked(BasicJsonType* ptr) const
10595 {
10596 using size_type = typename BasicJsonType::size_type;
10597 for (const auto& reference_token : reference_tokens)
10598 {
10599 switch (ptr->type())
10600 {
10601 case detail::value_t::object:
10602 {
10603 // note: at performs range check
10604 ptr = &ptr->at(reference_token);
10605 break;
10606 }
10607
10608 case detail::value_t::array:
10609 {
10610 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
10611 {
10612 // "-" always fails the range check
10613 JSON_THROW(detail::out_of_range::create(402,
10614 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
10615 ") is out of range"));
10616 }
10617
10618 // error condition (cf. RFC 6901, Sect. 4)
10619 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10620 {
10621 JSON_THROW(detail::parse_error::create(106, 0,
10622 "array index '" + reference_token +
10623 "' must not begin with '0'"));
10624 }
10625
10626 // note: at performs range check
10627 JSON_TRY
10628 {
10629 ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
10630 }
10631 JSON_CATCH(std::invalid_argument&)
10632 {
10633 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10634 }
10635 break;
10636 }
10637
10638 default:
10639 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
10640 }
10641 }
10642
10643 return *ptr;
10644 }
10645
10646 /*!
10647 @brief return a const reference to the pointed to value
10648
10649 @param[in] ptr a JSON value
10650
10651 @return const reference to the JSON value pointed to by the JSON
10652 pointer
10653
10654 @throw parse_error.106 if an array index begins with '0'
10655 @throw parse_error.109 if an array index was not a number
10656 @throw out_of_range.402 if the array index '-' is used
10657 @throw out_of_range.404 if the JSON pointer can not be resolved
10658 */
get_unchecked(const BasicJsonType * ptr) const10659 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
10660 {
10661 using size_type = typename BasicJsonType::size_type;
10662 for (const auto& reference_token : reference_tokens)
10663 {
10664 switch (ptr->type())
10665 {
10666 case detail::value_t::object:
10667 {
10668 // use unchecked object access
10669 ptr = &ptr->operator[](reference_token);
10670 break;
10671 }
10672
10673 case detail::value_t::array:
10674 {
10675 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
10676 {
10677 // "-" cannot be used for const access
10678 JSON_THROW(detail::out_of_range::create(402,
10679 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
10680 ") is out of range"));
10681 }
10682
10683 // error condition (cf. RFC 6901, Sect. 4)
10684 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10685 {
10686 JSON_THROW(detail::parse_error::create(106, 0,
10687 "array index '" + reference_token +
10688 "' must not begin with '0'"));
10689 }
10690
10691 // use unchecked array access
10692 JSON_TRY
10693 {
10694 ptr = &ptr->operator[](
10695 static_cast<size_type>(array_index(reference_token)));
10696 }
10697 JSON_CATCH(std::invalid_argument&)
10698 {
10699 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10700 }
10701 break;
10702 }
10703
10704 default:
10705 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
10706 }
10707 }
10708
10709 return *ptr;
10710 }
10711
10712 /*!
10713 @throw parse_error.106 if an array index begins with '0'
10714 @throw parse_error.109 if an array index was not a number
10715 @throw out_of_range.402 if the array index '-' is used
10716 @throw out_of_range.404 if the JSON pointer can not be resolved
10717 */
get_checked(const BasicJsonType * ptr) const10718 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
10719 {
10720 using size_type = typename BasicJsonType::size_type;
10721 for (const auto& reference_token : reference_tokens)
10722 {
10723 switch (ptr->type())
10724 {
10725 case detail::value_t::object:
10726 {
10727 // note: at performs range check
10728 ptr = &ptr->at(reference_token);
10729 break;
10730 }
10731
10732 case detail::value_t::array:
10733 {
10734 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
10735 {
10736 // "-" always fails the range check
10737 JSON_THROW(detail::out_of_range::create(402,
10738 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
10739 ") is out of range"));
10740 }
10741
10742 // error condition (cf. RFC 6901, Sect. 4)
10743 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10744 {
10745 JSON_THROW(detail::parse_error::create(106, 0,
10746 "array index '" + reference_token +
10747 "' must not begin with '0'"));
10748 }
10749
10750 // note: at performs range check
10751 JSON_TRY
10752 {
10753 ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
10754 }
10755 JSON_CATCH(std::invalid_argument&)
10756 {
10757 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10758 }
10759 break;
10760 }
10761
10762 default:
10763 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
10764 }
10765 }
10766
10767 return *ptr;
10768 }
10769
10770 /*!
10771 @throw parse_error.106 if an array index begins with '0'
10772 @throw parse_error.109 if an array index was not a number
10773 */
contains(const BasicJsonType * ptr) const10774 bool contains(const BasicJsonType* ptr) const
10775 {
10776 using size_type = typename BasicJsonType::size_type;
10777 for (const auto& reference_token : reference_tokens)
10778 {
10779 switch (ptr->type())
10780 {
10781 case detail::value_t::object:
10782 {
10783 if (not ptr->contains(reference_token))
10784 {
10785 // we did not find the key in the object
10786 return false;
10787 }
10788
10789 ptr = &ptr->operator[](reference_token);
10790 break;
10791 }
10792
10793 case detail::value_t::array:
10794 {
10795 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
10796 {
10797 // "-" always fails the range check
10798 return false;
10799 }
10800
10801 // error condition (cf. RFC 6901, Sect. 4)
10802 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10803 {
10804 JSON_THROW(detail::parse_error::create(106, 0,
10805 "array index '" + reference_token +
10806 "' must not begin with '0'"));
10807 }
10808
10809 JSON_TRY
10810 {
10811 const auto idx = static_cast<size_type>(array_index(reference_token));
10812 if (idx >= ptr->size())
10813 {
10814 // index out of range
10815 return false;
10816 }
10817
10818 ptr = &ptr->operator[](idx);
10819 break;
10820 }
10821 JSON_CATCH(std::invalid_argument&)
10822 {
10823 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10824 }
10825 break;
10826 }
10827
10828 default:
10829 {
10830 // we do not expect primitive values if there is still a
10831 // reference token to process
10832 return false;
10833 }
10834 }
10835 }
10836
10837 // no reference token left means we found a primitive value
10838 return true;
10839 }
10840
10841 /*!
10842 @brief split the string input to reference tokens
10843
10844 @note This function is only called by the json_pointer constructor.
10845 All exceptions below are documented there.
10846
10847 @throw parse_error.107 if the pointer is not empty or begins with '/'
10848 @throw parse_error.108 if character '~' is not followed by '0' or '1'
10849 */
split(const std::string & reference_string)10850 static std::vector<std::string> split(const std::string& reference_string)
10851 {
10852 std::vector<std::string> result;
10853
10854 // special case: empty reference string -> no reference tokens
10855 if (reference_string.empty())
10856 {
10857 return result;
10858 }
10859
10860 // check if nonempty reference string begins with slash
10861 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
10862 {
10863 JSON_THROW(detail::parse_error::create(107, 1,
10864 "JSON pointer must be empty or begin with '/' - was: '" +
10865 reference_string + "'"));
10866 }
10867
10868 // extract the reference tokens:
10869 // - slash: position of the last read slash (or end of string)
10870 // - start: position after the previous slash
10871 for (
10872 // search for the first slash after the first character
10873 std::size_t slash = reference_string.find_first_of('/', 1),
10874 // set the beginning of the first reference token
10875 start = 1;
10876 // we can stop if start == 0 (if slash == std::string::npos)
10877 start != 0;
10878 // set the beginning of the next reference token
10879 // (will eventually be 0 if slash == std::string::npos)
10880 start = (slash == std::string::npos) ? 0 : slash + 1,
10881 // find next slash
10882 slash = reference_string.find_first_of('/', start))
10883 {
10884 // use the text between the beginning of the reference token
10885 // (start) and the last slash (slash).
10886 auto reference_token = reference_string.substr(start, slash - start);
10887
10888 // check reference tokens are properly escaped
10889 for (std::size_t pos = reference_token.find_first_of('~');
10890 pos != std::string::npos;
10891 pos = reference_token.find_first_of('~', pos + 1))
10892 {
10893 assert(reference_token[pos] == '~');
10894
10895 // ~ must be followed by 0 or 1
10896 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 or
10897 (reference_token[pos + 1] != '0' and
10898 reference_token[pos + 1] != '1')))
10899 {
10900 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
10901 }
10902 }
10903
10904 // finally, store the reference token
10905 unescape(reference_token);
10906 result.push_back(reference_token);
10907 }
10908
10909 return result;
10910 }
10911
10912 /*!
10913 @brief replace all occurrences of a substring by another string
10914
10915 @param[in,out] s the string to manipulate; changed so that all
10916 occurrences of @a f are replaced with @a t
10917 @param[in] f the substring to replace with @a t
10918 @param[in] t the string to replace @a f
10919
10920 @pre The search string @a f must not be empty. **This precondition is
10921 enforced with an assertion.**
10922
10923 @since version 2.0.0
10924 */
replace_substring(std::string & s,const std::string & f,const std::string & t)10925 static void replace_substring(std::string& s, const std::string& f,
10926 const std::string& t)
10927 {
10928 assert(not f.empty());
10929 for (auto pos = s.find(f); // find first occurrence of f
10930 pos != std::string::npos; // make sure f was found
10931 s.replace(pos, f.size(), t), // replace with t, and
10932 pos = s.find(f, pos + t.size())) // find next occurrence of f
10933 {}
10934 }
10935
10936 /// escape "~" to "~0" and "/" to "~1"
escape(std::string s)10937 static std::string escape(std::string s)
10938 {
10939 replace_substring(s, "~", "~0");
10940 replace_substring(s, "/", "~1");
10941 return s;
10942 }
10943
10944 /// unescape "~1" to tilde and "~0" to slash (order is important!)
unescape(std::string & s)10945 static void unescape(std::string& s)
10946 {
10947 replace_substring(s, "~1", "/");
10948 replace_substring(s, "~0", "~");
10949 }
10950
10951 /*!
10952 @param[in] reference_string the reference string to the current value
10953 @param[in] value the value to consider
10954 @param[in,out] result the result object to insert values to
10955
10956 @note Empty objects or arrays are flattened to `null`.
10957 */
flatten(const std::string & reference_string,const BasicJsonType & value,BasicJsonType & result)10958 static void flatten(const std::string& reference_string,
10959 const BasicJsonType& value,
10960 BasicJsonType& result)
10961 {
10962 switch (value.type())
10963 {
10964 case detail::value_t::array:
10965 {
10966 if (value.m_value.array->empty())
10967 {
10968 // flatten empty array as null
10969 result[reference_string] = nullptr;
10970 }
10971 else
10972 {
10973 // iterate array and use index as reference string
10974 for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
10975 {
10976 flatten(reference_string + "/" + std::to_string(i),
10977 value.m_value.array->operator[](i), result);
10978 }
10979 }
10980 break;
10981 }
10982
10983 case detail::value_t::object:
10984 {
10985 if (value.m_value.object->empty())
10986 {
10987 // flatten empty object as null
10988 result[reference_string] = nullptr;
10989 }
10990 else
10991 {
10992 // iterate object and use keys as reference string
10993 for (const auto& element : *value.m_value.object)
10994 {
10995 flatten(reference_string + "/" + escape(element.first), element.second, result);
10996 }
10997 }
10998 break;
10999 }
11000
11001 default:
11002 {
11003 // add primitive value with its reference string
11004 result[reference_string] = value;
11005 break;
11006 }
11007 }
11008 }
11009
11010 /*!
11011 @param[in] value flattened JSON
11012
11013 @return unflattened JSON
11014
11015 @throw parse_error.109 if array index is not a number
11016 @throw type_error.314 if value is not an object
11017 @throw type_error.315 if object values are not primitive
11018 @throw type_error.313 if value cannot be unflattened
11019 */
11020 static BasicJsonType
unflatten(const BasicJsonType & value)11021 unflatten(const BasicJsonType& value)
11022 {
11023 if (JSON_HEDLEY_UNLIKELY(not value.is_object()))
11024 {
11025 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
11026 }
11027
11028 BasicJsonType result;
11029
11030 // iterate the JSON object values
11031 for (const auto& element : *value.m_value.object)
11032 {
11033 if (JSON_HEDLEY_UNLIKELY(not element.second.is_primitive()))
11034 {
11035 JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
11036 }
11037
11038 // assign value to reference pointed to by JSON pointer; Note that if
11039 // the JSON pointer is "" (i.e., points to the whole value), function
11040 // get_and_create returns a reference to result itself. An assignment
11041 // will then create a primitive value.
11042 json_pointer(element.first).get_and_create(result) = element.second;
11043 }
11044
11045 return result;
11046 }
11047
11048 /*!
11049 @brief compares two JSON pointers for equality
11050
11051 @param[in] lhs JSON pointer to compare
11052 @param[in] rhs JSON pointer to compare
11053 @return whether @a lhs is equal to @a rhs
11054
11055 @complexity Linear in the length of the JSON pointer
11056
11057 @exceptionsafety No-throw guarantee: this function never throws exceptions.
11058 */
operator ==(json_pointer const & lhs,json_pointer const & rhs)11059 friend bool operator==(json_pointer const& lhs,
11060 json_pointer const& rhs) noexcept
11061 {
11062 return lhs.reference_tokens == rhs.reference_tokens;
11063 }
11064
11065 /*!
11066 @brief compares two JSON pointers for inequality
11067
11068 @param[in] lhs JSON pointer to compare
11069 @param[in] rhs JSON pointer to compare
11070 @return whether @a lhs is not equal @a rhs
11071
11072 @complexity Linear in the length of the JSON pointer
11073
11074 @exceptionsafety No-throw guarantee: this function never throws exceptions.
11075 */
operator !=(json_pointer const & lhs,json_pointer const & rhs)11076 friend bool operator!=(json_pointer const& lhs,
11077 json_pointer const& rhs) noexcept
11078 {
11079 return not (lhs == rhs);
11080 }
11081
11082 /// the reference tokens
11083 std::vector<std::string> reference_tokens;
11084 };
11085 } // namespace nlohmann
11086
11087 // #include <nlohmann/detail/json_ref.hpp>
11088
11089
11090 #include <initializer_list>
11091 #include <utility>
11092
11093 // #include <nlohmann/detail/meta/type_traits.hpp>
11094
11095
11096 namespace nlohmann
11097 {
11098 namespace detail
11099 {
11100 template<typename BasicJsonType>
11101 class json_ref
11102 {
11103 public:
11104 using value_type = BasicJsonType;
11105
json_ref(value_type && value)11106 json_ref(value_type&& value)
11107 : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)
11108 {}
11109
json_ref(const value_type & value)11110 json_ref(const value_type& value)
11111 : value_ref(const_cast<value_type*>(&value)), is_rvalue(false)
11112 {}
11113
json_ref(std::initializer_list<json_ref> init)11114 json_ref(std::initializer_list<json_ref> init)
11115 : owned_value(init), value_ref(&owned_value), is_rvalue(true)
11116 {}
11117
11118 template <
11119 class... Args,
11120 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
json_ref(Args &&...args)11121 json_ref(Args && ... args)
11122 : owned_value(std::forward<Args>(args)...), value_ref(&owned_value),
11123 is_rvalue(true) {}
11124
11125 // class should be movable only
11126 json_ref(json_ref&&) = default;
11127 json_ref(const json_ref&) = delete;
11128 json_ref& operator=(const json_ref&) = delete;
11129 json_ref& operator=(json_ref&&) = delete;
11130 ~json_ref() = default;
11131
moved_or_copied() const11132 value_type moved_or_copied() const
11133 {
11134 if (is_rvalue)
11135 {
11136 return std::move(*value_ref);
11137 }
11138 return *value_ref;
11139 }
11140
operator *() const11141 value_type const& operator*() const
11142 {
11143 return *static_cast<value_type const*>(value_ref);
11144 }
11145
operator ->() const11146 value_type const* operator->() const
11147 {
11148 return static_cast<value_type const*>(value_ref);
11149 }
11150
11151 private:
11152 mutable value_type owned_value = nullptr;
11153 value_type* value_ref = nullptr;
11154 const bool is_rvalue;
11155 };
11156 } // namespace detail
11157 } // namespace nlohmann
11158
11159 // #include <nlohmann/detail/macro_scope.hpp>
11160
11161 // #include <nlohmann/detail/meta/cpp_future.hpp>
11162
11163 // #include <nlohmann/detail/meta/type_traits.hpp>
11164
11165 // #include <nlohmann/detail/output/binary_writer.hpp>
11166
11167
11168 #include <algorithm> // reverse
11169 #include <array> // array
11170 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
11171 #include <cstring> // memcpy
11172 #include <limits> // numeric_limits
11173 #include <string> // string
11174
11175 // #include <nlohmann/detail/input/binary_reader.hpp>
11176
11177 // #include <nlohmann/detail/macro_scope.hpp>
11178
11179 // #include <nlohmann/detail/output/output_adapters.hpp>
11180
11181
11182 #include <algorithm> // copy
11183 #include <cstddef> // size_t
11184 #include <ios> // streamsize
11185 #include <iterator> // back_inserter
11186 #include <memory> // shared_ptr, make_shared
11187 #include <ostream> // basic_ostream
11188 #include <string> // basic_string
11189 #include <vector> // vector
11190 // #include <nlohmann/detail/macro_scope.hpp>
11191
11192
11193 namespace nlohmann
11194 {
11195 namespace detail
11196 {
11197 /// abstract output adapter interface
11198 template<typename CharType> struct output_adapter_protocol
11199 {
11200 virtual void write_character(CharType c) = 0;
11201 virtual void write_characters(const CharType* s, std::size_t length) = 0;
11202 virtual ~output_adapter_protocol() = default;
11203 };
11204
11205 /// a type to simplify interfaces
11206 template<typename CharType>
11207 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
11208
11209 /// output adapter for byte vectors
11210 template<typename CharType>
11211 class output_vector_adapter : public output_adapter_protocol<CharType>
11212 {
11213 public:
output_vector_adapter(std::vector<CharType> & vec)11214 explicit output_vector_adapter(std::vector<CharType>& vec) noexcept
11215 : v(vec)
11216 {}
11217
write_character(CharType c)11218 void write_character(CharType c) override
11219 {
11220 v.push_back(c);
11221 }
11222
11223 JSON_HEDLEY_NON_NULL(2)
write_characters(const CharType * s,std::size_t length)11224 void write_characters(const CharType* s, std::size_t length) override
11225 {
11226 std::copy(s, s + length, std::back_inserter(v));
11227 }
11228
11229 private:
11230 std::vector<CharType>& v;
11231 };
11232
11233 /// output adapter for output streams
11234 template<typename CharType>
11235 class output_stream_adapter : public output_adapter_protocol<CharType>
11236 {
11237 public:
output_stream_adapter(std::basic_ostream<CharType> & s)11238 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
11239 : stream(s)
11240 {}
11241
write_character(CharType c)11242 void write_character(CharType c) override
11243 {
11244 stream.put(c);
11245 }
11246
11247 JSON_HEDLEY_NON_NULL(2)
write_characters(const CharType * s,std::size_t length)11248 void write_characters(const CharType* s, std::size_t length) override
11249 {
11250 stream.write(s, static_cast<std::streamsize>(length));
11251 }
11252
11253 private:
11254 std::basic_ostream<CharType>& stream;
11255 };
11256
11257 /// output adapter for basic_string
11258 template<typename CharType, typename StringType = std::basic_string<CharType>>
11259 class output_string_adapter : public output_adapter_protocol<CharType>
11260 {
11261 public:
output_string_adapter(StringType & s)11262 explicit output_string_adapter(StringType& s) noexcept
11263 : str(s)
11264 {}
11265
write_character(CharType c)11266 void write_character(CharType c) override
11267 {
11268 str.push_back(c);
11269 }
11270
11271 JSON_HEDLEY_NON_NULL(2)
write_characters(const CharType * s,std::size_t length)11272 void write_characters(const CharType* s, std::size_t length) override
11273 {
11274 str.append(s, length);
11275 }
11276
11277 private:
11278 StringType& str;
11279 };
11280
11281 template<typename CharType, typename StringType = std::basic_string<CharType>>
11282 class output_adapter
11283 {
11284 public:
output_adapter(std::vector<CharType> & vec)11285 output_adapter(std::vector<CharType>& vec)
11286 : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
11287
output_adapter(std::basic_ostream<CharType> & s)11288 output_adapter(std::basic_ostream<CharType>& s)
11289 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
11290
output_adapter(StringType & s)11291 output_adapter(StringType& s)
11292 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
11293
operator output_adapter_t<CharType>()11294 operator output_adapter_t<CharType>()
11295 {
11296 return oa;
11297 }
11298
11299 private:
11300 output_adapter_t<CharType> oa = nullptr;
11301 };
11302 } // namespace detail
11303 } // namespace nlohmann
11304
11305
11306 namespace nlohmann
11307 {
11308 namespace detail
11309 {
11310 ///////////////////
11311 // binary writer //
11312 ///////////////////
11313
11314 /*!
11315 @brief serialization to CBOR and MessagePack values
11316 */
11317 template<typename BasicJsonType, typename CharType>
11318 class binary_writer
11319 {
11320 using string_t = typename BasicJsonType::string_t;
11321
11322 public:
11323 /*!
11324 @brief create a binary writer
11325
11326 @param[in] adapter output adapter to write to
11327 */
binary_writer(output_adapter_t<CharType> adapter)11328 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
11329 {
11330 assert(oa);
11331 }
11332
11333 /*!
11334 @param[in] j JSON value to serialize
11335 @pre j.type() == value_t::object
11336 */
write_bson(const BasicJsonType & j)11337 void write_bson(const BasicJsonType& j)
11338 {
11339 switch (j.type())
11340 {
11341 case value_t::object:
11342 {
11343 write_bson_object(*j.m_value.object);
11344 break;
11345 }
11346
11347 default:
11348 {
11349 JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name())));
11350 }
11351 }
11352 }
11353
11354 /*!
11355 @param[in] j JSON value to serialize
11356 */
write_cbor(const BasicJsonType & j)11357 void write_cbor(const BasicJsonType& j)
11358 {
11359 switch (j.type())
11360 {
11361 case value_t::null:
11362 {
11363 oa->write_character(to_char_type(0xF6));
11364 break;
11365 }
11366
11367 case value_t::boolean:
11368 {
11369 oa->write_character(j.m_value.boolean
11370 ? to_char_type(0xF5)
11371 : to_char_type(0xF4));
11372 break;
11373 }
11374
11375 case value_t::number_integer:
11376 {
11377 if (j.m_value.number_integer >= 0)
11378 {
11379 // CBOR does not differentiate between positive signed
11380 // integers and unsigned integers. Therefore, we used the
11381 // code from the value_t::number_unsigned case here.
11382 if (j.m_value.number_integer <= 0x17)
11383 {
11384 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
11385 }
11386 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
11387 {
11388 oa->write_character(to_char_type(0x18));
11389 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
11390 }
11391 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
11392 {
11393 oa->write_character(to_char_type(0x19));
11394 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
11395 }
11396 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
11397 {
11398 oa->write_character(to_char_type(0x1A));
11399 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
11400 }
11401 else
11402 {
11403 oa->write_character(to_char_type(0x1B));
11404 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
11405 }
11406 }
11407 else
11408 {
11409 // The conversions below encode the sign in the first
11410 // byte, and the value is converted to a positive number.
11411 const auto positive_number = -1 - j.m_value.number_integer;
11412 if (j.m_value.number_integer >= -24)
11413 {
11414 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
11415 }
11416 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
11417 {
11418 oa->write_character(to_char_type(0x38));
11419 write_number(static_cast<std::uint8_t>(positive_number));
11420 }
11421 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
11422 {
11423 oa->write_character(to_char_type(0x39));
11424 write_number(static_cast<std::uint16_t>(positive_number));
11425 }
11426 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
11427 {
11428 oa->write_character(to_char_type(0x3A));
11429 write_number(static_cast<std::uint32_t>(positive_number));
11430 }
11431 else
11432 {
11433 oa->write_character(to_char_type(0x3B));
11434 write_number(static_cast<std::uint64_t>(positive_number));
11435 }
11436 }
11437 break;
11438 }
11439
11440 case value_t::number_unsigned:
11441 {
11442 if (j.m_value.number_unsigned <= 0x17)
11443 {
11444 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
11445 }
11446 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
11447 {
11448 oa->write_character(to_char_type(0x18));
11449 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
11450 }
11451 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
11452 {
11453 oa->write_character(to_char_type(0x19));
11454 write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
11455 }
11456 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
11457 {
11458 oa->write_character(to_char_type(0x1A));
11459 write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
11460 }
11461 else
11462 {
11463 oa->write_character(to_char_type(0x1B));
11464 write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
11465 }
11466 break;
11467 }
11468
11469 case value_t::number_float:
11470 {
11471 oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
11472 write_number(j.m_value.number_float);
11473 break;
11474 }
11475
11476 case value_t::string:
11477 {
11478 // step 1: write control byte and the string length
11479 const auto N = j.m_value.string->size();
11480 if (N <= 0x17)
11481 {
11482 write_number(static_cast<std::uint8_t>(0x60 + N));
11483 }
11484 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
11485 {
11486 oa->write_character(to_char_type(0x78));
11487 write_number(static_cast<std::uint8_t>(N));
11488 }
11489 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
11490 {
11491 oa->write_character(to_char_type(0x79));
11492 write_number(static_cast<std::uint16_t>(N));
11493 }
11494 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
11495 {
11496 oa->write_character(to_char_type(0x7A));
11497 write_number(static_cast<std::uint32_t>(N));
11498 }
11499 // LCOV_EXCL_START
11500 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
11501 {
11502 oa->write_character(to_char_type(0x7B));
11503 write_number(static_cast<std::uint64_t>(N));
11504 }
11505 // LCOV_EXCL_STOP
11506
11507 // step 2: write the string
11508 oa->write_characters(
11509 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
11510 j.m_value.string->size());
11511 break;
11512 }
11513
11514 case value_t::array:
11515 {
11516 // step 1: write control byte and the array size
11517 const auto N = j.m_value.array->size();
11518 if (N <= 0x17)
11519 {
11520 write_number(static_cast<std::uint8_t>(0x80 + N));
11521 }
11522 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
11523 {
11524 oa->write_character(to_char_type(0x98));
11525 write_number(static_cast<std::uint8_t>(N));
11526 }
11527 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
11528 {
11529 oa->write_character(to_char_type(0x99));
11530 write_number(static_cast<std::uint16_t>(N));
11531 }
11532 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
11533 {
11534 oa->write_character(to_char_type(0x9A));
11535 write_number(static_cast<std::uint32_t>(N));
11536 }
11537 // LCOV_EXCL_START
11538 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
11539 {
11540 oa->write_character(to_char_type(0x9B));
11541 write_number(static_cast<std::uint64_t>(N));
11542 }
11543 // LCOV_EXCL_STOP
11544
11545 // step 2: write each element
11546 for (const auto& el : *j.m_value.array)
11547 {
11548 write_cbor(el);
11549 }
11550 break;
11551 }
11552
11553 case value_t::object:
11554 {
11555 // step 1: write control byte and the object size
11556 const auto N = j.m_value.object->size();
11557 if (N <= 0x17)
11558 {
11559 write_number(static_cast<std::uint8_t>(0xA0 + N));
11560 }
11561 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
11562 {
11563 oa->write_character(to_char_type(0xB8));
11564 write_number(static_cast<std::uint8_t>(N));
11565 }
11566 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
11567 {
11568 oa->write_character(to_char_type(0xB9));
11569 write_number(static_cast<std::uint16_t>(N));
11570 }
11571 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
11572 {
11573 oa->write_character(to_char_type(0xBA));
11574 write_number(static_cast<std::uint32_t>(N));
11575 }
11576 // LCOV_EXCL_START
11577 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
11578 {
11579 oa->write_character(to_char_type(0xBB));
11580 write_number(static_cast<std::uint64_t>(N));
11581 }
11582 // LCOV_EXCL_STOP
11583
11584 // step 2: write each element
11585 for (const auto& el : *j.m_value.object)
11586 {
11587 write_cbor(el.first);
11588 write_cbor(el.second);
11589 }
11590 break;
11591 }
11592
11593 default:
11594 break;
11595 }
11596 }
11597
11598 /*!
11599 @param[in] j JSON value to serialize
11600 */
write_msgpack(const BasicJsonType & j)11601 void write_msgpack(const BasicJsonType& j)
11602 {
11603 switch (j.type())
11604 {
11605 case value_t::null: // nil
11606 {
11607 oa->write_character(to_char_type(0xC0));
11608 break;
11609 }
11610
11611 case value_t::boolean: // true and false
11612 {
11613 oa->write_character(j.m_value.boolean
11614 ? to_char_type(0xC3)
11615 : to_char_type(0xC2));
11616 break;
11617 }
11618
11619 case value_t::number_integer:
11620 {
11621 if (j.m_value.number_integer >= 0)
11622 {
11623 // MessagePack does not differentiate between positive
11624 // signed integers and unsigned integers. Therefore, we used
11625 // the code from the value_t::number_unsigned case here.
11626 if (j.m_value.number_unsigned < 128)
11627 {
11628 // positive fixnum
11629 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
11630 }
11631 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
11632 {
11633 // uint 8
11634 oa->write_character(to_char_type(0xCC));
11635 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
11636 }
11637 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
11638 {
11639 // uint 16
11640 oa->write_character(to_char_type(0xCD));
11641 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
11642 }
11643 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
11644 {
11645 // uint 32
11646 oa->write_character(to_char_type(0xCE));
11647 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
11648 }
11649 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
11650 {
11651 // uint 64
11652 oa->write_character(to_char_type(0xCF));
11653 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
11654 }
11655 }
11656 else
11657 {
11658 if (j.m_value.number_integer >= -32)
11659 {
11660 // negative fixnum
11661 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
11662 }
11663 else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() and
11664 j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
11665 {
11666 // int 8
11667 oa->write_character(to_char_type(0xD0));
11668 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
11669 }
11670 else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() and
11671 j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
11672 {
11673 // int 16
11674 oa->write_character(to_char_type(0xD1));
11675 write_number(static_cast<std::int16_t>(j.m_value.number_integer));
11676 }
11677 else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() and
11678 j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
11679 {
11680 // int 32
11681 oa->write_character(to_char_type(0xD2));
11682 write_number(static_cast<std::int32_t>(j.m_value.number_integer));
11683 }
11684 else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() and
11685 j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
11686 {
11687 // int 64
11688 oa->write_character(to_char_type(0xD3));
11689 write_number(static_cast<std::int64_t>(j.m_value.number_integer));
11690 }
11691 }
11692 break;
11693 }
11694
11695 case value_t::number_unsigned:
11696 {
11697 if (j.m_value.number_unsigned < 128)
11698 {
11699 // positive fixnum
11700 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
11701 }
11702 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
11703 {
11704 // uint 8
11705 oa->write_character(to_char_type(0xCC));
11706 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
11707 }
11708 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
11709 {
11710 // uint 16
11711 oa->write_character(to_char_type(0xCD));
11712 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
11713 }
11714 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
11715 {
11716 // uint 32
11717 oa->write_character(to_char_type(0xCE));
11718 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
11719 }
11720 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
11721 {
11722 // uint 64
11723 oa->write_character(to_char_type(0xCF));
11724 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
11725 }
11726 break;
11727 }
11728
11729 case value_t::number_float:
11730 {
11731 oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
11732 write_number(j.m_value.number_float);
11733 break;
11734 }
11735
11736 case value_t::string:
11737 {
11738 // step 1: write control byte and the string length
11739 const auto N = j.m_value.string->size();
11740 if (N <= 31)
11741 {
11742 // fixstr
11743 write_number(static_cast<std::uint8_t>(0xA0 | N));
11744 }
11745 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
11746 {
11747 // str 8
11748 oa->write_character(to_char_type(0xD9));
11749 write_number(static_cast<std::uint8_t>(N));
11750 }
11751 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
11752 {
11753 // str 16
11754 oa->write_character(to_char_type(0xDA));
11755 write_number(static_cast<std::uint16_t>(N));
11756 }
11757 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
11758 {
11759 // str 32
11760 oa->write_character(to_char_type(0xDB));
11761 write_number(static_cast<std::uint32_t>(N));
11762 }
11763
11764 // step 2: write the string
11765 oa->write_characters(
11766 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
11767 j.m_value.string->size());
11768 break;
11769 }
11770
11771 case value_t::array:
11772 {
11773 // step 1: write control byte and the array size
11774 const auto N = j.m_value.array->size();
11775 if (N <= 15)
11776 {
11777 // fixarray
11778 write_number(static_cast<std::uint8_t>(0x90 | N));
11779 }
11780 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
11781 {
11782 // array 16
11783 oa->write_character(to_char_type(0xDC));
11784 write_number(static_cast<std::uint16_t>(N));
11785 }
11786 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
11787 {
11788 // array 32
11789 oa->write_character(to_char_type(0xDD));
11790 write_number(static_cast<std::uint32_t>(N));
11791 }
11792
11793 // step 2: write each element
11794 for (const auto& el : *j.m_value.array)
11795 {
11796 write_msgpack(el);
11797 }
11798 break;
11799 }
11800
11801 case value_t::object:
11802 {
11803 // step 1: write control byte and the object size
11804 const auto N = j.m_value.object->size();
11805 if (N <= 15)
11806 {
11807 // fixmap
11808 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
11809 }
11810 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
11811 {
11812 // map 16
11813 oa->write_character(to_char_type(0xDE));
11814 write_number(static_cast<std::uint16_t>(N));
11815 }
11816 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
11817 {
11818 // map 32
11819 oa->write_character(to_char_type(0xDF));
11820 write_number(static_cast<std::uint32_t>(N));
11821 }
11822
11823 // step 2: write each element
11824 for (const auto& el : *j.m_value.object)
11825 {
11826 write_msgpack(el.first);
11827 write_msgpack(el.second);
11828 }
11829 break;
11830 }
11831
11832 default:
11833 break;
11834 }
11835 }
11836
11837 /*!
11838 @param[in] j JSON value to serialize
11839 @param[in] use_count whether to use '#' prefixes (optimized format)
11840 @param[in] use_type whether to use '$' prefixes (optimized format)
11841 @param[in] add_prefix whether prefixes need to be used for this value
11842 */
write_ubjson(const BasicJsonType & j,const bool use_count,const bool use_type,const bool add_prefix=true)11843 void write_ubjson(const BasicJsonType& j, const bool use_count,
11844 const bool use_type, const bool add_prefix = true)
11845 {
11846 switch (j.type())
11847 {
11848 case value_t::null:
11849 {
11850 if (add_prefix)
11851 {
11852 oa->write_character(to_char_type('Z'));
11853 }
11854 break;
11855 }
11856
11857 case value_t::boolean:
11858 {
11859 if (add_prefix)
11860 {
11861 oa->write_character(j.m_value.boolean
11862 ? to_char_type('T')
11863 : to_char_type('F'));
11864 }
11865 break;
11866 }
11867
11868 case value_t::number_integer:
11869 {
11870 write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
11871 break;
11872 }
11873
11874 case value_t::number_unsigned:
11875 {
11876 write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
11877 break;
11878 }
11879
11880 case value_t::number_float:
11881 {
11882 write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
11883 break;
11884 }
11885
11886 case value_t::string:
11887 {
11888 if (add_prefix)
11889 {
11890 oa->write_character(to_char_type('S'));
11891 }
11892 write_number_with_ubjson_prefix(j.m_value.string->size(), true);
11893 oa->write_characters(
11894 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
11895 j.m_value.string->size());
11896 break;
11897 }
11898
11899 case value_t::array:
11900 {
11901 if (add_prefix)
11902 {
11903 oa->write_character(to_char_type('['));
11904 }
11905
11906 bool prefix_required = true;
11907 if (use_type and not j.m_value.array->empty())
11908 {
11909 assert(use_count);
11910 const CharType first_prefix = ubjson_prefix(j.front());
11911 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
11912 [this, first_prefix](const BasicJsonType & v)
11913 {
11914 return ubjson_prefix(v) == first_prefix;
11915 });
11916
11917 if (same_prefix)
11918 {
11919 prefix_required = false;
11920 oa->write_character(to_char_type('$'));
11921 oa->write_character(first_prefix);
11922 }
11923 }
11924
11925 if (use_count)
11926 {
11927 oa->write_character(to_char_type('#'));
11928 write_number_with_ubjson_prefix(j.m_value.array->size(), true);
11929 }
11930
11931 for (const auto& el : *j.m_value.array)
11932 {
11933 write_ubjson(el, use_count, use_type, prefix_required);
11934 }
11935
11936 if (not use_count)
11937 {
11938 oa->write_character(to_char_type(']'));
11939 }
11940
11941 break;
11942 }
11943
11944 case value_t::object:
11945 {
11946 if (add_prefix)
11947 {
11948 oa->write_character(to_char_type('{'));
11949 }
11950
11951 bool prefix_required = true;
11952 if (use_type and not j.m_value.object->empty())
11953 {
11954 assert(use_count);
11955 const CharType first_prefix = ubjson_prefix(j.front());
11956 const bool same_prefix = std::all_of(j.begin(), j.end(),
11957 [this, first_prefix](const BasicJsonType & v)
11958 {
11959 return ubjson_prefix(v) == first_prefix;
11960 });
11961
11962 if (same_prefix)
11963 {
11964 prefix_required = false;
11965 oa->write_character(to_char_type('$'));
11966 oa->write_character(first_prefix);
11967 }
11968 }
11969
11970 if (use_count)
11971 {
11972 oa->write_character(to_char_type('#'));
11973 write_number_with_ubjson_prefix(j.m_value.object->size(), true);
11974 }
11975
11976 for (const auto& el : *j.m_value.object)
11977 {
11978 write_number_with_ubjson_prefix(el.first.size(), true);
11979 oa->write_characters(
11980 reinterpret_cast<const CharType*>(el.first.c_str()),
11981 el.first.size());
11982 write_ubjson(el.second, use_count, use_type, prefix_required);
11983 }
11984
11985 if (not use_count)
11986 {
11987 oa->write_character(to_char_type('}'));
11988 }
11989
11990 break;
11991 }
11992
11993 default:
11994 break;
11995 }
11996 }
11997
11998 private:
11999 //////////
12000 // BSON //
12001 //////////
12002
12003 /*!
12004 @return The size of a BSON document entry header, including the id marker
12005 and the entry name size (and its null-terminator).
12006 */
calc_bson_entry_header_size(const string_t & name)12007 static std::size_t calc_bson_entry_header_size(const string_t& name)
12008 {
12009 const auto it = name.find(static_cast<typename string_t::value_type>(0));
12010 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
12011 {
12012 JSON_THROW(out_of_range::create(409,
12013 "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")"));
12014 }
12015
12016 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
12017 }
12018
12019 /*!
12020 @brief Writes the given @a element_type and @a name to the output adapter
12021 */
write_bson_entry_header(const string_t & name,const std::uint8_t element_type)12022 void write_bson_entry_header(const string_t& name,
12023 const std::uint8_t element_type)
12024 {
12025 oa->write_character(to_char_type(element_type)); // boolean
12026 oa->write_characters(
12027 reinterpret_cast<const CharType*>(name.c_str()),
12028 name.size() + 1u);
12029 }
12030
12031 /*!
12032 @brief Writes a BSON element with key @a name and boolean value @a value
12033 */
write_bson_boolean(const string_t & name,const bool value)12034 void write_bson_boolean(const string_t& name,
12035 const bool value)
12036 {
12037 write_bson_entry_header(name, 0x08);
12038 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
12039 }
12040
12041 /*!
12042 @brief Writes a BSON element with key @a name and double value @a value
12043 */
write_bson_double(const string_t & name,const double value)12044 void write_bson_double(const string_t& name,
12045 const double value)
12046 {
12047 write_bson_entry_header(name, 0x01);
12048 write_number<double, true>(value);
12049 }
12050
12051 /*!
12052 @return The size of the BSON-encoded string in @a value
12053 */
calc_bson_string_size(const string_t & value)12054 static std::size_t calc_bson_string_size(const string_t& value)
12055 {
12056 return sizeof(std::int32_t) + value.size() + 1ul;
12057 }
12058
12059 /*!
12060 @brief Writes a BSON element with key @a name and string value @a value
12061 */
write_bson_string(const string_t & name,const string_t & value)12062 void write_bson_string(const string_t& name,
12063 const string_t& value)
12064 {
12065 write_bson_entry_header(name, 0x02);
12066
12067 write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
12068 oa->write_characters(
12069 reinterpret_cast<const CharType*>(value.c_str()),
12070 value.size() + 1);
12071 }
12072
12073 /*!
12074 @brief Writes a BSON element with key @a name and null value
12075 */
write_bson_null(const string_t & name)12076 void write_bson_null(const string_t& name)
12077 {
12078 write_bson_entry_header(name, 0x0A);
12079 }
12080
12081 /*!
12082 @return The size of the BSON-encoded integer @a value
12083 */
calc_bson_integer_size(const std::int64_t value)12084 static std::size_t calc_bson_integer_size(const std::int64_t value)
12085 {
12086 return (std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)()
12087 ? sizeof(std::int32_t)
12088 : sizeof(std::int64_t);
12089 }
12090
12091 /*!
12092 @brief Writes a BSON element with key @a name and integer @a value
12093 */
write_bson_integer(const string_t & name,const std::int64_t value)12094 void write_bson_integer(const string_t& name,
12095 const std::int64_t value)
12096 {
12097 if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
12098 {
12099 write_bson_entry_header(name, 0x10); // int32
12100 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
12101 }
12102 else
12103 {
12104 write_bson_entry_header(name, 0x12); // int64
12105 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
12106 }
12107 }
12108
12109 /*!
12110 @return The size of the BSON-encoded unsigned integer in @a j
12111 */
calc_bson_unsigned_size(const std::uint64_t value)12112 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
12113 {
12114 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
12115 ? sizeof(std::int32_t)
12116 : sizeof(std::int64_t);
12117 }
12118
12119 /*!
12120 @brief Writes a BSON element with key @a name and unsigned @a value
12121 */
write_bson_unsigned(const string_t & name,const std::uint64_t value)12122 void write_bson_unsigned(const string_t& name,
12123 const std::uint64_t value)
12124 {
12125 if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
12126 {
12127 write_bson_entry_header(name, 0x10 /* int32 */);
12128 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
12129 }
12130 else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
12131 {
12132 write_bson_entry_header(name, 0x12 /* int64 */);
12133 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
12134 }
12135 else
12136 {
12137 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64"));
12138 }
12139 }
12140
12141 /*!
12142 @brief Writes a BSON element with key @a name and object @a value
12143 */
write_bson_object_entry(const string_t & name,const typename BasicJsonType::object_t & value)12144 void write_bson_object_entry(const string_t& name,
12145 const typename BasicJsonType::object_t& value)
12146 {
12147 write_bson_entry_header(name, 0x03); // object
12148 write_bson_object(value);
12149 }
12150
12151 /*!
12152 @return The size of the BSON-encoded array @a value
12153 */
calc_bson_array_size(const typename BasicJsonType::array_t & value)12154 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
12155 {
12156 std::size_t array_index = 0ul;
12157
12158 const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), 0ul, [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
12159 {
12160 return result + calc_bson_element_size(std::to_string(array_index++), el);
12161 });
12162
12163 return sizeof(std::int32_t) + embedded_document_size + 1ul;
12164 }
12165
12166 /*!
12167 @brief Writes a BSON element with key @a name and array @a value
12168 */
write_bson_array(const string_t & name,const typename BasicJsonType::array_t & value)12169 void write_bson_array(const string_t& name,
12170 const typename BasicJsonType::array_t& value)
12171 {
12172 write_bson_entry_header(name, 0x04); // array
12173 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
12174
12175 std::size_t array_index = 0ul;
12176
12177 for (const auto& el : value)
12178 {
12179 write_bson_element(std::to_string(array_index++), el);
12180 }
12181
12182 oa->write_character(to_char_type(0x00));
12183 }
12184
12185 /*!
12186 @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
12187 @return The calculated size for the BSON document entry for @a j with the given @a name.
12188 */
calc_bson_element_size(const string_t & name,const BasicJsonType & j)12189 static std::size_t calc_bson_element_size(const string_t& name,
12190 const BasicJsonType& j)
12191 {
12192 const auto header_size = calc_bson_entry_header_size(name);
12193 switch (j.type())
12194 {
12195 case value_t::object:
12196 return header_size + calc_bson_object_size(*j.m_value.object);
12197
12198 case value_t::array:
12199 return header_size + calc_bson_array_size(*j.m_value.array);
12200
12201 case value_t::boolean:
12202 return header_size + 1ul;
12203
12204 case value_t::number_float:
12205 return header_size + 8ul;
12206
12207 case value_t::number_integer:
12208 return header_size + calc_bson_integer_size(j.m_value.number_integer);
12209
12210 case value_t::number_unsigned:
12211 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
12212
12213 case value_t::string:
12214 return header_size + calc_bson_string_size(*j.m_value.string);
12215
12216 case value_t::null:
12217 return header_size + 0ul;
12218
12219 // LCOV_EXCL_START
12220 default:
12221 assert(false);
12222 return 0ul;
12223 // LCOV_EXCL_STOP
12224 }
12225 }
12226
12227 /*!
12228 @brief Serializes the JSON value @a j to BSON and associates it with the
12229 key @a name.
12230 @param name The name to associate with the JSON entity @a j within the
12231 current BSON document
12232 @return The size of the BSON entry
12233 */
write_bson_element(const string_t & name,const BasicJsonType & j)12234 void write_bson_element(const string_t& name,
12235 const BasicJsonType& j)
12236 {
12237 switch (j.type())
12238 {
12239 case value_t::object:
12240 return write_bson_object_entry(name, *j.m_value.object);
12241
12242 case value_t::array:
12243 return write_bson_array(name, *j.m_value.array);
12244
12245 case value_t::boolean:
12246 return write_bson_boolean(name, j.m_value.boolean);
12247
12248 case value_t::number_float:
12249 return write_bson_double(name, j.m_value.number_float);
12250
12251 case value_t::number_integer:
12252 return write_bson_integer(name, j.m_value.number_integer);
12253
12254 case value_t::number_unsigned:
12255 return write_bson_unsigned(name, j.m_value.number_unsigned);
12256
12257 case value_t::string:
12258 return write_bson_string(name, *j.m_value.string);
12259
12260 case value_t::null:
12261 return write_bson_null(name);
12262
12263 // LCOV_EXCL_START
12264 default:
12265 assert(false);
12266 return;
12267 // LCOV_EXCL_STOP
12268 }
12269 }
12270
12271 /*!
12272 @brief Calculates the size of the BSON serialization of the given
12273 JSON-object @a j.
12274 @param[in] j JSON value to serialize
12275 @pre j.type() == value_t::object
12276 */
calc_bson_object_size(const typename BasicJsonType::object_t & value)12277 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
12278 {
12279 std::size_t document_size = std::accumulate(value.begin(), value.end(), 0ul,
12280 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
12281 {
12282 return result += calc_bson_element_size(el.first, el.second);
12283 });
12284
12285 return sizeof(std::int32_t) + document_size + 1ul;
12286 }
12287
12288 /*!
12289 @param[in] j JSON value to serialize
12290 @pre j.type() == value_t::object
12291 */
write_bson_object(const typename BasicJsonType::object_t & value)12292 void write_bson_object(const typename BasicJsonType::object_t& value)
12293 {
12294 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
12295
12296 for (const auto& el : value)
12297 {
12298 write_bson_element(el.first, el.second);
12299 }
12300
12301 oa->write_character(to_char_type(0x00));
12302 }
12303
12304 //////////
12305 // CBOR //
12306 //////////
12307
get_cbor_float_prefix(float)12308 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
12309 {
12310 return to_char_type(0xFA); // Single-Precision Float
12311 }
12312
get_cbor_float_prefix(double)12313 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
12314 {
12315 return to_char_type(0xFB); // Double-Precision Float
12316 }
12317
12318 /////////////
12319 // MsgPack //
12320 /////////////
12321
get_msgpack_float_prefix(float)12322 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
12323 {
12324 return to_char_type(0xCA); // float 32
12325 }
12326
get_msgpack_float_prefix(double)12327 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
12328 {
12329 return to_char_type(0xCB); // float 64
12330 }
12331
12332 ////////////
12333 // UBJSON //
12334 ////////////
12335
12336 // UBJSON: write number (floating point)
12337 template<typename NumberType, typename std::enable_if<
12338 std::is_floating_point<NumberType>::value, int>::type = 0>
write_number_with_ubjson_prefix(const NumberType n,const bool add_prefix)12339 void write_number_with_ubjson_prefix(const NumberType n,
12340 const bool add_prefix)
12341 {
12342 if (add_prefix)
12343 {
12344 oa->write_character(get_ubjson_float_prefix(n));
12345 }
12346 write_number(n);
12347 }
12348
12349 // UBJSON: write number (unsigned integer)
12350 template<typename NumberType, typename std::enable_if<
12351 std::is_unsigned<NumberType>::value, int>::type = 0>
write_number_with_ubjson_prefix(const NumberType n,const bool add_prefix)12352 void write_number_with_ubjson_prefix(const NumberType n,
12353 const bool add_prefix)
12354 {
12355 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
12356 {
12357 if (add_prefix)
12358 {
12359 oa->write_character(to_char_type('i')); // int8
12360 }
12361 write_number(static_cast<std::uint8_t>(n));
12362 }
12363 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
12364 {
12365 if (add_prefix)
12366 {
12367 oa->write_character(to_char_type('U')); // uint8
12368 }
12369 write_number(static_cast<std::uint8_t>(n));
12370 }
12371 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
12372 {
12373 if (add_prefix)
12374 {
12375 oa->write_character(to_char_type('I')); // int16
12376 }
12377 write_number(static_cast<std::int16_t>(n));
12378 }
12379 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
12380 {
12381 if (add_prefix)
12382 {
12383 oa->write_character(to_char_type('l')); // int32
12384 }
12385 write_number(static_cast<std::int32_t>(n));
12386 }
12387 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
12388 {
12389 if (add_prefix)
12390 {
12391 oa->write_character(to_char_type('L')); // int64
12392 }
12393 write_number(static_cast<std::int64_t>(n));
12394 }
12395 else
12396 {
12397 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
12398 }
12399 }
12400
12401 // UBJSON: write number (signed integer)
12402 template<typename NumberType, typename std::enable_if<
12403 std::is_signed<NumberType>::value and
12404 not std::is_floating_point<NumberType>::value, int>::type = 0>
write_number_with_ubjson_prefix(const NumberType n,const bool add_prefix)12405 void write_number_with_ubjson_prefix(const NumberType n,
12406 const bool add_prefix)
12407 {
12408 if ((std::numeric_limits<std::int8_t>::min)() <= n and n <= (std::numeric_limits<std::int8_t>::max)())
12409 {
12410 if (add_prefix)
12411 {
12412 oa->write_character(to_char_type('i')); // int8
12413 }
12414 write_number(static_cast<std::int8_t>(n));
12415 }
12416 else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n and n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
12417 {
12418 if (add_prefix)
12419 {
12420 oa->write_character(to_char_type('U')); // uint8
12421 }
12422 write_number(static_cast<std::uint8_t>(n));
12423 }
12424 else if ((std::numeric_limits<std::int16_t>::min)() <= n and n <= (std::numeric_limits<std::int16_t>::max)())
12425 {
12426 if (add_prefix)
12427 {
12428 oa->write_character(to_char_type('I')); // int16
12429 }
12430 write_number(static_cast<std::int16_t>(n));
12431 }
12432 else if ((std::numeric_limits<std::int32_t>::min)() <= n and n <= (std::numeric_limits<std::int32_t>::max)())
12433 {
12434 if (add_prefix)
12435 {
12436 oa->write_character(to_char_type('l')); // int32
12437 }
12438 write_number(static_cast<std::int32_t>(n));
12439 }
12440 else if ((std::numeric_limits<std::int64_t>::min)() <= n and n <= (std::numeric_limits<std::int64_t>::max)())
12441 {
12442 if (add_prefix)
12443 {
12444 oa->write_character(to_char_type('L')); // int64
12445 }
12446 write_number(static_cast<std::int64_t>(n));
12447 }
12448 // LCOV_EXCL_START
12449 else
12450 {
12451 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
12452 }
12453 // LCOV_EXCL_STOP
12454 }
12455
12456 /*!
12457 @brief determine the type prefix of container values
12458
12459 @note This function does not need to be 100% accurate when it comes to
12460 integer limits. In case a number exceeds the limits of int64_t,
12461 this will be detected by a later call to function
12462 write_number_with_ubjson_prefix. Therefore, we return 'L' for any
12463 value that does not fit the previous limits.
12464 */
ubjson_prefix(const BasicJsonType & j) const12465 CharType ubjson_prefix(const BasicJsonType& j) const noexcept
12466 {
12467 switch (j.type())
12468 {
12469 case value_t::null:
12470 return 'Z';
12471
12472 case value_t::boolean:
12473 return j.m_value.boolean ? 'T' : 'F';
12474
12475 case value_t::number_integer:
12476 {
12477 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
12478 {
12479 return 'i';
12480 }
12481 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
12482 {
12483 return 'U';
12484 }
12485 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
12486 {
12487 return 'I';
12488 }
12489 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
12490 {
12491 return 'l';
12492 }
12493 // no check and assume int64_t (see note above)
12494 return 'L';
12495 }
12496
12497 case value_t::number_unsigned:
12498 {
12499 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
12500 {
12501 return 'i';
12502 }
12503 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
12504 {
12505 return 'U';
12506 }
12507 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
12508 {
12509 return 'I';
12510 }
12511 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
12512 {
12513 return 'l';
12514 }
12515 // no check and assume int64_t (see note above)
12516 return 'L';
12517 }
12518
12519 case value_t::number_float:
12520 return get_ubjson_float_prefix(j.m_value.number_float);
12521
12522 case value_t::string:
12523 return 'S';
12524
12525 case value_t::array:
12526 return '[';
12527
12528 case value_t::object:
12529 return '{';
12530
12531 default: // discarded values
12532 return 'N';
12533 }
12534 }
12535
get_ubjson_float_prefix(float)12536 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
12537 {
12538 return 'd'; // float 32
12539 }
12540
get_ubjson_float_prefix(double)12541 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
12542 {
12543 return 'D'; // float 64
12544 }
12545
12546 ///////////////////////
12547 // Utility functions //
12548 ///////////////////////
12549
12550 /*
12551 @brief write a number to output input
12552 @param[in] n number of type @a NumberType
12553 @tparam NumberType the type of the number
12554 @tparam OutputIsLittleEndian Set to true if output data is
12555 required to be little endian
12556
12557 @note This function needs to respect the system's endianess, because bytes
12558 in CBOR, MessagePack, and UBJSON are stored in network order (big
12559 endian) and therefore need reordering on little endian systems.
12560 */
12561 template<typename NumberType, bool OutputIsLittleEndian = false>
write_number(const NumberType n)12562 void write_number(const NumberType n)
12563 {
12564 // step 1: write number to array of length NumberType
12565 std::array<CharType, sizeof(NumberType)> vec;
12566 std::memcpy(vec.data(), &n, sizeof(NumberType));
12567
12568 // step 2: write array to output (with possible reordering)
12569 if (is_little_endian != OutputIsLittleEndian)
12570 {
12571 // reverse byte order prior to conversion if necessary
12572 std::reverse(vec.begin(), vec.end());
12573 }
12574
12575 oa->write_characters(vec.data(), sizeof(NumberType));
12576 }
12577
12578 public:
12579 // The following to_char_type functions are implement the conversion
12580 // between uint8_t and CharType. In case CharType is not unsigned,
12581 // such a conversion is required to allow values greater than 128.
12582 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
12583 template < typename C = CharType,
12584 enable_if_t < std::is_signed<C>::value and std::is_signed<char>::value > * = nullptr >
to_char_type(std::uint8_t x)12585 static constexpr CharType to_char_type(std::uint8_t x) noexcept
12586 {
12587 return *reinterpret_cast<char*>(&x);
12588 }
12589
12590 template < typename C = CharType,
12591 enable_if_t < std::is_signed<C>::value and std::is_unsigned<char>::value > * = nullptr >
to_char_type(std::uint8_t x)12592 static CharType to_char_type(std::uint8_t x) noexcept
12593 {
12594 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
12595 static_assert(std::is_pod<CharType>::value, "CharType must be POD");
12596 CharType result;
12597 std::memcpy(&result, &x, sizeof(x));
12598 return result;
12599 }
12600
12601 template<typename C = CharType,
12602 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
to_char_type(std::uint8_t x)12603 static constexpr CharType to_char_type(std::uint8_t x) noexcept
12604 {
12605 return x;
12606 }
12607
12608 template < typename InputCharType, typename C = CharType,
12609 enable_if_t <
12610 std::is_signed<C>::value and
12611 std::is_signed<char>::value and
12612 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
12613 > * = nullptr >
to_char_type(InputCharType x)12614 static constexpr CharType to_char_type(InputCharType x) noexcept
12615 {
12616 return x;
12617 }
12618
12619 private:
12620 /// whether we can assume little endianess
12621 const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();
12622
12623 /// the output
12624 output_adapter_t<CharType> oa = nullptr;
12625 };
12626 } // namespace detail
12627 } // namespace nlohmann
12628
12629 // #include <nlohmann/detail/output/output_adapters.hpp>
12630
12631 // #include <nlohmann/detail/output/serializer.hpp>
12632
12633
12634 #include <algorithm> // reverse, remove, fill, find, none_of
12635 #include <array> // array
12636 #include <cassert> // assert
12637 #include <ciso646> // and, or
12638 #include <clocale> // localeconv, lconv
12639 #include <cmath> // labs, isfinite, isnan, signbit
12640 #include <cstddef> // size_t, ptrdiff_t
12641 #include <cstdint> // uint8_t
12642 #include <cstdio> // snprintf
12643 #include <limits> // numeric_limits
12644 #include <string> // string
12645 #include <type_traits> // is_same
12646 #include <utility> // move
12647
12648 // #include <nlohmann/detail/conversions/to_chars.hpp>
12649
12650
12651 #include <array> // array
12652 #include <cassert> // assert
12653 #include <ciso646> // or, and, not
12654 #include <cmath> // signbit, isfinite
12655 #include <cstdint> // intN_t, uintN_t
12656 #include <cstring> // memcpy, memmove
12657 #include <limits> // numeric_limits
12658 #include <type_traits> // conditional
12659 // #include <nlohmann/detail/macro_scope.hpp>
12660
12661
12662 namespace nlohmann
12663 {
12664 namespace detail
12665 {
12666
12667 /*!
12668 @brief implements the Grisu2 algorithm for binary to decimal floating-point
12669 conversion.
12670
12671 This implementation is a slightly modified version of the reference
12672 implementation which may be obtained from
12673 http://florian.loitsch.com/publications (bench.tar.gz).
12674
12675 The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
12676
12677 For a detailed description of the algorithm see:
12678
12679 [1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
12680 Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
12681 Language Design and Implementation, PLDI 2010
12682 [2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
12683 Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
12684 Design and Implementation, PLDI 1996
12685 */
12686 namespace dtoa_impl
12687 {
12688
12689 template <typename Target, typename Source>
12690 Target reinterpret_bits(const Source source)
12691 {
12692 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
12693
12694 Target target;
12695 std::memcpy(&target, &source, sizeof(Source));
12696 return target;
12697 }
12698
12699 struct diyfp // f * 2^e
12700 {
12701 static constexpr int kPrecision = 64; // = q
12702
12703 std::uint64_t f = 0;
12704 int e = 0;
12705
diyfpnlohmann::detail::dtoa_impl::diyfp12706 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
12707
12708 /*!
12709 @brief returns x - y
12710 @pre x.e == y.e and x.f >= y.f
12711 */
subnlohmann::detail::dtoa_impl::diyfp12712 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
12713 {
12714 assert(x.e == y.e);
12715 assert(x.f >= y.f);
12716
12717 return {x.f - y.f, x.e};
12718 }
12719
12720 /*!
12721 @brief returns x * y
12722 @note The result is rounded. (Only the upper q bits are returned.)
12723 */
mulnlohmann::detail::dtoa_impl::diyfp12724 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
12725 {
12726 static_assert(kPrecision == 64, "internal error");
12727
12728 // Computes:
12729 // f = round((x.f * y.f) / 2^q)
12730 // e = x.e + y.e + q
12731
12732 // Emulate the 64-bit * 64-bit multiplication:
12733 //
12734 // p = u * v
12735 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
12736 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
12737 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
12738 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
12739 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
12740 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
12741 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
12742 //
12743 // (Since Q might be larger than 2^32 - 1)
12744 //
12745 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
12746 //
12747 // (Q_hi + H does not overflow a 64-bit int)
12748 //
12749 // = p_lo + 2^64 p_hi
12750
12751 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
12752 const std::uint64_t u_hi = x.f >> 32u;
12753 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
12754 const std::uint64_t v_hi = y.f >> 32u;
12755
12756 const std::uint64_t p0 = u_lo * v_lo;
12757 const std::uint64_t p1 = u_lo * v_hi;
12758 const std::uint64_t p2 = u_hi * v_lo;
12759 const std::uint64_t p3 = u_hi * v_hi;
12760
12761 const std::uint64_t p0_hi = p0 >> 32u;
12762 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
12763 const std::uint64_t p1_hi = p1 >> 32u;
12764 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
12765 const std::uint64_t p2_hi = p2 >> 32u;
12766
12767 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
12768
12769 // The full product might now be computed as
12770 //
12771 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
12772 // p_lo = p0_lo + (Q << 32)
12773 //
12774 // But in this particular case here, the full p_lo is not required.
12775 // Effectively we only need to add the highest bit in p_lo to p_hi (and
12776 // Q_hi + 1 does not overflow).
12777
12778 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
12779
12780 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
12781
12782 return {h, x.e + y.e + 64};
12783 }
12784
12785 /*!
12786 @brief normalize x such that the significand is >= 2^(q-1)
12787 @pre x.f != 0
12788 */
normalizenlohmann::detail::dtoa_impl::diyfp12789 static diyfp normalize(diyfp x) noexcept
12790 {
12791 assert(x.f != 0);
12792
12793 while ((x.f >> 63u) == 0)
12794 {
12795 x.f <<= 1u;
12796 x.e--;
12797 }
12798
12799 return x;
12800 }
12801
12802 /*!
12803 @brief normalize x such that the result has the exponent E
12804 @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
12805 */
normalize_tonlohmann::detail::dtoa_impl::diyfp12806 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
12807 {
12808 const int delta = x.e - target_exponent;
12809
12810 assert(delta >= 0);
12811 assert(((x.f << delta) >> delta) == x.f);
12812
12813 return {x.f << delta, target_exponent};
12814 }
12815 };
12816
12817 struct boundaries
12818 {
12819 diyfp w;
12820 diyfp minus;
12821 diyfp plus;
12822 };
12823
12824 /*!
12825 Compute the (normalized) diyfp representing the input number 'value' and its
12826 boundaries.
12827
12828 @pre value must be finite and positive
12829 */
12830 template <typename FloatType>
compute_boundaries(FloatType value)12831 boundaries compute_boundaries(FloatType value)
12832 {
12833 assert(std::isfinite(value));
12834 assert(value > 0);
12835
12836 // Convert the IEEE representation into a diyfp.
12837 //
12838 // If v is denormal:
12839 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
12840 // If v is normalized:
12841 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
12842
12843 static_assert(std::numeric_limits<FloatType>::is_iec559,
12844 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
12845
12846 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
12847 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
12848 constexpr int kMinExp = 1 - kBias;
12849 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
12850
12851 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
12852
12853 const std::uint64_t bits = reinterpret_bits<bits_type>(value);
12854 const std::uint64_t E = bits >> (kPrecision - 1);
12855 const std::uint64_t F = bits & (kHiddenBit - 1);
12856
12857 const bool is_denormal = E == 0;
12858 const diyfp v = is_denormal
12859 ? diyfp(F, kMinExp)
12860 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
12861
12862 // Compute the boundaries m- and m+ of the floating-point value
12863 // v = f * 2^e.
12864 //
12865 // Determine v- and v+, the floating-point predecessor and successor if v,
12866 // respectively.
12867 //
12868 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
12869 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
12870 //
12871 // v+ = v + 2^e
12872 //
12873 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
12874 // between m- and m+ round to v, regardless of how the input rounding
12875 // algorithm breaks ties.
12876 //
12877 // ---+-------------+-------------+-------------+-------------+--- (A)
12878 // v- m- v m+ v+
12879 //
12880 // -----------------+------+------+-------------+-------------+--- (B)
12881 // v- m- v m+ v+
12882
12883 const bool lower_boundary_is_closer = F == 0 and E > 1;
12884 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
12885 const diyfp m_minus = lower_boundary_is_closer
12886 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
12887 : diyfp(2 * v.f - 1, v.e - 1); // (A)
12888
12889 // Determine the normalized w+ = m+.
12890 const diyfp w_plus = diyfp::normalize(m_plus);
12891
12892 // Determine w- = m- such that e_(w-) = e_(w+).
12893 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
12894
12895 return {diyfp::normalize(v), w_minus, w_plus};
12896 }
12897
12898 // Given normalized diyfp w, Grisu needs to find a (normalized) cached
12899 // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
12900 // within a certain range [alpha, gamma] (Definition 3.2 from [1])
12901 //
12902 // alpha <= e = e_c + e_w + q <= gamma
12903 //
12904 // or
12905 //
12906 // f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
12907 // <= f_c * f_w * 2^gamma
12908 //
12909 // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
12910 //
12911 // 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
12912 //
12913 // or
12914 //
12915 // 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
12916 //
12917 // The choice of (alpha,gamma) determines the size of the table and the form of
12918 // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
12919 // in practice:
12920 //
12921 // The idea is to cut the number c * w = f * 2^e into two parts, which can be
12922 // processed independently: An integral part p1, and a fractional part p2:
12923 //
12924 // f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
12925 // = (f div 2^-e) + (f mod 2^-e) * 2^e
12926 // = p1 + p2 * 2^e
12927 //
12928 // The conversion of p1 into decimal form requires a series of divisions and
12929 // modulos by (a power of) 10. These operations are faster for 32-bit than for
12930 // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
12931 // achieved by choosing
12932 //
12933 // -e >= 32 or e <= -32 := gamma
12934 //
12935 // In order to convert the fractional part
12936 //
12937 // p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
12938 //
12939 // into decimal form, the fraction is repeatedly multiplied by 10 and the digits
12940 // d[-i] are extracted in order:
12941 //
12942 // (10 * p2) div 2^-e = d[-1]
12943 // (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
12944 //
12945 // The multiplication by 10 must not overflow. It is sufficient to choose
12946 //
12947 // 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
12948 //
12949 // Since p2 = f mod 2^-e < 2^-e,
12950 //
12951 // -e <= 60 or e >= -60 := alpha
12952
12953 constexpr int kAlpha = -60;
12954 constexpr int kGamma = -32;
12955
12956 struct cached_power // c = f * 2^e ~= 10^k
12957 {
12958 std::uint64_t f;
12959 int e;
12960 int k;
12961 };
12962
12963 /*!
12964 For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
12965 power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
12966 satisfies (Definition 3.2 from [1])
12967
12968 alpha <= e_c + e + q <= gamma.
12969 */
get_cached_power_for_binary_exponent(int e)12970 inline cached_power get_cached_power_for_binary_exponent(int e)
12971 {
12972 // Now
12973 //
12974 // alpha <= e_c + e + q <= gamma (1)
12975 // ==> f_c * 2^alpha <= c * 2^e * 2^q
12976 //
12977 // and since the c's are normalized, 2^(q-1) <= f_c,
12978 //
12979 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
12980 // ==> 2^(alpha - e - 1) <= c
12981 //
12982 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
12983 //
12984 // k = ceil( log_10( 2^(alpha - e - 1) ) )
12985 // = ceil( (alpha - e - 1) * log_10(2) )
12986 //
12987 // From the paper:
12988 // "In theory the result of the procedure could be wrong since c is rounded,
12989 // and the computation itself is approximated [...]. In practice, however,
12990 // this simple function is sufficient."
12991 //
12992 // For IEEE double precision floating-point numbers converted into
12993 // normalized diyfp's w = f * 2^e, with q = 64,
12994 //
12995 // e >= -1022 (min IEEE exponent)
12996 // -52 (p - 1)
12997 // -52 (p - 1, possibly normalize denormal IEEE numbers)
12998 // -11 (normalize the diyfp)
12999 // = -1137
13000 //
13001 // and
13002 //
13003 // e <= +1023 (max IEEE exponent)
13004 // -52 (p - 1)
13005 // -11 (normalize the diyfp)
13006 // = 960
13007 //
13008 // This binary exponent range [-1137,960] results in a decimal exponent
13009 // range [-307,324]. One does not need to store a cached power for each
13010 // k in this range. For each such k it suffices to find a cached power
13011 // such that the exponent of the product lies in [alpha,gamma].
13012 // This implies that the difference of the decimal exponents of adjacent
13013 // table entries must be less than or equal to
13014 //
13015 // floor( (gamma - alpha) * log_10(2) ) = 8.
13016 //
13017 // (A smaller distance gamma-alpha would require a larger table.)
13018
13019 // NB:
13020 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
13021
13022 constexpr int kCachedPowersMinDecExp = -300;
13023 constexpr int kCachedPowersDecStep = 8;
13024
13025 static constexpr std::array<cached_power, 79> kCachedPowers =
13026 {
13027 {
13028 { 0xAB70FE17C79AC6CA, -1060, -300 },
13029 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
13030 { 0xBE5691EF416BD60C, -1007, -284 },
13031 { 0x8DD01FAD907FFC3C, -980, -276 },
13032 { 0xD3515C2831559A83, -954, -268 },
13033 { 0x9D71AC8FADA6C9B5, -927, -260 },
13034 { 0xEA9C227723EE8BCB, -901, -252 },
13035 { 0xAECC49914078536D, -874, -244 },
13036 { 0x823C12795DB6CE57, -847, -236 },
13037 { 0xC21094364DFB5637, -821, -228 },
13038 { 0x9096EA6F3848984F, -794, -220 },
13039 { 0xD77485CB25823AC7, -768, -212 },
13040 { 0xA086CFCD97BF97F4, -741, -204 },
13041 { 0xEF340A98172AACE5, -715, -196 },
13042 { 0xB23867FB2A35B28E, -688, -188 },
13043 { 0x84C8D4DFD2C63F3B, -661, -180 },
13044 { 0xC5DD44271AD3CDBA, -635, -172 },
13045 { 0x936B9FCEBB25C996, -608, -164 },
13046 { 0xDBAC6C247D62A584, -582, -156 },
13047 { 0xA3AB66580D5FDAF6, -555, -148 },
13048 { 0xF3E2F893DEC3F126, -529, -140 },
13049 { 0xB5B5ADA8AAFF80B8, -502, -132 },
13050 { 0x87625F056C7C4A8B, -475, -124 },
13051 { 0xC9BCFF6034C13053, -449, -116 },
13052 { 0x964E858C91BA2655, -422, -108 },
13053 { 0xDFF9772470297EBD, -396, -100 },
13054 { 0xA6DFBD9FB8E5B88F, -369, -92 },
13055 { 0xF8A95FCF88747D94, -343, -84 },
13056 { 0xB94470938FA89BCF, -316, -76 },
13057 { 0x8A08F0F8BF0F156B, -289, -68 },
13058 { 0xCDB02555653131B6, -263, -60 },
13059 { 0x993FE2C6D07B7FAC, -236, -52 },
13060 { 0xE45C10C42A2B3B06, -210, -44 },
13061 { 0xAA242499697392D3, -183, -36 },
13062 { 0xFD87B5F28300CA0E, -157, -28 },
13063 { 0xBCE5086492111AEB, -130, -20 },
13064 { 0x8CBCCC096F5088CC, -103, -12 },
13065 { 0xD1B71758E219652C, -77, -4 },
13066 { 0x9C40000000000000, -50, 4 },
13067 { 0xE8D4A51000000000, -24, 12 },
13068 { 0xAD78EBC5AC620000, 3, 20 },
13069 { 0x813F3978F8940984, 30, 28 },
13070 { 0xC097CE7BC90715B3, 56, 36 },
13071 { 0x8F7E32CE7BEA5C70, 83, 44 },
13072 { 0xD5D238A4ABE98068, 109, 52 },
13073 { 0x9F4F2726179A2245, 136, 60 },
13074 { 0xED63A231D4C4FB27, 162, 68 },
13075 { 0xB0DE65388CC8ADA8, 189, 76 },
13076 { 0x83C7088E1AAB65DB, 216, 84 },
13077 { 0xC45D1DF942711D9A, 242, 92 },
13078 { 0x924D692CA61BE758, 269, 100 },
13079 { 0xDA01EE641A708DEA, 295, 108 },
13080 { 0xA26DA3999AEF774A, 322, 116 },
13081 { 0xF209787BB47D6B85, 348, 124 },
13082 { 0xB454E4A179DD1877, 375, 132 },
13083 { 0x865B86925B9BC5C2, 402, 140 },
13084 { 0xC83553C5C8965D3D, 428, 148 },
13085 { 0x952AB45CFA97A0B3, 455, 156 },
13086 { 0xDE469FBD99A05FE3, 481, 164 },
13087 { 0xA59BC234DB398C25, 508, 172 },
13088 { 0xF6C69A72A3989F5C, 534, 180 },
13089 { 0xB7DCBF5354E9BECE, 561, 188 },
13090 { 0x88FCF317F22241E2, 588, 196 },
13091 { 0xCC20CE9BD35C78A5, 614, 204 },
13092 { 0x98165AF37B2153DF, 641, 212 },
13093 { 0xE2A0B5DC971F303A, 667, 220 },
13094 { 0xA8D9D1535CE3B396, 694, 228 },
13095 { 0xFB9B7CD9A4A7443C, 720, 236 },
13096 { 0xBB764C4CA7A44410, 747, 244 },
13097 { 0x8BAB8EEFB6409C1A, 774, 252 },
13098 { 0xD01FEF10A657842C, 800, 260 },
13099 { 0x9B10A4E5E9913129, 827, 268 },
13100 { 0xE7109BFBA19C0C9D, 853, 276 },
13101 { 0xAC2820D9623BF429, 880, 284 },
13102 { 0x80444B5E7AA7CF85, 907, 292 },
13103 { 0xBF21E44003ACDD2D, 933, 300 },
13104 { 0x8E679C2F5E44FF8F, 960, 308 },
13105 { 0xD433179D9C8CB841, 986, 316 },
13106 { 0x9E19DB92B4E31BA9, 1013, 324 },
13107 }
13108 };
13109
13110 // This computation gives exactly the same results for k as
13111 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
13112 // for |e| <= 1500, but doesn't require floating-point operations.
13113 // NB: log_10(2) ~= 78913 / 2^18
13114 assert(e >= -1500);
13115 assert(e <= 1500);
13116 const int f = kAlpha - e - 1;
13117 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
13118
13119 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
13120 assert(index >= 0);
13121 assert(static_cast<std::size_t>(index) < kCachedPowers.size());
13122
13123 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
13124 assert(kAlpha <= cached.e + e + 64);
13125 assert(kGamma >= cached.e + e + 64);
13126
13127 return cached;
13128 }
13129
13130 /*!
13131 For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
13132 For n == 0, returns 1 and sets pow10 := 1.
13133 */
find_largest_pow10(const std::uint32_t n,std::uint32_t & pow10)13134 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
13135 {
13136 // LCOV_EXCL_START
13137 if (n >= 1000000000)
13138 {
13139 pow10 = 1000000000;
13140 return 10;
13141 }
13142 // LCOV_EXCL_STOP
13143 else if (n >= 100000000)
13144 {
13145 pow10 = 100000000;
13146 return 9;
13147 }
13148 else if (n >= 10000000)
13149 {
13150 pow10 = 10000000;
13151 return 8;
13152 }
13153 else if (n >= 1000000)
13154 {
13155 pow10 = 1000000;
13156 return 7;
13157 }
13158 else if (n >= 100000)
13159 {
13160 pow10 = 100000;
13161 return 6;
13162 }
13163 else if (n >= 10000)
13164 {
13165 pow10 = 10000;
13166 return 5;
13167 }
13168 else if (n >= 1000)
13169 {
13170 pow10 = 1000;
13171 return 4;
13172 }
13173 else if (n >= 100)
13174 {
13175 pow10 = 100;
13176 return 3;
13177 }
13178 else if (n >= 10)
13179 {
13180 pow10 = 10;
13181 return 2;
13182 }
13183 else
13184 {
13185 pow10 = 1;
13186 return 1;
13187 }
13188 }
13189
grisu2_round(char * buf,int len,std::uint64_t dist,std::uint64_t delta,std::uint64_t rest,std::uint64_t ten_k)13190 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
13191 std::uint64_t rest, std::uint64_t ten_k)
13192 {
13193 assert(len >= 1);
13194 assert(dist <= delta);
13195 assert(rest <= delta);
13196 assert(ten_k > 0);
13197
13198 // <--------------------------- delta ---->
13199 // <---- dist --------->
13200 // --------------[------------------+-------------------]--------------
13201 // M- w M+
13202 //
13203 // ten_k
13204 // <------>
13205 // <---- rest ---->
13206 // --------------[------------------+----+--------------]--------------
13207 // w V
13208 // = buf * 10^k
13209 //
13210 // ten_k represents a unit-in-the-last-place in the decimal representation
13211 // stored in buf.
13212 // Decrement buf by ten_k while this takes buf closer to w.
13213
13214 // The tests are written in this order to avoid overflow in unsigned
13215 // integer arithmetic.
13216
13217 while (rest < dist
13218 and delta - rest >= ten_k
13219 and (rest + ten_k < dist or dist - rest > rest + ten_k - dist))
13220 {
13221 assert(buf[len - 1] != '0');
13222 buf[len - 1]--;
13223 rest += ten_k;
13224 }
13225 }
13226
13227 /*!
13228 Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
13229 M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
13230 */
grisu2_digit_gen(char * buffer,int & length,int & decimal_exponent,diyfp M_minus,diyfp w,diyfp M_plus)13231 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
13232 diyfp M_minus, diyfp w, diyfp M_plus)
13233 {
13234 static_assert(kAlpha >= -60, "internal error");
13235 static_assert(kGamma <= -32, "internal error");
13236
13237 // Generates the digits (and the exponent) of a decimal floating-point
13238 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
13239 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
13240 //
13241 // <--------------------------- delta ---->
13242 // <---- dist --------->
13243 // --------------[------------------+-------------------]--------------
13244 // M- w M+
13245 //
13246 // Grisu2 generates the digits of M+ from left to right and stops as soon as
13247 // V is in [M-,M+].
13248
13249 assert(M_plus.e >= kAlpha);
13250 assert(M_plus.e <= kGamma);
13251
13252 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
13253 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
13254
13255 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
13256 //
13257 // M+ = f * 2^e
13258 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
13259 // = ((p1 ) * 2^-e + (p2 )) * 2^e
13260 // = p1 + p2 * 2^e
13261
13262 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
13263
13264 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.)
13265 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
13266
13267 // 1)
13268 //
13269 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
13270
13271 assert(p1 > 0);
13272
13273 std::uint32_t pow10;
13274 const int k = find_largest_pow10(p1, pow10);
13275
13276 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
13277 //
13278 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
13279 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
13280 //
13281 // M+ = p1 + p2 * 2^e
13282 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
13283 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
13284 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
13285 //
13286 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
13287 //
13288 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
13289 //
13290 // but stop as soon as
13291 //
13292 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
13293
13294 int n = k;
13295 while (n > 0)
13296 {
13297 // Invariants:
13298 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
13299 // pow10 = 10^(n-1) <= p1 < 10^n
13300 //
13301 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
13302 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
13303 //
13304 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
13305 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
13306 //
13307 assert(d <= 9);
13308 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
13309 //
13310 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
13311 //
13312 p1 = r;
13313 n--;
13314 //
13315 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
13316 // pow10 = 10^n
13317 //
13318
13319 // Now check if enough digits have been generated.
13320 // Compute
13321 //
13322 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
13323 //
13324 // Note:
13325 // Since rest and delta share the same exponent e, it suffices to
13326 // compare the significands.
13327 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
13328 if (rest <= delta)
13329 {
13330 // V = buffer * 10^n, with M- <= V <= M+.
13331
13332 decimal_exponent += n;
13333
13334 // We may now just stop. But instead look if the buffer could be
13335 // decremented to bring V closer to w.
13336 //
13337 // pow10 = 10^n is now 1 ulp in the decimal representation V.
13338 // The rounding procedure works with diyfp's with an implicit
13339 // exponent of e.
13340 //
13341 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
13342 //
13343 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
13344 grisu2_round(buffer, length, dist, delta, rest, ten_n);
13345
13346 return;
13347 }
13348
13349 pow10 /= 10;
13350 //
13351 // pow10 = 10^(n-1) <= p1 < 10^n
13352 // Invariants restored.
13353 }
13354
13355 // 2)
13356 //
13357 // The digits of the integral part have been generated:
13358 //
13359 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
13360 // = buffer + p2 * 2^e
13361 //
13362 // Now generate the digits of the fractional part p2 * 2^e.
13363 //
13364 // Note:
13365 // No decimal point is generated: the exponent is adjusted instead.
13366 //
13367 // p2 actually represents the fraction
13368 //
13369 // p2 * 2^e
13370 // = p2 / 2^-e
13371 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
13372 //
13373 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
13374 //
13375 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
13376 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
13377 //
13378 // using
13379 //
13380 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
13381 // = ( d) * 2^-e + ( r)
13382 //
13383 // or
13384 // 10^m * p2 * 2^e = d + r * 2^e
13385 //
13386 // i.e.
13387 //
13388 // M+ = buffer + p2 * 2^e
13389 // = buffer + 10^-m * (d + r * 2^e)
13390 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
13391 //
13392 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
13393
13394 assert(p2 > delta);
13395
13396 int m = 0;
13397 for (;;)
13398 {
13399 // Invariant:
13400 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
13401 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
13402 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
13403 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
13404 //
13405 assert(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
13406 p2 *= 10;
13407 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
13408 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
13409 //
13410 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
13411 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
13412 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
13413 //
13414 assert(d <= 9);
13415 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
13416 //
13417 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
13418 //
13419 p2 = r;
13420 m++;
13421 //
13422 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
13423 // Invariant restored.
13424
13425 // Check if enough digits have been generated.
13426 //
13427 // 10^-m * p2 * 2^e <= delta * 2^e
13428 // p2 * 2^e <= 10^m * delta * 2^e
13429 // p2 <= 10^m * delta
13430 delta *= 10;
13431 dist *= 10;
13432 if (p2 <= delta)
13433 {
13434 break;
13435 }
13436 }
13437
13438 // V = buffer * 10^-m, with M- <= V <= M+.
13439
13440 decimal_exponent -= m;
13441
13442 // 1 ulp in the decimal representation is now 10^-m.
13443 // Since delta and dist are now scaled by 10^m, we need to do the
13444 // same with ulp in order to keep the units in sync.
13445 //
13446 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
13447 //
13448 const std::uint64_t ten_m = one.f;
13449 grisu2_round(buffer, length, dist, delta, p2, ten_m);
13450
13451 // By construction this algorithm generates the shortest possible decimal
13452 // number (Loitsch, Theorem 6.2) which rounds back to w.
13453 // For an input number of precision p, at least
13454 //
13455 // N = 1 + ceil(p * log_10(2))
13456 //
13457 // decimal digits are sufficient to identify all binary floating-point
13458 // numbers (Matula, "In-and-Out conversions").
13459 // This implies that the algorithm does not produce more than N decimal
13460 // digits.
13461 //
13462 // N = 17 for p = 53 (IEEE double precision)
13463 // N = 9 for p = 24 (IEEE single precision)
13464 }
13465
13466 /*!
13467 v = buf * 10^decimal_exponent
13468 len is the length of the buffer (number of decimal digits)
13469 The buffer must be large enough, i.e. >= max_digits10.
13470 */
13471 JSON_HEDLEY_NON_NULL(1)
grisu2(char * buf,int & len,int & decimal_exponent,diyfp m_minus,diyfp v,diyfp m_plus)13472 inline void grisu2(char* buf, int& len, int& decimal_exponent,
13473 diyfp m_minus, diyfp v, diyfp m_plus)
13474 {
13475 assert(m_plus.e == m_minus.e);
13476 assert(m_plus.e == v.e);
13477
13478 // --------(-----------------------+-----------------------)-------- (A)
13479 // m- v m+
13480 //
13481 // --------------------(-----------+-----------------------)-------- (B)
13482 // m- v m+
13483 //
13484 // First scale v (and m- and m+) such that the exponent is in the range
13485 // [alpha, gamma].
13486
13487 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
13488
13489 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
13490
13491 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
13492 const diyfp w = diyfp::mul(v, c_minus_k);
13493 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
13494 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
13495
13496 // ----(---+---)---------------(---+---)---------------(---+---)----
13497 // w- w w+
13498 // = c*m- = c*v = c*m+
13499 //
13500 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
13501 // w+ are now off by a small amount.
13502 // In fact:
13503 //
13504 // w - v * 10^k < 1 ulp
13505 //
13506 // To account for this inaccuracy, add resp. subtract 1 ulp.
13507 //
13508 // --------+---[---------------(---+---)---------------]---+--------
13509 // w- M- w M+ w+
13510 //
13511 // Now any number in [M-, M+] (bounds included) will round to w when input,
13512 // regardless of how the input rounding algorithm breaks ties.
13513 //
13514 // And digit_gen generates the shortest possible such number in [M-, M+].
13515 // Note that this does not mean that Grisu2 always generates the shortest
13516 // possible number in the interval (m-, m+).
13517 const diyfp M_minus(w_minus.f + 1, w_minus.e);
13518 const diyfp M_plus (w_plus.f - 1, w_plus.e );
13519
13520 decimal_exponent = -cached.k; // = -(-k) = k
13521
13522 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
13523 }
13524
13525 /*!
13526 v = buf * 10^decimal_exponent
13527 len is the length of the buffer (number of decimal digits)
13528 The buffer must be large enough, i.e. >= max_digits10.
13529 */
13530 template <typename FloatType>
13531 JSON_HEDLEY_NON_NULL(1)
grisu2(char * buf,int & len,int & decimal_exponent,FloatType value)13532 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
13533 {
13534 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
13535 "internal error: not enough precision");
13536
13537 assert(std::isfinite(value));
13538 assert(value > 0);
13539
13540 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
13541 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
13542 // decimal representations are not exactly "short".
13543 //
13544 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
13545 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
13546 // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
13547 // does.
13548 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
13549 // representation using the corresponding std::from_chars function recovers value exactly". That
13550 // indicates that single precision floating-point numbers should be recovered using
13551 // 'std::strtof'.
13552 //
13553 // NB: If the neighbors are computed for single-precision numbers, there is a single float
13554 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
13555 // value is off by 1 ulp.
13556 #if 0
13557 const boundaries w = compute_boundaries(static_cast<double>(value));
13558 #else
13559 const boundaries w = compute_boundaries(value);
13560 #endif
13561
13562 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
13563 }
13564
13565 /*!
13566 @brief appends a decimal representation of e to buf
13567 @return a pointer to the element following the exponent.
13568 @pre -1000 < e < 1000
13569 */
13570 JSON_HEDLEY_NON_NULL(1)
13571 JSON_HEDLEY_RETURNS_NON_NULL
append_exponent(char * buf,int e)13572 inline char* append_exponent(char* buf, int e)
13573 {
13574 assert(e > -1000);
13575 assert(e < 1000);
13576
13577 if (e < 0)
13578 {
13579 e = -e;
13580 *buf++ = '-';
13581 }
13582 else
13583 {
13584 *buf++ = '+';
13585 }
13586
13587 auto k = static_cast<std::uint32_t>(e);
13588 if (k < 10)
13589 {
13590 // Always print at least two digits in the exponent.
13591 // This is for compatibility with printf("%g").
13592 *buf++ = '0';
13593 *buf++ = static_cast<char>('0' + k);
13594 }
13595 else if (k < 100)
13596 {
13597 *buf++ = static_cast<char>('0' + k / 10);
13598 k %= 10;
13599 *buf++ = static_cast<char>('0' + k);
13600 }
13601 else
13602 {
13603 *buf++ = static_cast<char>('0' + k / 100);
13604 k %= 100;
13605 *buf++ = static_cast<char>('0' + k / 10);
13606 k %= 10;
13607 *buf++ = static_cast<char>('0' + k);
13608 }
13609
13610 return buf;
13611 }
13612
13613 /*!
13614 @brief prettify v = buf * 10^decimal_exponent
13615
13616 If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
13617 notation. Otherwise it will be printed in exponential notation.
13618
13619 @pre min_exp < 0
13620 @pre max_exp > 0
13621 */
13622 JSON_HEDLEY_NON_NULL(1)
13623 JSON_HEDLEY_RETURNS_NON_NULL
format_buffer(char * buf,int len,int decimal_exponent,int min_exp,int max_exp)13624 inline char* format_buffer(char* buf, int len, int decimal_exponent,
13625 int min_exp, int max_exp)
13626 {
13627 assert(min_exp < 0);
13628 assert(max_exp > 0);
13629
13630 const int k = len;
13631 const int n = len + decimal_exponent;
13632
13633 // v = buf * 10^(n-k)
13634 // k is the length of the buffer (number of decimal digits)
13635 // n is the position of the decimal point relative to the start of the buffer.
13636
13637 if (k <= n and n <= max_exp)
13638 {
13639 // digits[000]
13640 // len <= max_exp + 2
13641
13642 std::memset(buf + k, '0', static_cast<size_t>(n - k));
13643 // Make it look like a floating-point number (#362, #378)
13644 buf[n + 0] = '.';
13645 buf[n + 1] = '0';
13646 return buf + (n + 2);
13647 }
13648
13649 if (0 < n and n <= max_exp)
13650 {
13651 // dig.its
13652 // len <= max_digits10 + 1
13653
13654 assert(k > n);
13655
13656 std::memmove(buf + (n + 1), buf + n, static_cast<size_t>(k - n));
13657 buf[n] = '.';
13658 return buf + (k + 1);
13659 }
13660
13661 if (min_exp < n and n <= 0)
13662 {
13663 // 0.[000]digits
13664 // len <= 2 + (-min_exp - 1) + max_digits10
13665
13666 std::memmove(buf + (2 + -n), buf, static_cast<size_t>(k));
13667 buf[0] = '0';
13668 buf[1] = '.';
13669 std::memset(buf + 2, '0', static_cast<size_t>(-n));
13670 return buf + (2 + (-n) + k);
13671 }
13672
13673 if (k == 1)
13674 {
13675 // dE+123
13676 // len <= 1 + 5
13677
13678 buf += 1;
13679 }
13680 else
13681 {
13682 // d.igitsE+123
13683 // len <= max_digits10 + 1 + 5
13684
13685 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k - 1));
13686 buf[1] = '.';
13687 buf += 1 + k;
13688 }
13689
13690 *buf++ = 'e';
13691 return append_exponent(buf, n - 1);
13692 }
13693
13694 } // namespace dtoa_impl
13695
13696 /*!
13697 @brief generates a decimal representation of the floating-point number value in [first, last).
13698
13699 The format of the resulting decimal representation is similar to printf's %g
13700 format. Returns an iterator pointing past-the-end of the decimal representation.
13701
13702 @note The input number must be finite, i.e. NaN's and Inf's are not supported.
13703 @note The buffer must be large enough.
13704 @note The result is NOT null-terminated.
13705 */
13706 template <typename FloatType>
13707 JSON_HEDLEY_NON_NULL(1, 2)
13708 JSON_HEDLEY_RETURNS_NON_NULL
to_chars(char * first,const char * last,FloatType value)13709 char* to_chars(char* first, const char* last, FloatType value)
13710 {
13711 static_cast<void>(last); // maybe unused - fix warning
13712 assert(std::isfinite(value));
13713
13714 // Use signbit(value) instead of (value < 0) since signbit works for -0.
13715 if (std::signbit(value))
13716 {
13717 value = -value;
13718 *first++ = '-';
13719 }
13720
13721 if (value == 0) // +-0
13722 {
13723 *first++ = '0';
13724 // Make it look like a floating-point number (#362, #378)
13725 *first++ = '.';
13726 *first++ = '0';
13727 return first;
13728 }
13729
13730 assert(last - first >= std::numeric_limits<FloatType>::max_digits10);
13731
13732 // Compute v = buffer * 10^decimal_exponent.
13733 // The decimal digits are stored in the buffer, which needs to be interpreted
13734 // as an unsigned decimal integer.
13735 // len is the length of the buffer, i.e. the number of decimal digits.
13736 int len = 0;
13737 int decimal_exponent = 0;
13738 dtoa_impl::grisu2(first, len, decimal_exponent, value);
13739
13740 assert(len <= std::numeric_limits<FloatType>::max_digits10);
13741
13742 // Format the buffer like printf("%.*g", prec, value)
13743 constexpr int kMinExp = -4;
13744 // Use digits10 here to increase compatibility with version 2.
13745 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
13746
13747 assert(last - first >= kMaxExp + 2);
13748 assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
13749 assert(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
13750
13751 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
13752 }
13753
13754 } // namespace detail
13755 } // namespace nlohmann
13756
13757 // #include <nlohmann/detail/exceptions.hpp>
13758
13759 // #include <nlohmann/detail/macro_scope.hpp>
13760
13761 // #include <nlohmann/detail/meta/cpp_future.hpp>
13762
13763 // #include <nlohmann/detail/output/binary_writer.hpp>
13764
13765 // #include <nlohmann/detail/output/output_adapters.hpp>
13766
13767 // #include <nlohmann/detail/value_t.hpp>
13768
13769
13770 namespace nlohmann
13771 {
13772 namespace detail
13773 {
13774 ///////////////////
13775 // serialization //
13776 ///////////////////
13777
13778 /// how to treat decoding errors
13779 enum class error_handler_t
13780 {
13781 strict, ///< throw a type_error exception in case of invalid UTF-8
13782 replace, ///< replace invalid UTF-8 sequences with U+FFFD
13783 ignore ///< ignore invalid UTF-8 sequences
13784 };
13785
13786 template<typename BasicJsonType>
13787 class serializer
13788 {
13789 using string_t = typename BasicJsonType::string_t;
13790 using number_float_t = typename BasicJsonType::number_float_t;
13791 using number_integer_t = typename BasicJsonType::number_integer_t;
13792 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
13793 static constexpr std::uint8_t UTF8_ACCEPT = 0;
13794 static constexpr std::uint8_t UTF8_REJECT = 1;
13795
13796 public:
13797 /*!
13798 @param[in] s output stream to serialize to
13799 @param[in] ichar indentation character to use
13800 @param[in] error_handler_ how to react on decoding errors
13801 */
serializer(output_adapter_t<char> s,const char ichar,error_handler_t error_handler_=error_handler_t::strict)13802 serializer(output_adapter_t<char> s, const char ichar,
13803 error_handler_t error_handler_ = error_handler_t::strict)
13804 : o(std::move(s))
13805 , loc(std::localeconv())
13806 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : * (loc->thousands_sep))
13807 , decimal_point(loc->decimal_point == nullptr ? '\0' : * (loc->decimal_point))
13808 , indent_char(ichar)
13809 , indent_string(512, indent_char)
13810 , error_handler(error_handler_)
13811 {}
13812
13813 // delete because of pointer members
13814 serializer(const serializer&) = delete;
13815 serializer& operator=(const serializer&) = delete;
13816 serializer(serializer&&) = delete;
13817 serializer& operator=(serializer&&) = delete;
13818 ~serializer() = default;
13819
13820 /*!
13821 @brief internal implementation of the serialization function
13822
13823 This function is called by the public member function dump and organizes
13824 the serialization internally. The indentation level is propagated as
13825 additional parameter. In case of arrays and objects, the function is
13826 called recursively.
13827
13828 - strings and object keys are escaped using `escape_string()`
13829 - integer numbers are converted implicitly via `operator<<`
13830 - floating-point numbers are converted to a string using `"%g"` format
13831
13832 @param[in] val value to serialize
13833 @param[in] pretty_print whether the output shall be pretty-printed
13834 @param[in] indent_step the indent level
13835 @param[in] current_indent the current indent level (only used internally)
13836 */
dump(const BasicJsonType & val,const bool pretty_print,const bool ensure_ascii,const unsigned int indent_step,const unsigned int current_indent=0)13837 void dump(const BasicJsonType& val, const bool pretty_print,
13838 const bool ensure_ascii,
13839 const unsigned int indent_step,
13840 const unsigned int current_indent = 0)
13841 {
13842 switch (val.m_type)
13843 {
13844 case value_t::object:
13845 {
13846 if (val.m_value.object->empty())
13847 {
13848 o->write_characters("{}", 2);
13849 return;
13850 }
13851
13852 if (pretty_print)
13853 {
13854 o->write_characters("{\n", 2);
13855
13856 // variable to hold indentation for recursive calls
13857 const auto new_indent = current_indent + indent_step;
13858 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
13859 {
13860 indent_string.resize(indent_string.size() * 2, ' ');
13861 }
13862
13863 // first n-1 elements
13864 auto i = val.m_value.object->cbegin();
13865 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
13866 {
13867 o->write_characters(indent_string.c_str(), new_indent);
13868 o->write_character('\"');
13869 dump_escaped(i->first, ensure_ascii);
13870 o->write_characters("\": ", 3);
13871 dump(i->second, true, ensure_ascii, indent_step, new_indent);
13872 o->write_characters(",\n", 2);
13873 }
13874
13875 // last element
13876 assert(i != val.m_value.object->cend());
13877 assert(std::next(i) == val.m_value.object->cend());
13878 o->write_characters(indent_string.c_str(), new_indent);
13879 o->write_character('\"');
13880 dump_escaped(i->first, ensure_ascii);
13881 o->write_characters("\": ", 3);
13882 dump(i->second, true, ensure_ascii, indent_step, new_indent);
13883
13884 o->write_character('\n');
13885 o->write_characters(indent_string.c_str(), current_indent);
13886 o->write_character('}');
13887 }
13888 else
13889 {
13890 o->write_character('{');
13891
13892 // first n-1 elements
13893 auto i = val.m_value.object->cbegin();
13894 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
13895 {
13896 o->write_character('\"');
13897 dump_escaped(i->first, ensure_ascii);
13898 o->write_characters("\":", 2);
13899 dump(i->second, false, ensure_ascii, indent_step, current_indent);
13900 o->write_character(',');
13901 }
13902
13903 // last element
13904 assert(i != val.m_value.object->cend());
13905 assert(std::next(i) == val.m_value.object->cend());
13906 o->write_character('\"');
13907 dump_escaped(i->first, ensure_ascii);
13908 o->write_characters("\":", 2);
13909 dump(i->second, false, ensure_ascii, indent_step, current_indent);
13910
13911 o->write_character('}');
13912 }
13913
13914 return;
13915 }
13916
13917 case value_t::array:
13918 {
13919 if (val.m_value.array->empty())
13920 {
13921 o->write_characters("[]", 2);
13922 return;
13923 }
13924
13925 if (pretty_print)
13926 {
13927 o->write_characters("[\n", 2);
13928
13929 // variable to hold indentation for recursive calls
13930 const auto new_indent = current_indent + indent_step;
13931 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
13932 {
13933 indent_string.resize(indent_string.size() * 2, ' ');
13934 }
13935
13936 // first n-1 elements
13937 for (auto i = val.m_value.array->cbegin();
13938 i != val.m_value.array->cend() - 1; ++i)
13939 {
13940 o->write_characters(indent_string.c_str(), new_indent);
13941 dump(*i, true, ensure_ascii, indent_step, new_indent);
13942 o->write_characters(",\n", 2);
13943 }
13944
13945 // last element
13946 assert(not val.m_value.array->empty());
13947 o->write_characters(indent_string.c_str(), new_indent);
13948 dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
13949
13950 o->write_character('\n');
13951 o->write_characters(indent_string.c_str(), current_indent);
13952 o->write_character(']');
13953 }
13954 else
13955 {
13956 o->write_character('[');
13957
13958 // first n-1 elements
13959 for (auto i = val.m_value.array->cbegin();
13960 i != val.m_value.array->cend() - 1; ++i)
13961 {
13962 dump(*i, false, ensure_ascii, indent_step, current_indent);
13963 o->write_character(',');
13964 }
13965
13966 // last element
13967 assert(not val.m_value.array->empty());
13968 dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
13969
13970 o->write_character(']');
13971 }
13972
13973 return;
13974 }
13975
13976 case value_t::string:
13977 {
13978 o->write_character('\"');
13979 dump_escaped(*val.m_value.string, ensure_ascii);
13980 o->write_character('\"');
13981 return;
13982 }
13983
13984 case value_t::boolean:
13985 {
13986 if (val.m_value.boolean)
13987 {
13988 o->write_characters("true", 4);
13989 }
13990 else
13991 {
13992 o->write_characters("false", 5);
13993 }
13994 return;
13995 }
13996
13997 case value_t::number_integer:
13998 {
13999 dump_integer(val.m_value.number_integer);
14000 return;
14001 }
14002
14003 case value_t::number_unsigned:
14004 {
14005 dump_integer(val.m_value.number_unsigned);
14006 return;
14007 }
14008
14009 case value_t::number_float:
14010 {
14011 dump_float(val.m_value.number_float);
14012 return;
14013 }
14014
14015 case value_t::discarded:
14016 {
14017 o->write_characters("<discarded>", 11);
14018 return;
14019 }
14020
14021 case value_t::null:
14022 {
14023 o->write_characters("null", 4);
14024 return;
14025 }
14026
14027 default: // LCOV_EXCL_LINE
14028 assert(false); // LCOV_EXCL_LINE
14029 }
14030 }
14031
14032 private:
14033 /*!
14034 @brief dump escaped string
14035
14036 Escape a string by replacing certain special characters by a sequence of an
14037 escape character (backslash) and another character and other control
14038 characters by a sequence of "\u" followed by a four-digit hex
14039 representation. The escaped string is written to output stream @a o.
14040
14041 @param[in] s the string to escape
14042 @param[in] ensure_ascii whether to escape non-ASCII characters with
14043 \uXXXX sequences
14044
14045 @complexity Linear in the length of string @a s.
14046 */
dump_escaped(const string_t & s,const bool ensure_ascii)14047 void dump_escaped(const string_t& s, const bool ensure_ascii)
14048 {
14049 std::uint32_t codepoint;
14050 std::uint8_t state = UTF8_ACCEPT;
14051 std::size_t bytes = 0; // number of bytes written to string_buffer
14052
14053 // number of bytes written at the point of the last valid byte
14054 std::size_t bytes_after_last_accept = 0;
14055 std::size_t undumped_chars = 0;
14056
14057 for (std::size_t i = 0; i < s.size(); ++i)
14058 {
14059 const auto byte = static_cast<uint8_t>(s[i]);
14060
14061 switch (decode(state, codepoint, byte))
14062 {
14063 case UTF8_ACCEPT: // decode found a new code point
14064 {
14065 switch (codepoint)
14066 {
14067 case 0x08: // backspace
14068 {
14069 string_buffer[bytes++] = '\\';
14070 string_buffer[bytes++] = 'b';
14071 break;
14072 }
14073
14074 case 0x09: // horizontal tab
14075 {
14076 string_buffer[bytes++] = '\\';
14077 string_buffer[bytes++] = 't';
14078 break;
14079 }
14080
14081 case 0x0A: // newline
14082 {
14083 string_buffer[bytes++] = '\\';
14084 string_buffer[bytes++] = 'n';
14085 break;
14086 }
14087
14088 case 0x0C: // formfeed
14089 {
14090 string_buffer[bytes++] = '\\';
14091 string_buffer[bytes++] = 'f';
14092 break;
14093 }
14094
14095 case 0x0D: // carriage return
14096 {
14097 string_buffer[bytes++] = '\\';
14098 string_buffer[bytes++] = 'r';
14099 break;
14100 }
14101
14102 case 0x22: // quotation mark
14103 {
14104 string_buffer[bytes++] = '\\';
14105 string_buffer[bytes++] = '\"';
14106 break;
14107 }
14108
14109 case 0x5C: // reverse solidus
14110 {
14111 string_buffer[bytes++] = '\\';
14112 string_buffer[bytes++] = '\\';
14113 break;
14114 }
14115
14116 default:
14117 {
14118 // escape control characters (0x00..0x1F) or, if
14119 // ensure_ascii parameter is used, non-ASCII characters
14120 if ((codepoint <= 0x1F) or (ensure_ascii and (codepoint >= 0x7F)))
14121 {
14122 if (codepoint <= 0xFFFF)
14123 {
14124 (std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
14125 static_cast<std::uint16_t>(codepoint));
14126 bytes += 6;
14127 }
14128 else
14129 {
14130 (std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
14131 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
14132 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)));
14133 bytes += 12;
14134 }
14135 }
14136 else
14137 {
14138 // copy byte to buffer (all previous bytes
14139 // been copied have in default case above)
14140 string_buffer[bytes++] = s[i];
14141 }
14142 break;
14143 }
14144 }
14145
14146 // write buffer and reset index; there must be 13 bytes
14147 // left, as this is the maximal number of bytes to be
14148 // written ("\uxxxx\uxxxx\0") for one code point
14149 if (string_buffer.size() - bytes < 13)
14150 {
14151 o->write_characters(string_buffer.data(), bytes);
14152 bytes = 0;
14153 }
14154
14155 // remember the byte position of this accept
14156 bytes_after_last_accept = bytes;
14157 undumped_chars = 0;
14158 break;
14159 }
14160
14161 case UTF8_REJECT: // decode found invalid UTF-8 byte
14162 {
14163 switch (error_handler)
14164 {
14165 case error_handler_t::strict:
14166 {
14167 std::string sn(3, '\0');
14168 (std::snprintf)(&sn[0], sn.size(), "%.2X", byte);
14169 JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn));
14170 }
14171
14172 case error_handler_t::ignore:
14173 case error_handler_t::replace:
14174 {
14175 // in case we saw this character the first time, we
14176 // would like to read it again, because the byte
14177 // may be OK for itself, but just not OK for the
14178 // previous sequence
14179 if (undumped_chars > 0)
14180 {
14181 --i;
14182 }
14183
14184 // reset length buffer to the last accepted index;
14185 // thus removing/ignoring the invalid characters
14186 bytes = bytes_after_last_accept;
14187
14188 if (error_handler == error_handler_t::replace)
14189 {
14190 // add a replacement character
14191 if (ensure_ascii)
14192 {
14193 string_buffer[bytes++] = '\\';
14194 string_buffer[bytes++] = 'u';
14195 string_buffer[bytes++] = 'f';
14196 string_buffer[bytes++] = 'f';
14197 string_buffer[bytes++] = 'f';
14198 string_buffer[bytes++] = 'd';
14199 }
14200 else
14201 {
14202 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
14203 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
14204 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
14205 }
14206
14207 // write buffer and reset index; there must be 13 bytes
14208 // left, as this is the maximal number of bytes to be
14209 // written ("\uxxxx\uxxxx\0") for one code point
14210 if (string_buffer.size() - bytes < 13)
14211 {
14212 o->write_characters(string_buffer.data(), bytes);
14213 bytes = 0;
14214 }
14215
14216 bytes_after_last_accept = bytes;
14217 }
14218
14219 undumped_chars = 0;
14220
14221 // continue processing the string
14222 state = UTF8_ACCEPT;
14223 break;
14224 }
14225
14226 default: // LCOV_EXCL_LINE
14227 assert(false); // LCOV_EXCL_LINE
14228 }
14229 break;
14230 }
14231
14232 default: // decode found yet incomplete multi-byte code point
14233 {
14234 if (not ensure_ascii)
14235 {
14236 // code point will not be escaped - copy byte to buffer
14237 string_buffer[bytes++] = s[i];
14238 }
14239 ++undumped_chars;
14240 break;
14241 }
14242 }
14243 }
14244
14245 // we finished processing the string
14246 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
14247 {
14248 // write buffer
14249 if (bytes > 0)
14250 {
14251 o->write_characters(string_buffer.data(), bytes);
14252 }
14253 }
14254 else
14255 {
14256 // we finish reading, but do not accept: string was incomplete
14257 switch (error_handler)
14258 {
14259 case error_handler_t::strict:
14260 {
14261 std::string sn(3, '\0');
14262 (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast<std::uint8_t>(s.back()));
14263 JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
14264 }
14265
14266 case error_handler_t::ignore:
14267 {
14268 // write all accepted bytes
14269 o->write_characters(string_buffer.data(), bytes_after_last_accept);
14270 break;
14271 }
14272
14273 case error_handler_t::replace:
14274 {
14275 // write all accepted bytes
14276 o->write_characters(string_buffer.data(), bytes_after_last_accept);
14277 // add a replacement character
14278 if (ensure_ascii)
14279 {
14280 o->write_characters("\\ufffd", 6);
14281 }
14282 else
14283 {
14284 o->write_characters("\xEF\xBF\xBD", 3);
14285 }
14286 break;
14287 }
14288
14289 default: // LCOV_EXCL_LINE
14290 assert(false); // LCOV_EXCL_LINE
14291 }
14292 }
14293 }
14294
14295 /*!
14296 @brief count digits
14297
14298 Count the number of decimal (base 10) digits for an input unsigned integer.
14299
14300 @param[in] x unsigned integer number to count its digits
14301 @return number of decimal digits
14302 */
count_digits(number_unsigned_t x)14303 inline unsigned int count_digits(number_unsigned_t x) noexcept
14304 {
14305 unsigned int n_digits = 1;
14306 for (;;)
14307 {
14308 if (x < 10)
14309 {
14310 return n_digits;
14311 }
14312 if (x < 100)
14313 {
14314 return n_digits + 1;
14315 }
14316 if (x < 1000)
14317 {
14318 return n_digits + 2;
14319 }
14320 if (x < 10000)
14321 {
14322 return n_digits + 3;
14323 }
14324 x = x / 10000u;
14325 n_digits += 4;
14326 }
14327 }
14328
14329 /*!
14330 @brief dump an integer
14331
14332 Dump a given integer to output stream @a o. Works internally with
14333 @a number_buffer.
14334
14335 @param[in] x integer number (signed or unsigned) to dump
14336 @tparam NumberType either @a number_integer_t or @a number_unsigned_t
14337 */
14338 template<typename NumberType, detail::enable_if_t<
14339 std::is_same<NumberType, number_unsigned_t>::value or
14340 std::is_same<NumberType, number_integer_t>::value,
14341 int> = 0>
dump_integer(NumberType x)14342 void dump_integer(NumberType x)
14343 {
14344 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
14345 {
14346 {
14347 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
14348 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
14349 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
14350 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
14351 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
14352 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
14353 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
14354 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
14355 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
14356 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
14357 }
14358 };
14359
14360 // special case for "0"
14361 if (x == 0)
14362 {
14363 o->write_character('0');
14364 return;
14365 }
14366
14367 // use a pointer to fill the buffer
14368 auto buffer_ptr = number_buffer.begin();
14369
14370 const bool is_negative = std::is_same<NumberType, number_integer_t>::value and not(x >= 0); // see issue #755
14371 number_unsigned_t abs_value;
14372
14373 unsigned int n_chars;
14374
14375 if (is_negative)
14376 {
14377 *buffer_ptr = '-';
14378 abs_value = remove_sign(x);
14379
14380 // account one more byte for the minus sign
14381 n_chars = 1 + count_digits(abs_value);
14382 }
14383 else
14384 {
14385 abs_value = static_cast<number_unsigned_t>(x);
14386 n_chars = count_digits(abs_value);
14387 }
14388
14389 // spare 1 byte for '\0'
14390 assert(n_chars < number_buffer.size() - 1);
14391
14392 // jump to the end to generate the string from backward
14393 // so we later avoid reversing the result
14394 buffer_ptr += n_chars;
14395
14396 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
14397 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
14398 while (abs_value >= 100)
14399 {
14400 const auto digits_index = static_cast<unsigned>((abs_value % 100));
14401 abs_value /= 100;
14402 *(--buffer_ptr) = digits_to_99[digits_index][1];
14403 *(--buffer_ptr) = digits_to_99[digits_index][0];
14404 }
14405
14406 if (abs_value >= 10)
14407 {
14408 const auto digits_index = static_cast<unsigned>(abs_value);
14409 *(--buffer_ptr) = digits_to_99[digits_index][1];
14410 *(--buffer_ptr) = digits_to_99[digits_index][0];
14411 }
14412 else
14413 {
14414 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
14415 }
14416
14417 o->write_characters(number_buffer.data(), n_chars);
14418 }
14419
14420 /*!
14421 @brief dump a floating-point number
14422
14423 Dump a given floating-point number to output stream @a o. Works internally
14424 with @a number_buffer.
14425
14426 @param[in] x floating-point number to dump
14427 */
dump_float(number_float_t x)14428 void dump_float(number_float_t x)
14429 {
14430 // NaN / inf
14431 if (not std::isfinite(x))
14432 {
14433 o->write_characters("null", 4);
14434 return;
14435 }
14436
14437 // If number_float_t is an IEEE-754 single or double precision number,
14438 // use the Grisu2 algorithm to produce short numbers which are
14439 // guaranteed to round-trip, using strtof and strtod, resp.
14440 //
14441 // NB: The test below works if <long double> == <double>.
14442 static constexpr bool is_ieee_single_or_double
14443 = (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 24 and std::numeric_limits<number_float_t>::max_exponent == 128) or
14444 (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 53 and std::numeric_limits<number_float_t>::max_exponent == 1024);
14445
14446 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
14447 }
14448
dump_float(number_float_t x,std::true_type)14449 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
14450 {
14451 char* begin = number_buffer.data();
14452 char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
14453
14454 o->write_characters(begin, static_cast<size_t>(end - begin));
14455 }
14456
dump_float(number_float_t x,std::false_type)14457 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
14458 {
14459 // get number of digits for a float -> text -> float round-trip
14460 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
14461
14462 // the actual conversion
14463 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
14464
14465 // negative value indicates an error
14466 assert(len > 0);
14467 // check if buffer was large enough
14468 assert(static_cast<std::size_t>(len) < number_buffer.size());
14469
14470 // erase thousands separator
14471 if (thousands_sep != '\0')
14472 {
14473 const auto end = std::remove(number_buffer.begin(),
14474 number_buffer.begin() + len, thousands_sep);
14475 std::fill(end, number_buffer.end(), '\0');
14476 assert((end - number_buffer.begin()) <= len);
14477 len = (end - number_buffer.begin());
14478 }
14479
14480 // convert decimal point to '.'
14481 if (decimal_point != '\0' and decimal_point != '.')
14482 {
14483 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
14484 if (dec_pos != number_buffer.end())
14485 {
14486 *dec_pos = '.';
14487 }
14488 }
14489
14490 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
14491
14492 // determine if need to append ".0"
14493 const bool value_is_int_like =
14494 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
14495 [](char c)
14496 {
14497 return c == '.' or c == 'e';
14498 });
14499
14500 if (value_is_int_like)
14501 {
14502 o->write_characters(".0", 2);
14503 }
14504 }
14505
14506 /*!
14507 @brief check whether a string is UTF-8 encoded
14508
14509 The function checks each byte of a string whether it is UTF-8 encoded. The
14510 result of the check is stored in the @a state parameter. The function must
14511 be called initially with state 0 (accept). State 1 means the string must
14512 be rejected, because the current byte is not allowed. If the string is
14513 completely processed, but the state is non-zero, the string ended
14514 prematurely; that is, the last byte indicated more bytes should have
14515 followed.
14516
14517 @param[in,out] state the state of the decoding
14518 @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
14519 @param[in] byte next byte to decode
14520 @return new state
14521
14522 @note The function has been edited: a std::array is used.
14523
14524 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
14525 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
14526 */
decode(std::uint8_t & state,std::uint32_t & codep,const std::uint8_t byte)14527 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
14528 {
14529 static const std::array<std::uint8_t, 400> utf8d =
14530 {
14531 {
14532 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
14533 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
14534 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
14535 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
14536 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
14537 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
14538 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
14539 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
14540 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
14541 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
14542 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
14543 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
14544 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
14545 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
14546 }
14547 };
14548
14549 const std::uint8_t type = utf8d[byte];
14550
14551 codep = (state != UTF8_ACCEPT)
14552 ? (byte & 0x3fu) | (codep << 6u)
14553 : (0xFFu >> type) & (byte);
14554
14555 state = utf8d[256u + state * 16u + type];
14556 return state;
14557 }
14558
14559 /*
14560 * Overload to make the compiler happy while it is instantiating
14561 * dump_integer for number_unsigned_t.
14562 * Must never be called.
14563 */
remove_sign(number_unsigned_t x)14564 number_unsigned_t remove_sign(number_unsigned_t x)
14565 {
14566 assert(false); // LCOV_EXCL_LINE
14567 return x; // LCOV_EXCL_LINE
14568 }
14569
14570 /*
14571 * Helper function for dump_integer
14572 *
14573 * This function takes a negative signed integer and returns its absolute
14574 * value as unsigned integer. The plus/minus shuffling is necessary as we can
14575 * not directly remove the sign of an arbitrary signed integer as the
14576 * absolute values of INT_MIN and INT_MAX are usually not the same. See
14577 * #1708 for details.
14578 */
remove_sign(number_integer_t x)14579 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
14580 {
14581 assert(x < 0 and x < (std::numeric_limits<number_integer_t>::max)());
14582 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
14583 }
14584
14585 private:
14586 /// the output of the serializer
14587 output_adapter_t<char> o = nullptr;
14588
14589 /// a (hopefully) large enough character buffer
14590 std::array<char, 64> number_buffer{{}};
14591
14592 /// the locale
14593 const std::lconv* loc = nullptr;
14594 /// the locale's thousand separator character
14595 const char thousands_sep = '\0';
14596 /// the locale's decimal point character
14597 const char decimal_point = '\0';
14598
14599 /// string buffer
14600 std::array<char, 512> string_buffer{{}};
14601
14602 /// the indentation character
14603 const char indent_char;
14604 /// the indentation string
14605 string_t indent_string;
14606
14607 /// error_handler how to react on decoding errors
14608 const error_handler_t error_handler;
14609 };
14610 } // namespace detail
14611 } // namespace nlohmann
14612
14613 // #include <nlohmann/detail/value_t.hpp>
14614
14615 // #include <nlohmann/json_fwd.hpp>
14616
14617
14618 /*!
14619 @brief namespace for Niels Lohmann
14620 @see https://github.com/nlohmann
14621 @since version 1.0.0
14622 */
14623 namespace nlohmann
14624 {
14625
14626 /*!
14627 @brief a class to store JSON values
14628
14629 @tparam ObjectType type for JSON objects (`std::map` by default; will be used
14630 in @ref object_t)
14631 @tparam ArrayType type for JSON arrays (`std::vector` by default; will be used
14632 in @ref array_t)
14633 @tparam StringType type for JSON strings and object keys (`std::string` by
14634 default; will be used in @ref string_t)
14635 @tparam BooleanType type for JSON booleans (`bool` by default; will be used
14636 in @ref boolean_t)
14637 @tparam NumberIntegerType type for JSON integer numbers (`int64_t` by
14638 default; will be used in @ref number_integer_t)
14639 @tparam NumberUnsignedType type for JSON unsigned integer numbers (@c
14640 `uint64_t` by default; will be used in @ref number_unsigned_t)
14641 @tparam NumberFloatType type for JSON floating-point numbers (`double` by
14642 default; will be used in @ref number_float_t)
14643 @tparam AllocatorType type of the allocator to use (`std::allocator` by
14644 default)
14645 @tparam JSONSerializer the serializer to resolve internal calls to `to_json()`
14646 and `from_json()` (@ref adl_serializer by default)
14647
14648 @requirement The class satisfies the following concept requirements:
14649 - Basic
14650 - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible):
14651 JSON values can be default constructed. The result will be a JSON null
14652 value.
14653 - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible):
14654 A JSON value can be constructed from an rvalue argument.
14655 - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible):
14656 A JSON value can be copy-constructed from an lvalue expression.
14657 - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable):
14658 A JSON value van be assigned from an rvalue argument.
14659 - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable):
14660 A JSON value can be copy-assigned from an lvalue expression.
14661 - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible):
14662 JSON values can be destructed.
14663 - Layout
14664 - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType):
14665 JSON values have
14666 [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
14667 All non-static data members are private and standard layout types, the
14668 class has no virtual functions or (virtual) base classes.
14669 - Library-wide
14670 - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable):
14671 JSON values can be compared with `==`, see @ref
14672 operator==(const_reference,const_reference).
14673 - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable):
14674 JSON values can be compared with `<`, see @ref
14675 operator<(const_reference,const_reference).
14676 - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable):
14677 Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
14678 other compatible types, using unqualified function call @ref swap().
14679 - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer):
14680 JSON values can be compared against `std::nullptr_t` objects which are used
14681 to model the `null` value.
14682 - Container
14683 - [Container](https://en.cppreference.com/w/cpp/named_req/Container):
14684 JSON values can be used like STL containers and provide iterator access.
14685 - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer);
14686 JSON values can be used like STL containers and provide reverse iterator
14687 access.
14688
14689 @invariant The member variables @a m_value and @a m_type have the following
14690 relationship:
14691 - If `m_type == value_t::object`, then `m_value.object != nullptr`.
14692 - If `m_type == value_t::array`, then `m_value.array != nullptr`.
14693 - If `m_type == value_t::string`, then `m_value.string != nullptr`.
14694 The invariants are checked by member function assert_invariant().
14695
14696 @internal
14697 @note ObjectType trick from http://stackoverflow.com/a/9860911
14698 @endinternal
14699
14700 @see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange
14701 Format](http://rfc7159.net/rfc7159)
14702
14703 @since version 1.0.0
14704
14705 @nosubgrouping
14706 */
14707 NLOHMANN_BASIC_JSON_TPL_DECLARATION
14708 class basic_json
14709 {
14710 private:
14711 template<detail::value_t> friend struct detail::external_constructor;
14712 friend ::nlohmann::json_pointer<basic_json>;
14713 friend ::nlohmann::detail::parser<basic_json>;
14714 friend ::nlohmann::detail::serializer<basic_json>;
14715 template<typename BasicJsonType>
14716 friend class ::nlohmann::detail::iter_impl;
14717 template<typename BasicJsonType, typename CharType>
14718 friend class ::nlohmann::detail::binary_writer;
14719 template<typename BasicJsonType, typename SAX>
14720 friend class ::nlohmann::detail::binary_reader;
14721 template<typename BasicJsonType>
14722 friend class ::nlohmann::detail::json_sax_dom_parser;
14723 template<typename BasicJsonType>
14724 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
14725
14726 /// workaround type for MSVC
14727 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
14728
14729 // convenience aliases for types residing in namespace detail;
14730 using lexer = ::nlohmann::detail::lexer<basic_json>;
14731 using parser = ::nlohmann::detail::parser<basic_json>;
14732
14733 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
14734 template<typename BasicJsonType>
14735 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
14736 template<typename BasicJsonType>
14737 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
14738 template<typename Iterator>
14739 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
14740 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
14741
14742 template<typename CharType>
14743 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
14744
14745 using binary_reader = ::nlohmann::detail::binary_reader<basic_json>;
14746 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
14747
14748 using serializer = ::nlohmann::detail::serializer<basic_json>;
14749
14750 public:
14751 using value_t = detail::value_t;
14752 /// JSON Pointer, see @ref nlohmann::json_pointer
14753 using json_pointer = ::nlohmann::json_pointer<basic_json>;
14754 template<typename T, typename SFINAE>
14755 using json_serializer = JSONSerializer<T, SFINAE>;
14756 /// how to treat decoding errors
14757 using error_handler_t = detail::error_handler_t;
14758 /// helper type for initializer lists of basic_json values
14759 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
14760
14761 using input_format_t = detail::input_format_t;
14762 /// SAX interface type, see @ref nlohmann::json_sax
14763 using json_sax_t = json_sax<basic_json>;
14764
14765 ////////////////
14766 // exceptions //
14767 ////////////////
14768
14769 /// @name exceptions
14770 /// Classes to implement user-defined exceptions.
14771 /// @{
14772
14773 /// @copydoc detail::exception
14774 using exception = detail::exception;
14775 /// @copydoc detail::parse_error
14776 using parse_error = detail::parse_error;
14777 /// @copydoc detail::invalid_iterator
14778 using invalid_iterator = detail::invalid_iterator;
14779 /// @copydoc detail::type_error
14780 using type_error = detail::type_error;
14781 /// @copydoc detail::out_of_range
14782 using out_of_range = detail::out_of_range;
14783 /// @copydoc detail::other_error
14784 using other_error = detail::other_error;
14785
14786 /// @}
14787
14788
14789 /////////////////////
14790 // container types //
14791 /////////////////////
14792
14793 /// @name container types
14794 /// The canonic container types to use @ref basic_json like any other STL
14795 /// container.
14796 /// @{
14797
14798 /// the type of elements in a basic_json container
14799 using value_type = basic_json;
14800
14801 /// the type of an element reference
14802 using reference = value_type&;
14803 /// the type of an element const reference
14804 using const_reference = const value_type&;
14805
14806 /// a type to represent differences between iterators
14807 using difference_type = std::ptrdiff_t;
14808 /// a type to represent container sizes
14809 using size_type = std::size_t;
14810
14811 /// the allocator type
14812 using allocator_type = AllocatorType<basic_json>;
14813
14814 /// the type of an element pointer
14815 using pointer = typename std::allocator_traits<allocator_type>::pointer;
14816 /// the type of an element const pointer
14817 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
14818
14819 /// an iterator for a basic_json container
14820 using iterator = iter_impl<basic_json>;
14821 /// a const iterator for a basic_json container
14822 using const_iterator = iter_impl<const basic_json>;
14823 /// a reverse iterator for a basic_json container
14824 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
14825 /// a const reverse iterator for a basic_json container
14826 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
14827
14828 /// @}
14829
14830
14831 /*!
14832 @brief returns the allocator associated with the container
14833 */
get_allocator()14834 static allocator_type get_allocator()
14835 {
14836 return allocator_type();
14837 }
14838
14839 /*!
14840 @brief returns version information on the library
14841
14842 This function returns a JSON object with information about the library,
14843 including the version number and information on the platform and compiler.
14844
14845 @return JSON object holding version information
14846 key | description
14847 ----------- | ---------------
14848 `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).
14849 `copyright` | The copyright line for the library as string.
14850 `name` | The name of the library as string.
14851 `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`.
14852 `url` | The URL of the project as string.
14853 `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string).
14854
14855 @liveexample{The following code shows an example output of the `meta()`
14856 function.,meta}
14857
14858 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
14859 changes to any JSON value.
14860
14861 @complexity Constant.
14862
14863 @since 2.1.0
14864 */
14865 JSON_HEDLEY_WARN_UNUSED_RESULT
meta()14866 static basic_json meta()
14867 {
14868 basic_json result;
14869
14870 result["copyright"] = "(C) 2013-2017 Niels Lohmann";
14871 result["name"] = "JSON for Modern C++";
14872 result["url"] = "https://github.com/nlohmann/json";
14873 result["version"]["string"] =
14874 std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
14875 std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
14876 std::to_string(NLOHMANN_JSON_VERSION_PATCH);
14877 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
14878 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
14879 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
14880
14881 #ifdef _WIN32
14882 result["platform"] = "win32";
14883 #elif defined __linux__
14884 result["platform"] = "linux";
14885 #elif defined __APPLE__
14886 result["platform"] = "apple";
14887 #elif defined __unix__
14888 result["platform"] = "unix";
14889 #else
14890 result["platform"] = "unknown";
14891 #endif
14892
14893 #if defined(__ICC) || defined(__INTEL_COMPILER)
14894 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
14895 #elif defined(__clang__)
14896 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
14897 #elif defined(__GNUC__) || defined(__GNUG__)
14898 result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
14899 #elif defined(__HP_cc) || defined(__HP_aCC)
14900 result["compiler"] = "hp"
14901 #elif defined(__IBMCPP__)
14902 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
14903 #elif defined(_MSC_VER)
14904 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
14905 #elif defined(__PGI)
14906 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
14907 #elif defined(__SUNPRO_CC)
14908 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
14909 #else
14910 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
14911 #endif
14912
14913 #ifdef __cplusplus
14914 result["compiler"]["c++"] = std::to_string(__cplusplus);
14915 #else
14916 result["compiler"]["c++"] = "unknown";
14917 #endif
14918 return result;
14919 }
14920
14921
14922 ///////////////////////////
14923 // JSON value data types //
14924 ///////////////////////////
14925
14926 /// @name JSON value data types
14927 /// The data types to store a JSON value. These types are derived from
14928 /// the template arguments passed to class @ref basic_json.
14929 /// @{
14930
14931 #if defined(JSON_HAS_CPP_14)
14932 // Use transparent comparator if possible, combined with perfect forwarding
14933 // on find() and count() calls prevents unnecessary string construction.
14934 using object_comparator_t = std::less<>;
14935 #else
14936 using object_comparator_t = std::less<StringType>;
14937 #endif
14938
14939 /*!
14940 @brief a type for an object
14941
14942 [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:
14943 > An object is an unordered collection of zero or more name/value pairs,
14944 > where a name is a string and a value is a string, number, boolean, null,
14945 > object, or array.
14946
14947 To store objects in C++, a type is defined by the template parameters
14948 described below.
14949
14950 @tparam ObjectType the container to store objects (e.g., `std::map` or
14951 `std::unordered_map`)
14952 @tparam StringType the type of the keys or names (e.g., `std::string`).
14953 The comparison function `std::less<StringType>` is used to order elements
14954 inside the container.
14955 @tparam AllocatorType the allocator to use for objects (e.g.,
14956 `std::allocator`)
14957
14958 #### Default type
14959
14960 With the default values for @a ObjectType (`std::map`), @a StringType
14961 (`std::string`), and @a AllocatorType (`std::allocator`), the default
14962 value for @a object_t is:
14963
14964 @code {.cpp}
14965 std::map<
14966 std::string, // key_type
14967 basic_json, // value_type
14968 std::less<std::string>, // key_compare
14969 std::allocator<std::pair<const std::string, basic_json>> // allocator_type
14970 >
14971 @endcode
14972
14973 #### Behavior
14974
14975 The choice of @a object_t influences the behavior of the JSON class. With
14976 the default type, objects have the following behavior:
14977
14978 - When all names are unique, objects will be interoperable in the sense
14979 that all software implementations receiving that object will agree on
14980 the name-value mappings.
14981 - When the names within an object are not unique, it is unspecified which
14982 one of the values for a given key will be chosen. For instance,
14983 `{"key": 2, "key": 1}` could be equal to either `{"key": 1}` or
14984 `{"key": 2}`.
14985 - Internally, name/value pairs are stored in lexicographical order of the
14986 names. Objects will also be serialized (see @ref dump) in this order.
14987 For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored
14988 and serialized as `{"a": 2, "b": 1}`.
14989 - When comparing objects, the order of the name/value pairs is irrelevant.
14990 This makes objects interoperable in the sense that they will not be
14991 affected by these differences. For instance, `{"b": 1, "a": 2}` and
14992 `{"a": 2, "b": 1}` will be treated as equal.
14993
14994 #### Limits
14995
14996 [RFC 7159](http://rfc7159.net/rfc7159) specifies:
14997 > An implementation may set limits on the maximum depth of nesting.
14998
14999 In this class, the object's limit of nesting is not explicitly constrained.
15000 However, a maximum depth of nesting may be introduced by the compiler or
15001 runtime environment. A theoretical limit can be queried by calling the
15002 @ref max_size function of a JSON object.
15003
15004 #### Storage
15005
15006 Objects are stored as pointers in a @ref basic_json type. That is, for any
15007 access to object values, a pointer of type `object_t*` must be
15008 dereferenced.
15009
15010 @sa @ref array_t -- type for an array value
15011
15012 @since version 1.0.0
15013
15014 @note The order name/value pairs are added to the object is *not*
15015 preserved by the library. Therefore, iterating an object may return
15016 name/value pairs in a different order than they were originally stored. In
15017 fact, keys will be traversed in alphabetical order as `std::map` with
15018 `std::less` is used by default. Please note this behavior conforms to [RFC
15019 7159](http://rfc7159.net/rfc7159), because any order implements the
15020 specified "unordered" nature of JSON objects.
15021 */
15022 using object_t = ObjectType<StringType,
15023 basic_json,
15024 object_comparator_t,
15025 AllocatorType<std::pair<const StringType,
15026 basic_json>>>;
15027
15028 /*!
15029 @brief a type for an array
15030
15031 [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:
15032 > An array is an ordered sequence of zero or more values.
15033
15034 To store objects in C++, a type is defined by the template parameters
15035 explained below.
15036
15037 @tparam ArrayType container type to store arrays (e.g., `std::vector` or
15038 `std::list`)
15039 @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)
15040
15041 #### Default type
15042
15043 With the default values for @a ArrayType (`std::vector`) and @a
15044 AllocatorType (`std::allocator`), the default value for @a array_t is:
15045
15046 @code {.cpp}
15047 std::vector<
15048 basic_json, // value_type
15049 std::allocator<basic_json> // allocator_type
15050 >
15051 @endcode
15052
15053 #### Limits
15054
15055 [RFC 7159](http://rfc7159.net/rfc7159) specifies:
15056 > An implementation may set limits on the maximum depth of nesting.
15057
15058 In this class, the array's limit of nesting is not explicitly constrained.
15059 However, a maximum depth of nesting may be introduced by the compiler or
15060 runtime environment. A theoretical limit can be queried by calling the
15061 @ref max_size function of a JSON array.
15062
15063 #### Storage
15064
15065 Arrays are stored as pointers in a @ref basic_json type. That is, for any
15066 access to array values, a pointer of type `array_t*` must be dereferenced.
15067
15068 @sa @ref object_t -- type for an object value
15069
15070 @since version 1.0.0
15071 */
15072 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
15073
15074 /*!
15075 @brief a type for a string
15076
15077 [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:
15078 > A string is a sequence of zero or more Unicode characters.
15079
15080 To store objects in C++, a type is defined by the template parameter
15081 described below. Unicode values are split by the JSON class into
15082 byte-sized characters during deserialization.
15083
15084 @tparam StringType the container to store strings (e.g., `std::string`).
15085 Note this container is used for keys/names in objects, see @ref object_t.
15086
15087 #### Default type
15088
15089 With the default values for @a StringType (`std::string`), the default
15090 value for @a string_t is:
15091
15092 @code {.cpp}
15093 std::string
15094 @endcode
15095
15096 #### Encoding
15097
15098 Strings are stored in UTF-8 encoding. Therefore, functions like
15099 `std::string::size()` or `std::string::length()` return the number of
15100 bytes in the string rather than the number of characters or glyphs.
15101
15102 #### String comparison
15103
15104 [RFC 7159](http://rfc7159.net/rfc7159) states:
15105 > Software implementations are typically required to test names of object
15106 > members for equality. Implementations that transform the textual
15107 > representation into sequences of Unicode code units and then perform the
15108 > comparison numerically, code unit by code unit, are interoperable in the
15109 > sense that implementations will agree in all cases on equality or
15110 > inequality of two strings. For example, implementations that compare
15111 > strings with escaped characters unconverted may incorrectly find that
15112 > `"a\\b"` and `"a\u005Cb"` are not equal.
15113
15114 This implementation is interoperable as it does compare strings code unit
15115 by code unit.
15116
15117 #### Storage
15118
15119 String values are stored as pointers in a @ref basic_json type. That is,
15120 for any access to string values, a pointer of type `string_t*` must be
15121 dereferenced.
15122
15123 @since version 1.0.0
15124 */
15125 using string_t = StringType;
15126
15127 /*!
15128 @brief a type for a boolean
15129
15130 [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a
15131 type which differentiates the two literals `true` and `false`.
15132
15133 To store objects in C++, a type is defined by the template parameter @a
15134 BooleanType which chooses the type to use.
15135
15136 #### Default type
15137
15138 With the default values for @a BooleanType (`bool`), the default value for
15139 @a boolean_t is:
15140
15141 @code {.cpp}
15142 bool
15143 @endcode
15144
15145 #### Storage
15146
15147 Boolean values are stored directly inside a @ref basic_json type.
15148
15149 @since version 1.0.0
15150 */
15151 using boolean_t = BooleanType;
15152
15153 /*!
15154 @brief a type for a number (integer)
15155
15156 [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
15157 > The representation of numbers is similar to that used in most
15158 > programming languages. A number is represented in base 10 using decimal
15159 > digits. It contains an integer component that may be prefixed with an
15160 > optional minus sign, which may be followed by a fraction part and/or an
15161 > exponent part. Leading zeros are not allowed. (...) Numeric values that
15162 > cannot be represented in the grammar below (such as Infinity and NaN)
15163 > are not permitted.
15164
15165 This description includes both integer and floating-point numbers.
15166 However, C++ allows more precise storage if it is known whether the number
15167 is a signed integer, an unsigned integer or a floating-point number.
15168 Therefore, three different types, @ref number_integer_t, @ref
15169 number_unsigned_t and @ref number_float_t are used.
15170
15171 To store integer numbers in C++, a type is defined by the template
15172 parameter @a NumberIntegerType which chooses the type to use.
15173
15174 #### Default type
15175
15176 With the default values for @a NumberIntegerType (`int64_t`), the default
15177 value for @a number_integer_t is:
15178
15179 @code {.cpp}
15180 int64_t
15181 @endcode
15182
15183 #### Default behavior
15184
15185 - The restrictions about leading zeros is not enforced in C++. Instead,
15186 leading zeros in integer literals lead to an interpretation as octal
15187 number. Internally, the value will be stored as decimal number. For
15188 instance, the C++ integer literal `010` will be serialized to `8`.
15189 During deserialization, leading zeros yield an error.
15190 - Not-a-number (NaN) values will be serialized to `null`.
15191
15192 #### Limits
15193
15194 [RFC 7159](http://rfc7159.net/rfc7159) specifies:
15195 > An implementation may set limits on the range and precision of numbers.
15196
15197 When the default type is used, the maximal integer number that can be
15198 stored is `9223372036854775807` (INT64_MAX) and the minimal integer number
15199 that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
15200 that are out of range will yield over/underflow when used in a
15201 constructor. During deserialization, too large or small integer numbers
15202 will be automatically be stored as @ref number_unsigned_t or @ref
15203 number_float_t.
15204
15205 [RFC 7159](http://rfc7159.net/rfc7159) further states:
15206 > Note that when such software is used, numbers that are integers and are
15207 > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
15208 > that implementations will agree exactly on their numeric values.
15209
15210 As this range is a subrange of the exactly supported range [INT64_MIN,
15211 INT64_MAX], this class's integer type is interoperable.
15212
15213 #### Storage
15214
15215 Integer number values are stored directly inside a @ref basic_json type.
15216
15217 @sa @ref number_float_t -- type for number values (floating-point)
15218
15219 @sa @ref number_unsigned_t -- type for number values (unsigned integer)
15220
15221 @since version 1.0.0
15222 */
15223 using number_integer_t = NumberIntegerType;
15224
15225 /*!
15226 @brief a type for a number (unsigned)
15227
15228 [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
15229 > The representation of numbers is similar to that used in most
15230 > programming languages. A number is represented in base 10 using decimal
15231 > digits. It contains an integer component that may be prefixed with an
15232 > optional minus sign, which may be followed by a fraction part and/or an
15233 > exponent part. Leading zeros are not allowed. (...) Numeric values that
15234 > cannot be represented in the grammar below (such as Infinity and NaN)
15235 > are not permitted.
15236
15237 This description includes both integer and floating-point numbers.
15238 However, C++ allows more precise storage if it is known whether the number
15239 is a signed integer, an unsigned integer or a floating-point number.
15240 Therefore, three different types, @ref number_integer_t, @ref
15241 number_unsigned_t and @ref number_float_t are used.
15242
15243 To store unsigned integer numbers in C++, a type is defined by the
15244 template parameter @a NumberUnsignedType which chooses the type to use.
15245
15246 #### Default type
15247
15248 With the default values for @a NumberUnsignedType (`uint64_t`), the
15249 default value for @a number_unsigned_t is:
15250
15251 @code {.cpp}
15252 uint64_t
15253 @endcode
15254
15255 #### Default behavior
15256
15257 - The restrictions about leading zeros is not enforced in C++. Instead,
15258 leading zeros in integer literals lead to an interpretation as octal
15259 number. Internally, the value will be stored as decimal number. For
15260 instance, the C++ integer literal `010` will be serialized to `8`.
15261 During deserialization, leading zeros yield an error.
15262 - Not-a-number (NaN) values will be serialized to `null`.
15263
15264 #### Limits
15265
15266 [RFC 7159](http://rfc7159.net/rfc7159) specifies:
15267 > An implementation may set limits on the range and precision of numbers.
15268
15269 When the default type is used, the maximal integer number that can be
15270 stored is `18446744073709551615` (UINT64_MAX) and the minimal integer
15271 number that can be stored is `0`. Integer numbers that are out of range
15272 will yield over/underflow when used in a constructor. During
15273 deserialization, too large or small integer numbers will be automatically
15274 be stored as @ref number_integer_t or @ref number_float_t.
15275
15276 [RFC 7159](http://rfc7159.net/rfc7159) further states:
15277 > Note that when such software is used, numbers that are integers and are
15278 > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
15279 > that implementations will agree exactly on their numeric values.
15280
15281 As this range is a subrange (when considered in conjunction with the
15282 number_integer_t type) of the exactly supported range [0, UINT64_MAX],
15283 this class's integer type is interoperable.
15284
15285 #### Storage
15286
15287 Integer number values are stored directly inside a @ref basic_json type.
15288
15289 @sa @ref number_float_t -- type for number values (floating-point)
15290 @sa @ref number_integer_t -- type for number values (integer)
15291
15292 @since version 2.0.0
15293 */
15294 using number_unsigned_t = NumberUnsignedType;
15295
15296 /*!
15297 @brief a type for a number (floating-point)
15298
15299 [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
15300 > The representation of numbers is similar to that used in most
15301 > programming languages. A number is represented in base 10 using decimal
15302 > digits. It contains an integer component that may be prefixed with an
15303 > optional minus sign, which may be followed by a fraction part and/or an
15304 > exponent part. Leading zeros are not allowed. (...) Numeric values that
15305 > cannot be represented in the grammar below (such as Infinity and NaN)
15306 > are not permitted.
15307
15308 This description includes both integer and floating-point numbers.
15309 However, C++ allows more precise storage if it is known whether the number
15310 is a signed integer, an unsigned integer or a floating-point number.
15311 Therefore, three different types, @ref number_integer_t, @ref
15312 number_unsigned_t and @ref number_float_t are used.
15313
15314 To store floating-point numbers in C++, a type is defined by the template
15315 parameter @a NumberFloatType which chooses the type to use.
15316
15317 #### Default type
15318
15319 With the default values for @a NumberFloatType (`double`), the default
15320 value for @a number_float_t is:
15321
15322 @code {.cpp}
15323 double
15324 @endcode
15325
15326 #### Default behavior
15327
15328 - The restrictions about leading zeros is not enforced in C++. Instead,
15329 leading zeros in floating-point literals will be ignored. Internally,
15330 the value will be stored as decimal number. For instance, the C++
15331 floating-point literal `01.2` will be serialized to `1.2`. During
15332 deserialization, leading zeros yield an error.
15333 - Not-a-number (NaN) values will be serialized to `null`.
15334
15335 #### Limits
15336
15337 [RFC 7159](http://rfc7159.net/rfc7159) states:
15338 > This specification allows implementations to set limits on the range and
15339 > precision of numbers accepted. Since software that implements IEEE
15340 > 754-2008 binary64 (double precision) numbers is generally available and
15341 > widely used, good interoperability can be achieved by implementations
15342 > that expect no more precision or range than these provide, in the sense
15343 > that implementations will approximate JSON numbers within the expected
15344 > precision.
15345
15346 This implementation does exactly follow this approach, as it uses double
15347 precision floating-point numbers. Note values smaller than
15348 `-1.79769313486232e+308` and values greater than `1.79769313486232e+308`
15349 will be stored as NaN internally and be serialized to `null`.
15350
15351 #### Storage
15352
15353 Floating-point number values are stored directly inside a @ref basic_json
15354 type.
15355
15356 @sa @ref number_integer_t -- type for number values (integer)
15357
15358 @sa @ref number_unsigned_t -- type for number values (unsigned integer)
15359
15360 @since version 1.0.0
15361 */
15362 using number_float_t = NumberFloatType;
15363
15364 /// @}
15365
15366 private:
15367
15368 /// helper for exception-safe object creation
15369 template<typename T, typename... Args>
15370 JSON_HEDLEY_RETURNS_NON_NULL
create(Args &&...args)15371 static T* create(Args&& ... args)
15372 {
15373 AllocatorType<T> alloc;
15374 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
15375
15376 auto deleter = [&](T * object)
15377 {
15378 AllocatorTraits::deallocate(alloc, object, 1);
15379 };
15380 std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
15381 AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
15382 assert(object != nullptr);
15383 return object.release();
15384 }
15385
15386 ////////////////////////
15387 // JSON value storage //
15388 ////////////////////////
15389
15390 /*!
15391 @brief a JSON value
15392
15393 The actual storage for a JSON value of the @ref basic_json class. This
15394 union combines the different storage types for the JSON value types
15395 defined in @ref value_t.
15396
15397 JSON type | value_t type | used type
15398 --------- | --------------- | ------------------------
15399 object | object | pointer to @ref object_t
15400 array | array | pointer to @ref array_t
15401 string | string | pointer to @ref string_t
15402 boolean | boolean | @ref boolean_t
15403 number | number_integer | @ref number_integer_t
15404 number | number_unsigned | @ref number_unsigned_t
15405 number | number_float | @ref number_float_t
15406 null | null | *no value is stored*
15407
15408 @note Variable-length types (objects, arrays, and strings) are stored as
15409 pointers. The size of the union should not exceed 64 bits if the default
15410 value types are used.
15411
15412 @since version 1.0.0
15413 */
15414 union json_value
15415 {
15416 /// object (stored with pointer to save storage)
15417 object_t* object;
15418 /// array (stored with pointer to save storage)
15419 array_t* array;
15420 /// string (stored with pointer to save storage)
15421 string_t* string;
15422 /// boolean
15423 boolean_t boolean;
15424 /// number (integer)
15425 number_integer_t number_integer;
15426 /// number (unsigned integer)
15427 number_unsigned_t number_unsigned;
15428 /// number (floating-point)
15429 number_float_t number_float;
15430
15431 /// default constructor (for null values)
15432 json_value() = default;
15433 /// constructor for booleans
json_value(boolean_t v)15434 json_value(boolean_t v) noexcept : boolean(v) {}
15435 /// constructor for numbers (integer)
json_value(number_integer_t v)15436 json_value(number_integer_t v) noexcept : number_integer(v) {}
15437 /// constructor for numbers (unsigned)
json_value(number_unsigned_t v)15438 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
15439 /// constructor for numbers (floating-point)
json_value(number_float_t v)15440 json_value(number_float_t v) noexcept : number_float(v) {}
15441 /// constructor for empty values of a given type
json_value(value_t t)15442 json_value(value_t t)
15443 {
15444 switch (t)
15445 {
15446 case value_t::object:
15447 {
15448 object = create<object_t>();
15449 break;
15450 }
15451
15452 case value_t::array:
15453 {
15454 array = create<array_t>();
15455 break;
15456 }
15457
15458 case value_t::string:
15459 {
15460 string = create<string_t>("");
15461 break;
15462 }
15463
15464 case value_t::boolean:
15465 {
15466 boolean = boolean_t(false);
15467 break;
15468 }
15469
15470 case value_t::number_integer:
15471 {
15472 number_integer = number_integer_t(0);
15473 break;
15474 }
15475
15476 case value_t::number_unsigned:
15477 {
15478 number_unsigned = number_unsigned_t(0);
15479 break;
15480 }
15481
15482 case value_t::number_float:
15483 {
15484 number_float = number_float_t(0.0);
15485 break;
15486 }
15487
15488 case value_t::null:
15489 {
15490 object = nullptr; // silence warning, see #821
15491 break;
15492 }
15493
15494 default:
15495 {
15496 object = nullptr; // silence warning, see #821
15497 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
15498 {
15499 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.7.1")); // LCOV_EXCL_LINE
15500 }
15501 break;
15502 }
15503 }
15504 }
15505
15506 /// constructor for strings
json_value(const string_t & value)15507 json_value(const string_t& value)
15508 {
15509 string = create<string_t>(value);
15510 }
15511
15512 /// constructor for rvalue strings
json_value(string_t && value)15513 json_value(string_t&& value)
15514 {
15515 string = create<string_t>(std::move(value));
15516 }
15517
15518 /// constructor for objects
json_value(const object_t & value)15519 json_value(const object_t& value)
15520 {
15521 object = create<object_t>(value);
15522 }
15523
15524 /// constructor for rvalue objects
json_value(object_t && value)15525 json_value(object_t&& value)
15526 {
15527 object = create<object_t>(std::move(value));
15528 }
15529
15530 /// constructor for arrays
json_value(const array_t & value)15531 json_value(const array_t& value)
15532 {
15533 array = create<array_t>(value);
15534 }
15535
15536 /// constructor for rvalue arrays
json_value(array_t && value)15537 json_value(array_t&& value)
15538 {
15539 array = create<array_t>(std::move(value));
15540 }
15541
destroy(value_t t)15542 void destroy(value_t t) noexcept
15543 {
15544 switch (t)
15545 {
15546 case value_t::object:
15547 {
15548 AllocatorType<object_t> alloc;
15549 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
15550 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
15551 break;
15552 }
15553
15554 case value_t::array:
15555 {
15556 AllocatorType<array_t> alloc;
15557 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
15558 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
15559 break;
15560 }
15561
15562 case value_t::string:
15563 {
15564 AllocatorType<string_t> alloc;
15565 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
15566 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
15567 break;
15568 }
15569
15570 default:
15571 {
15572 break;
15573 }
15574 }
15575 }
15576 };
15577
15578 /*!
15579 @brief checks the class invariants
15580
15581 This function asserts the class invariants. It needs to be called at the
15582 end of every constructor to make sure that created objects respect the
15583 invariant. Furthermore, it has to be called each time the type of a JSON
15584 value is changed, because the invariant expresses a relationship between
15585 @a m_type and @a m_value.
15586 */
assert_invariant() const15587 void assert_invariant() const noexcept
15588 {
15589 assert(m_type != value_t::object or m_value.object != nullptr);
15590 assert(m_type != value_t::array or m_value.array != nullptr);
15591 assert(m_type != value_t::string or m_value.string != nullptr);
15592 }
15593
15594 public:
15595 //////////////////////////
15596 // JSON parser callback //
15597 //////////////////////////
15598
15599 /*!
15600 @brief parser event types
15601
15602 The parser callback distinguishes the following events:
15603 - `object_start`: the parser read `{` and started to process a JSON object
15604 - `key`: the parser read a key of a value in an object
15605 - `object_end`: the parser read `}` and finished processing a JSON object
15606 - `array_start`: the parser read `[` and started to process a JSON array
15607 - `array_end`: the parser read `]` and finished processing a JSON array
15608 - `value`: the parser finished reading a JSON value
15609
15610 @image html callback_events.png "Example when certain parse events are triggered"
15611
15612 @sa @ref parser_callback_t for more information and examples
15613 */
15614 using parse_event_t = typename parser::parse_event_t;
15615
15616 /*!
15617 @brief per-element parser callback type
15618
15619 With a parser callback function, the result of parsing a JSON text can be
15620 influenced. When passed to @ref parse, it is called on certain events
15621 (passed as @ref parse_event_t via parameter @a event) with a set recursion
15622 depth @a depth and context JSON value @a parsed. The return value of the
15623 callback function is a boolean indicating whether the element that emitted
15624 the callback shall be kept or not.
15625
15626 We distinguish six scenarios (determined by the event type) in which the
15627 callback function can be called. The following table describes the values
15628 of the parameters @a depth, @a event, and @a parsed.
15629
15630 parameter @a event | description | parameter @a depth | parameter @a parsed
15631 ------------------ | ----------- | ------------------ | -------------------
15632 parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded
15633 parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key
15634 parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object
15635 parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded
15636 parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
15637 parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
15638
15639 @image html callback_events.png "Example when certain parse events are triggered"
15640
15641 Discarding a value (i.e., returning `false`) has different effects
15642 depending on the context in which function was called:
15643
15644 - Discarded values in structured types are skipped. That is, the parser
15645 will behave as if the discarded value was never read.
15646 - In case a value outside a structured type is skipped, it is replaced
15647 with `null`. This case happens if the top-level element is skipped.
15648
15649 @param[in] depth the depth of the recursion during parsing
15650
15651 @param[in] event an event of type parse_event_t indicating the context in
15652 the callback function has been called
15653
15654 @param[in,out] parsed the current intermediate parse result; note that
15655 writing to this value has no effect for parse_event_t::key events
15656
15657 @return Whether the JSON value which called the function during parsing
15658 should be kept (`true`) or not (`false`). In the latter case, it is either
15659 skipped completely or replaced by an empty discarded object.
15660
15661 @sa @ref parse for examples
15662
15663 @since version 1.0.0
15664 */
15665 using parser_callback_t = typename parser::parser_callback_t;
15666
15667 //////////////////
15668 // constructors //
15669 //////////////////
15670
15671 /// @name constructors and destructors
15672 /// Constructors of class @ref basic_json, copy/move constructor, copy
15673 /// assignment, static functions creating objects, and the destructor.
15674 /// @{
15675
15676 /*!
15677 @brief create an empty value with a given type
15678
15679 Create an empty JSON value with a given type. The value will be default
15680 initialized with an empty value which depends on the type:
15681
15682 Value type | initial value
15683 ----------- | -------------
15684 null | `null`
15685 boolean | `false`
15686 string | `""`
15687 number | `0`
15688 object | `{}`
15689 array | `[]`
15690
15691 @param[in] v the type of the value to create
15692
15693 @complexity Constant.
15694
15695 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
15696 changes to any JSON value.
15697
15698 @liveexample{The following code shows the constructor for different @ref
15699 value_t values,basic_json__value_t}
15700
15701 @sa @ref clear() -- restores the postcondition of this constructor
15702
15703 @since version 1.0.0
15704 */
basic_json(const value_t v)15705 basic_json(const value_t v)
15706 : m_type(v), m_value(v)
15707 {
15708 assert_invariant();
15709 }
15710
15711 /*!
15712 @brief create a null object
15713
15714 Create a `null` JSON value. It either takes a null pointer as parameter
15715 (explicitly creating `null`) or no parameter (implicitly creating `null`).
15716 The passed null pointer itself is not read -- it is only used to choose
15717 the right constructor.
15718
15719 @complexity Constant.
15720
15721 @exceptionsafety No-throw guarantee: this constructor never throws
15722 exceptions.
15723
15724 @liveexample{The following code shows the constructor with and without a
15725 null pointer parameter.,basic_json__nullptr_t}
15726
15727 @since version 1.0.0
15728 */
basic_json(std::nullptr_t=nullptr)15729 basic_json(std::nullptr_t = nullptr) noexcept
15730 : basic_json(value_t::null)
15731 {
15732 assert_invariant();
15733 }
15734
15735 /*!
15736 @brief create a JSON value
15737
15738 This is a "catch all" constructor for all compatible JSON types; that is,
15739 types for which a `to_json()` method exists. The constructor forwards the
15740 parameter @a val to that method (to `json_serializer<U>::to_json` method
15741 with `U = uncvref_t<CompatibleType>`, to be exact).
15742
15743 Template type @a CompatibleType includes, but is not limited to, the
15744 following types:
15745 - **arrays**: @ref array_t and all kinds of compatible containers such as
15746 `std::vector`, `std::deque`, `std::list`, `std::forward_list`,
15747 `std::array`, `std::valarray`, `std::set`, `std::unordered_set`,
15748 `std::multiset`, and `std::unordered_multiset` with a `value_type` from
15749 which a @ref basic_json value can be constructed.
15750 - **objects**: @ref object_t and all kinds of compatible associative
15751 containers such as `std::map`, `std::unordered_map`, `std::multimap`,
15752 and `std::unordered_multimap` with a `key_type` compatible to
15753 @ref string_t and a `value_type` from which a @ref basic_json value can
15754 be constructed.
15755 - **strings**: @ref string_t, string literals, and all compatible string
15756 containers can be used.
15757 - **numbers**: @ref number_integer_t, @ref number_unsigned_t,
15758 @ref number_float_t, and all convertible number types such as `int`,
15759 `size_t`, `int64_t`, `float` or `double` can be used.
15760 - **boolean**: @ref boolean_t / `bool` can be used.
15761
15762 See the examples below.
15763
15764 @tparam CompatibleType a type such that:
15765 - @a CompatibleType is not derived from `std::istream`,
15766 - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move
15767 constructors),
15768 - @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments)
15769 - @a CompatibleType is not a @ref basic_json nested type (e.g.,
15770 @ref json_pointer, @ref iterator, etc ...)
15771 - @ref @ref json_serializer<U> has a
15772 `to_json(basic_json_t&, CompatibleType&&)` method
15773
15774 @tparam U = `uncvref_t<CompatibleType>`
15775
15776 @param[in] val the value to be forwarded to the respective constructor
15777
15778 @complexity Usually linear in the size of the passed @a val, also
15779 depending on the implementation of the called `to_json()`
15780 method.
15781
15782 @exceptionsafety Depends on the called constructor. For types directly
15783 supported by the library (i.e., all types for which no `to_json()` function
15784 was provided), strong guarantee holds: if an exception is thrown, there are
15785 no changes to any JSON value.
15786
15787 @liveexample{The following code shows the constructor with several
15788 compatible types.,basic_json__CompatibleType}
15789
15790 @since version 2.1.0
15791 */
15792 template <typename CompatibleType,
15793 typename U = detail::uncvref_t<CompatibleType>,
15794 detail::enable_if_t<
15795 not detail::is_basic_json<U>::value and detail::is_compatible_type<basic_json_t, U>::value, int> = 0>
basic_json(CompatibleType && val)15796 basic_json(CompatibleType && val) noexcept(noexcept(
15797 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
15798 std::forward<CompatibleType>(val))))
15799 {
15800 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
15801 assert_invariant();
15802 }
15803
15804 /*!
15805 @brief create a JSON value from an existing one
15806
15807 This is a constructor for existing @ref basic_json types.
15808 It does not hijack copy/move constructors, since the parameter has different
15809 template arguments than the current ones.
15810
15811 The constructor tries to convert the internal @ref m_value of the parameter.
15812
15813 @tparam BasicJsonType a type such that:
15814 - @a BasicJsonType is a @ref basic_json type.
15815 - @a BasicJsonType has different template arguments than @ref basic_json_t.
15816
15817 @param[in] val the @ref basic_json value to be converted.
15818
15819 @complexity Usually linear in the size of the passed @a val, also
15820 depending on the implementation of the called `to_json()`
15821 method.
15822
15823 @exceptionsafety Depends on the called constructor. For types directly
15824 supported by the library (i.e., all types for which no `to_json()` function
15825 was provided), strong guarantee holds: if an exception is thrown, there are
15826 no changes to any JSON value.
15827
15828 @since version 3.2.0
15829 */
15830 template <typename BasicJsonType,
15831 detail::enable_if_t<
15832 detail::is_basic_json<BasicJsonType>::value and not std::is_same<basic_json, BasicJsonType>::value, int> = 0>
basic_json(const BasicJsonType & val)15833 basic_json(const BasicJsonType& val)
15834 {
15835 using other_boolean_t = typename BasicJsonType::boolean_t;
15836 using other_number_float_t = typename BasicJsonType::number_float_t;
15837 using other_number_integer_t = typename BasicJsonType::number_integer_t;
15838 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
15839 using other_string_t = typename BasicJsonType::string_t;
15840 using other_object_t = typename BasicJsonType::object_t;
15841 using other_array_t = typename BasicJsonType::array_t;
15842
15843 switch (val.type())
15844 {
15845 case value_t::boolean:
15846 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
15847 break;
15848 case value_t::number_float:
15849 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
15850 break;
15851 case value_t::number_integer:
15852 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
15853 break;
15854 case value_t::number_unsigned:
15855 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
15856 break;
15857 case value_t::string:
15858 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
15859 break;
15860 case value_t::object:
15861 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
15862 break;
15863 case value_t::array:
15864 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
15865 break;
15866 case value_t::null:
15867 *this = nullptr;
15868 break;
15869 case value_t::discarded:
15870 m_type = value_t::discarded;
15871 break;
15872 default: // LCOV_EXCL_LINE
15873 assert(false); // LCOV_EXCL_LINE
15874 }
15875 assert_invariant();
15876 }
15877
15878 /*!
15879 @brief create a container (array or object) from an initializer list
15880
15881 Creates a JSON value of type array or object from the passed initializer
15882 list @a init. In case @a type_deduction is `true` (default), the type of
15883 the JSON value to be created is deducted from the initializer list @a init
15884 according to the following rules:
15885
15886 1. If the list is empty, an empty JSON object value `{}` is created.
15887 2. If the list consists of pairs whose first element is a string, a JSON
15888 object value is created where the first elements of the pairs are
15889 treated as keys and the second elements are as values.
15890 3. In all other cases, an array is created.
15891
15892 The rules aim to create the best fit between a C++ initializer list and
15893 JSON values. The rationale is as follows:
15894
15895 1. The empty initializer list is written as `{}` which is exactly an empty
15896 JSON object.
15897 2. C++ has no way of describing mapped types other than to list a list of
15898 pairs. As JSON requires that keys must be of type string, rule 2 is the
15899 weakest constraint one can pose on initializer lists to interpret them
15900 as an object.
15901 3. In all other cases, the initializer list could not be interpreted as
15902 JSON object type, so interpreting it as JSON array type is safe.
15903
15904 With the rules described above, the following JSON values cannot be
15905 expressed by an initializer list:
15906
15907 - the empty array (`[]`): use @ref array(initializer_list_t)
15908 with an empty initializer list in this case
15909 - arrays whose elements satisfy rule 2: use @ref
15910 array(initializer_list_t) with the same initializer list
15911 in this case
15912
15913 @note When used without parentheses around an empty initializer list, @ref
15914 basic_json() is called instead of this function, yielding the JSON null
15915 value.
15916
15917 @param[in] init initializer list with JSON values
15918
15919 @param[in] type_deduction internal parameter; when set to `true`, the type
15920 of the JSON value is deducted from the initializer list @a init; when set
15921 to `false`, the type provided via @a manual_type is forced. This mode is
15922 used by the functions @ref array(initializer_list_t) and
15923 @ref object(initializer_list_t).
15924
15925 @param[in] manual_type internal parameter; when @a type_deduction is set
15926 to `false`, the created JSON value will use the provided type (only @ref
15927 value_t::array and @ref value_t::object are valid); when @a type_deduction
15928 is set to `true`, this parameter has no effect
15929
15930 @throw type_error.301 if @a type_deduction is `false`, @a manual_type is
15931 `value_t::object`, but @a init contains an element which is not a pair
15932 whose first element is a string. In this case, the constructor could not
15933 create an object. If @a type_deduction would have be `true`, an array
15934 would have been created. See @ref object(initializer_list_t)
15935 for an example.
15936
15937 @complexity Linear in the size of the initializer list @a init.
15938
15939 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
15940 changes to any JSON value.
15941
15942 @liveexample{The example below shows how JSON values are created from
15943 initializer lists.,basic_json__list_init_t}
15944
15945 @sa @ref array(initializer_list_t) -- create a JSON array
15946 value from an initializer list
15947 @sa @ref object(initializer_list_t) -- create a JSON object
15948 value from an initializer list
15949
15950 @since version 1.0.0
15951 */
basic_json(initializer_list_t init,bool type_deduction=true,value_t manual_type=value_t::array)15952 basic_json(initializer_list_t init,
15953 bool type_deduction = true,
15954 value_t manual_type = value_t::array)
15955 {
15956 // check if each element is an array with two elements whose first
15957 // element is a string
15958 bool is_an_object = std::all_of(init.begin(), init.end(),
15959 [](const detail::json_ref<basic_json>& element_ref)
15960 {
15961 return element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string();
15962 });
15963
15964 // adjust type if type deduction is not wanted
15965 if (not type_deduction)
15966 {
15967 // if array is wanted, do not create an object though possible
15968 if (manual_type == value_t::array)
15969 {
15970 is_an_object = false;
15971 }
15972
15973 // if object is wanted but impossible, throw an exception
15974 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object and not is_an_object))
15975 {
15976 JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
15977 }
15978 }
15979
15980 if (is_an_object)
15981 {
15982 // the initializer list is a list of pairs -> create object
15983 m_type = value_t::object;
15984 m_value = value_t::object;
15985
15986 std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
15987 {
15988 auto element = element_ref.moved_or_copied();
15989 m_value.object->emplace(
15990 std::move(*((*element.m_value.array)[0].m_value.string)),
15991 std::move((*element.m_value.array)[1]));
15992 });
15993 }
15994 else
15995 {
15996 // the initializer list describes an array -> create array
15997 m_type = value_t::array;
15998 m_value.array = create<array_t>(init.begin(), init.end());
15999 }
16000
16001 assert_invariant();
16002 }
16003
16004 /*!
16005 @brief explicitly create an array from an initializer list
16006
16007 Creates a JSON array value from a given initializer list. That is, given a
16008 list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the
16009 initializer list is empty, the empty array `[]` is created.
16010
16011 @note This function is only needed to express two edge cases that cannot
16012 be realized with the initializer list constructor (@ref
16013 basic_json(initializer_list_t, bool, value_t)). These cases
16014 are:
16015 1. creating an array whose elements are all pairs whose first element is a
16016 string -- in this case, the initializer list constructor would create an
16017 object, taking the first elements as keys
16018 2. creating an empty array -- passing the empty initializer list to the
16019 initializer list constructor yields an empty object
16020
16021 @param[in] init initializer list with JSON values to create an array from
16022 (optional)
16023
16024 @return JSON array value
16025
16026 @complexity Linear in the size of @a init.
16027
16028 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
16029 changes to any JSON value.
16030
16031 @liveexample{The following code shows an example for the `array`
16032 function.,array}
16033
16034 @sa @ref basic_json(initializer_list_t, bool, value_t) --
16035 create a JSON value from an initializer list
16036 @sa @ref object(initializer_list_t) -- create a JSON object
16037 value from an initializer list
16038
16039 @since version 1.0.0
16040 */
16041 JSON_HEDLEY_WARN_UNUSED_RESULT
array(initializer_list_t init={})16042 static basic_json array(initializer_list_t init = {})
16043 {
16044 return basic_json(init, false, value_t::array);
16045 }
16046
16047 /*!
16048 @brief explicitly create an object from an initializer list
16049
16050 Creates a JSON object value from a given initializer list. The initializer
16051 lists elements must be pairs, and their first elements must be strings. If
16052 the initializer list is empty, the empty object `{}` is created.
16053
16054 @note This function is only added for symmetry reasons. In contrast to the
16055 related function @ref array(initializer_list_t), there are
16056 no cases which can only be expressed by this function. That is, any
16057 initializer list @a init can also be passed to the initializer list
16058 constructor @ref basic_json(initializer_list_t, bool, value_t).
16059
16060 @param[in] init initializer list to create an object from (optional)
16061
16062 @return JSON object value
16063
16064 @throw type_error.301 if @a init is not a list of pairs whose first
16065 elements are strings. In this case, no object can be created. When such a
16066 value is passed to @ref basic_json(initializer_list_t, bool, value_t),
16067 an array would have been created from the passed initializer list @a init.
16068 See example below.
16069
16070 @complexity Linear in the size of @a init.
16071
16072 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
16073 changes to any JSON value.
16074
16075 @liveexample{The following code shows an example for the `object`
16076 function.,object}
16077
16078 @sa @ref basic_json(initializer_list_t, bool, value_t) --
16079 create a JSON value from an initializer list
16080 @sa @ref array(initializer_list_t) -- create a JSON array
16081 value from an initializer list
16082
16083 @since version 1.0.0
16084 */
16085 JSON_HEDLEY_WARN_UNUSED_RESULT
object(initializer_list_t init={})16086 static basic_json object(initializer_list_t init = {})
16087 {
16088 return basic_json(init, false, value_t::object);
16089 }
16090
16091 /*!
16092 @brief construct an array with count copies of given value
16093
16094 Constructs a JSON array value by creating @a cnt copies of a passed value.
16095 In case @a cnt is `0`, an empty array is created.
16096
16097 @param[in] cnt the number of JSON copies of @a val to create
16098 @param[in] val the JSON value to copy
16099
16100 @post `std::distance(begin(),end()) == cnt` holds.
16101
16102 @complexity Linear in @a cnt.
16103
16104 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
16105 changes to any JSON value.
16106
16107 @liveexample{The following code shows examples for the @ref
16108 basic_json(size_type\, const basic_json&)
16109 constructor.,basic_json__size_type_basic_json}
16110
16111 @since version 1.0.0
16112 */
basic_json(size_type cnt,const basic_json & val)16113 basic_json(size_type cnt, const basic_json& val)
16114 : m_type(value_t::array)
16115 {
16116 m_value.array = create<array_t>(cnt, val);
16117 assert_invariant();
16118 }
16119
16120 /*!
16121 @brief construct a JSON container given an iterator range
16122
16123 Constructs the JSON value with the contents of the range `[first, last)`.
16124 The semantics depends on the different types a JSON value can have:
16125 - In case of a null type, invalid_iterator.206 is thrown.
16126 - In case of other primitive types (number, boolean, or string), @a first
16127 must be `begin()` and @a last must be `end()`. In this case, the value is
16128 copied. Otherwise, invalid_iterator.204 is thrown.
16129 - In case of structured types (array, object), the constructor behaves as
16130 similar versions for `std::vector` or `std::map`; that is, a JSON array
16131 or object is constructed from the values in the range.
16132
16133 @tparam InputIT an input iterator type (@ref iterator or @ref
16134 const_iterator)
16135
16136 @param[in] first begin of the range to copy from (included)
16137 @param[in] last end of the range to copy from (excluded)
16138
16139 @pre Iterators @a first and @a last must be initialized. **This
16140 precondition is enforced with an assertion (see warning).** If
16141 assertions are switched off, a violation of this precondition yields
16142 undefined behavior.
16143
16144 @pre Range `[first, last)` is valid. Usually, this precondition cannot be
16145 checked efficiently. Only certain edge cases are detected; see the
16146 description of the exceptions below. A violation of this precondition
16147 yields undefined behavior.
16148
16149 @warning A precondition is enforced with a runtime assertion that will
16150 result in calling `std::abort` if this precondition is not met.
16151 Assertions can be disabled by defining `NDEBUG` at compile time.
16152 See https://en.cppreference.com/w/cpp/error/assert for more
16153 information.
16154
16155 @throw invalid_iterator.201 if iterators @a first and @a last are not
16156 compatible (i.e., do not belong to the same JSON value). In this case,
16157 the range `[first, last)` is undefined.
16158 @throw invalid_iterator.204 if iterators @a first and @a last belong to a
16159 primitive type (number, boolean, or string), but @a first does not point
16160 to the first element any more. In this case, the range `[first, last)` is
16161 undefined. See example code below.
16162 @throw invalid_iterator.206 if iterators @a first and @a last belong to a
16163 null value. In this case, the range `[first, last)` is undefined.
16164
16165 @complexity Linear in distance between @a first and @a last.
16166
16167 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
16168 changes to any JSON value.
16169
16170 @liveexample{The example below shows several ways to create JSON values by
16171 specifying a subrange with iterators.,basic_json__InputIt_InputIt}
16172
16173 @since version 1.0.0
16174 */
16175 template<class InputIT, typename std::enable_if<
16176 std::is_same<InputIT, typename basic_json_t::iterator>::value or
16177 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
basic_json(InputIT first,InputIT last)16178 basic_json(InputIT first, InputIT last)
16179 {
16180 assert(first.m_object != nullptr);
16181 assert(last.m_object != nullptr);
16182
16183 // make sure iterator fits the current value
16184 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
16185 {
16186 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
16187 }
16188
16189 // copy type from first iterator
16190 m_type = first.m_object->m_type;
16191
16192 // check if iterator range is complete for primitive values
16193 switch (m_type)
16194 {
16195 case value_t::boolean:
16196 case value_t::number_float:
16197 case value_t::number_integer:
16198 case value_t::number_unsigned:
16199 case value_t::string:
16200 {
16201 if (JSON_HEDLEY_UNLIKELY(not first.m_it.primitive_iterator.is_begin()
16202 or not last.m_it.primitive_iterator.is_end()))
16203 {
16204 JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
16205 }
16206 break;
16207 }
16208
16209 default:
16210 break;
16211 }
16212
16213 switch (m_type)
16214 {
16215 case value_t::number_integer:
16216 {
16217 m_value.number_integer = first.m_object->m_value.number_integer;
16218 break;
16219 }
16220
16221 case value_t::number_unsigned:
16222 {
16223 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
16224 break;
16225 }
16226
16227 case value_t::number_float:
16228 {
16229 m_value.number_float = first.m_object->m_value.number_float;
16230 break;
16231 }
16232
16233 case value_t::boolean:
16234 {
16235 m_value.boolean = first.m_object->m_value.boolean;
16236 break;
16237 }
16238
16239 case value_t::string:
16240 {
16241 m_value = *first.m_object->m_value.string;
16242 break;
16243 }
16244
16245 case value_t::object:
16246 {
16247 m_value.object = create<object_t>(first.m_it.object_iterator,
16248 last.m_it.object_iterator);
16249 break;
16250 }
16251
16252 case value_t::array:
16253 {
16254 m_value.array = create<array_t>(first.m_it.array_iterator,
16255 last.m_it.array_iterator);
16256 break;
16257 }
16258
16259 default:
16260 JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
16261 std::string(first.m_object->type_name())));
16262 }
16263
16264 assert_invariant();
16265 }
16266
16267
16268 ///////////////////////////////////////
16269 // other constructors and destructor //
16270 ///////////////////////////////////////
16271
16272 /// @private
basic_json(const detail::json_ref<basic_json> & ref)16273 basic_json(const detail::json_ref<basic_json>& ref)
16274 : basic_json(ref.moved_or_copied())
16275 {}
16276
16277 /*!
16278 @brief copy constructor
16279
16280 Creates a copy of a given JSON value.
16281
16282 @param[in] other the JSON value to copy
16283
16284 @post `*this == other`
16285
16286 @complexity Linear in the size of @a other.
16287
16288 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
16289 changes to any JSON value.
16290
16291 @requirement This function helps `basic_json` satisfying the
16292 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
16293 requirements:
16294 - The complexity is linear.
16295 - As postcondition, it holds: `other == basic_json(other)`.
16296
16297 @liveexample{The following code shows an example for the copy
16298 constructor.,basic_json__basic_json}
16299
16300 @since version 1.0.0
16301 */
basic_json(const basic_json & other)16302 basic_json(const basic_json& other)
16303 : m_type(other.m_type)
16304 {
16305 // check of passed value is valid
16306 other.assert_invariant();
16307
16308 switch (m_type)
16309 {
16310 case value_t::object:
16311 {
16312 m_value = *other.m_value.object;
16313 break;
16314 }
16315
16316 case value_t::array:
16317 {
16318 m_value = *other.m_value.array;
16319 break;
16320 }
16321
16322 case value_t::string:
16323 {
16324 m_value = *other.m_value.string;
16325 break;
16326 }
16327
16328 case value_t::boolean:
16329 {
16330 m_value = other.m_value.boolean;
16331 break;
16332 }
16333
16334 case value_t::number_integer:
16335 {
16336 m_value = other.m_value.number_integer;
16337 break;
16338 }
16339
16340 case value_t::number_unsigned:
16341 {
16342 m_value = other.m_value.number_unsigned;
16343 break;
16344 }
16345
16346 case value_t::number_float:
16347 {
16348 m_value = other.m_value.number_float;
16349 break;
16350 }
16351
16352 default:
16353 break;
16354 }
16355
16356 assert_invariant();
16357 }
16358
16359 /*!
16360 @brief move constructor
16361
16362 Move constructor. Constructs a JSON value with the contents of the given
16363 value @a other using move semantics. It "steals" the resources from @a
16364 other and leaves it as JSON null value.
16365
16366 @param[in,out] other value to move to this object
16367
16368 @post `*this` has the same value as @a other before the call.
16369 @post @a other is a JSON null value.
16370
16371 @complexity Constant.
16372
16373 @exceptionsafety No-throw guarantee: this constructor never throws
16374 exceptions.
16375
16376 @requirement This function helps `basic_json` satisfying the
16377 [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible)
16378 requirements.
16379
16380 @liveexample{The code below shows the move constructor explicitly called
16381 via std::move.,basic_json__moveconstructor}
16382
16383 @since version 1.0.0
16384 */
basic_json(basic_json && other)16385 basic_json(basic_json&& other) noexcept
16386 : m_type(std::move(other.m_type)),
16387 m_value(std::move(other.m_value))
16388 {
16389 // check that passed value is valid
16390 other.assert_invariant();
16391
16392 // invalidate payload
16393 other.m_type = value_t::null;
16394 other.m_value = {};
16395
16396 assert_invariant();
16397 }
16398
16399 /*!
16400 @brief copy assignment
16401
16402 Copy assignment operator. Copies a JSON value via the "copy and swap"
16403 strategy: It is expressed in terms of the copy constructor, destructor,
16404 and the `swap()` member function.
16405
16406 @param[in] other value to copy from
16407
16408 @complexity Linear.
16409
16410 @requirement This function helps `basic_json` satisfying the
16411 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
16412 requirements:
16413 - The complexity is linear.
16414
16415 @liveexample{The code below shows and example for the copy assignment. It
16416 creates a copy of value `a` which is then swapped with `b`. Finally\, the
16417 copy of `a` (which is the null value after the swap) is
16418 destroyed.,basic_json__copyassignment}
16419
16420 @since version 1.0.0
16421 */
operator =(basic_json other)16422 basic_json& operator=(basic_json other) noexcept (
16423 std::is_nothrow_move_constructible<value_t>::value and
16424 std::is_nothrow_move_assignable<value_t>::value and
16425 std::is_nothrow_move_constructible<json_value>::value and
16426 std::is_nothrow_move_assignable<json_value>::value
16427 )
16428 {
16429 // check that passed value is valid
16430 other.assert_invariant();
16431
16432 using std::swap;
16433 swap(m_type, other.m_type);
16434 swap(m_value, other.m_value);
16435
16436 assert_invariant();
16437 return *this;
16438 }
16439
16440 /*!
16441 @brief destructor
16442
16443 Destroys the JSON value and frees all allocated memory.
16444
16445 @complexity Linear.
16446
16447 @requirement This function helps `basic_json` satisfying the
16448 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
16449 requirements:
16450 - The complexity is linear.
16451 - All stored elements are destroyed and all memory is freed.
16452
16453 @since version 1.0.0
16454 */
~basic_json()16455 ~basic_json() noexcept
16456 {
16457 assert_invariant();
16458 m_value.destroy(m_type);
16459 }
16460
16461 /// @}
16462
16463 public:
16464 ///////////////////////
16465 // object inspection //
16466 ///////////////////////
16467
16468 /// @name object inspection
16469 /// Functions to inspect the type of a JSON value.
16470 /// @{
16471
16472 /*!
16473 @brief serialization
16474
16475 Serialization function for JSON values. The function tries to mimic
16476 Python's `json.dumps()` function, and currently supports its @a indent
16477 and @a ensure_ascii parameters.
16478
16479 @param[in] indent If indent is nonnegative, then array elements and object
16480 members will be pretty-printed with that indent level. An indent level of
16481 `0` will only insert newlines. `-1` (the default) selects the most compact
16482 representation.
16483 @param[in] indent_char The character to use for indentation if @a indent is
16484 greater than `0`. The default is ` ` (space).
16485 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
16486 in the output are escaped with `\uXXXX` sequences, and the result consists
16487 of ASCII characters only.
16488 @param[in] error_handler how to react on decoding errors; there are three
16489 possible values: `strict` (throws and exception in case a decoding error
16490 occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD),
16491 and `ignore` (ignore invalid UTF-8 sequences during serialization).
16492
16493 @return string containing the serialization of the JSON value
16494
16495 @throw type_error.316 if a string stored inside the JSON value is not
16496 UTF-8 encoded
16497
16498 @complexity Linear.
16499
16500 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
16501 changes in the JSON value.
16502
16503 @liveexample{The following example shows the effect of different @a indent\,
16504 @a indent_char\, and @a ensure_ascii parameters to the result of the
16505 serialization.,dump}
16506
16507 @see https://docs.python.org/2/library/json.html#json.dump
16508
16509 @since version 1.0.0; indentation character @a indent_char, option
16510 @a ensure_ascii and exceptions added in version 3.0.0; error
16511 handlers added in version 3.4.0.
16512 */
dump(const int indent=-1,const char indent_char=' ',const bool ensure_ascii=false,const error_handler_t error_handler=error_handler_t::strict) const16513 string_t dump(const int indent = -1,
16514 const char indent_char = ' ',
16515 const bool ensure_ascii = false,
16516 const error_handler_t error_handler = error_handler_t::strict) const
16517 {
16518 string_t result;
16519 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
16520
16521 if (indent >= 0)
16522 {
16523 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
16524 }
16525 else
16526 {
16527 s.dump(*this, false, ensure_ascii, 0);
16528 }
16529
16530 return result;
16531 }
16532
16533 /*!
16534 @brief return the type of the JSON value (explicit)
16535
16536 Return the type of the JSON value as a value from the @ref value_t
16537 enumeration.
16538
16539 @return the type of the JSON value
16540 Value type | return value
16541 ------------------------- | -------------------------
16542 null | value_t::null
16543 boolean | value_t::boolean
16544 string | value_t::string
16545 number (integer) | value_t::number_integer
16546 number (unsigned integer) | value_t::number_unsigned
16547 number (floating-point) | value_t::number_float
16548 object | value_t::object
16549 array | value_t::array
16550 discarded | value_t::discarded
16551
16552 @complexity Constant.
16553
16554 @exceptionsafety No-throw guarantee: this member function never throws
16555 exceptions.
16556
16557 @liveexample{The following code exemplifies `type()` for all JSON
16558 types.,type}
16559
16560 @sa @ref operator value_t() -- return the type of the JSON value (implicit)
16561 @sa @ref type_name() -- return the type as string
16562
16563 @since version 1.0.0
16564 */
type() const16565 constexpr value_t type() const noexcept
16566 {
16567 return m_type;
16568 }
16569
16570 /*!
16571 @brief return whether type is primitive
16572
16573 This function returns true if and only if the JSON type is primitive
16574 (string, number, boolean, or null).
16575
16576 @return `true` if type is primitive (string, number, boolean, or null),
16577 `false` otherwise.
16578
16579 @complexity Constant.
16580
16581 @exceptionsafety No-throw guarantee: this member function never throws
16582 exceptions.
16583
16584 @liveexample{The following code exemplifies `is_primitive()` for all JSON
16585 types.,is_primitive}
16586
16587 @sa @ref is_structured() -- returns whether JSON value is structured
16588 @sa @ref is_null() -- returns whether JSON value is `null`
16589 @sa @ref is_string() -- returns whether JSON value is a string
16590 @sa @ref is_boolean() -- returns whether JSON value is a boolean
16591 @sa @ref is_number() -- returns whether JSON value is a number
16592
16593 @since version 1.0.0
16594 */
is_primitive() const16595 constexpr bool is_primitive() const noexcept
16596 {
16597 return is_null() or is_string() or is_boolean() or is_number();
16598 }
16599
16600 /*!
16601 @brief return whether type is structured
16602
16603 This function returns true if and only if the JSON type is structured
16604 (array or object).
16605
16606 @return `true` if type is structured (array or object), `false` otherwise.
16607
16608 @complexity Constant.
16609
16610 @exceptionsafety No-throw guarantee: this member function never throws
16611 exceptions.
16612
16613 @liveexample{The following code exemplifies `is_structured()` for all JSON
16614 types.,is_structured}
16615
16616 @sa @ref is_primitive() -- returns whether value is primitive
16617 @sa @ref is_array() -- returns whether value is an array
16618 @sa @ref is_object() -- returns whether value is an object
16619
16620 @since version 1.0.0
16621 */
is_structured() const16622 constexpr bool is_structured() const noexcept
16623 {
16624 return is_array() or is_object();
16625 }
16626
16627 /*!
16628 @brief return whether value is null
16629
16630 This function returns true if and only if the JSON value is null.
16631
16632 @return `true` if type is null, `false` otherwise.
16633
16634 @complexity Constant.
16635
16636 @exceptionsafety No-throw guarantee: this member function never throws
16637 exceptions.
16638
16639 @liveexample{The following code exemplifies `is_null()` for all JSON
16640 types.,is_null}
16641
16642 @since version 1.0.0
16643 */
is_null() const16644 constexpr bool is_null() const noexcept
16645 {
16646 return m_type == value_t::null;
16647 }
16648
16649 /*!
16650 @brief return whether value is a boolean
16651
16652 This function returns true if and only if the JSON value is a boolean.
16653
16654 @return `true` if type is boolean, `false` otherwise.
16655
16656 @complexity Constant.
16657
16658 @exceptionsafety No-throw guarantee: this member function never throws
16659 exceptions.
16660
16661 @liveexample{The following code exemplifies `is_boolean()` for all JSON
16662 types.,is_boolean}
16663
16664 @since version 1.0.0
16665 */
is_boolean() const16666 constexpr bool is_boolean() const noexcept
16667 {
16668 return m_type == value_t::boolean;
16669 }
16670
16671 /*!
16672 @brief return whether value is a number
16673
16674 This function returns true if and only if the JSON value is a number. This
16675 includes both integer (signed and unsigned) and floating-point values.
16676
16677 @return `true` if type is number (regardless whether integer, unsigned
16678 integer or floating-type), `false` otherwise.
16679
16680 @complexity Constant.
16681
16682 @exceptionsafety No-throw guarantee: this member function never throws
16683 exceptions.
16684
16685 @liveexample{The following code exemplifies `is_number()` for all JSON
16686 types.,is_number}
16687
16688 @sa @ref is_number_integer() -- check if value is an integer or unsigned
16689 integer number
16690 @sa @ref is_number_unsigned() -- check if value is an unsigned integer
16691 number
16692 @sa @ref is_number_float() -- check if value is a floating-point number
16693
16694 @since version 1.0.0
16695 */
is_number() const16696 constexpr bool is_number() const noexcept
16697 {
16698 return is_number_integer() or is_number_float();
16699 }
16700
16701 /*!
16702 @brief return whether value is an integer number
16703
16704 This function returns true if and only if the JSON value is a signed or
16705 unsigned integer number. This excludes floating-point values.
16706
16707 @return `true` if type is an integer or unsigned integer number, `false`
16708 otherwise.
16709
16710 @complexity Constant.
16711
16712 @exceptionsafety No-throw guarantee: this member function never throws
16713 exceptions.
16714
16715 @liveexample{The following code exemplifies `is_number_integer()` for all
16716 JSON types.,is_number_integer}
16717
16718 @sa @ref is_number() -- check if value is a number
16719 @sa @ref is_number_unsigned() -- check if value is an unsigned integer
16720 number
16721 @sa @ref is_number_float() -- check if value is a floating-point number
16722
16723 @since version 1.0.0
16724 */
is_number_integer() const16725 constexpr bool is_number_integer() const noexcept
16726 {
16727 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
16728 }
16729
16730 /*!
16731 @brief return whether value is an unsigned integer number
16732
16733 This function returns true if and only if the JSON value is an unsigned
16734 integer number. This excludes floating-point and signed integer values.
16735
16736 @return `true` if type is an unsigned integer number, `false` otherwise.
16737
16738 @complexity Constant.
16739
16740 @exceptionsafety No-throw guarantee: this member function never throws
16741 exceptions.
16742
16743 @liveexample{The following code exemplifies `is_number_unsigned()` for all
16744 JSON types.,is_number_unsigned}
16745
16746 @sa @ref is_number() -- check if value is a number
16747 @sa @ref is_number_integer() -- check if value is an integer or unsigned
16748 integer number
16749 @sa @ref is_number_float() -- check if value is a floating-point number
16750
16751 @since version 2.0.0
16752 */
is_number_unsigned() const16753 constexpr bool is_number_unsigned() const noexcept
16754 {
16755 return m_type == value_t::number_unsigned;
16756 }
16757
16758 /*!
16759 @brief return whether value is a floating-point number
16760
16761 This function returns true if and only if the JSON value is a
16762 floating-point number. This excludes signed and unsigned integer values.
16763
16764 @return `true` if type is a floating-point number, `false` otherwise.
16765
16766 @complexity Constant.
16767
16768 @exceptionsafety No-throw guarantee: this member function never throws
16769 exceptions.
16770
16771 @liveexample{The following code exemplifies `is_number_float()` for all
16772 JSON types.,is_number_float}
16773
16774 @sa @ref is_number() -- check if value is number
16775 @sa @ref is_number_integer() -- check if value is an integer number
16776 @sa @ref is_number_unsigned() -- check if value is an unsigned integer
16777 number
16778
16779 @since version 1.0.0
16780 */
is_number_float() const16781 constexpr bool is_number_float() const noexcept
16782 {
16783 return m_type == value_t::number_float;
16784 }
16785
16786 /*!
16787 @brief return whether value is an object
16788
16789 This function returns true if and only if the JSON value is an object.
16790
16791 @return `true` if type is object, `false` otherwise.
16792
16793 @complexity Constant.
16794
16795 @exceptionsafety No-throw guarantee: this member function never throws
16796 exceptions.
16797
16798 @liveexample{The following code exemplifies `is_object()` for all JSON
16799 types.,is_object}
16800
16801 @since version 1.0.0
16802 */
is_object() const16803 constexpr bool is_object() const noexcept
16804 {
16805 return m_type == value_t::object;
16806 }
16807
16808 /*!
16809 @brief return whether value is an array
16810
16811 This function returns true if and only if the JSON value is an array.
16812
16813 @return `true` if type is array, `false` otherwise.
16814
16815 @complexity Constant.
16816
16817 @exceptionsafety No-throw guarantee: this member function never throws
16818 exceptions.
16819
16820 @liveexample{The following code exemplifies `is_array()` for all JSON
16821 types.,is_array}
16822
16823 @since version 1.0.0
16824 */
is_array() const16825 constexpr bool is_array() const noexcept
16826 {
16827 return m_type == value_t::array;
16828 }
16829
16830 /*!
16831 @brief return whether value is a string
16832
16833 This function returns true if and only if the JSON value is a string.
16834
16835 @return `true` if type is string, `false` otherwise.
16836
16837 @complexity Constant.
16838
16839 @exceptionsafety No-throw guarantee: this member function never throws
16840 exceptions.
16841
16842 @liveexample{The following code exemplifies `is_string()` for all JSON
16843 types.,is_string}
16844
16845 @since version 1.0.0
16846 */
is_string() const16847 constexpr bool is_string() const noexcept
16848 {
16849 return m_type == value_t::string;
16850 }
16851
16852 /*!
16853 @brief return whether value is discarded
16854
16855 This function returns true if and only if the JSON value was discarded
16856 during parsing with a callback function (see @ref parser_callback_t).
16857
16858 @note This function will always be `false` for JSON values after parsing.
16859 That is, discarded values can only occur during parsing, but will be
16860 removed when inside a structured value or replaced by null in other cases.
16861
16862 @return `true` if type is discarded, `false` otherwise.
16863
16864 @complexity Constant.
16865
16866 @exceptionsafety No-throw guarantee: this member function never throws
16867 exceptions.
16868
16869 @liveexample{The following code exemplifies `is_discarded()` for all JSON
16870 types.,is_discarded}
16871
16872 @since version 1.0.0
16873 */
is_discarded() const16874 constexpr bool is_discarded() const noexcept
16875 {
16876 return m_type == value_t::discarded;
16877 }
16878
16879 /*!
16880 @brief return the type of the JSON value (implicit)
16881
16882 Implicitly return the type of the JSON value as a value from the @ref
16883 value_t enumeration.
16884
16885 @return the type of the JSON value
16886
16887 @complexity Constant.
16888
16889 @exceptionsafety No-throw guarantee: this member function never throws
16890 exceptions.
16891
16892 @liveexample{The following code exemplifies the @ref value_t operator for
16893 all JSON types.,operator__value_t}
16894
16895 @sa @ref type() -- return the type of the JSON value (explicit)
16896 @sa @ref type_name() -- return the type as string
16897
16898 @since version 1.0.0
16899 */
operator value_t() const16900 constexpr operator value_t() const noexcept
16901 {
16902 return m_type;
16903 }
16904
16905 /// @}
16906
16907 private:
16908 //////////////////
16909 // value access //
16910 //////////////////
16911
16912 /// get a boolean (explicit)
get_impl(boolean_t *) const16913 boolean_t get_impl(boolean_t* /*unused*/) const
16914 {
16915 if (JSON_HEDLEY_LIKELY(is_boolean()))
16916 {
16917 return m_value.boolean;
16918 }
16919
16920 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name())));
16921 }
16922
16923 /// get a pointer to the value (object)
get_impl_ptr(object_t *)16924 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
16925 {
16926 return is_object() ? m_value.object : nullptr;
16927 }
16928
16929 /// get a pointer to the value (object)
get_impl_ptr(const object_t *) const16930 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
16931 {
16932 return is_object() ? m_value.object : nullptr;
16933 }
16934
16935 /// get a pointer to the value (array)
get_impl_ptr(array_t *)16936 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
16937 {
16938 return is_array() ? m_value.array : nullptr;
16939 }
16940
16941 /// get a pointer to the value (array)
get_impl_ptr(const array_t *) const16942 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
16943 {
16944 return is_array() ? m_value.array : nullptr;
16945 }
16946
16947 /// get a pointer to the value (string)
get_impl_ptr(string_t *)16948 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
16949 {
16950 return is_string() ? m_value.string : nullptr;
16951 }
16952
16953 /// get a pointer to the value (string)
get_impl_ptr(const string_t *) const16954 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
16955 {
16956 return is_string() ? m_value.string : nullptr;
16957 }
16958
16959 /// get a pointer to the value (boolean)
get_impl_ptr(boolean_t *)16960 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
16961 {
16962 return is_boolean() ? &m_value.boolean : nullptr;
16963 }
16964
16965 /// get a pointer to the value (boolean)
get_impl_ptr(const boolean_t *) const16966 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
16967 {
16968 return is_boolean() ? &m_value.boolean : nullptr;
16969 }
16970
16971 /// get a pointer to the value (integer number)
get_impl_ptr(number_integer_t *)16972 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
16973 {
16974 return is_number_integer() ? &m_value.number_integer : nullptr;
16975 }
16976
16977 /// get a pointer to the value (integer number)
get_impl_ptr(const number_integer_t *) const16978 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
16979 {
16980 return is_number_integer() ? &m_value.number_integer : nullptr;
16981 }
16982
16983 /// get a pointer to the value (unsigned number)
get_impl_ptr(number_unsigned_t *)16984 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
16985 {
16986 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
16987 }
16988
16989 /// get a pointer to the value (unsigned number)
get_impl_ptr(const number_unsigned_t *) const16990 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
16991 {
16992 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
16993 }
16994
16995 /// get a pointer to the value (floating-point number)
get_impl_ptr(number_float_t *)16996 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
16997 {
16998 return is_number_float() ? &m_value.number_float : nullptr;
16999 }
17000
17001 /// get a pointer to the value (floating-point number)
get_impl_ptr(const number_float_t *) const17002 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
17003 {
17004 return is_number_float() ? &m_value.number_float : nullptr;
17005 }
17006
17007 /*!
17008 @brief helper function to implement get_ref()
17009
17010 This function helps to implement get_ref() without code duplication for
17011 const and non-const overloads
17012
17013 @tparam ThisType will be deduced as `basic_json` or `const basic_json`
17014
17015 @throw type_error.303 if ReferenceType does not match underlying value
17016 type of the current JSON
17017 */
17018 template<typename ReferenceType, typename ThisType>
get_ref_impl(ThisType & obj)17019 static ReferenceType get_ref_impl(ThisType& obj)
17020 {
17021 // delegate the call to get_ptr<>()
17022 auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
17023
17024 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
17025 {
17026 return *ptr;
17027 }
17028
17029 JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
17030 }
17031
17032 public:
17033 /// @name value access
17034 /// Direct access to the stored value of a JSON value.
17035 /// @{
17036
17037 /*!
17038 @brief get special-case overload
17039
17040 This overloads avoids a lot of template boilerplate, it can be seen as the
17041 identity method
17042
17043 @tparam BasicJsonType == @ref basic_json
17044
17045 @return a copy of *this
17046
17047 @complexity Constant.
17048
17049 @since version 2.1.0
17050 */
17051 template<typename BasicJsonType, detail::enable_if_t<
17052 std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,
17053 int> = 0>
get() const17054 basic_json get() const
17055 {
17056 return *this;
17057 }
17058
17059 /*!
17060 @brief get special-case overload
17061
17062 This overloads converts the current @ref basic_json in a different
17063 @ref basic_json type
17064
17065 @tparam BasicJsonType == @ref basic_json
17066
17067 @return a copy of *this, converted into @tparam BasicJsonType
17068
17069 @complexity Depending on the implementation of the called `from_json()`
17070 method.
17071
17072 @since version 3.2.0
17073 */
17074 template<typename BasicJsonType, detail::enable_if_t<
17075 not std::is_same<BasicJsonType, basic_json>::value and
17076 detail::is_basic_json<BasicJsonType>::value, int> = 0>
17077 BasicJsonType get() const
17078 {
17079 return *this;
17080 }
17081
17082 /*!
17083 @brief get a value (explicit)
17084
17085 Explicit type conversion between the JSON value and a compatible value
17086 which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
17087 and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
17088 The value is converted by calling the @ref json_serializer<ValueType>
17089 `from_json()` method.
17090
17091 The function is equivalent to executing
17092 @code {.cpp}
17093 ValueType ret;
17094 JSONSerializer<ValueType>::from_json(*this, ret);
17095 return ret;
17096 @endcode
17097
17098 This overloads is chosen if:
17099 - @a ValueType is not @ref basic_json,
17100 - @ref json_serializer<ValueType> has a `from_json()` method of the form
17101 `void from_json(const basic_json&, ValueType&)`, and
17102 - @ref json_serializer<ValueType> does not have a `from_json()` method of
17103 the form `ValueType from_json(const basic_json&)`
17104
17105 @tparam ValueTypeCV the provided value type
17106 @tparam ValueType the returned value type
17107
17108 @return copy of the JSON value, converted to @a ValueType
17109
17110 @throw what @ref json_serializer<ValueType> `from_json()` method throws
17111
17112 @liveexample{The example below shows several conversions from JSON values
17113 to other types. There a few things to note: (1) Floating-point numbers can
17114 be converted to integers\, (2) A JSON array can be converted to a standard
17115 `std::vector<short>`\, (3) A JSON object can be converted to C++
17116 associative containers such as `std::unordered_map<std::string\,
17117 json>`.,get__ValueType_const}
17118
17119 @since version 2.1.0
17120 */
17121 template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
17122 detail::enable_if_t <
17123 not detail::is_basic_json<ValueType>::value and
17124 detail::has_from_json<basic_json_t, ValueType>::value and
17125 not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
17126 int> = 0>
17127 ValueType get() const noexcept(noexcept(
17128 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
17129 {
17130 // we cannot static_assert on ValueTypeCV being non-const, because
17131 // there is support for get<const basic_json_t>(), which is why we
17132 // still need the uncvref
17133 static_assert(not std::is_reference<ValueTypeCV>::value,
17134 "get() cannot be used with reference types, you might want to use get_ref()");
17135 static_assert(std::is_default_constructible<ValueType>::value,
17136 "types must be DefaultConstructible when used with get()");
17137
17138 ValueType ret;
17139 JSONSerializer<ValueType>::from_json(*this, ret);
17140 return ret;
17141 }
17142
17143 /*!
17144 @brief get a value (explicit); special case
17145
17146 Explicit type conversion between the JSON value and a compatible value
17147 which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
17148 and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
17149 The value is converted by calling the @ref json_serializer<ValueType>
17150 `from_json()` method.
17151
17152 The function is equivalent to executing
17153 @code {.cpp}
17154 return JSONSerializer<ValueTypeCV>::from_json(*this);
17155 @endcode
17156
17157 This overloads is chosen if:
17158 - @a ValueType is not @ref basic_json and
17159 - @ref json_serializer<ValueType> has a `from_json()` method of the form
17160 `ValueType from_json(const basic_json&)`
17161
17162 @note If @ref json_serializer<ValueType> has both overloads of
17163 `from_json()`, this one is chosen.
17164
17165 @tparam ValueTypeCV the provided value type
17166 @tparam ValueType the returned value type
17167
17168 @return copy of the JSON value, converted to @a ValueType
17169
17170 @throw what @ref json_serializer<ValueType> `from_json()` method throws
17171
17172 @since version 2.1.0
17173 */
17174 template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
17175 detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
17176 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
17177 int> = 0>
17178 ValueType get() const noexcept(noexcept(
17179 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
17180 {
17181 static_assert(not std::is_reference<ValueTypeCV>::value,
17182 "get() cannot be used with reference types, you might want to use get_ref()");
17183 return JSONSerializer<ValueType>::from_json(*this);
17184 }
17185
17186 /*!
17187 @brief get a value (explicit)
17188
17189 Explicit type conversion between the JSON value and a compatible value.
17190 The value is filled into the input parameter by calling the @ref json_serializer<ValueType>
17191 `from_json()` method.
17192
17193 The function is equivalent to executing
17194 @code {.cpp}
17195 ValueType v;
17196 JSONSerializer<ValueType>::from_json(*this, v);
17197 @endcode
17198
17199 This overloads is chosen if:
17200 - @a ValueType is not @ref basic_json,
17201 - @ref json_serializer<ValueType> has a `from_json()` method of the form
17202 `void from_json(const basic_json&, ValueType&)`, and
17203
17204 @tparam ValueType the input parameter type.
17205
17206 @return the input parameter, allowing chaining calls.
17207
17208 @throw what @ref json_serializer<ValueType> `from_json()` method throws
17209
17210 @liveexample{The example below shows several conversions from JSON values
17211 to other types. There a few things to note: (1) Floating-point numbers can
17212 be converted to integers\, (2) A JSON array can be converted to a standard
17213 `std::vector<short>`\, (3) A JSON object can be converted to C++
17214 associative containers such as `std::unordered_map<std::string\,
17215 json>`.,get_to}
17216
17217 @since version 3.3.0
17218 */
17219 template<typename ValueType,
17220 detail::enable_if_t <
17221 not detail::is_basic_json<ValueType>::value and
17222 detail::has_from_json<basic_json_t, ValueType>::value,
17223 int> = 0>
17224 ValueType & get_to(ValueType& v) const noexcept(noexcept(
17225 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
17226 {
17227 JSONSerializer<ValueType>::from_json(*this, v);
17228 return v;
17229 }
17230
17231 template <
17232 typename T, std::size_t N,
17233 typename Array = T (&)[N],
17234 detail::enable_if_t <
17235 detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
17236 Array get_to(T (&v)[N]) const
17237 noexcept(noexcept(JSONSerializer<Array>::from_json(
17238 std::declval<const basic_json_t&>(), v)))
17239 {
17240 JSONSerializer<Array>::from_json(*this, v);
17241 return v;
17242 }
17243
17244
17245 /*!
17246 @brief get a pointer value (implicit)
17247
17248 Implicit pointer access to the internally stored JSON value. No copies are
17249 made.
17250
17251 @warning Writing data to the pointee of the result yields an undefined
17252 state.
17253
17254 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
17255 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
17256 @ref number_unsigned_t, or @ref number_float_t. Enforced by a static
17257 assertion.
17258
17259 @return pointer to the internally stored JSON value if the requested
17260 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
17261
17262 @complexity Constant.
17263
17264 @liveexample{The example below shows how pointers to internal values of a
17265 JSON value can be requested. Note that no type conversions are made and a
17266 `nullptr` is returned if the value and the requested pointer type does not
17267 match.,get_ptr}
17268
17269 @since version 1.0.0
17270 */
17271 template<typename PointerType, typename std::enable_if<
17272 std::is_pointer<PointerType>::value, int>::type = 0>
get_ptr()17273 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
17274 {
17275 // delegate the call to get_impl_ptr<>()
17276 return get_impl_ptr(static_cast<PointerType>(nullptr));
17277 }
17278
17279 /*!
17280 @brief get a pointer value (implicit)
17281 @copydoc get_ptr()
17282 */
17283 template<typename PointerType, typename std::enable_if<
17284 std::is_pointer<PointerType>::value and
17285 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
get_ptr() const17286 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
17287 {
17288 // delegate the call to get_impl_ptr<>() const
17289 return get_impl_ptr(static_cast<PointerType>(nullptr));
17290 }
17291
17292 /*!
17293 @brief get a pointer value (explicit)
17294
17295 Explicit pointer access to the internally stored JSON value. No copies are
17296 made.
17297
17298 @warning The pointer becomes invalid if the underlying JSON object
17299 changes.
17300
17301 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
17302 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
17303 @ref number_unsigned_t, or @ref number_float_t.
17304
17305 @return pointer to the internally stored JSON value if the requested
17306 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
17307
17308 @complexity Constant.
17309
17310 @liveexample{The example below shows how pointers to internal values of a
17311 JSON value can be requested. Note that no type conversions are made and a
17312 `nullptr` is returned if the value and the requested pointer type does not
17313 match.,get__PointerType}
17314
17315 @sa @ref get_ptr() for explicit pointer-member access
17316
17317 @since version 1.0.0
17318 */
17319 template<typename PointerType, typename std::enable_if<
17320 std::is_pointer<PointerType>::value, int>::type = 0>
get()17321 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
17322 {
17323 // delegate the call to get_ptr
17324 return get_ptr<PointerType>();
17325 }
17326
17327 /*!
17328 @brief get a pointer value (explicit)
17329 @copydoc get()
17330 */
17331 template<typename PointerType, typename std::enable_if<
17332 std::is_pointer<PointerType>::value, int>::type = 0>
get() const17333 constexpr auto get() const noexcept -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
17334 {
17335 // delegate the call to get_ptr
17336 return get_ptr<PointerType>();
17337 }
17338
17339 /*!
17340 @brief get a reference value (implicit)
17341
17342 Implicit reference access to the internally stored JSON value. No copies
17343 are made.
17344
17345 @warning Writing data to the referee of the result yields an undefined
17346 state.
17347
17348 @tparam ReferenceType reference type; must be a reference to @ref array_t,
17349 @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or
17350 @ref number_float_t. Enforced by static assertion.
17351
17352 @return reference to the internally stored JSON value if the requested
17353 reference type @a ReferenceType fits to the JSON value; throws
17354 type_error.303 otherwise
17355
17356 @throw type_error.303 in case passed type @a ReferenceType is incompatible
17357 with the stored JSON value; see example below
17358
17359 @complexity Constant.
17360
17361 @liveexample{The example shows several calls to `get_ref()`.,get_ref}
17362
17363 @since version 1.1.0
17364 */
17365 template<typename ReferenceType, typename std::enable_if<
17366 std::is_reference<ReferenceType>::value, int>::type = 0>
17367 ReferenceType get_ref()
17368 {
17369 // delegate call to get_ref_impl
17370 return get_ref_impl<ReferenceType>(*this);
17371 }
17372
17373 /*!
17374 @brief get a reference value (implicit)
17375 @copydoc get_ref()
17376 */
17377 template<typename ReferenceType, typename std::enable_if<
17378 std::is_reference<ReferenceType>::value and
17379 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
17380 ReferenceType get_ref() const
17381 {
17382 // delegate call to get_ref_impl
17383 return get_ref_impl<ReferenceType>(*this);
17384 }
17385
17386 /*!
17387 @brief get a value (implicit)
17388
17389 Implicit type conversion between the JSON value and a compatible value.
17390 The call is realized by calling @ref get() const.
17391
17392 @tparam ValueType non-pointer type compatible to the JSON value, for
17393 instance `int` for JSON integer numbers, `bool` for JSON booleans, or
17394 `std::vector` types for JSON arrays. The character type of @ref string_t
17395 as well as an initializer list of this type is excluded to avoid
17396 ambiguities as these types implicitly convert to `std::string`.
17397
17398 @return copy of the JSON value, converted to type @a ValueType
17399
17400 @throw type_error.302 in case passed type @a ValueType is incompatible
17401 to the JSON value type (e.g., the JSON value is of type boolean, but a
17402 string is requested); see example below
17403
17404 @complexity Linear in the size of the JSON value.
17405
17406 @liveexample{The example below shows several conversions from JSON values
17407 to other types. There a few things to note: (1) Floating-point numbers can
17408 be converted to integers\, (2) A JSON array can be converted to a standard
17409 `std::vector<short>`\, (3) A JSON object can be converted to C++
17410 associative containers such as `std::unordered_map<std::string\,
17411 json>`.,operator__ValueType}
17412
17413 @since version 1.0.0
17414 */
17415 template < typename ValueType, typename std::enable_if <
17416 not std::is_pointer<ValueType>::value and
17417 not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
17418 not std::is_same<ValueType, typename string_t::value_type>::value and
17419 not detail::is_basic_json<ValueType>::value
17420
17421 #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
17422 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
17423 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) and _MSC_VER <= 1914))
17424 and not std::is_same<ValueType, typename std::string_view>::value
17425 #endif
17426 #endif
17427 and detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value
17428 , int >::type = 0 >
operator ValueType() const17429 operator ValueType() const
17430 {
17431 // delegate the call to get<>() const
17432 return get<ValueType>();
17433 }
17434
17435 /// @}
17436
17437
17438 ////////////////////
17439 // element access //
17440 ////////////////////
17441
17442 /// @name element access
17443 /// Access to the JSON value.
17444 /// @{
17445
17446 /*!
17447 @brief access specified array element with bounds checking
17448
17449 Returns a reference to the element at specified location @a idx, with
17450 bounds checking.
17451
17452 @param[in] idx index of the element to access
17453
17454 @return reference to the element at index @a idx
17455
17456 @throw type_error.304 if the JSON value is not an array; in this case,
17457 calling `at` with an index makes no sense. See example below.
17458 @throw out_of_range.401 if the index @a idx is out of range of the array;
17459 that is, `idx >= size()`. See example below.
17460
17461 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
17462 changes in the JSON value.
17463
17464 @complexity Constant.
17465
17466 @since version 1.0.0
17467
17468 @liveexample{The example below shows how array elements can be read and
17469 written using `at()`. It also demonstrates the different exceptions that
17470 can be thrown.,at__size_type}
17471 */
at(size_type idx)17472 reference at(size_type idx)
17473 {
17474 // at only works for arrays
17475 if (JSON_HEDLEY_LIKELY(is_array()))
17476 {
17477 JSON_TRY
17478 {
17479 return m_value.array->at(idx);
17480 }
17481 JSON_CATCH (std::out_of_range&)
17482 {
17483 // create better exception explanation
17484 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
17485 }
17486 }
17487 else
17488 {
17489 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
17490 }
17491 }
17492
17493 /*!
17494 @brief access specified array element with bounds checking
17495
17496 Returns a const reference to the element at specified location @a idx,
17497 with bounds checking.
17498
17499 @param[in] idx index of the element to access
17500
17501 @return const reference to the element at index @a idx
17502
17503 @throw type_error.304 if the JSON value is not an array; in this case,
17504 calling `at` with an index makes no sense. See example below.
17505 @throw out_of_range.401 if the index @a idx is out of range of the array;
17506 that is, `idx >= size()`. See example below.
17507
17508 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
17509 changes in the JSON value.
17510
17511 @complexity Constant.
17512
17513 @since version 1.0.0
17514
17515 @liveexample{The example below shows how array elements can be read using
17516 `at()`. It also demonstrates the different exceptions that can be thrown.,
17517 at__size_type_const}
17518 */
at(size_type idx) const17519 const_reference at(size_type idx) const
17520 {
17521 // at only works for arrays
17522 if (JSON_HEDLEY_LIKELY(is_array()))
17523 {
17524 JSON_TRY
17525 {
17526 return m_value.array->at(idx);
17527 }
17528 JSON_CATCH (std::out_of_range&)
17529 {
17530 // create better exception explanation
17531 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
17532 }
17533 }
17534 else
17535 {
17536 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
17537 }
17538 }
17539
17540 /*!
17541 @brief access specified object element with bounds checking
17542
17543 Returns a reference to the element at with specified key @a key, with
17544 bounds checking.
17545
17546 @param[in] key key of the element to access
17547
17548 @return reference to the element at key @a key
17549
17550 @throw type_error.304 if the JSON value is not an object; in this case,
17551 calling `at` with a key makes no sense. See example below.
17552 @throw out_of_range.403 if the key @a key is is not stored in the object;
17553 that is, `find(key) == end()`. See example below.
17554
17555 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
17556 changes in the JSON value.
17557
17558 @complexity Logarithmic in the size of the container.
17559
17560 @sa @ref operator[](const typename object_t::key_type&) for unchecked
17561 access by reference
17562 @sa @ref value() for access by value with a default value
17563
17564 @since version 1.0.0
17565
17566 @liveexample{The example below shows how object elements can be read and
17567 written using `at()`. It also demonstrates the different exceptions that
17568 can be thrown.,at__object_t_key_type}
17569 */
at(const typename object_t::key_type & key)17570 reference at(const typename object_t::key_type& key)
17571 {
17572 // at only works for objects
17573 if (JSON_HEDLEY_LIKELY(is_object()))
17574 {
17575 JSON_TRY
17576 {
17577 return m_value.object->at(key);
17578 }
17579 JSON_CATCH (std::out_of_range&)
17580 {
17581 // create better exception explanation
17582 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
17583 }
17584 }
17585 else
17586 {
17587 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
17588 }
17589 }
17590
17591 /*!
17592 @brief access specified object element with bounds checking
17593
17594 Returns a const reference to the element at with specified key @a key,
17595 with bounds checking.
17596
17597 @param[in] key key of the element to access
17598
17599 @return const reference to the element at key @a key
17600
17601 @throw type_error.304 if the JSON value is not an object; in this case,
17602 calling `at` with a key makes no sense. See example below.
17603 @throw out_of_range.403 if the key @a key is is not stored in the object;
17604 that is, `find(key) == end()`. See example below.
17605
17606 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
17607 changes in the JSON value.
17608
17609 @complexity Logarithmic in the size of the container.
17610
17611 @sa @ref operator[](const typename object_t::key_type&) for unchecked
17612 access by reference
17613 @sa @ref value() for access by value with a default value
17614
17615 @since version 1.0.0
17616
17617 @liveexample{The example below shows how object elements can be read using
17618 `at()`. It also demonstrates the different exceptions that can be thrown.,
17619 at__object_t_key_type_const}
17620 */
at(const typename object_t::key_type & key) const17621 const_reference at(const typename object_t::key_type& key) const
17622 {
17623 // at only works for objects
17624 if (JSON_HEDLEY_LIKELY(is_object()))
17625 {
17626 JSON_TRY
17627 {
17628 return m_value.object->at(key);
17629 }
17630 JSON_CATCH (std::out_of_range&)
17631 {
17632 // create better exception explanation
17633 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
17634 }
17635 }
17636 else
17637 {
17638 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
17639 }
17640 }
17641
17642 /*!
17643 @brief access specified array element
17644
17645 Returns a reference to the element at specified location @a idx.
17646
17647 @note If @a idx is beyond the range of the array (i.e., `idx >= size()`),
17648 then the array is silently filled up with `null` values to make `idx` a
17649 valid reference to the last stored element.
17650
17651 @param[in] idx index of the element to access
17652
17653 @return reference to the element at index @a idx
17654
17655 @throw type_error.305 if the JSON value is not an array or null; in that
17656 cases, using the [] operator with an index makes no sense.
17657
17658 @complexity Constant if @a idx is in the range of the array. Otherwise
17659 linear in `idx - size()`.
17660
17661 @liveexample{The example below shows how array elements can be read and
17662 written using `[]` operator. Note the addition of `null`
17663 values.,operatorarray__size_type}
17664
17665 @since version 1.0.0
17666 */
operator [](size_type idx)17667 reference operator[](size_type idx)
17668 {
17669 // implicitly convert null value to an empty array
17670 if (is_null())
17671 {
17672 m_type = value_t::array;
17673 m_value.array = create<array_t>();
17674 assert_invariant();
17675 }
17676
17677 // operator[] only works for arrays
17678 if (JSON_HEDLEY_LIKELY(is_array()))
17679 {
17680 // fill up array with null values if given idx is outside range
17681 if (idx >= m_value.array->size())
17682 {
17683 m_value.array->insert(m_value.array->end(),
17684 idx - m_value.array->size() + 1,
17685 basic_json());
17686 }
17687
17688 return m_value.array->operator[](idx);
17689 }
17690
17691 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
17692 }
17693
17694 /*!
17695 @brief access specified array element
17696
17697 Returns a const reference to the element at specified location @a idx.
17698
17699 @param[in] idx index of the element to access
17700
17701 @return const reference to the element at index @a idx
17702
17703 @throw type_error.305 if the JSON value is not an array; in that case,
17704 using the [] operator with an index makes no sense.
17705
17706 @complexity Constant.
17707
17708 @liveexample{The example below shows how array elements can be read using
17709 the `[]` operator.,operatorarray__size_type_const}
17710
17711 @since version 1.0.0
17712 */
operator [](size_type idx) const17713 const_reference operator[](size_type idx) const
17714 {
17715 // const operator[] only works for arrays
17716 if (JSON_HEDLEY_LIKELY(is_array()))
17717 {
17718 return m_value.array->operator[](idx);
17719 }
17720
17721 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
17722 }
17723
17724 /*!
17725 @brief access specified object element
17726
17727 Returns a reference to the element at with specified key @a key.
17728
17729 @note If @a key is not found in the object, then it is silently added to
17730 the object and filled with a `null` value to make `key` a valid reference.
17731 In case the value was `null` before, it is converted to an object.
17732
17733 @param[in] key key of the element to access
17734
17735 @return reference to the element at key @a key
17736
17737 @throw type_error.305 if the JSON value is not an object or null; in that
17738 cases, using the [] operator with a key makes no sense.
17739
17740 @complexity Logarithmic in the size of the container.
17741
17742 @liveexample{The example below shows how object elements can be read and
17743 written using the `[]` operator.,operatorarray__key_type}
17744
17745 @sa @ref at(const typename object_t::key_type&) for access by reference
17746 with range checking
17747 @sa @ref value() for access by value with a default value
17748
17749 @since version 1.0.0
17750 */
operator [](const typename object_t::key_type & key)17751 reference operator[](const typename object_t::key_type& key)
17752 {
17753 // implicitly convert null value to an empty object
17754 if (is_null())
17755 {
17756 m_type = value_t::object;
17757 m_value.object = create<object_t>();
17758 assert_invariant();
17759 }
17760
17761 // operator[] only works for objects
17762 if (JSON_HEDLEY_LIKELY(is_object()))
17763 {
17764 return m_value.object->operator[](key);
17765 }
17766
17767 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
17768 }
17769
17770 /*!
17771 @brief read-only access specified object element
17772
17773 Returns a const reference to the element at with specified key @a key. No
17774 bounds checking is performed.
17775
17776 @warning If the element with key @a key does not exist, the behavior is
17777 undefined.
17778
17779 @param[in] key key of the element to access
17780
17781 @return const reference to the element at key @a key
17782
17783 @pre The element with key @a key must exist. **This precondition is
17784 enforced with an assertion.**
17785
17786 @throw type_error.305 if the JSON value is not an object; in that case,
17787 using the [] operator with a key makes no sense.
17788
17789 @complexity Logarithmic in the size of the container.
17790
17791 @liveexample{The example below shows how object elements can be read using
17792 the `[]` operator.,operatorarray__key_type_const}
17793
17794 @sa @ref at(const typename object_t::key_type&) for access by reference
17795 with range checking
17796 @sa @ref value() for access by value with a default value
17797
17798 @since version 1.0.0
17799 */
operator [](const typename object_t::key_type & key) const17800 const_reference operator[](const typename object_t::key_type& key) const
17801 {
17802 // const operator[] only works for objects
17803 if (JSON_HEDLEY_LIKELY(is_object()))
17804 {
17805 assert(m_value.object->find(key) != m_value.object->end());
17806 return m_value.object->find(key)->second;
17807 }
17808
17809 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
17810 }
17811
17812 /*!
17813 @brief access specified object element
17814
17815 Returns a reference to the element at with specified key @a key.
17816
17817 @note If @a key is not found in the object, then it is silently added to
17818 the object and filled with a `null` value to make `key` a valid reference.
17819 In case the value was `null` before, it is converted to an object.
17820
17821 @param[in] key key of the element to access
17822
17823 @return reference to the element at key @a key
17824
17825 @throw type_error.305 if the JSON value is not an object or null; in that
17826 cases, using the [] operator with a key makes no sense.
17827
17828 @complexity Logarithmic in the size of the container.
17829
17830 @liveexample{The example below shows how object elements can be read and
17831 written using the `[]` operator.,operatorarray__key_type}
17832
17833 @sa @ref at(const typename object_t::key_type&) for access by reference
17834 with range checking
17835 @sa @ref value() for access by value with a default value
17836
17837 @since version 1.1.0
17838 */
17839 template<typename T>
17840 JSON_HEDLEY_NON_NULL(2)
operator [](T * key)17841 reference operator[](T* key)
17842 {
17843 // implicitly convert null to object
17844 if (is_null())
17845 {
17846 m_type = value_t::object;
17847 m_value = value_t::object;
17848 assert_invariant();
17849 }
17850
17851 // at only works for objects
17852 if (JSON_HEDLEY_LIKELY(is_object()))
17853 {
17854 return m_value.object->operator[](key);
17855 }
17856
17857 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
17858 }
17859
17860 /*!
17861 @brief read-only access specified object element
17862
17863 Returns a const reference to the element at with specified key @a key. No
17864 bounds checking is performed.
17865
17866 @warning If the element with key @a key does not exist, the behavior is
17867 undefined.
17868
17869 @param[in] key key of the element to access
17870
17871 @return const reference to the element at key @a key
17872
17873 @pre The element with key @a key must exist. **This precondition is
17874 enforced with an assertion.**
17875
17876 @throw type_error.305 if the JSON value is not an object; in that case,
17877 using the [] operator with a key makes no sense.
17878
17879 @complexity Logarithmic in the size of the container.
17880
17881 @liveexample{The example below shows how object elements can be read using
17882 the `[]` operator.,operatorarray__key_type_const}
17883
17884 @sa @ref at(const typename object_t::key_type&) for access by reference
17885 with range checking
17886 @sa @ref value() for access by value with a default value
17887
17888 @since version 1.1.0
17889 */
17890 template<typename T>
17891 JSON_HEDLEY_NON_NULL(2)
operator [](T * key) const17892 const_reference operator[](T* key) const
17893 {
17894 // at only works for objects
17895 if (JSON_HEDLEY_LIKELY(is_object()))
17896 {
17897 assert(m_value.object->find(key) != m_value.object->end());
17898 return m_value.object->find(key)->second;
17899 }
17900
17901 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
17902 }
17903
17904 /*!
17905 @brief access specified object element with default value
17906
17907 Returns either a copy of an object's element at the specified key @a key
17908 or a given default value if no element with key @a key exists.
17909
17910 The function is basically equivalent to executing
17911 @code {.cpp}
17912 try {
17913 return at(key);
17914 } catch(out_of_range) {
17915 return default_value;
17916 }
17917 @endcode
17918
17919 @note Unlike @ref at(const typename object_t::key_type&), this function
17920 does not throw if the given key @a key was not found.
17921
17922 @note Unlike @ref operator[](const typename object_t::key_type& key), this
17923 function does not implicitly add an element to the position defined by @a
17924 key. This function is furthermore also applicable to const objects.
17925
17926 @param[in] key key of the element to access
17927 @param[in] default_value the value to return if @a key is not found
17928
17929 @tparam ValueType type compatible to JSON values, for instance `int` for
17930 JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
17931 JSON arrays. Note the type of the expected value at @a key and the default
17932 value @a default_value must be compatible.
17933
17934 @return copy of the element at key @a key or @a default_value if @a key
17935 is not found
17936
17937 @throw type_error.302 if @a default_value does not match the type of the
17938 value at @a key
17939 @throw type_error.306 if the JSON value is not an object; in that case,
17940 using `value()` with a key makes no sense.
17941
17942 @complexity Logarithmic in the size of the container.
17943
17944 @liveexample{The example below shows how object elements can be queried
17945 with a default value.,basic_json__value}
17946
17947 @sa @ref at(const typename object_t::key_type&) for access by reference
17948 with range checking
17949 @sa @ref operator[](const typename object_t::key_type&) for unchecked
17950 access by reference
17951
17952 @since version 1.0.0
17953 */
17954 template<class ValueType, typename std::enable_if<
17955 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
17956 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
17957 {
17958 // at only works for objects
17959 if (JSON_HEDLEY_LIKELY(is_object()))
17960 {
17961 // if key is found, return value and given default value otherwise
17962 const auto it = find(key);
17963 if (it != end())
17964 {
17965 return *it;
17966 }
17967
17968 return default_value;
17969 }
17970
17971 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
17972 }
17973
17974 /*!
17975 @brief overload for a default value of type const char*
17976 @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const
17977 */
value(const typename object_t::key_type & key,const char * default_value) const17978 string_t value(const typename object_t::key_type& key, const char* default_value) const
17979 {
17980 return value(key, string_t(default_value));
17981 }
17982
17983 /*!
17984 @brief access specified object element via JSON Pointer with default value
17985
17986 Returns either a copy of an object's element at the specified key @a key
17987 or a given default value if no element with key @a key exists.
17988
17989 The function is basically equivalent to executing
17990 @code {.cpp}
17991 try {
17992 return at(ptr);
17993 } catch(out_of_range) {
17994 return default_value;
17995 }
17996 @endcode
17997
17998 @note Unlike @ref at(const json_pointer&), this function does not throw
17999 if the given key @a key was not found.
18000
18001 @param[in] ptr a JSON pointer to the element to access
18002 @param[in] default_value the value to return if @a ptr found no value
18003
18004 @tparam ValueType type compatible to JSON values, for instance `int` for
18005 JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
18006 JSON arrays. Note the type of the expected value at @a key and the default
18007 value @a default_value must be compatible.
18008
18009 @return copy of the element at key @a key or @a default_value if @a key
18010 is not found
18011
18012 @throw type_error.302 if @a default_value does not match the type of the
18013 value at @a ptr
18014 @throw type_error.306 if the JSON value is not an object; in that case,
18015 using `value()` with a key makes no sense.
18016
18017 @complexity Logarithmic in the size of the container.
18018
18019 @liveexample{The example below shows how object elements can be queried
18020 with a default value.,basic_json__value_ptr}
18021
18022 @sa @ref operator[](const json_pointer&) for unchecked access by reference
18023
18024 @since version 2.0.2
18025 */
18026 template<class ValueType, typename std::enable_if<
18027 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
18028 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
18029 {
18030 // at only works for objects
18031 if (JSON_HEDLEY_LIKELY(is_object()))
18032 {
18033 // if pointer resolves a value, return it or use default value
18034 JSON_TRY
18035 {
18036 return ptr.get_checked(this);
18037 }
18038 JSON_INTERNAL_CATCH (out_of_range&)
18039 {
18040 return default_value;
18041 }
18042 }
18043
18044 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
18045 }
18046
18047 /*!
18048 @brief overload for a default value of type const char*
18049 @copydoc basic_json::value(const json_pointer&, ValueType) const
18050 */
18051 JSON_HEDLEY_NON_NULL(3)
value(const json_pointer & ptr,const char * default_value) const18052 string_t value(const json_pointer& ptr, const char* default_value) const
18053 {
18054 return value(ptr, string_t(default_value));
18055 }
18056
18057 /*!
18058 @brief access the first element
18059
18060 Returns a reference to the first element in the container. For a JSON
18061 container `c`, the expression `c.front()` is equivalent to `*c.begin()`.
18062
18063 @return In case of a structured type (array or object), a reference to the
18064 first element is returned. In case of number, string, or boolean values, a
18065 reference to the value is returned.
18066
18067 @complexity Constant.
18068
18069 @pre The JSON value must not be `null` (would throw `std::out_of_range`)
18070 or an empty array or object (undefined behavior, **guarded by
18071 assertions**).
18072 @post The JSON value remains unchanged.
18073
18074 @throw invalid_iterator.214 when called on `null` value
18075
18076 @liveexample{The following code shows an example for `front()`.,front}
18077
18078 @sa @ref back() -- access the last element
18079
18080 @since version 1.0.0
18081 */
front()18082 reference front()
18083 {
18084 return *begin();
18085 }
18086
18087 /*!
18088 @copydoc basic_json::front()
18089 */
front() const18090 const_reference front() const
18091 {
18092 return *cbegin();
18093 }
18094
18095 /*!
18096 @brief access the last element
18097
18098 Returns a reference to the last element in the container. For a JSON
18099 container `c`, the expression `c.back()` is equivalent to
18100 @code {.cpp}
18101 auto tmp = c.end();
18102 --tmp;
18103 return *tmp;
18104 @endcode
18105
18106 @return In case of a structured type (array or object), a reference to the
18107 last element is returned. In case of number, string, or boolean values, a
18108 reference to the value is returned.
18109
18110 @complexity Constant.
18111
18112 @pre The JSON value must not be `null` (would throw `std::out_of_range`)
18113 or an empty array or object (undefined behavior, **guarded by
18114 assertions**).
18115 @post The JSON value remains unchanged.
18116
18117 @throw invalid_iterator.214 when called on a `null` value. See example
18118 below.
18119
18120 @liveexample{The following code shows an example for `back()`.,back}
18121
18122 @sa @ref front() -- access the first element
18123
18124 @since version 1.0.0
18125 */
back()18126 reference back()
18127 {
18128 auto tmp = end();
18129 --tmp;
18130 return *tmp;
18131 }
18132
18133 /*!
18134 @copydoc basic_json::back()
18135 */
back() const18136 const_reference back() const
18137 {
18138 auto tmp = cend();
18139 --tmp;
18140 return *tmp;
18141 }
18142
18143 /*!
18144 @brief remove element given an iterator
18145
18146 Removes the element specified by iterator @a pos. The iterator @a pos must
18147 be valid and dereferenceable. Thus the `end()` iterator (which is valid,
18148 but is not dereferenceable) cannot be used as a value for @a pos.
18149
18150 If called on a primitive type other than `null`, the resulting JSON value
18151 will be `null`.
18152
18153 @param[in] pos iterator to the element to remove
18154 @return Iterator following the last removed element. If the iterator @a
18155 pos refers to the last element, the `end()` iterator is returned.
18156
18157 @tparam IteratorType an @ref iterator or @ref const_iterator
18158
18159 @post Invalidates iterators and references at or after the point of the
18160 erase, including the `end()` iterator.
18161
18162 @throw type_error.307 if called on a `null` value; example: `"cannot use
18163 erase() with null"`
18164 @throw invalid_iterator.202 if called on an iterator which does not belong
18165 to the current JSON value; example: `"iterator does not fit current
18166 value"`
18167 @throw invalid_iterator.205 if called on a primitive type with invalid
18168 iterator (i.e., any iterator which is not `begin()`); example: `"iterator
18169 out of range"`
18170
18171 @complexity The complexity depends on the type:
18172 - objects: amortized constant
18173 - arrays: linear in distance between @a pos and the end of the container
18174 - strings: linear in the length of the string
18175 - other types: constant
18176
18177 @liveexample{The example shows the result of `erase()` for different JSON
18178 types.,erase__IteratorType}
18179
18180 @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
18181 the given range
18182 @sa @ref erase(const typename object_t::key_type&) -- removes the element
18183 from an object at the given key
18184 @sa @ref erase(const size_type) -- removes the element from an array at
18185 the given index
18186
18187 @since version 1.0.0
18188 */
18189 template<class IteratorType, typename std::enable_if<
18190 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
18191 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
18192 = 0>
18193 IteratorType erase(IteratorType pos)
18194 {
18195 // make sure iterator fits the current value
18196 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
18197 {
18198 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
18199 }
18200
18201 IteratorType result = end();
18202
18203 switch (m_type)
18204 {
18205 case value_t::boolean:
18206 case value_t::number_float:
18207 case value_t::number_integer:
18208 case value_t::number_unsigned:
18209 case value_t::string:
18210 {
18211 if (JSON_HEDLEY_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
18212 {
18213 JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
18214 }
18215
18216 if (is_string())
18217 {
18218 AllocatorType<string_t> alloc;
18219 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
18220 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
18221 m_value.string = nullptr;
18222 }
18223
18224 m_type = value_t::null;
18225 assert_invariant();
18226 break;
18227 }
18228
18229 case value_t::object:
18230 {
18231 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
18232 break;
18233 }
18234
18235 case value_t::array:
18236 {
18237 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
18238 break;
18239 }
18240
18241 default:
18242 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
18243 }
18244
18245 return result;
18246 }
18247
18248 /*!
18249 @brief remove elements given an iterator range
18250
18251 Removes the element specified by the range `[first; last)`. The iterator
18252 @a first does not need to be dereferenceable if `first == last`: erasing
18253 an empty range is a no-op.
18254
18255 If called on a primitive type other than `null`, the resulting JSON value
18256 will be `null`.
18257
18258 @param[in] first iterator to the beginning of the range to remove
18259 @param[in] last iterator past the end of the range to remove
18260 @return Iterator following the last removed element. If the iterator @a
18261 second refers to the last element, the `end()` iterator is returned.
18262
18263 @tparam IteratorType an @ref iterator or @ref const_iterator
18264
18265 @post Invalidates iterators and references at or after the point of the
18266 erase, including the `end()` iterator.
18267
18268 @throw type_error.307 if called on a `null` value; example: `"cannot use
18269 erase() with null"`
18270 @throw invalid_iterator.203 if called on iterators which does not belong
18271 to the current JSON value; example: `"iterators do not fit current value"`
18272 @throw invalid_iterator.204 if called on a primitive type with invalid
18273 iterators (i.e., if `first != begin()` and `last != end()`); example:
18274 `"iterators out of range"`
18275
18276 @complexity The complexity depends on the type:
18277 - objects: `log(size()) + std::distance(first, last)`
18278 - arrays: linear in the distance between @a first and @a last, plus linear
18279 in the distance between @a last and end of the container
18280 - strings: linear in the length of the string
18281 - other types: constant
18282
18283 @liveexample{The example shows the result of `erase()` for different JSON
18284 types.,erase__IteratorType_IteratorType}
18285
18286 @sa @ref erase(IteratorType) -- removes the element at a given position
18287 @sa @ref erase(const typename object_t::key_type&) -- removes the element
18288 from an object at the given key
18289 @sa @ref erase(const size_type) -- removes the element from an array at
18290 the given index
18291
18292 @since version 1.0.0
18293 */
18294 template<class IteratorType, typename std::enable_if<
18295 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
18296 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
18297 = 0>
18298 IteratorType erase(IteratorType first, IteratorType last)
18299 {
18300 // make sure iterator fits the current value
18301 if (JSON_HEDLEY_UNLIKELY(this != first.m_object or this != last.m_object))
18302 {
18303 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
18304 }
18305
18306 IteratorType result = end();
18307
18308 switch (m_type)
18309 {
18310 case value_t::boolean:
18311 case value_t::number_float:
18312 case value_t::number_integer:
18313 case value_t::number_unsigned:
18314 case value_t::string:
18315 {
18316 if (JSON_HEDLEY_LIKELY(not first.m_it.primitive_iterator.is_begin()
18317 or not last.m_it.primitive_iterator.is_end()))
18318 {
18319 JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
18320 }
18321
18322 if (is_string())
18323 {
18324 AllocatorType<string_t> alloc;
18325 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
18326 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
18327 m_value.string = nullptr;
18328 }
18329
18330 m_type = value_t::null;
18331 assert_invariant();
18332 break;
18333 }
18334
18335 case value_t::object:
18336 {
18337 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
18338 last.m_it.object_iterator);
18339 break;
18340 }
18341
18342 case value_t::array:
18343 {
18344 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
18345 last.m_it.array_iterator);
18346 break;
18347 }
18348
18349 default:
18350 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
18351 }
18352
18353 return result;
18354 }
18355
18356 /*!
18357 @brief remove element from a JSON object given a key
18358
18359 Removes elements from a JSON object with the key value @a key.
18360
18361 @param[in] key value of the elements to remove
18362
18363 @return Number of elements removed. If @a ObjectType is the default
18364 `std::map` type, the return value will always be `0` (@a key was not
18365 found) or `1` (@a key was found).
18366
18367 @post References and iterators to the erased elements are invalidated.
18368 Other references and iterators are not affected.
18369
18370 @throw type_error.307 when called on a type other than JSON object;
18371 example: `"cannot use erase() with null"`
18372
18373 @complexity `log(size()) + count(key)`
18374
18375 @liveexample{The example shows the effect of `erase()`.,erase__key_type}
18376
18377 @sa @ref erase(IteratorType) -- removes the element at a given position
18378 @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
18379 the given range
18380 @sa @ref erase(const size_type) -- removes the element from an array at
18381 the given index
18382
18383 @since version 1.0.0
18384 */
erase(const typename object_t::key_type & key)18385 size_type erase(const typename object_t::key_type& key)
18386 {
18387 // this erase only works for objects
18388 if (JSON_HEDLEY_LIKELY(is_object()))
18389 {
18390 return m_value.object->erase(key);
18391 }
18392
18393 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
18394 }
18395
18396 /*!
18397 @brief remove element from a JSON array given an index
18398
18399 Removes element from a JSON array at the index @a idx.
18400
18401 @param[in] idx index of the element to remove
18402
18403 @throw type_error.307 when called on a type other than JSON object;
18404 example: `"cannot use erase() with null"`
18405 @throw out_of_range.401 when `idx >= size()`; example: `"array index 17
18406 is out of range"`
18407
18408 @complexity Linear in distance between @a idx and the end of the container.
18409
18410 @liveexample{The example shows the effect of `erase()`.,erase__size_type}
18411
18412 @sa @ref erase(IteratorType) -- removes the element at a given position
18413 @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
18414 the given range
18415 @sa @ref erase(const typename object_t::key_type&) -- removes the element
18416 from an object at the given key
18417
18418 @since version 1.0.0
18419 */
erase(const size_type idx)18420 void erase(const size_type idx)
18421 {
18422 // this erase only works for arrays
18423 if (JSON_HEDLEY_LIKELY(is_array()))
18424 {
18425 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
18426 {
18427 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
18428 }
18429
18430 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
18431 }
18432 else
18433 {
18434 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
18435 }
18436 }
18437
18438 /// @}
18439
18440
18441 ////////////
18442 // lookup //
18443 ////////////
18444
18445 /// @name lookup
18446 /// @{
18447
18448 /*!
18449 @brief find an element in a JSON object
18450
18451 Finds an element in a JSON object with key equivalent to @a key. If the
18452 element is not found or the JSON value is not an object, end() is
18453 returned.
18454
18455 @note This method always returns @ref end() when executed on a JSON type
18456 that is not an object.
18457
18458 @param[in] key key value of the element to search for.
18459
18460 @return Iterator to an element with key equivalent to @a key. If no such
18461 element is found or the JSON value is not an object, past-the-end (see
18462 @ref end()) iterator is returned.
18463
18464 @complexity Logarithmic in the size of the JSON object.
18465
18466 @liveexample{The example shows how `find()` is used.,find__key_type}
18467
18468 @sa @ref contains(KeyT&&) const -- checks whether a key exists
18469
18470 @since version 1.0.0
18471 */
18472 template<typename KeyT>
find(KeyT && key)18473 iterator find(KeyT&& key)
18474 {
18475 auto result = end();
18476
18477 if (is_object())
18478 {
18479 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
18480 }
18481
18482 return result;
18483 }
18484
18485 /*!
18486 @brief find an element in a JSON object
18487 @copydoc find(KeyT&&)
18488 */
18489 template<typename KeyT>
find(KeyT && key) const18490 const_iterator find(KeyT&& key) const
18491 {
18492 auto result = cend();
18493
18494 if (is_object())
18495 {
18496 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
18497 }
18498
18499 return result;
18500 }
18501
18502 /*!
18503 @brief returns the number of occurrences of a key in a JSON object
18504
18505 Returns the number of elements with key @a key. If ObjectType is the
18506 default `std::map` type, the return value will always be `0` (@a key was
18507 not found) or `1` (@a key was found).
18508
18509 @note This method always returns `0` when executed on a JSON type that is
18510 not an object.
18511
18512 @param[in] key key value of the element to count
18513
18514 @return Number of elements with key @a key. If the JSON value is not an
18515 object, the return value will be `0`.
18516
18517 @complexity Logarithmic in the size of the JSON object.
18518
18519 @liveexample{The example shows how `count()` is used.,count}
18520
18521 @since version 1.0.0
18522 */
18523 template<typename KeyT>
count(KeyT && key) const18524 size_type count(KeyT&& key) const
18525 {
18526 // return 0 for all nonobject types
18527 return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
18528 }
18529
18530 /*!
18531 @brief check the existence of an element in a JSON object
18532
18533 Check whether an element exists in a JSON object with key equivalent to
18534 @a key. If the element is not found or the JSON value is not an object,
18535 false is returned.
18536
18537 @note This method always returns false when executed on a JSON type
18538 that is not an object.
18539
18540 @param[in] key key value to check its existence.
18541
18542 @return true if an element with specified @a key exists. If no such
18543 element with such key is found or the JSON value is not an object,
18544 false is returned.
18545
18546 @complexity Logarithmic in the size of the JSON object.
18547
18548 @liveexample{The following code shows an example for `contains()`.,contains}
18549
18550 @sa @ref find(KeyT&&) -- returns an iterator to an object element
18551 @sa @ref contains(const json_pointer&) const -- checks the existence for a JSON pointer
18552
18553 @since version 3.6.0
18554 */
18555 template<typename KeyT, typename std::enable_if<
18556 not std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int>::type = 0>
contains(KeyT && key) const18557 bool contains(KeyT && key) const
18558 {
18559 return is_object() and m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
18560 }
18561
18562 /*!
18563 @brief check the existence of an element in a JSON object given a JSON pointer
18564
18565 Check whether the given JSON pointer @a ptr can be resolved in the current
18566 JSON value.
18567
18568 @note This method can be executed on any JSON value type.
18569
18570 @param[in] ptr JSON pointer to check its existence.
18571
18572 @return true if the JSON pointer can be resolved to a stored value, false
18573 otherwise.
18574
18575 @post If `j.contains(ptr)` returns true, it is safe to call `j[ptr]`.
18576
18577 @throw parse_error.106 if an array index begins with '0'
18578 @throw parse_error.109 if an array index was not a number
18579
18580 @complexity Logarithmic in the size of the JSON object.
18581
18582 @liveexample{The following code shows an example for `contains()`.,contains_json_pointer}
18583
18584 @sa @ref contains(KeyT &&) const -- checks the existence of a key
18585
18586 @since version 3.7.0
18587 */
contains(const json_pointer & ptr) const18588 bool contains(const json_pointer& ptr) const
18589 {
18590 return ptr.contains(this);
18591 }
18592
18593 /// @}
18594
18595
18596 ///////////////
18597 // iterators //
18598 ///////////////
18599
18600 /// @name iterators
18601 /// @{
18602
18603 /*!
18604 @brief returns an iterator to the first element
18605
18606 Returns an iterator to the first element.
18607
18608 @image html range-begin-end.svg "Illustration from cppreference.com"
18609
18610 @return iterator to the first element
18611
18612 @complexity Constant.
18613
18614 @requirement This function helps `basic_json` satisfying the
18615 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
18616 requirements:
18617 - The complexity is constant.
18618
18619 @liveexample{The following code shows an example for `begin()`.,begin}
18620
18621 @sa @ref cbegin() -- returns a const iterator to the beginning
18622 @sa @ref end() -- returns an iterator to the end
18623 @sa @ref cend() -- returns a const iterator to the end
18624
18625 @since version 1.0.0
18626 */
begin()18627 iterator begin() noexcept
18628 {
18629 iterator result(this);
18630 result.set_begin();
18631 return result;
18632 }
18633
18634 /*!
18635 @copydoc basic_json::cbegin()
18636 */
begin() const18637 const_iterator begin() const noexcept
18638 {
18639 return cbegin();
18640 }
18641
18642 /*!
18643 @brief returns a const iterator to the first element
18644
18645 Returns a const iterator to the first element.
18646
18647 @image html range-begin-end.svg "Illustration from cppreference.com"
18648
18649 @return const iterator to the first element
18650
18651 @complexity Constant.
18652
18653 @requirement This function helps `basic_json` satisfying the
18654 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
18655 requirements:
18656 - The complexity is constant.
18657 - Has the semantics of `const_cast<const basic_json&>(*this).begin()`.
18658
18659 @liveexample{The following code shows an example for `cbegin()`.,cbegin}
18660
18661 @sa @ref begin() -- returns an iterator to the beginning
18662 @sa @ref end() -- returns an iterator to the end
18663 @sa @ref cend() -- returns a const iterator to the end
18664
18665 @since version 1.0.0
18666 */
cbegin() const18667 const_iterator cbegin() const noexcept
18668 {
18669 const_iterator result(this);
18670 result.set_begin();
18671 return result;
18672 }
18673
18674 /*!
18675 @brief returns an iterator to one past the last element
18676
18677 Returns an iterator to one past the last element.
18678
18679 @image html range-begin-end.svg "Illustration from cppreference.com"
18680
18681 @return iterator one past the last element
18682
18683 @complexity Constant.
18684
18685 @requirement This function helps `basic_json` satisfying the
18686 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
18687 requirements:
18688 - The complexity is constant.
18689
18690 @liveexample{The following code shows an example for `end()`.,end}
18691
18692 @sa @ref cend() -- returns a const iterator to the end
18693 @sa @ref begin() -- returns an iterator to the beginning
18694 @sa @ref cbegin() -- returns a const iterator to the beginning
18695
18696 @since version 1.0.0
18697 */
end()18698 iterator end() noexcept
18699 {
18700 iterator result(this);
18701 result.set_end();
18702 return result;
18703 }
18704
18705 /*!
18706 @copydoc basic_json::cend()
18707 */
end() const18708 const_iterator end() const noexcept
18709 {
18710 return cend();
18711 }
18712
18713 /*!
18714 @brief returns a const iterator to one past the last element
18715
18716 Returns a const iterator to one past the last element.
18717
18718 @image html range-begin-end.svg "Illustration from cppreference.com"
18719
18720 @return const iterator one past the last element
18721
18722 @complexity Constant.
18723
18724 @requirement This function helps `basic_json` satisfying the
18725 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
18726 requirements:
18727 - The complexity is constant.
18728 - Has the semantics of `const_cast<const basic_json&>(*this).end()`.
18729
18730 @liveexample{The following code shows an example for `cend()`.,cend}
18731
18732 @sa @ref end() -- returns an iterator to the end
18733 @sa @ref begin() -- returns an iterator to the beginning
18734 @sa @ref cbegin() -- returns a const iterator to the beginning
18735
18736 @since version 1.0.0
18737 */
cend() const18738 const_iterator cend() const noexcept
18739 {
18740 const_iterator result(this);
18741 result.set_end();
18742 return result;
18743 }
18744
18745 /*!
18746 @brief returns an iterator to the reverse-beginning
18747
18748 Returns an iterator to the reverse-beginning; that is, the last element.
18749
18750 @image html range-rbegin-rend.svg "Illustration from cppreference.com"
18751
18752 @complexity Constant.
18753
18754 @requirement This function helps `basic_json` satisfying the
18755 [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
18756 requirements:
18757 - The complexity is constant.
18758 - Has the semantics of `reverse_iterator(end())`.
18759
18760 @liveexample{The following code shows an example for `rbegin()`.,rbegin}
18761
18762 @sa @ref crbegin() -- returns a const reverse iterator to the beginning
18763 @sa @ref rend() -- returns a reverse iterator to the end
18764 @sa @ref crend() -- returns a const reverse iterator to the end
18765
18766 @since version 1.0.0
18767 */
rbegin()18768 reverse_iterator rbegin() noexcept
18769 {
18770 return reverse_iterator(end());
18771 }
18772
18773 /*!
18774 @copydoc basic_json::crbegin()
18775 */
rbegin() const18776 const_reverse_iterator rbegin() const noexcept
18777 {
18778 return crbegin();
18779 }
18780
18781 /*!
18782 @brief returns an iterator to the reverse-end
18783
18784 Returns an iterator to the reverse-end; that is, one before the first
18785 element.
18786
18787 @image html range-rbegin-rend.svg "Illustration from cppreference.com"
18788
18789 @complexity Constant.
18790
18791 @requirement This function helps `basic_json` satisfying the
18792 [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
18793 requirements:
18794 - The complexity is constant.
18795 - Has the semantics of `reverse_iterator(begin())`.
18796
18797 @liveexample{The following code shows an example for `rend()`.,rend}
18798
18799 @sa @ref crend() -- returns a const reverse iterator to the end
18800 @sa @ref rbegin() -- returns a reverse iterator to the beginning
18801 @sa @ref crbegin() -- returns a const reverse iterator to the beginning
18802
18803 @since version 1.0.0
18804 */
rend()18805 reverse_iterator rend() noexcept
18806 {
18807 return reverse_iterator(begin());
18808 }
18809
18810 /*!
18811 @copydoc basic_json::crend()
18812 */
rend() const18813 const_reverse_iterator rend() const noexcept
18814 {
18815 return crend();
18816 }
18817
18818 /*!
18819 @brief returns a const reverse iterator to the last element
18820
18821 Returns a const iterator to the reverse-beginning; that is, the last
18822 element.
18823
18824 @image html range-rbegin-rend.svg "Illustration from cppreference.com"
18825
18826 @complexity Constant.
18827
18828 @requirement This function helps `basic_json` satisfying the
18829 [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
18830 requirements:
18831 - The complexity is constant.
18832 - Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.
18833
18834 @liveexample{The following code shows an example for `crbegin()`.,crbegin}
18835
18836 @sa @ref rbegin() -- returns a reverse iterator to the beginning
18837 @sa @ref rend() -- returns a reverse iterator to the end
18838 @sa @ref crend() -- returns a const reverse iterator to the end
18839
18840 @since version 1.0.0
18841 */
crbegin() const18842 const_reverse_iterator crbegin() const noexcept
18843 {
18844 return const_reverse_iterator(cend());
18845 }
18846
18847 /*!
18848 @brief returns a const reverse iterator to one before the first
18849
18850 Returns a const reverse iterator to the reverse-end; that is, one before
18851 the first element.
18852
18853 @image html range-rbegin-rend.svg "Illustration from cppreference.com"
18854
18855 @complexity Constant.
18856
18857 @requirement This function helps `basic_json` satisfying the
18858 [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
18859 requirements:
18860 - The complexity is constant.
18861 - Has the semantics of `const_cast<const basic_json&>(*this).rend()`.
18862
18863 @liveexample{The following code shows an example for `crend()`.,crend}
18864
18865 @sa @ref rend() -- returns a reverse iterator to the end
18866 @sa @ref rbegin() -- returns a reverse iterator to the beginning
18867 @sa @ref crbegin() -- returns a const reverse iterator to the beginning
18868
18869 @since version 1.0.0
18870 */
crend() const18871 const_reverse_iterator crend() const noexcept
18872 {
18873 return const_reverse_iterator(cbegin());
18874 }
18875
18876 public:
18877 /*!
18878 @brief wrapper to access iterator member functions in range-based for
18879
18880 This function allows to access @ref iterator::key() and @ref
18881 iterator::value() during range-based for loops. In these loops, a
18882 reference to the JSON values is returned, so there is no access to the
18883 underlying iterator.
18884
18885 For loop without iterator_wrapper:
18886
18887 @code{cpp}
18888 for (auto it = j_object.begin(); it != j_object.end(); ++it)
18889 {
18890 std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
18891 }
18892 @endcode
18893
18894 Range-based for loop without iterator proxy:
18895
18896 @code{cpp}
18897 for (auto it : j_object)
18898 {
18899 // "it" is of type json::reference and has no key() member
18900 std::cout << "value: " << it << '\n';
18901 }
18902 @endcode
18903
18904 Range-based for loop with iterator proxy:
18905
18906 @code{cpp}
18907 for (auto it : json::iterator_wrapper(j_object))
18908 {
18909 std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
18910 }
18911 @endcode
18912
18913 @note When iterating over an array, `key()` will return the index of the
18914 element as string (see example).
18915
18916 @param[in] ref reference to a JSON value
18917 @return iteration proxy object wrapping @a ref with an interface to use in
18918 range-based for loops
18919
18920 @liveexample{The following code shows how the wrapper is used,iterator_wrapper}
18921
18922 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18923 changes in the JSON value.
18924
18925 @complexity Constant.
18926
18927 @note The name of this function is not yet final and may change in the
18928 future.
18929
18930 @deprecated This stream operator is deprecated and will be removed in
18931 future 4.0.0 of the library. Please use @ref items() instead;
18932 that is, replace `json::iterator_wrapper(j)` with `j.items()`.
18933 */
18934 JSON_HEDLEY_DEPRECATED(3.1.0)
iterator_wrapper(reference ref)18935 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
18936 {
18937 return ref.items();
18938 }
18939
18940 /*!
18941 @copydoc iterator_wrapper(reference)
18942 */
18943 JSON_HEDLEY_DEPRECATED(3.1.0)
iterator_wrapper(const_reference ref)18944 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
18945 {
18946 return ref.items();
18947 }
18948
18949 /*!
18950 @brief helper to access iterator member functions in range-based for
18951
18952 This function allows to access @ref iterator::key() and @ref
18953 iterator::value() during range-based for loops. In these loops, a
18954 reference to the JSON values is returned, so there is no access to the
18955 underlying iterator.
18956
18957 For loop without `items()` function:
18958
18959 @code{cpp}
18960 for (auto it = j_object.begin(); it != j_object.end(); ++it)
18961 {
18962 std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
18963 }
18964 @endcode
18965
18966 Range-based for loop without `items()` function:
18967
18968 @code{cpp}
18969 for (auto it : j_object)
18970 {
18971 // "it" is of type json::reference and has no key() member
18972 std::cout << "value: " << it << '\n';
18973 }
18974 @endcode
18975
18976 Range-based for loop with `items()` function:
18977
18978 @code{cpp}
18979 for (auto& el : j_object.items())
18980 {
18981 std::cout << "key: " << el.key() << ", value:" << el.value() << '\n';
18982 }
18983 @endcode
18984
18985 The `items()` function also allows to use
18986 [structured bindings](https://en.cppreference.com/w/cpp/language/structured_binding)
18987 (C++17):
18988
18989 @code{cpp}
18990 for (auto& [key, val] : j_object.items())
18991 {
18992 std::cout << "key: " << key << ", value:" << val << '\n';
18993 }
18994 @endcode
18995
18996 @note When iterating over an array, `key()` will return the index of the
18997 element as string (see example). For primitive types (e.g., numbers),
18998 `key()` returns an empty string.
18999
19000 @return iteration proxy object wrapping @a ref with an interface to use in
19001 range-based for loops
19002
19003 @liveexample{The following code shows how the function is used.,items}
19004
19005 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
19006 changes in the JSON value.
19007
19008 @complexity Constant.
19009
19010 @since version 3.1.0, structured bindings support since 3.5.0.
19011 */
items()19012 iteration_proxy<iterator> items() noexcept
19013 {
19014 return iteration_proxy<iterator>(*this);
19015 }
19016
19017 /*!
19018 @copydoc items()
19019 */
items() const19020 iteration_proxy<const_iterator> items() const noexcept
19021 {
19022 return iteration_proxy<const_iterator>(*this);
19023 }
19024
19025 /// @}
19026
19027
19028 //////////////
19029 // capacity //
19030 //////////////
19031
19032 /// @name capacity
19033 /// @{
19034
19035 /*!
19036 @brief checks whether the container is empty.
19037
19038 Checks if a JSON value has no elements (i.e. whether its @ref size is `0`).
19039
19040 @return The return value depends on the different types and is
19041 defined as follows:
19042 Value type | return value
19043 ----------- | -------------
19044 null | `true`
19045 boolean | `false`
19046 string | `false`
19047 number | `false`
19048 object | result of function `object_t::empty()`
19049 array | result of function `array_t::empty()`
19050
19051 @liveexample{The following code uses `empty()` to check if a JSON
19052 object contains any elements.,empty}
19053
19054 @complexity Constant, as long as @ref array_t and @ref object_t satisfy
19055 the Container concept; that is, their `empty()` functions have constant
19056 complexity.
19057
19058 @iterators No changes.
19059
19060 @exceptionsafety No-throw guarantee: this function never throws exceptions.
19061
19062 @note This function does not return whether a string stored as JSON value
19063 is empty - it returns whether the JSON container itself is empty which is
19064 false in the case of a string.
19065
19066 @requirement This function helps `basic_json` satisfying the
19067 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
19068 requirements:
19069 - The complexity is constant.
19070 - Has the semantics of `begin() == end()`.
19071
19072 @sa @ref size() -- returns the number of elements
19073
19074 @since version 1.0.0
19075 */
empty() const19076 bool empty() const noexcept
19077 {
19078 switch (m_type)
19079 {
19080 case value_t::null:
19081 {
19082 // null values are empty
19083 return true;
19084 }
19085
19086 case value_t::array:
19087 {
19088 // delegate call to array_t::empty()
19089 return m_value.array->empty();
19090 }
19091
19092 case value_t::object:
19093 {
19094 // delegate call to object_t::empty()
19095 return m_value.object->empty();
19096 }
19097
19098 default:
19099 {
19100 // all other types are nonempty
19101 return false;
19102 }
19103 }
19104 }
19105
19106 /*!
19107 @brief returns the number of elements
19108
19109 Returns the number of elements in a JSON value.
19110
19111 @return The return value depends on the different types and is
19112 defined as follows:
19113 Value type | return value
19114 ----------- | -------------
19115 null | `0`
19116 boolean | `1`
19117 string | `1`
19118 number | `1`
19119 object | result of function object_t::size()
19120 array | result of function array_t::size()
19121
19122 @liveexample{The following code calls `size()` on the different value
19123 types.,size}
19124
19125 @complexity Constant, as long as @ref array_t and @ref object_t satisfy
19126 the Container concept; that is, their size() functions have constant
19127 complexity.
19128
19129 @iterators No changes.
19130
19131 @exceptionsafety No-throw guarantee: this function never throws exceptions.
19132
19133 @note This function does not return the length of a string stored as JSON
19134 value - it returns the number of elements in the JSON value which is 1 in
19135 the case of a string.
19136
19137 @requirement This function helps `basic_json` satisfying the
19138 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
19139 requirements:
19140 - The complexity is constant.
19141 - Has the semantics of `std::distance(begin(), end())`.
19142
19143 @sa @ref empty() -- checks whether the container is empty
19144 @sa @ref max_size() -- returns the maximal number of elements
19145
19146 @since version 1.0.0
19147 */
size() const19148 size_type size() const noexcept
19149 {
19150 switch (m_type)
19151 {
19152 case value_t::null:
19153 {
19154 // null values are empty
19155 return 0;
19156 }
19157
19158 case value_t::array:
19159 {
19160 // delegate call to array_t::size()
19161 return m_value.array->size();
19162 }
19163
19164 case value_t::object:
19165 {
19166 // delegate call to object_t::size()
19167 return m_value.object->size();
19168 }
19169
19170 default:
19171 {
19172 // all other types have size 1
19173 return 1;
19174 }
19175 }
19176 }
19177
19178 /*!
19179 @brief returns the maximum possible number of elements
19180
19181 Returns the maximum number of elements a JSON value is able to hold due to
19182 system or library implementation limitations, i.e. `std::distance(begin(),
19183 end())` for the JSON value.
19184
19185 @return The return value depends on the different types and is
19186 defined as follows:
19187 Value type | return value
19188 ----------- | -------------
19189 null | `0` (same as `size()`)
19190 boolean | `1` (same as `size()`)
19191 string | `1` (same as `size()`)
19192 number | `1` (same as `size()`)
19193 object | result of function `object_t::max_size()`
19194 array | result of function `array_t::max_size()`
19195
19196 @liveexample{The following code calls `max_size()` on the different value
19197 types. Note the output is implementation specific.,max_size}
19198
19199 @complexity Constant, as long as @ref array_t and @ref object_t satisfy
19200 the Container concept; that is, their `max_size()` functions have constant
19201 complexity.
19202
19203 @iterators No changes.
19204
19205 @exceptionsafety No-throw guarantee: this function never throws exceptions.
19206
19207 @requirement This function helps `basic_json` satisfying the
19208 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
19209 requirements:
19210 - The complexity is constant.
19211 - Has the semantics of returning `b.size()` where `b` is the largest
19212 possible JSON value.
19213
19214 @sa @ref size() -- returns the number of elements
19215
19216 @since version 1.0.0
19217 */
max_size() const19218 size_type max_size() const noexcept
19219 {
19220 switch (m_type)
19221 {
19222 case value_t::array:
19223 {
19224 // delegate call to array_t::max_size()
19225 return m_value.array->max_size();
19226 }
19227
19228 case value_t::object:
19229 {
19230 // delegate call to object_t::max_size()
19231 return m_value.object->max_size();
19232 }
19233
19234 default:
19235 {
19236 // all other types have max_size() == size()
19237 return size();
19238 }
19239 }
19240 }
19241
19242 /// @}
19243
19244
19245 ///////////////
19246 // modifiers //
19247 ///////////////
19248
19249 /// @name modifiers
19250 /// @{
19251
19252 /*!
19253 @brief clears the contents
19254
19255 Clears the content of a JSON value and resets it to the default value as
19256 if @ref basic_json(value_t) would have been called with the current value
19257 type from @ref type():
19258
19259 Value type | initial value
19260 ----------- | -------------
19261 null | `null`
19262 boolean | `false`
19263 string | `""`
19264 number | `0`
19265 object | `{}`
19266 array | `[]`
19267
19268 @post Has the same effect as calling
19269 @code {.cpp}
19270 *this = basic_json(type());
19271 @endcode
19272
19273 @liveexample{The example below shows the effect of `clear()` to different
19274 JSON types.,clear}
19275
19276 @complexity Linear in the size of the JSON value.
19277
19278 @iterators All iterators, pointers and references related to this container
19279 are invalidated.
19280
19281 @exceptionsafety No-throw guarantee: this function never throws exceptions.
19282
19283 @sa @ref basic_json(value_t) -- constructor that creates an object with the
19284 same value than calling `clear()`
19285
19286 @since version 1.0.0
19287 */
clear()19288 void clear() noexcept
19289 {
19290 switch (m_type)
19291 {
19292 case value_t::number_integer:
19293 {
19294 m_value.number_integer = 0;
19295 break;
19296 }
19297
19298 case value_t::number_unsigned:
19299 {
19300 m_value.number_unsigned = 0;
19301 break;
19302 }
19303
19304 case value_t::number_float:
19305 {
19306 m_value.number_float = 0.0;
19307 break;
19308 }
19309
19310 case value_t::boolean:
19311 {
19312 m_value.boolean = false;
19313 break;
19314 }
19315
19316 case value_t::string:
19317 {
19318 m_value.string->clear();
19319 break;
19320 }
19321
19322 case value_t::array:
19323 {
19324 m_value.array->clear();
19325 break;
19326 }
19327
19328 case value_t::object:
19329 {
19330 m_value.object->clear();
19331 break;
19332 }
19333
19334 default:
19335 break;
19336 }
19337 }
19338
19339 /*!
19340 @brief add an object to an array
19341
19342 Appends the given element @a val to the end of the JSON value. If the
19343 function is called on a JSON null value, an empty array is created before
19344 appending @a val.
19345
19346 @param[in] val the value to add to the JSON array
19347
19348 @throw type_error.308 when called on a type other than JSON array or
19349 null; example: `"cannot use push_back() with number"`
19350
19351 @complexity Amortized constant.
19352
19353 @liveexample{The example shows how `push_back()` and `+=` can be used to
19354 add elements to a JSON array. Note how the `null` value was silently
19355 converted to a JSON array.,push_back}
19356
19357 @since version 1.0.0
19358 */
push_back(basic_json && val)19359 void push_back(basic_json&& val)
19360 {
19361 // push_back only works for null objects or arrays
19362 if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_array())))
19363 {
19364 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
19365 }
19366
19367 // transform null object into an array
19368 if (is_null())
19369 {
19370 m_type = value_t::array;
19371 m_value = value_t::array;
19372 assert_invariant();
19373 }
19374
19375 // add element to array (move semantics)
19376 m_value.array->push_back(std::move(val));
19377 // invalidate object: mark it null so we do not call the destructor
19378 // cppcheck-suppress accessMoved
19379 val.m_type = value_t::null;
19380 }
19381
19382 /*!
19383 @brief add an object to an array
19384 @copydoc push_back(basic_json&&)
19385 */
operator +=(basic_json && val)19386 reference operator+=(basic_json&& val)
19387 {
19388 push_back(std::move(val));
19389 return *this;
19390 }
19391
19392 /*!
19393 @brief add an object to an array
19394 @copydoc push_back(basic_json&&)
19395 */
push_back(const basic_json & val)19396 void push_back(const basic_json& val)
19397 {
19398 // push_back only works for null objects or arrays
19399 if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_array())))
19400 {
19401 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
19402 }
19403
19404 // transform null object into an array
19405 if (is_null())
19406 {
19407 m_type = value_t::array;
19408 m_value = value_t::array;
19409 assert_invariant();
19410 }
19411
19412 // add element to array
19413 m_value.array->push_back(val);
19414 }
19415
19416 /*!
19417 @brief add an object to an array
19418 @copydoc push_back(basic_json&&)
19419 */
operator +=(const basic_json & val)19420 reference operator+=(const basic_json& val)
19421 {
19422 push_back(val);
19423 return *this;
19424 }
19425
19426 /*!
19427 @brief add an object to an object
19428
19429 Inserts the given element @a val to the JSON object. If the function is
19430 called on a JSON null value, an empty object is created before inserting
19431 @a val.
19432
19433 @param[in] val the value to add to the JSON object
19434
19435 @throw type_error.308 when called on a type other than JSON object or
19436 null; example: `"cannot use push_back() with number"`
19437
19438 @complexity Logarithmic in the size of the container, O(log(`size()`)).
19439
19440 @liveexample{The example shows how `push_back()` and `+=` can be used to
19441 add elements to a JSON object. Note how the `null` value was silently
19442 converted to a JSON object.,push_back__object_t__value}
19443
19444 @since version 1.0.0
19445 */
push_back(const typename object_t::value_type & val)19446 void push_back(const typename object_t::value_type& val)
19447 {
19448 // push_back only works for null objects or objects
19449 if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_object())))
19450 {
19451 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
19452 }
19453
19454 // transform null object into an object
19455 if (is_null())
19456 {
19457 m_type = value_t::object;
19458 m_value = value_t::object;
19459 assert_invariant();
19460 }
19461
19462 // add element to array
19463 m_value.object->insert(val);
19464 }
19465
19466 /*!
19467 @brief add an object to an object
19468 @copydoc push_back(const typename object_t::value_type&)
19469 */
operator +=(const typename object_t::value_type & val)19470 reference operator+=(const typename object_t::value_type& val)
19471 {
19472 push_back(val);
19473 return *this;
19474 }
19475
19476 /*!
19477 @brief add an object to an object
19478
19479 This function allows to use `push_back` with an initializer list. In case
19480
19481 1. the current value is an object,
19482 2. the initializer list @a init contains only two elements, and
19483 3. the first element of @a init is a string,
19484
19485 @a init is converted into an object element and added using
19486 @ref push_back(const typename object_t::value_type&). Otherwise, @a init
19487 is converted to a JSON value and added using @ref push_back(basic_json&&).
19488
19489 @param[in] init an initializer list
19490
19491 @complexity Linear in the size of the initializer list @a init.
19492
19493 @note This function is required to resolve an ambiguous overload error,
19494 because pairs like `{"key", "value"}` can be both interpreted as
19495 `object_t::value_type` or `std::initializer_list<basic_json>`, see
19496 https://github.com/nlohmann/json/issues/235 for more information.
19497
19498 @liveexample{The example shows how initializer lists are treated as
19499 objects when possible.,push_back__initializer_list}
19500 */
push_back(initializer_list_t init)19501 void push_back(initializer_list_t init)
19502 {
19503 if (is_object() and init.size() == 2 and (*init.begin())->is_string())
19504 {
19505 basic_json&& key = init.begin()->moved_or_copied();
19506 push_back(typename object_t::value_type(
19507 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
19508 }
19509 else
19510 {
19511 push_back(basic_json(init));
19512 }
19513 }
19514
19515 /*!
19516 @brief add an object to an object
19517 @copydoc push_back(initializer_list_t)
19518 */
operator +=(initializer_list_t init)19519 reference operator+=(initializer_list_t init)
19520 {
19521 push_back(init);
19522 return *this;
19523 }
19524
19525 /*!
19526 @brief add an object to an array
19527
19528 Creates a JSON value from the passed parameters @a args to the end of the
19529 JSON value. If the function is called on a JSON null value, an empty array
19530 is created before appending the value created from @a args.
19531
19532 @param[in] args arguments to forward to a constructor of @ref basic_json
19533 @tparam Args compatible types to create a @ref basic_json object
19534
19535 @return reference to the inserted element
19536
19537 @throw type_error.311 when called on a type other than JSON array or
19538 null; example: `"cannot use emplace_back() with number"`
19539
19540 @complexity Amortized constant.
19541
19542 @liveexample{The example shows how `push_back()` can be used to add
19543 elements to a JSON array. Note how the `null` value was silently converted
19544 to a JSON array.,emplace_back}
19545
19546 @since version 2.0.8, returns reference since 3.7.0
19547 */
19548 template<class... Args>
emplace_back(Args &&...args)19549 reference emplace_back(Args&& ... args)
19550 {
19551 // emplace_back only works for null objects or arrays
19552 if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_array())))
19553 {
19554 JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
19555 }
19556
19557 // transform null object into an array
19558 if (is_null())
19559 {
19560 m_type = value_t::array;
19561 m_value = value_t::array;
19562 assert_invariant();
19563 }
19564
19565 // add element to array (perfect forwarding)
19566 #ifdef JSON_HAS_CPP_17
19567 return m_value.array->emplace_back(std::forward<Args>(args)...);
19568 #else
19569 m_value.array->emplace_back(std::forward<Args>(args)...);
19570 return m_value.array->back();
19571 #endif
19572 }
19573
19574 /*!
19575 @brief add an object to an object if key does not exist
19576
19577 Inserts a new element into a JSON object constructed in-place with the
19578 given @a args if there is no element with the key in the container. If the
19579 function is called on a JSON null value, an empty object is created before
19580 appending the value created from @a args.
19581
19582 @param[in] args arguments to forward to a constructor of @ref basic_json
19583 @tparam Args compatible types to create a @ref basic_json object
19584
19585 @return a pair consisting of an iterator to the inserted element, or the
19586 already-existing element if no insertion happened, and a bool
19587 denoting whether the insertion took place.
19588
19589 @throw type_error.311 when called on a type other than JSON object or
19590 null; example: `"cannot use emplace() with number"`
19591
19592 @complexity Logarithmic in the size of the container, O(log(`size()`)).
19593
19594 @liveexample{The example shows how `emplace()` can be used to add elements
19595 to a JSON object. Note how the `null` value was silently converted to a
19596 JSON object. Further note how no value is added if there was already one
19597 value stored with the same key.,emplace}
19598
19599 @since version 2.0.8
19600 */
19601 template<class... Args>
emplace(Args &&...args)19602 std::pair<iterator, bool> emplace(Args&& ... args)
19603 {
19604 // emplace only works for null objects or arrays
19605 if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_object())))
19606 {
19607 JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
19608 }
19609
19610 // transform null object into an object
19611 if (is_null())
19612 {
19613 m_type = value_t::object;
19614 m_value = value_t::object;
19615 assert_invariant();
19616 }
19617
19618 // add element to array (perfect forwarding)
19619 auto res = m_value.object->emplace(std::forward<Args>(args)...);
19620 // create result iterator and set iterator to the result of emplace
19621 auto it = begin();
19622 it.m_it.object_iterator = res.first;
19623
19624 // return pair of iterator and boolean
19625 return {it, res.second};
19626 }
19627
19628 /// Helper for insertion of an iterator
19629 /// @note: This uses std::distance to support GCC 4.8,
19630 /// see https://github.com/nlohmann/json/pull/1257
19631 template<typename... Args>
insert_iterator(const_iterator pos,Args &&...args)19632 iterator insert_iterator(const_iterator pos, Args&& ... args)
19633 {
19634 iterator result(this);
19635 assert(m_value.array != nullptr);
19636
19637 auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
19638 m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
19639 result.m_it.array_iterator = m_value.array->begin() + insert_pos;
19640
19641 // This could have been written as:
19642 // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
19643 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
19644
19645 return result;
19646 }
19647
19648 /*!
19649 @brief inserts element
19650
19651 Inserts element @a val before iterator @a pos.
19652
19653 @param[in] pos iterator before which the content will be inserted; may be
19654 the end() iterator
19655 @param[in] val element to insert
19656 @return iterator pointing to the inserted @a val.
19657
19658 @throw type_error.309 if called on JSON values other than arrays;
19659 example: `"cannot use insert() with string"`
19660 @throw invalid_iterator.202 if @a pos is not an iterator of *this;
19661 example: `"iterator does not fit current value"`
19662
19663 @complexity Constant plus linear in the distance between @a pos and end of
19664 the container.
19665
19666 @liveexample{The example shows how `insert()` is used.,insert}
19667
19668 @since version 1.0.0
19669 */
insert(const_iterator pos,const basic_json & val)19670 iterator insert(const_iterator pos, const basic_json& val)
19671 {
19672 // insert only works for arrays
19673 if (JSON_HEDLEY_LIKELY(is_array()))
19674 {
19675 // check if iterator pos fits to this JSON value
19676 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
19677 {
19678 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
19679 }
19680
19681 // insert to array and return iterator
19682 return insert_iterator(pos, val);
19683 }
19684
19685 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
19686 }
19687
19688 /*!
19689 @brief inserts element
19690 @copydoc insert(const_iterator, const basic_json&)
19691 */
insert(const_iterator pos,basic_json && val)19692 iterator insert(const_iterator pos, basic_json&& val)
19693 {
19694 return insert(pos, val);
19695 }
19696
19697 /*!
19698 @brief inserts elements
19699
19700 Inserts @a cnt copies of @a val before iterator @a pos.
19701
19702 @param[in] pos iterator before which the content will be inserted; may be
19703 the end() iterator
19704 @param[in] cnt number of copies of @a val to insert
19705 @param[in] val element to insert
19706 @return iterator pointing to the first element inserted, or @a pos if
19707 `cnt==0`
19708
19709 @throw type_error.309 if called on JSON values other than arrays; example:
19710 `"cannot use insert() with string"`
19711 @throw invalid_iterator.202 if @a pos is not an iterator of *this;
19712 example: `"iterator does not fit current value"`
19713
19714 @complexity Linear in @a cnt plus linear in the distance between @a pos
19715 and end of the container.
19716
19717 @liveexample{The example shows how `insert()` is used.,insert__count}
19718
19719 @since version 1.0.0
19720 */
insert(const_iterator pos,size_type cnt,const basic_json & val)19721 iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
19722 {
19723 // insert only works for arrays
19724 if (JSON_HEDLEY_LIKELY(is_array()))
19725 {
19726 // check if iterator pos fits to this JSON value
19727 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
19728 {
19729 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
19730 }
19731
19732 // insert to array and return iterator
19733 return insert_iterator(pos, cnt, val);
19734 }
19735
19736 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
19737 }
19738
19739 /*!
19740 @brief inserts elements
19741
19742 Inserts elements from range `[first, last)` before iterator @a pos.
19743
19744 @param[in] pos iterator before which the content will be inserted; may be
19745 the end() iterator
19746 @param[in] first begin of the range of elements to insert
19747 @param[in] last end of the range of elements to insert
19748
19749 @throw type_error.309 if called on JSON values other than arrays; example:
19750 `"cannot use insert() with string"`
19751 @throw invalid_iterator.202 if @a pos is not an iterator of *this;
19752 example: `"iterator does not fit current value"`
19753 @throw invalid_iterator.210 if @a first and @a last do not belong to the
19754 same JSON value; example: `"iterators do not fit"`
19755 @throw invalid_iterator.211 if @a first or @a last are iterators into
19756 container for which insert is called; example: `"passed iterators may not
19757 belong to container"`
19758
19759 @return iterator pointing to the first element inserted, or @a pos if
19760 `first==last`
19761
19762 @complexity Linear in `std::distance(first, last)` plus linear in the
19763 distance between @a pos and end of the container.
19764
19765 @liveexample{The example shows how `insert()` is used.,insert__range}
19766
19767 @since version 1.0.0
19768 */
insert(const_iterator pos,const_iterator first,const_iterator last)19769 iterator insert(const_iterator pos, const_iterator first, const_iterator last)
19770 {
19771 // insert only works for arrays
19772 if (JSON_HEDLEY_UNLIKELY(not is_array()))
19773 {
19774 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
19775 }
19776
19777 // check if iterator pos fits to this JSON value
19778 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
19779 {
19780 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
19781 }
19782
19783 // check if range iterators belong to the same JSON object
19784 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
19785 {
19786 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
19787 }
19788
19789 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
19790 {
19791 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
19792 }
19793
19794 // insert to array and return iterator
19795 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
19796 }
19797
19798 /*!
19799 @brief inserts elements
19800
19801 Inserts elements from initializer list @a ilist before iterator @a pos.
19802
19803 @param[in] pos iterator before which the content will be inserted; may be
19804 the end() iterator
19805 @param[in] ilist initializer list to insert the values from
19806
19807 @throw type_error.309 if called on JSON values other than arrays; example:
19808 `"cannot use insert() with string"`
19809 @throw invalid_iterator.202 if @a pos is not an iterator of *this;
19810 example: `"iterator does not fit current value"`
19811
19812 @return iterator pointing to the first element inserted, or @a pos if
19813 `ilist` is empty
19814
19815 @complexity Linear in `ilist.size()` plus linear in the distance between
19816 @a pos and end of the container.
19817
19818 @liveexample{The example shows how `insert()` is used.,insert__ilist}
19819
19820 @since version 1.0.0
19821 */
insert(const_iterator pos,initializer_list_t ilist)19822 iterator insert(const_iterator pos, initializer_list_t ilist)
19823 {
19824 // insert only works for arrays
19825 if (JSON_HEDLEY_UNLIKELY(not is_array()))
19826 {
19827 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
19828 }
19829
19830 // check if iterator pos fits to this JSON value
19831 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
19832 {
19833 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
19834 }
19835
19836 // insert to array and return iterator
19837 return insert_iterator(pos, ilist.begin(), ilist.end());
19838 }
19839
19840 /*!
19841 @brief inserts elements
19842
19843 Inserts elements from range `[first, last)`.
19844
19845 @param[in] first begin of the range of elements to insert
19846 @param[in] last end of the range of elements to insert
19847
19848 @throw type_error.309 if called on JSON values other than objects; example:
19849 `"cannot use insert() with string"`
19850 @throw invalid_iterator.202 if iterator @a first or @a last does does not
19851 point to an object; example: `"iterators first and last must point to
19852 objects"`
19853 @throw invalid_iterator.210 if @a first and @a last do not belong to the
19854 same JSON value; example: `"iterators do not fit"`
19855
19856 @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number
19857 of elements to insert.
19858
19859 @liveexample{The example shows how `insert()` is used.,insert__range_object}
19860
19861 @since version 3.0.0
19862 */
insert(const_iterator first,const_iterator last)19863 void insert(const_iterator first, const_iterator last)
19864 {
19865 // insert only works for objects
19866 if (JSON_HEDLEY_UNLIKELY(not is_object()))
19867 {
19868 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
19869 }
19870
19871 // check if range iterators belong to the same JSON object
19872 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
19873 {
19874 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
19875 }
19876
19877 // passed iterators must belong to objects
19878 if (JSON_HEDLEY_UNLIKELY(not first.m_object->is_object()))
19879 {
19880 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
19881 }
19882
19883 m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
19884 }
19885
19886 /*!
19887 @brief updates a JSON object from another object, overwriting existing keys
19888
19889 Inserts all values from JSON object @a j and overwrites existing keys.
19890
19891 @param[in] j JSON object to read values from
19892
19893 @throw type_error.312 if called on JSON values other than objects; example:
19894 `"cannot use update() with string"`
19895
19896 @complexity O(N*log(size() + N)), where N is the number of elements to
19897 insert.
19898
19899 @liveexample{The example shows how `update()` is used.,update}
19900
19901 @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
19902
19903 @since version 3.0.0
19904 */
update(const_reference j)19905 void update(const_reference j)
19906 {
19907 // implicitly convert null value to an empty object
19908 if (is_null())
19909 {
19910 m_type = value_t::object;
19911 m_value.object = create<object_t>();
19912 assert_invariant();
19913 }
19914
19915 if (JSON_HEDLEY_UNLIKELY(not is_object()))
19916 {
19917 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
19918 }
19919 if (JSON_HEDLEY_UNLIKELY(not j.is_object()))
19920 {
19921 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name())));
19922 }
19923
19924 for (auto it = j.cbegin(); it != j.cend(); ++it)
19925 {
19926 m_value.object->operator[](it.key()) = it.value();
19927 }
19928 }
19929
19930 /*!
19931 @brief updates a JSON object from another object, overwriting existing keys
19932
19933 Inserts all values from from range `[first, last)` and overwrites existing
19934 keys.
19935
19936 @param[in] first begin of the range of elements to insert
19937 @param[in] last end of the range of elements to insert
19938
19939 @throw type_error.312 if called on JSON values other than objects; example:
19940 `"cannot use update() with string"`
19941 @throw invalid_iterator.202 if iterator @a first or @a last does does not
19942 point to an object; example: `"iterators first and last must point to
19943 objects"`
19944 @throw invalid_iterator.210 if @a first and @a last do not belong to the
19945 same JSON value; example: `"iterators do not fit"`
19946
19947 @complexity O(N*log(size() + N)), where N is the number of elements to
19948 insert.
19949
19950 @liveexample{The example shows how `update()` is used__range.,update}
19951
19952 @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
19953
19954 @since version 3.0.0
19955 */
update(const_iterator first,const_iterator last)19956 void update(const_iterator first, const_iterator last)
19957 {
19958 // implicitly convert null value to an empty object
19959 if (is_null())
19960 {
19961 m_type = value_t::object;
19962 m_value.object = create<object_t>();
19963 assert_invariant();
19964 }
19965
19966 if (JSON_HEDLEY_UNLIKELY(not is_object()))
19967 {
19968 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
19969 }
19970
19971 // check if range iterators belong to the same JSON object
19972 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
19973 {
19974 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
19975 }
19976
19977 // passed iterators must belong to objects
19978 if (JSON_HEDLEY_UNLIKELY(not first.m_object->is_object()
19979 or not last.m_object->is_object()))
19980 {
19981 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
19982 }
19983
19984 for (auto it = first; it != last; ++it)
19985 {
19986 m_value.object->operator[](it.key()) = it.value();
19987 }
19988 }
19989
19990 /*!
19991 @brief exchanges the values
19992
19993 Exchanges the contents of the JSON value with those of @a other. Does not
19994 invoke any move, copy, or swap operations on individual elements. All
19995 iterators and references remain valid. The past-the-end iterator is
19996 invalidated.
19997
19998 @param[in,out] other JSON value to exchange the contents with
19999
20000 @complexity Constant.
20001
20002 @liveexample{The example below shows how JSON values can be swapped with
20003 `swap()`.,swap__reference}
20004
20005 @since version 1.0.0
20006 */
swap(reference other)20007 void swap(reference other) noexcept (
20008 std::is_nothrow_move_constructible<value_t>::value and
20009 std::is_nothrow_move_assignable<value_t>::value and
20010 std::is_nothrow_move_constructible<json_value>::value and
20011 std::is_nothrow_move_assignable<json_value>::value
20012 )
20013 {
20014 std::swap(m_type, other.m_type);
20015 std::swap(m_value, other.m_value);
20016 assert_invariant();
20017 }
20018
20019 /*!
20020 @brief exchanges the values
20021
20022 Exchanges the contents of a JSON array with those of @a other. Does not
20023 invoke any move, copy, or swap operations on individual elements. All
20024 iterators and references remain valid. The past-the-end iterator is
20025 invalidated.
20026
20027 @param[in,out] other array to exchange the contents with
20028
20029 @throw type_error.310 when JSON value is not an array; example: `"cannot
20030 use swap() with string"`
20031
20032 @complexity Constant.
20033
20034 @liveexample{The example below shows how arrays can be swapped with
20035 `swap()`.,swap__array_t}
20036
20037 @since version 1.0.0
20038 */
swap(array_t & other)20039 void swap(array_t& other)
20040 {
20041 // swap only works for arrays
20042 if (JSON_HEDLEY_LIKELY(is_array()))
20043 {
20044 std::swap(*(m_value.array), other);
20045 }
20046 else
20047 {
20048 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
20049 }
20050 }
20051
20052 /*!
20053 @brief exchanges the values
20054
20055 Exchanges the contents of a JSON object with those of @a other. Does not
20056 invoke any move, copy, or swap operations on individual elements. All
20057 iterators and references remain valid. The past-the-end iterator is
20058 invalidated.
20059
20060 @param[in,out] other object to exchange the contents with
20061
20062 @throw type_error.310 when JSON value is not an object; example:
20063 `"cannot use swap() with string"`
20064
20065 @complexity Constant.
20066
20067 @liveexample{The example below shows how objects can be swapped with
20068 `swap()`.,swap__object_t}
20069
20070 @since version 1.0.0
20071 */
swap(object_t & other)20072 void swap(object_t& other)
20073 {
20074 // swap only works for objects
20075 if (JSON_HEDLEY_LIKELY(is_object()))
20076 {
20077 std::swap(*(m_value.object), other);
20078 }
20079 else
20080 {
20081 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
20082 }
20083 }
20084
20085 /*!
20086 @brief exchanges the values
20087
20088 Exchanges the contents of a JSON string with those of @a other. Does not
20089 invoke any move, copy, or swap operations on individual elements. All
20090 iterators and references remain valid. The past-the-end iterator is
20091 invalidated.
20092
20093 @param[in,out] other string to exchange the contents with
20094
20095 @throw type_error.310 when JSON value is not a string; example: `"cannot
20096 use swap() with boolean"`
20097
20098 @complexity Constant.
20099
20100 @liveexample{The example below shows how strings can be swapped with
20101 `swap()`.,swap__string_t}
20102
20103 @since version 1.0.0
20104 */
swap(string_t & other)20105 void swap(string_t& other)
20106 {
20107 // swap only works for strings
20108 if (JSON_HEDLEY_LIKELY(is_string()))
20109 {
20110 std::swap(*(m_value.string), other);
20111 }
20112 else
20113 {
20114 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
20115 }
20116 }
20117
20118 /// @}
20119
20120 public:
20121 //////////////////////////////////////////
20122 // lexicographical comparison operators //
20123 //////////////////////////////////////////
20124
20125 /// @name lexicographical comparison operators
20126 /// @{
20127
20128 /*!
20129 @brief comparison: equal
20130
20131 Compares two JSON values for equality according to the following rules:
20132 - Two JSON values are equal if (1) they are from the same type and (2)
20133 their stored values are the same according to their respective
20134 `operator==`.
20135 - Integer and floating-point numbers are automatically converted before
20136 comparison. Note than two NaN values are always treated as unequal.
20137 - Two JSON null values are equal.
20138
20139 @note Floating-point inside JSON values numbers are compared with
20140 `json::number_float_t::operator==` which is `double::operator==` by
20141 default. To compare floating-point while respecting an epsilon, an alternative
20142 [comparison function](https://github.com/mariokonrad/marnav/blob/master/src/marnav/math/floatingpoint.hpp#L34-#L39)
20143 could be used, for instance
20144 @code {.cpp}
20145 template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>
20146 inline bool is_same(T a, T b, T epsilon = std::numeric_limits<T>::epsilon()) noexcept
20147 {
20148 return std::abs(a - b) <= epsilon;
20149 }
20150 @endcode
20151
20152 @note NaN values never compare equal to themselves or to other NaN values.
20153
20154 @param[in] lhs first JSON value to consider
20155 @param[in] rhs second JSON value to consider
20156 @return whether the values @a lhs and @a rhs are equal
20157
20158 @exceptionsafety No-throw guarantee: this function never throws exceptions.
20159
20160 @complexity Linear.
20161
20162 @liveexample{The example demonstrates comparing several JSON
20163 types.,operator__equal}
20164
20165 @since version 1.0.0
20166 */
operator ==(const_reference lhs,const_reference rhs)20167 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
20168 {
20169 const auto lhs_type = lhs.type();
20170 const auto rhs_type = rhs.type();
20171
20172 if (lhs_type == rhs_type)
20173 {
20174 switch (lhs_type)
20175 {
20176 case value_t::array:
20177 return *lhs.m_value.array == *rhs.m_value.array;
20178
20179 case value_t::object:
20180 return *lhs.m_value.object == *rhs.m_value.object;
20181
20182 case value_t::null:
20183 return true;
20184
20185 case value_t::string:
20186 return *lhs.m_value.string == *rhs.m_value.string;
20187
20188 case value_t::boolean:
20189 return lhs.m_value.boolean == rhs.m_value.boolean;
20190
20191 case value_t::number_integer:
20192 return lhs.m_value.number_integer == rhs.m_value.number_integer;
20193
20194 case value_t::number_unsigned:
20195 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
20196
20197 case value_t::number_float:
20198 return lhs.m_value.number_float == rhs.m_value.number_float;
20199
20200 default:
20201 return false;
20202 }
20203 }
20204 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
20205 {
20206 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
20207 }
20208 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
20209 {
20210 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
20211 }
20212 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
20213 {
20214 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
20215 }
20216 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
20217 {
20218 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
20219 }
20220 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
20221 {
20222 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
20223 }
20224 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
20225 {
20226 return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
20227 }
20228
20229 return false;
20230 }
20231
20232 /*!
20233 @brief comparison: equal
20234 @copydoc operator==(const_reference, const_reference)
20235 */
20236 template<typename ScalarType, typename std::enable_if<
20237 std::is_scalar<ScalarType>::value, int>::type = 0>
operator ==(const_reference lhs,const ScalarType rhs)20238 friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
20239 {
20240 return lhs == basic_json(rhs);
20241 }
20242
20243 /*!
20244 @brief comparison: equal
20245 @copydoc operator==(const_reference, const_reference)
20246 */
20247 template<typename ScalarType, typename std::enable_if<
20248 std::is_scalar<ScalarType>::value, int>::type = 0>
operator ==(const ScalarType lhs,const_reference rhs)20249 friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
20250 {
20251 return basic_json(lhs) == rhs;
20252 }
20253
20254 /*!
20255 @brief comparison: not equal
20256
20257 Compares two JSON values for inequality by calculating `not (lhs == rhs)`.
20258
20259 @param[in] lhs first JSON value to consider
20260 @param[in] rhs second JSON value to consider
20261 @return whether the values @a lhs and @a rhs are not equal
20262
20263 @complexity Linear.
20264
20265 @exceptionsafety No-throw guarantee: this function never throws exceptions.
20266
20267 @liveexample{The example demonstrates comparing several JSON
20268 types.,operator__notequal}
20269
20270 @since version 1.0.0
20271 */
operator !=(const_reference lhs,const_reference rhs)20272 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
20273 {
20274 return not (lhs == rhs);
20275 }
20276
20277 /*!
20278 @brief comparison: not equal
20279 @copydoc operator!=(const_reference, const_reference)
20280 */
20281 template<typename ScalarType, typename std::enable_if<
20282 std::is_scalar<ScalarType>::value, int>::type = 0>
operator !=(const_reference lhs,const ScalarType rhs)20283 friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
20284 {
20285 return lhs != basic_json(rhs);
20286 }
20287
20288 /*!
20289 @brief comparison: not equal
20290 @copydoc operator!=(const_reference, const_reference)
20291 */
20292 template<typename ScalarType, typename std::enable_if<
20293 std::is_scalar<ScalarType>::value, int>::type = 0>
operator !=(const ScalarType lhs,const_reference rhs)20294 friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
20295 {
20296 return basic_json(lhs) != rhs;
20297 }
20298
20299 /*!
20300 @brief comparison: less than
20301
20302 Compares whether one JSON value @a lhs is less than another JSON value @a
20303 rhs according to the following rules:
20304 - If @a lhs and @a rhs have the same type, the values are compared using
20305 the default `<` operator.
20306 - Integer and floating-point numbers are automatically converted before
20307 comparison
20308 - In case @a lhs and @a rhs have different types, the values are ignored
20309 and the order of the types is considered, see
20310 @ref operator<(const value_t, const value_t).
20311
20312 @param[in] lhs first JSON value to consider
20313 @param[in] rhs second JSON value to consider
20314 @return whether @a lhs is less than @a rhs
20315
20316 @complexity Linear.
20317
20318 @exceptionsafety No-throw guarantee: this function never throws exceptions.
20319
20320 @liveexample{The example demonstrates comparing several JSON
20321 types.,operator__less}
20322
20323 @since version 1.0.0
20324 */
operator <(const_reference lhs,const_reference rhs)20325 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
20326 {
20327 const auto lhs_type = lhs.type();
20328 const auto rhs_type = rhs.type();
20329
20330 if (lhs_type == rhs_type)
20331 {
20332 switch (lhs_type)
20333 {
20334 case value_t::array:
20335 // note parentheses are necessary, see
20336 // https://github.com/nlohmann/json/issues/1530
20337 return (*lhs.m_value.array) < (*rhs.m_value.array);
20338
20339 case value_t::object:
20340 return (*lhs.m_value.object) < (*rhs.m_value.object);
20341
20342 case value_t::null:
20343 return false;
20344
20345 case value_t::string:
20346 return (*lhs.m_value.string) < (*rhs.m_value.string);
20347
20348 case value_t::boolean:
20349 return (lhs.m_value.boolean) < (rhs.m_value.boolean);
20350
20351 case value_t::number_integer:
20352 return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
20353
20354 case value_t::number_unsigned:
20355 return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned);
20356
20357 case value_t::number_float:
20358 return (lhs.m_value.number_float) < (rhs.m_value.number_float);
20359
20360 default:
20361 return false;
20362 }
20363 }
20364 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
20365 {
20366 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
20367 }
20368 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
20369 {
20370 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
20371 }
20372 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
20373 {
20374 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
20375 }
20376 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
20377 {
20378 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
20379 }
20380 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
20381 {
20382 return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
20383 }
20384 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
20385 {
20386 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
20387 }
20388
20389 // We only reach this line if we cannot compare values. In that case,
20390 // we compare types. Note we have to call the operator explicitly,
20391 // because MSVC has problems otherwise.
20392 return operator<(lhs_type, rhs_type);
20393 }
20394
20395 /*!
20396 @brief comparison: less than
20397 @copydoc operator<(const_reference, const_reference)
20398 */
20399 template<typename ScalarType, typename std::enable_if<
20400 std::is_scalar<ScalarType>::value, int>::type = 0>
operator <(const_reference lhs,const ScalarType rhs)20401 friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
20402 {
20403 return lhs < basic_json(rhs);
20404 }
20405
20406 /*!
20407 @brief comparison: less than
20408 @copydoc operator<(const_reference, const_reference)
20409 */
20410 template<typename ScalarType, typename std::enable_if<
20411 std::is_scalar<ScalarType>::value, int>::type = 0>
operator <(const ScalarType lhs,const_reference rhs)20412 friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
20413 {
20414 return basic_json(lhs) < rhs;
20415 }
20416
20417 /*!
20418 @brief comparison: less than or equal
20419
20420 Compares whether one JSON value @a lhs is less than or equal to another
20421 JSON value by calculating `not (rhs < lhs)`.
20422
20423 @param[in] lhs first JSON value to consider
20424 @param[in] rhs second JSON value to consider
20425 @return whether @a lhs is less than or equal to @a rhs
20426
20427 @complexity Linear.
20428
20429 @exceptionsafety No-throw guarantee: this function never throws exceptions.
20430
20431 @liveexample{The example demonstrates comparing several JSON
20432 types.,operator__greater}
20433
20434 @since version 1.0.0
20435 */
operator <=(const_reference lhs,const_reference rhs)20436 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
20437 {
20438 return not (rhs < lhs);
20439 }
20440
20441 /*!
20442 @brief comparison: less than or equal
20443 @copydoc operator<=(const_reference, const_reference)
20444 */
20445 template<typename ScalarType, typename std::enable_if<
20446 std::is_scalar<ScalarType>::value, int>::type = 0>
operator <=(const_reference lhs,const ScalarType rhs)20447 friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
20448 {
20449 return lhs <= basic_json(rhs);
20450 }
20451
20452 /*!
20453 @brief comparison: less than or equal
20454 @copydoc operator<=(const_reference, const_reference)
20455 */
20456 template<typename ScalarType, typename std::enable_if<
20457 std::is_scalar<ScalarType>::value, int>::type = 0>
operator <=(const ScalarType lhs,const_reference rhs)20458 friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
20459 {
20460 return basic_json(lhs) <= rhs;
20461 }
20462
20463 /*!
20464 @brief comparison: greater than
20465
20466 Compares whether one JSON value @a lhs is greater than another
20467 JSON value by calculating `not (lhs <= rhs)`.
20468
20469 @param[in] lhs first JSON value to consider
20470 @param[in] rhs second JSON value to consider
20471 @return whether @a lhs is greater than to @a rhs
20472
20473 @complexity Linear.
20474
20475 @exceptionsafety No-throw guarantee: this function never throws exceptions.
20476
20477 @liveexample{The example demonstrates comparing several JSON
20478 types.,operator__lessequal}
20479
20480 @since version 1.0.0
20481 */
operator >(const_reference lhs,const_reference rhs)20482 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
20483 {
20484 return not (lhs <= rhs);
20485 }
20486
20487 /*!
20488 @brief comparison: greater than
20489 @copydoc operator>(const_reference, const_reference)
20490 */
20491 template<typename ScalarType, typename std::enable_if<
20492 std::is_scalar<ScalarType>::value, int>::type = 0>
operator >(const_reference lhs,const ScalarType rhs)20493 friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
20494 {
20495 return lhs > basic_json(rhs);
20496 }
20497
20498 /*!
20499 @brief comparison: greater than
20500 @copydoc operator>(const_reference, const_reference)
20501 */
20502 template<typename ScalarType, typename std::enable_if<
20503 std::is_scalar<ScalarType>::value, int>::type = 0>
operator >(const ScalarType lhs,const_reference rhs)20504 friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
20505 {
20506 return basic_json(lhs) > rhs;
20507 }
20508
20509 /*!
20510 @brief comparison: greater than or equal
20511
20512 Compares whether one JSON value @a lhs is greater than or equal to another
20513 JSON value by calculating `not (lhs < rhs)`.
20514
20515 @param[in] lhs first JSON value to consider
20516 @param[in] rhs second JSON value to consider
20517 @return whether @a lhs is greater than or equal to @a rhs
20518
20519 @complexity Linear.
20520
20521 @exceptionsafety No-throw guarantee: this function never throws exceptions.
20522
20523 @liveexample{The example demonstrates comparing several JSON
20524 types.,operator__greaterequal}
20525
20526 @since version 1.0.0
20527 */
operator >=(const_reference lhs,const_reference rhs)20528 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
20529 {
20530 return not (lhs < rhs);
20531 }
20532
20533 /*!
20534 @brief comparison: greater than or equal
20535 @copydoc operator>=(const_reference, const_reference)
20536 */
20537 template<typename ScalarType, typename std::enable_if<
20538 std::is_scalar<ScalarType>::value, int>::type = 0>
operator >=(const_reference lhs,const ScalarType rhs)20539 friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
20540 {
20541 return lhs >= basic_json(rhs);
20542 }
20543
20544 /*!
20545 @brief comparison: greater than or equal
20546 @copydoc operator>=(const_reference, const_reference)
20547 */
20548 template<typename ScalarType, typename std::enable_if<
20549 std::is_scalar<ScalarType>::value, int>::type = 0>
operator >=(const ScalarType lhs,const_reference rhs)20550 friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
20551 {
20552 return basic_json(lhs) >= rhs;
20553 }
20554
20555 /// @}
20556
20557 ///////////////////
20558 // serialization //
20559 ///////////////////
20560
20561 /// @name serialization
20562 /// @{
20563
20564 /*!
20565 @brief serialize to stream
20566
20567 Serialize the given JSON value @a j to the output stream @a o. The JSON
20568 value will be serialized using the @ref dump member function.
20569
20570 - The indentation of the output can be controlled with the member variable
20571 `width` of the output stream @a o. For instance, using the manipulator
20572 `std::setw(4)` on @a o sets the indentation level to `4` and the
20573 serialization result is the same as calling `dump(4)`.
20574
20575 - The indentation character can be controlled with the member variable
20576 `fill` of the output stream @a o. For instance, the manipulator
20577 `std::setfill('\\t')` sets indentation to use a tab character rather than
20578 the default space character.
20579
20580 @param[in,out] o stream to serialize to
20581 @param[in] j JSON value to serialize
20582
20583 @return the stream @a o
20584
20585 @throw type_error.316 if a string stored inside the JSON value is not
20586 UTF-8 encoded
20587
20588 @complexity Linear.
20589
20590 @liveexample{The example below shows the serialization with different
20591 parameters to `width` to adjust the indentation level.,operator_serialize}
20592
20593 @since version 1.0.0; indentation character added in version 3.0.0
20594 */
operator <<(std::ostream & o,const basic_json & j)20595 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
20596 {
20597 // read width member and use it as indentation parameter if nonzero
20598 const bool pretty_print = o.width() > 0;
20599 const auto indentation = pretty_print ? o.width() : 0;
20600
20601 // reset width to 0 for subsequent calls to this stream
20602 o.width(0);
20603
20604 // do the actual serialization
20605 serializer s(detail::output_adapter<char>(o), o.fill());
20606 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
20607 return o;
20608 }
20609
20610 /*!
20611 @brief serialize to stream
20612 @deprecated This stream operator is deprecated and will be removed in
20613 future 4.0.0 of the library. Please use
20614 @ref operator<<(std::ostream&, const basic_json&)
20615 instead; that is, replace calls like `j >> o;` with `o << j;`.
20616 @since version 1.0.0; deprecated since version 3.0.0
20617 */
20618 JSON_HEDLEY_DEPRECATED(3.0.0)
operator >>(const basic_json & j,std::ostream & o)20619 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
20620 {
20621 return o << j;
20622 }
20623
20624 /// @}
20625
20626
20627 /////////////////////
20628 // deserialization //
20629 /////////////////////
20630
20631 /// @name deserialization
20632 /// @{
20633
20634 /*!
20635 @brief deserialize from a compatible input
20636
20637 This function reads from a compatible input. Examples are:
20638 - an array of 1-byte values
20639 - strings with character/literal type with size of 1 byte
20640 - input streams
20641 - container with contiguous storage of 1-byte values. Compatible container
20642 types include `std::vector`, `std::string`, `std::array`,
20643 `std::valarray`, and `std::initializer_list`. Furthermore, C-style
20644 arrays can be used with `std::begin()`/`std::end()`. User-defined
20645 containers can be used as long as they implement random-access iterators
20646 and a contiguous storage.
20647
20648 @pre Each element of the container has a size of 1 byte. Violating this
20649 precondition yields undefined behavior. **This precondition is enforced
20650 with a static assertion.**
20651
20652 @pre The container storage is contiguous. Violating this precondition
20653 yields undefined behavior. **This precondition is enforced with an
20654 assertion.**
20655
20656 @warning There is no way to enforce all preconditions at compile-time. If
20657 the function is called with a noncompliant container and with
20658 assertions switched off, the behavior is undefined and will most
20659 likely yield segmentation violation.
20660
20661 @param[in] i input to read from
20662 @param[in] cb a parser callback function of type @ref parser_callback_t
20663 which is used to control the deserialization by filtering unwanted values
20664 (optional)
20665 @param[in] allow_exceptions whether to throw exceptions in case of a
20666 parse error (optional, true by default)
20667
20668 @return deserialized JSON value; in case of a parse error and
20669 @a allow_exceptions set to `false`, the return value will be
20670 value_t::discarded.
20671
20672 @throw parse_error.101 if a parse error occurs; example: `""unexpected end
20673 of input; expected string literal""`
20674 @throw parse_error.102 if to_unicode fails or surrogate error
20675 @throw parse_error.103 if to_unicode fails
20676
20677 @complexity Linear in the length of the input. The parser is a predictive
20678 LL(1) parser. The complexity can be higher if the parser callback function
20679 @a cb has a super-linear complexity.
20680
20681 @note A UTF-8 byte order mark is silently ignored.
20682
20683 @liveexample{The example below demonstrates the `parse()` function reading
20684 from an array.,parse__array__parser_callback_t}
20685
20686 @liveexample{The example below demonstrates the `parse()` function with
20687 and without callback function.,parse__string__parser_callback_t}
20688
20689 @liveexample{The example below demonstrates the `parse()` function with
20690 and without callback function.,parse__istream__parser_callback_t}
20691
20692 @liveexample{The example below demonstrates the `parse()` function reading
20693 from a contiguous container.,parse__contiguouscontainer__parser_callback_t}
20694
20695 @since version 2.0.3 (contiguous containers)
20696 */
20697 JSON_HEDLEY_WARN_UNUSED_RESULT
parse(detail::input_adapter && i,const parser_callback_t cb=nullptr,const bool allow_exceptions=true)20698 static basic_json parse(detail::input_adapter&& i,
20699 const parser_callback_t cb = nullptr,
20700 const bool allow_exceptions = true)
20701 {
20702 basic_json result;
20703 parser(i, cb, allow_exceptions).parse(true, result);
20704 return result;
20705 }
20706
accept(detail::input_adapter && i)20707 static bool accept(detail::input_adapter&& i)
20708 {
20709 return parser(i).accept(true);
20710 }
20711
20712 /*!
20713 @brief generate SAX events
20714
20715 The SAX event lister must follow the interface of @ref json_sax.
20716
20717 This function reads from a compatible input. Examples are:
20718 - an array of 1-byte values
20719 - strings with character/literal type with size of 1 byte
20720 - input streams
20721 - container with contiguous storage of 1-byte values. Compatible container
20722 types include `std::vector`, `std::string`, `std::array`,
20723 `std::valarray`, and `std::initializer_list`. Furthermore, C-style
20724 arrays can be used with `std::begin()`/`std::end()`. User-defined
20725 containers can be used as long as they implement random-access iterators
20726 and a contiguous storage.
20727
20728 @pre Each element of the container has a size of 1 byte. Violating this
20729 precondition yields undefined behavior. **This precondition is enforced
20730 with a static assertion.**
20731
20732 @pre The container storage is contiguous. Violating this precondition
20733 yields undefined behavior. **This precondition is enforced with an
20734 assertion.**
20735
20736 @warning There is no way to enforce all preconditions at compile-time. If
20737 the function is called with a noncompliant container and with
20738 assertions switched off, the behavior is undefined and will most
20739 likely yield segmentation violation.
20740
20741 @param[in] i input to read from
20742 @param[in,out] sax SAX event listener
20743 @param[in] format the format to parse (JSON, CBOR, MessagePack, or UBJSON)
20744 @param[in] strict whether the input has to be consumed completely
20745
20746 @return return value of the last processed SAX event
20747
20748 @throw parse_error.101 if a parse error occurs; example: `""unexpected end
20749 of input; expected string literal""`
20750 @throw parse_error.102 if to_unicode fails or surrogate error
20751 @throw parse_error.103 if to_unicode fails
20752
20753 @complexity Linear in the length of the input. The parser is a predictive
20754 LL(1) parser. The complexity can be higher if the SAX consumer @a sax has
20755 a super-linear complexity.
20756
20757 @note A UTF-8 byte order mark is silently ignored.
20758
20759 @liveexample{The example below demonstrates the `sax_parse()` function
20760 reading from string and processing the events with a user-defined SAX
20761 event consumer.,sax_parse}
20762
20763 @since version 3.2.0
20764 */
20765 template <typename SAX>
20766 JSON_HEDLEY_NON_NULL(2)
sax_parse(detail::input_adapter && i,SAX * sax,input_format_t format=input_format_t::json,const bool strict=true)20767 static bool sax_parse(detail::input_adapter&& i, SAX* sax,
20768 input_format_t format = input_format_t::json,
20769 const bool strict = true)
20770 {
20771 assert(sax);
20772 return format == input_format_t::json
20773 ? parser(std::move(i)).sax_parse(sax, strict)
20774 : detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
20775 }
20776
20777 /*!
20778 @brief deserialize from an iterator range with contiguous storage
20779
20780 This function reads from an iterator range of a container with contiguous
20781 storage of 1-byte values. Compatible container types include
20782 `std::vector`, `std::string`, `std::array`, `std::valarray`, and
20783 `std::initializer_list`. Furthermore, C-style arrays can be used with
20784 `std::begin()`/`std::end()`. User-defined containers can be used as long
20785 as they implement random-access iterators and a contiguous storage.
20786
20787 @pre The iterator range is contiguous. Violating this precondition yields
20788 undefined behavior. **This precondition is enforced with an assertion.**
20789 @pre Each element in the range has a size of 1 byte. Violating this
20790 precondition yields undefined behavior. **This precondition is enforced
20791 with a static assertion.**
20792
20793 @warning There is no way to enforce all preconditions at compile-time. If
20794 the function is called with noncompliant iterators and with
20795 assertions switched off, the behavior is undefined and will most
20796 likely yield segmentation violation.
20797
20798 @tparam IteratorType iterator of container with contiguous storage
20799 @param[in] first begin of the range to parse (included)
20800 @param[in] last end of the range to parse (excluded)
20801 @param[in] cb a parser callback function of type @ref parser_callback_t
20802 which is used to control the deserialization by filtering unwanted values
20803 (optional)
20804 @param[in] allow_exceptions whether to throw exceptions in case of a
20805 parse error (optional, true by default)
20806
20807 @return deserialized JSON value; in case of a parse error and
20808 @a allow_exceptions set to `false`, the return value will be
20809 value_t::discarded.
20810
20811 @throw parse_error.101 in case of an unexpected token
20812 @throw parse_error.102 if to_unicode fails or surrogate error
20813 @throw parse_error.103 if to_unicode fails
20814
20815 @complexity Linear in the length of the input. The parser is a predictive
20816 LL(1) parser. The complexity can be higher if the parser callback function
20817 @a cb has a super-linear complexity.
20818
20819 @note A UTF-8 byte order mark is silently ignored.
20820
20821 @liveexample{The example below demonstrates the `parse()` function reading
20822 from an iterator range.,parse__iteratortype__parser_callback_t}
20823
20824 @since version 2.0.3
20825 */
20826 template<class IteratorType, typename std::enable_if<
20827 std::is_base_of<
20828 std::random_access_iterator_tag,
20829 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
parse(IteratorType first,IteratorType last,const parser_callback_t cb=nullptr,const bool allow_exceptions=true)20830 static basic_json parse(IteratorType first, IteratorType last,
20831 const parser_callback_t cb = nullptr,
20832 const bool allow_exceptions = true)
20833 {
20834 basic_json result;
20835 parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result);
20836 return result;
20837 }
20838
20839 template<class IteratorType, typename std::enable_if<
20840 std::is_base_of<
20841 std::random_access_iterator_tag,
20842 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
accept(IteratorType first,IteratorType last)20843 static bool accept(IteratorType first, IteratorType last)
20844 {
20845 return parser(detail::input_adapter(first, last)).accept(true);
20846 }
20847
20848 template<class IteratorType, class SAX, typename std::enable_if<
20849 std::is_base_of<
20850 std::random_access_iterator_tag,
20851 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
20852 JSON_HEDLEY_NON_NULL(3)
sax_parse(IteratorType first,IteratorType last,SAX * sax)20853 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax)
20854 {
20855 return parser(detail::input_adapter(first, last)).sax_parse(sax);
20856 }
20857
20858 /*!
20859 @brief deserialize from stream
20860 @deprecated This stream operator is deprecated and will be removed in
20861 version 4.0.0 of the library. Please use
20862 @ref operator>>(std::istream&, basic_json&)
20863 instead; that is, replace calls like `j << i;` with `i >> j;`.
20864 @since version 1.0.0; deprecated since version 3.0.0
20865 */
20866 JSON_HEDLEY_DEPRECATED(3.0.0)
operator <<(basic_json & j,std::istream & i)20867 friend std::istream& operator<<(basic_json& j, std::istream& i)
20868 {
20869 return operator>>(i, j);
20870 }
20871
20872 /*!
20873 @brief deserialize from stream
20874
20875 Deserializes an input stream to a JSON value.
20876
20877 @param[in,out] i input stream to read a serialized JSON value from
20878 @param[in,out] j JSON value to write the deserialized input to
20879
20880 @throw parse_error.101 in case of an unexpected token
20881 @throw parse_error.102 if to_unicode fails or surrogate error
20882 @throw parse_error.103 if to_unicode fails
20883
20884 @complexity Linear in the length of the input. The parser is a predictive
20885 LL(1) parser.
20886
20887 @note A UTF-8 byte order mark is silently ignored.
20888
20889 @liveexample{The example below shows how a JSON value is constructed by
20890 reading a serialization from a stream.,operator_deserialize}
20891
20892 @sa parse(std::istream&, const parser_callback_t) for a variant with a
20893 parser callback function to filter values while parsing
20894
20895 @since version 1.0.0
20896 */
operator >>(std::istream & i,basic_json & j)20897 friend std::istream& operator>>(std::istream& i, basic_json& j)
20898 {
20899 parser(detail::input_adapter(i)).parse(false, j);
20900 return i;
20901 }
20902
20903 /// @}
20904
20905 ///////////////////////////
20906 // convenience functions //
20907 ///////////////////////////
20908
20909 /*!
20910 @brief return the type as string
20911
20912 Returns the type name as string to be used in error messages - usually to
20913 indicate that a function was called on a wrong JSON type.
20914
20915 @return a string representation of a the @a m_type member:
20916 Value type | return value
20917 ----------- | -------------
20918 null | `"null"`
20919 boolean | `"boolean"`
20920 string | `"string"`
20921 number | `"number"` (for all number types)
20922 object | `"object"`
20923 array | `"array"`
20924 discarded | `"discarded"`
20925
20926 @exceptionsafety No-throw guarantee: this function never throws exceptions.
20927
20928 @complexity Constant.
20929
20930 @liveexample{The following code exemplifies `type_name()` for all JSON
20931 types.,type_name}
20932
20933 @sa @ref type() -- return the type of the JSON value
20934 @sa @ref operator value_t() -- return the type of the JSON value (implicit)
20935
20936 @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept`
20937 since 3.0.0
20938 */
20939 JSON_HEDLEY_RETURNS_NON_NULL
type_name() const20940 const char* type_name() const noexcept
20941 {
20942 {
20943 switch (m_type)
20944 {
20945 case value_t::null:
20946 return "null";
20947 case value_t::object:
20948 return "object";
20949 case value_t::array:
20950 return "array";
20951 case value_t::string:
20952 return "string";
20953 case value_t::boolean:
20954 return "boolean";
20955 case value_t::discarded:
20956 return "discarded";
20957 default:
20958 return "number";
20959 }
20960 }
20961 }
20962
20963
20964 private:
20965 //////////////////////
20966 // member variables //
20967 //////////////////////
20968
20969 /// the type of the current element
20970 value_t m_type = value_t::null;
20971
20972 /// the value of the current element
20973 json_value m_value = {};
20974
20975 //////////////////////////////////////////
20976 // binary serialization/deserialization //
20977 //////////////////////////////////////////
20978
20979 /// @name binary serialization/deserialization support
20980 /// @{
20981
20982 public:
20983 /*!
20984 @brief create a CBOR serialization of a given JSON value
20985
20986 Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
20987 Binary Object Representation) serialization format. CBOR is a binary
20988 serialization format which aims to be more compact than JSON itself, yet
20989 more efficient to parse.
20990
20991 The library uses the following mapping from JSON values types to
20992 CBOR types according to the CBOR specification (RFC 7049):
20993
20994 JSON value type | value/range | CBOR type | first byte
20995 --------------- | ------------------------------------------ | ---------------------------------- | ---------------
20996 null | `null` | Null | 0xF6
20997 boolean | `true` | True | 0xF5
20998 boolean | `false` | False | 0xF4
20999 number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3B
21000 number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3A
21001 number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39
21002 number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38
21003 number_integer | -24..-1 | Negative integer | 0x20..0x37
21004 number_integer | 0..23 | Integer | 0x00..0x17
21005 number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18
21006 number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19
21007 number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A
21008 number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B
21009 number_unsigned | 0..23 | Integer | 0x00..0x17
21010 number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18
21011 number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19
21012 number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A
21013 number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B
21014 number_float | *any value* | Double-Precision Float | 0xFB
21015 string | *length*: 0..23 | UTF-8 string | 0x60..0x77
21016 string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78
21017 string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79
21018 string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A
21019 string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B
21020 array | *size*: 0..23 | array | 0x80..0x97
21021 array | *size*: 23..255 | array (1 byte follow) | 0x98
21022 array | *size*: 256..65535 | array (2 bytes follow) | 0x99
21023 array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A
21024 array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B
21025 object | *size*: 0..23 | map | 0xA0..0xB7
21026 object | *size*: 23..255 | map (1 byte follow) | 0xB8
21027 object | *size*: 256..65535 | map (2 bytes follow) | 0xB9
21028 object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA
21029 object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB
21030
21031 @note The mapping is **complete** in the sense that any JSON value type
21032 can be converted to a CBOR value.
21033
21034 @note If NaN or Infinity are stored inside a JSON number, they are
21035 serialized properly. This behavior differs from the @ref dump()
21036 function which serializes NaN or Infinity to `null`.
21037
21038 @note The following CBOR types are not used in the conversion:
21039 - byte strings (0x40..0x5F)
21040 - UTF-8 strings terminated by "break" (0x7F)
21041 - arrays terminated by "break" (0x9F)
21042 - maps terminated by "break" (0xBF)
21043 - date/time (0xC0..0xC1)
21044 - bignum (0xC2..0xC3)
21045 - decimal fraction (0xC4)
21046 - bigfloat (0xC5)
21047 - tagged items (0xC6..0xD4, 0xD8..0xDB)
21048 - expected conversions (0xD5..0xD7)
21049 - simple values (0xE0..0xF3, 0xF8)
21050 - undefined (0xF7)
21051 - half and single-precision floats (0xF9-0xFA)
21052 - break (0xFF)
21053
21054 @param[in] j JSON value to serialize
21055 @return MessagePack serialization as byte vector
21056
21057 @complexity Linear in the size of the JSON value @a j.
21058
21059 @liveexample{The example shows the serialization of a JSON value to a byte
21060 vector in CBOR format.,to_cbor}
21061
21062 @sa http://cbor.io
21063 @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the
21064 analogous deserialization
21065 @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
21066 @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
21067 related UBJSON format
21068
21069 @since version 2.0.9
21070 */
to_cbor(const basic_json & j)21071 static std::vector<uint8_t> to_cbor(const basic_json& j)
21072 {
21073 std::vector<uint8_t> result;
21074 to_cbor(j, result);
21075 return result;
21076 }
21077
to_cbor(const basic_json & j,detail::output_adapter<uint8_t> o)21078 static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
21079 {
21080 binary_writer<uint8_t>(o).write_cbor(j);
21081 }
21082
to_cbor(const basic_json & j,detail::output_adapter<char> o)21083 static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
21084 {
21085 binary_writer<char>(o).write_cbor(j);
21086 }
21087
21088 /*!
21089 @brief create a MessagePack serialization of a given JSON value
21090
21091 Serializes a given JSON value @a j to a byte vector using the MessagePack
21092 serialization format. MessagePack is a binary serialization format which
21093 aims to be more compact than JSON itself, yet more efficient to parse.
21094
21095 The library uses the following mapping from JSON values types to
21096 MessagePack types according to the MessagePack specification:
21097
21098 JSON value type | value/range | MessagePack type | first byte
21099 --------------- | --------------------------------- | ---------------- | ----------
21100 null | `null` | nil | 0xC0
21101 boolean | `true` | true | 0xC3
21102 boolean | `false` | false | 0xC2
21103 number_integer | -9223372036854775808..-2147483649 | int64 | 0xD3
21104 number_integer | -2147483648..-32769 | int32 | 0xD2
21105 number_integer | -32768..-129 | int16 | 0xD1
21106 number_integer | -128..-33 | int8 | 0xD0
21107 number_integer | -32..-1 | negative fixint | 0xE0..0xFF
21108 number_integer | 0..127 | positive fixint | 0x00..0x7F
21109 number_integer | 128..255 | uint 8 | 0xCC
21110 number_integer | 256..65535 | uint 16 | 0xCD
21111 number_integer | 65536..4294967295 | uint 32 | 0xCE
21112 number_integer | 4294967296..18446744073709551615 | uint 64 | 0xCF
21113 number_unsigned | 0..127 | positive fixint | 0x00..0x7F
21114 number_unsigned | 128..255 | uint 8 | 0xCC
21115 number_unsigned | 256..65535 | uint 16 | 0xCD
21116 number_unsigned | 65536..4294967295 | uint 32 | 0xCE
21117 number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF
21118 number_float | *any value* | float 64 | 0xCB
21119 string | *length*: 0..31 | fixstr | 0xA0..0xBF
21120 string | *length*: 32..255 | str 8 | 0xD9
21121 string | *length*: 256..65535 | str 16 | 0xDA
21122 string | *length*: 65536..4294967295 | str 32 | 0xDB
21123 array | *size*: 0..15 | fixarray | 0x90..0x9F
21124 array | *size*: 16..65535 | array 16 | 0xDC
21125 array | *size*: 65536..4294967295 | array 32 | 0xDD
21126 object | *size*: 0..15 | fix map | 0x80..0x8F
21127 object | *size*: 16..65535 | map 16 | 0xDE
21128 object | *size*: 65536..4294967295 | map 32 | 0xDF
21129
21130 @note The mapping is **complete** in the sense that any JSON value type
21131 can be converted to a MessagePack value.
21132
21133 @note The following values can **not** be converted to a MessagePack value:
21134 - strings with more than 4294967295 bytes
21135 - arrays with more than 4294967295 elements
21136 - objects with more than 4294967295 elements
21137
21138 @note The following MessagePack types are not used in the conversion:
21139 - bin 8 - bin 32 (0xC4..0xC6)
21140 - ext 8 - ext 32 (0xC7..0xC9)
21141 - float 32 (0xCA)
21142 - fixext 1 - fixext 16 (0xD4..0xD8)
21143
21144 @note Any MessagePack output created @ref to_msgpack can be successfully
21145 parsed by @ref from_msgpack.
21146
21147 @note If NaN or Infinity are stored inside a JSON number, they are
21148 serialized properly. This behavior differs from the @ref dump()
21149 function which serializes NaN or Infinity to `null`.
21150
21151 @param[in] j JSON value to serialize
21152 @return MessagePack serialization as byte vector
21153
21154 @complexity Linear in the size of the JSON value @a j.
21155
21156 @liveexample{The example shows the serialization of a JSON value to a byte
21157 vector in MessagePack format.,to_msgpack}
21158
21159 @sa http://msgpack.org
21160 @sa @ref from_msgpack for the analogous deserialization
21161 @sa @ref to_cbor(const basic_json& for the related CBOR format
21162 @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
21163 related UBJSON format
21164
21165 @since version 2.0.9
21166 */
to_msgpack(const basic_json & j)21167 static std::vector<uint8_t> to_msgpack(const basic_json& j)
21168 {
21169 std::vector<uint8_t> result;
21170 to_msgpack(j, result);
21171 return result;
21172 }
21173
to_msgpack(const basic_json & j,detail::output_adapter<uint8_t> o)21174 static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
21175 {
21176 binary_writer<uint8_t>(o).write_msgpack(j);
21177 }
21178
to_msgpack(const basic_json & j,detail::output_adapter<char> o)21179 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
21180 {
21181 binary_writer<char>(o).write_msgpack(j);
21182 }
21183
21184 /*!
21185 @brief create a UBJSON serialization of a given JSON value
21186
21187 Serializes a given JSON value @a j to a byte vector using the UBJSON
21188 (Universal Binary JSON) serialization format. UBJSON aims to be more compact
21189 than JSON itself, yet more efficient to parse.
21190
21191 The library uses the following mapping from JSON values types to
21192 UBJSON types according to the UBJSON specification:
21193
21194 JSON value type | value/range | UBJSON type | marker
21195 --------------- | --------------------------------- | ----------- | ------
21196 null | `null` | null | `Z`
21197 boolean | `true` | true | `T`
21198 boolean | `false` | false | `F`
21199 number_integer | -9223372036854775808..-2147483649 | int64 | `L`
21200 number_integer | -2147483648..-32769 | int32 | `l`
21201 number_integer | -32768..-129 | int16 | `I`
21202 number_integer | -128..127 | int8 | `i`
21203 number_integer | 128..255 | uint8 | `U`
21204 number_integer | 256..32767 | int16 | `I`
21205 number_integer | 32768..2147483647 | int32 | `l`
21206 number_integer | 2147483648..9223372036854775807 | int64 | `L`
21207 number_unsigned | 0..127 | int8 | `i`
21208 number_unsigned | 128..255 | uint8 | `U`
21209 number_unsigned | 256..32767 | int16 | `I`
21210 number_unsigned | 32768..2147483647 | int32 | `l`
21211 number_unsigned | 2147483648..9223372036854775807 | int64 | `L`
21212 number_float | *any value* | float64 | `D`
21213 string | *with shortest length indicator* | string | `S`
21214 array | *see notes on optimized format* | array | `[`
21215 object | *see notes on optimized format* | map | `{`
21216
21217 @note The mapping is **complete** in the sense that any JSON value type
21218 can be converted to a UBJSON value.
21219
21220 @note The following values can **not** be converted to a UBJSON value:
21221 - strings with more than 9223372036854775807 bytes (theoretical)
21222 - unsigned integer numbers above 9223372036854775807
21223
21224 @note The following markers are not used in the conversion:
21225 - `Z`: no-op values are not created.
21226 - `C`: single-byte strings are serialized with `S` markers.
21227
21228 @note Any UBJSON output created @ref to_ubjson can be successfully parsed
21229 by @ref from_ubjson.
21230
21231 @note If NaN or Infinity are stored inside a JSON number, they are
21232 serialized properly. This behavior differs from the @ref dump()
21233 function which serializes NaN or Infinity to `null`.
21234
21235 @note The optimized formats for containers are supported: Parameter
21236 @a use_size adds size information to the beginning of a container and
21237 removes the closing marker. Parameter @a use_type further checks
21238 whether all elements of a container have the same type and adds the
21239 type marker to the beginning of the container. The @a use_type
21240 parameter must only be used together with @a use_size = true. Note
21241 that @a use_size = true alone may result in larger representations -
21242 the benefit of this parameter is that the receiving side is
21243 immediately informed on the number of elements of the container.
21244
21245 @param[in] j JSON value to serialize
21246 @param[in] use_size whether to add size annotations to container types
21247 @param[in] use_type whether to add type annotations to container types
21248 (must be combined with @a use_size = true)
21249 @return UBJSON serialization as byte vector
21250
21251 @complexity Linear in the size of the JSON value @a j.
21252
21253 @liveexample{The example shows the serialization of a JSON value to a byte
21254 vector in UBJSON format.,to_ubjson}
21255
21256 @sa http://ubjson.org
21257 @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
21258 analogous deserialization
21259 @sa @ref to_cbor(const basic_json& for the related CBOR format
21260 @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
21261
21262 @since version 3.1.0
21263 */
to_ubjson(const basic_json & j,const bool use_size=false,const bool use_type=false)21264 static std::vector<uint8_t> to_ubjson(const basic_json& j,
21265 const bool use_size = false,
21266 const bool use_type = false)
21267 {
21268 std::vector<uint8_t> result;
21269 to_ubjson(j, result, use_size, use_type);
21270 return result;
21271 }
21272
to_ubjson(const basic_json & j,detail::output_adapter<uint8_t> o,const bool use_size=false,const bool use_type=false)21273 static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,
21274 const bool use_size = false, const bool use_type = false)
21275 {
21276 binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
21277 }
21278
to_ubjson(const basic_json & j,detail::output_adapter<char> o,const bool use_size=false,const bool use_type=false)21279 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
21280 const bool use_size = false, const bool use_type = false)
21281 {
21282 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
21283 }
21284
21285
21286 /*!
21287 @brief Serializes the given JSON object `j` to BSON and returns a vector
21288 containing the corresponding BSON-representation.
21289
21290 BSON (Binary JSON) is a binary format in which zero or more ordered key/value pairs are
21291 stored as a single entity (a so-called document).
21292
21293 The library uses the following mapping from JSON values types to BSON types:
21294
21295 JSON value type | value/range | BSON type | marker
21296 --------------- | --------------------------------- | ----------- | ------
21297 null | `null` | null | 0x0A
21298 boolean | `true`, `false` | boolean | 0x08
21299 number_integer | -9223372036854775808..-2147483649 | int64 | 0x12
21300 number_integer | -2147483648..2147483647 | int32 | 0x10
21301 number_integer | 2147483648..9223372036854775807 | int64 | 0x12
21302 number_unsigned | 0..2147483647 | int32 | 0x10
21303 number_unsigned | 2147483648..9223372036854775807 | int64 | 0x12
21304 number_unsigned | 9223372036854775808..18446744073709551615| -- | --
21305 number_float | *any value* | double | 0x01
21306 string | *any value* | string | 0x02
21307 array | *any value* | document | 0x04
21308 object | *any value* | document | 0x03
21309
21310 @warning The mapping is **incomplete**, since only JSON-objects (and things
21311 contained therein) can be serialized to BSON.
21312 Also, integers larger than 9223372036854775807 cannot be serialized to BSON,
21313 and the keys may not contain U+0000, since they are serialized a
21314 zero-terminated c-strings.
21315
21316 @throw out_of_range.407 if `j.is_number_unsigned() && j.get<std::uint64_t>() > 9223372036854775807`
21317 @throw out_of_range.409 if a key in `j` contains a NULL (U+0000)
21318 @throw type_error.317 if `!j.is_object()`
21319
21320 @pre The input `j` is required to be an object: `j.is_object() == true`.
21321
21322 @note Any BSON output created via @ref to_bson can be successfully parsed
21323 by @ref from_bson.
21324
21325 @param[in] j JSON value to serialize
21326 @return BSON serialization as byte vector
21327
21328 @complexity Linear in the size of the JSON value @a j.
21329
21330 @liveexample{The example shows the serialization of a JSON value to a byte
21331 vector in BSON format.,to_bson}
21332
21333 @sa http://bsonspec.org/spec.html
21334 @sa @ref from_bson(detail::input_adapter&&, const bool strict) for the
21335 analogous deserialization
21336 @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
21337 related UBJSON format
21338 @sa @ref to_cbor(const basic_json&) for the related CBOR format
21339 @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
21340 */
to_bson(const basic_json & j)21341 static std::vector<uint8_t> to_bson(const basic_json& j)
21342 {
21343 std::vector<uint8_t> result;
21344 to_bson(j, result);
21345 return result;
21346 }
21347
21348 /*!
21349 @brief Serializes the given JSON object `j` to BSON and forwards the
21350 corresponding BSON-representation to the given output_adapter `o`.
21351 @param j The JSON object to convert to BSON.
21352 @param o The output adapter that receives the binary BSON representation.
21353 @pre The input `j` shall be an object: `j.is_object() == true`
21354 @sa @ref to_bson(const basic_json&)
21355 */
to_bson(const basic_json & j,detail::output_adapter<uint8_t> o)21356 static void to_bson(const basic_json& j, detail::output_adapter<uint8_t> o)
21357 {
21358 binary_writer<uint8_t>(o).write_bson(j);
21359 }
21360
21361 /*!
21362 @copydoc to_bson(const basic_json&, detail::output_adapter<uint8_t>)
21363 */
to_bson(const basic_json & j,detail::output_adapter<char> o)21364 static void to_bson(const basic_json& j, detail::output_adapter<char> o)
21365 {
21366 binary_writer<char>(o).write_bson(j);
21367 }
21368
21369
21370 /*!
21371 @brief create a JSON value from an input in CBOR format
21372
21373 Deserializes a given input @a i to a JSON value using the CBOR (Concise
21374 Binary Object Representation) serialization format.
21375
21376 The library maps CBOR types to JSON value types as follows:
21377
21378 CBOR type | JSON value type | first byte
21379 ---------------------- | --------------- | ----------
21380 Integer | number_unsigned | 0x00..0x17
21381 Unsigned integer | number_unsigned | 0x18
21382 Unsigned integer | number_unsigned | 0x19
21383 Unsigned integer | number_unsigned | 0x1A
21384 Unsigned integer | number_unsigned | 0x1B
21385 Negative integer | number_integer | 0x20..0x37
21386 Negative integer | number_integer | 0x38
21387 Negative integer | number_integer | 0x39
21388 Negative integer | number_integer | 0x3A
21389 Negative integer | number_integer | 0x3B
21390 Negative integer | number_integer | 0x40..0x57
21391 UTF-8 string | string | 0x60..0x77
21392 UTF-8 string | string | 0x78
21393 UTF-8 string | string | 0x79
21394 UTF-8 string | string | 0x7A
21395 UTF-8 string | string | 0x7B
21396 UTF-8 string | string | 0x7F
21397 array | array | 0x80..0x97
21398 array | array | 0x98
21399 array | array | 0x99
21400 array | array | 0x9A
21401 array | array | 0x9B
21402 array | array | 0x9F
21403 map | object | 0xA0..0xB7
21404 map | object | 0xB8
21405 map | object | 0xB9
21406 map | object | 0xBA
21407 map | object | 0xBB
21408 map | object | 0xBF
21409 False | `false` | 0xF4
21410 True | `true` | 0xF5
21411 Null | `null` | 0xF6
21412 Half-Precision Float | number_float | 0xF9
21413 Single-Precision Float | number_float | 0xFA
21414 Double-Precision Float | number_float | 0xFB
21415
21416 @warning The mapping is **incomplete** in the sense that not all CBOR
21417 types can be converted to a JSON value. The following CBOR types
21418 are not supported and will yield parse errors (parse_error.112):
21419 - byte strings (0x40..0x5F)
21420 - date/time (0xC0..0xC1)
21421 - bignum (0xC2..0xC3)
21422 - decimal fraction (0xC4)
21423 - bigfloat (0xC5)
21424 - tagged items (0xC6..0xD4, 0xD8..0xDB)
21425 - expected conversions (0xD5..0xD7)
21426 - simple values (0xE0..0xF3, 0xF8)
21427 - undefined (0xF7)
21428
21429 @warning CBOR allows map keys of any type, whereas JSON only allows
21430 strings as keys in object values. Therefore, CBOR maps with keys
21431 other than UTF-8 strings are rejected (parse_error.113).
21432
21433 @note Any CBOR output created @ref to_cbor can be successfully parsed by
21434 @ref from_cbor.
21435
21436 @param[in] i an input in CBOR format convertible to an input adapter
21437 @param[in] strict whether to expect the input to be consumed until EOF
21438 (true by default)
21439 @param[in] allow_exceptions whether to throw exceptions in case of a
21440 parse error (optional, true by default)
21441
21442 @return deserialized JSON value; in case of a parse error and
21443 @a allow_exceptions set to `false`, the return value will be
21444 value_t::discarded.
21445
21446 @throw parse_error.110 if the given input ends prematurely or the end of
21447 file was not reached when @a strict was set to true
21448 @throw parse_error.112 if unsupported features from CBOR were
21449 used in the given input @a v or if the input is not valid CBOR
21450 @throw parse_error.113 if a string was expected as map key, but not found
21451
21452 @complexity Linear in the size of the input @a i.
21453
21454 @liveexample{The example shows the deserialization of a byte vector in CBOR
21455 format to a JSON value.,from_cbor}
21456
21457 @sa http://cbor.io
21458 @sa @ref to_cbor(const basic_json&) for the analogous serialization
21459 @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for the
21460 related MessagePack format
21461 @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
21462 related UBJSON format
21463
21464 @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
21465 consume input adapters, removed start_index parameter, and added
21466 @a strict parameter since 3.0.0; added @a allow_exceptions parameter
21467 since 3.2.0
21468 */
21469 JSON_HEDLEY_WARN_UNUSED_RESULT
from_cbor(detail::input_adapter && i,const bool strict=true,const bool allow_exceptions=true)21470 static basic_json from_cbor(detail::input_adapter&& i,
21471 const bool strict = true,
21472 const bool allow_exceptions = true)
21473 {
21474 basic_json result;
21475 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21476 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict);
21477 return res ? result : basic_json(value_t::discarded);
21478 }
21479
21480 /*!
21481 @copydoc from_cbor(detail::input_adapter&&, const bool, const bool)
21482 */
21483 template<typename A1, typename A2,
21484 detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
21485 JSON_HEDLEY_WARN_UNUSED_RESULT
from_cbor(A1 && a1,A2 && a2,const bool strict=true,const bool allow_exceptions=true)21486 static basic_json from_cbor(A1 && a1, A2 && a2,
21487 const bool strict = true,
21488 const bool allow_exceptions = true)
21489 {
21490 basic_json result;
21491 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21492 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict);
21493 return res ? result : basic_json(value_t::discarded);
21494 }
21495
21496 /*!
21497 @brief create a JSON value from an input in MessagePack format
21498
21499 Deserializes a given input @a i to a JSON value using the MessagePack
21500 serialization format.
21501
21502 The library maps MessagePack types to JSON value types as follows:
21503
21504 MessagePack type | JSON value type | first byte
21505 ---------------- | --------------- | ----------
21506 positive fixint | number_unsigned | 0x00..0x7F
21507 fixmap | object | 0x80..0x8F
21508 fixarray | array | 0x90..0x9F
21509 fixstr | string | 0xA0..0xBF
21510 nil | `null` | 0xC0
21511 false | `false` | 0xC2
21512 true | `true` | 0xC3
21513 float 32 | number_float | 0xCA
21514 float 64 | number_float | 0xCB
21515 uint 8 | number_unsigned | 0xCC
21516 uint 16 | number_unsigned | 0xCD
21517 uint 32 | number_unsigned | 0xCE
21518 uint 64 | number_unsigned | 0xCF
21519 int 8 | number_integer | 0xD0
21520 int 16 | number_integer | 0xD1
21521 int 32 | number_integer | 0xD2
21522 int 64 | number_integer | 0xD3
21523 str 8 | string | 0xD9
21524 str 16 | string | 0xDA
21525 str 32 | string | 0xDB
21526 array 16 | array | 0xDC
21527 array 32 | array | 0xDD
21528 map 16 | object | 0xDE
21529 map 32 | object | 0xDF
21530 negative fixint | number_integer | 0xE0-0xFF
21531
21532 @warning The mapping is **incomplete** in the sense that not all
21533 MessagePack types can be converted to a JSON value. The following
21534 MessagePack types are not supported and will yield parse errors:
21535 - bin 8 - bin 32 (0xC4..0xC6)
21536 - ext 8 - ext 32 (0xC7..0xC9)
21537 - fixext 1 - fixext 16 (0xD4..0xD8)
21538
21539 @note Any MessagePack output created @ref to_msgpack can be successfully
21540 parsed by @ref from_msgpack.
21541
21542 @param[in] i an input in MessagePack format convertible to an input
21543 adapter
21544 @param[in] strict whether to expect the input to be consumed until EOF
21545 (true by default)
21546 @param[in] allow_exceptions whether to throw exceptions in case of a
21547 parse error (optional, true by default)
21548
21549 @return deserialized JSON value; in case of a parse error and
21550 @a allow_exceptions set to `false`, the return value will be
21551 value_t::discarded.
21552
21553 @throw parse_error.110 if the given input ends prematurely or the end of
21554 file was not reached when @a strict was set to true
21555 @throw parse_error.112 if unsupported features from MessagePack were
21556 used in the given input @a i or if the input is not valid MessagePack
21557 @throw parse_error.113 if a string was expected as map key, but not found
21558
21559 @complexity Linear in the size of the input @a i.
21560
21561 @liveexample{The example shows the deserialization of a byte vector in
21562 MessagePack format to a JSON value.,from_msgpack}
21563
21564 @sa http://msgpack.org
21565 @sa @ref to_msgpack(const basic_json&) for the analogous serialization
21566 @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the
21567 related CBOR format
21568 @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for
21569 the related UBJSON format
21570 @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for
21571 the related BSON format
21572
21573 @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
21574 consume input adapters, removed start_index parameter, and added
21575 @a strict parameter since 3.0.0; added @a allow_exceptions parameter
21576 since 3.2.0
21577 */
21578 JSON_HEDLEY_WARN_UNUSED_RESULT
from_msgpack(detail::input_adapter && i,const bool strict=true,const bool allow_exceptions=true)21579 static basic_json from_msgpack(detail::input_adapter&& i,
21580 const bool strict = true,
21581 const bool allow_exceptions = true)
21582 {
21583 basic_json result;
21584 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21585 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict);
21586 return res ? result : basic_json(value_t::discarded);
21587 }
21588
21589 /*!
21590 @copydoc from_msgpack(detail::input_adapter&&, const bool, const bool)
21591 */
21592 template<typename A1, typename A2,
21593 detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
21594 JSON_HEDLEY_WARN_UNUSED_RESULT
from_msgpack(A1 && a1,A2 && a2,const bool strict=true,const bool allow_exceptions=true)21595 static basic_json from_msgpack(A1 && a1, A2 && a2,
21596 const bool strict = true,
21597 const bool allow_exceptions = true)
21598 {
21599 basic_json result;
21600 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21601 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict);
21602 return res ? result : basic_json(value_t::discarded);
21603 }
21604
21605 /*!
21606 @brief create a JSON value from an input in UBJSON format
21607
21608 Deserializes a given input @a i to a JSON value using the UBJSON (Universal
21609 Binary JSON) serialization format.
21610
21611 The library maps UBJSON types to JSON value types as follows:
21612
21613 UBJSON type | JSON value type | marker
21614 ----------- | --------------------------------------- | ------
21615 no-op | *no value, next value is read* | `N`
21616 null | `null` | `Z`
21617 false | `false` | `F`
21618 true | `true` | `T`
21619 float32 | number_float | `d`
21620 float64 | number_float | `D`
21621 uint8 | number_unsigned | `U`
21622 int8 | number_integer | `i`
21623 int16 | number_integer | `I`
21624 int32 | number_integer | `l`
21625 int64 | number_integer | `L`
21626 string | string | `S`
21627 char | string | `C`
21628 array | array (optimized values are supported) | `[`
21629 object | object (optimized values are supported) | `{`
21630
21631 @note The mapping is **complete** in the sense that any UBJSON value can
21632 be converted to a JSON value.
21633
21634 @param[in] i an input in UBJSON format convertible to an input adapter
21635 @param[in] strict whether to expect the input to be consumed until EOF
21636 (true by default)
21637 @param[in] allow_exceptions whether to throw exceptions in case of a
21638 parse error (optional, true by default)
21639
21640 @return deserialized JSON value; in case of a parse error and
21641 @a allow_exceptions set to `false`, the return value will be
21642 value_t::discarded.
21643
21644 @throw parse_error.110 if the given input ends prematurely or the end of
21645 file was not reached when @a strict was set to true
21646 @throw parse_error.112 if a parse error occurs
21647 @throw parse_error.113 if a string could not be parsed successfully
21648
21649 @complexity Linear in the size of the input @a i.
21650
21651 @liveexample{The example shows the deserialization of a byte vector in
21652 UBJSON format to a JSON value.,from_ubjson}
21653
21654 @sa http://ubjson.org
21655 @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
21656 analogous serialization
21657 @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the
21658 related CBOR format
21659 @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
21660 the related MessagePack format
21661 @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for
21662 the related BSON format
21663
21664 @since version 3.1.0; added @a allow_exceptions parameter since 3.2.0
21665 */
21666 JSON_HEDLEY_WARN_UNUSED_RESULT
from_ubjson(detail::input_adapter && i,const bool strict=true,const bool allow_exceptions=true)21667 static basic_json from_ubjson(detail::input_adapter&& i,
21668 const bool strict = true,
21669 const bool allow_exceptions = true)
21670 {
21671 basic_json result;
21672 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21673 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict);
21674 return res ? result : basic_json(value_t::discarded);
21675 }
21676
21677 /*!
21678 @copydoc from_ubjson(detail::input_adapter&&, const bool, const bool)
21679 */
21680 template<typename A1, typename A2,
21681 detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
21682 JSON_HEDLEY_WARN_UNUSED_RESULT
from_ubjson(A1 && a1,A2 && a2,const bool strict=true,const bool allow_exceptions=true)21683 static basic_json from_ubjson(A1 && a1, A2 && a2,
21684 const bool strict = true,
21685 const bool allow_exceptions = true)
21686 {
21687 basic_json result;
21688 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21689 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict);
21690 return res ? result : basic_json(value_t::discarded);
21691 }
21692
21693 /*!
21694 @brief Create a JSON value from an input in BSON format
21695
21696 Deserializes a given input @a i to a JSON value using the BSON (Binary JSON)
21697 serialization format.
21698
21699 The library maps BSON record types to JSON value types as follows:
21700
21701 BSON type | BSON marker byte | JSON value type
21702 --------------- | ---------------- | ---------------------------
21703 double | 0x01 | number_float
21704 string | 0x02 | string
21705 document | 0x03 | object
21706 array | 0x04 | array
21707 binary | 0x05 | still unsupported
21708 undefined | 0x06 | still unsupported
21709 ObjectId | 0x07 | still unsupported
21710 boolean | 0x08 | boolean
21711 UTC Date-Time | 0x09 | still unsupported
21712 null | 0x0A | null
21713 Regular Expr. | 0x0B | still unsupported
21714 DB Pointer | 0x0C | still unsupported
21715 JavaScript Code | 0x0D | still unsupported
21716 Symbol | 0x0E | still unsupported
21717 JavaScript Code | 0x0F | still unsupported
21718 int32 | 0x10 | number_integer
21719 Timestamp | 0x11 | still unsupported
21720 128-bit decimal float | 0x13 | still unsupported
21721 Max Key | 0x7F | still unsupported
21722 Min Key | 0xFF | still unsupported
21723
21724 @warning The mapping is **incomplete**. The unsupported mappings
21725 are indicated in the table above.
21726
21727 @param[in] i an input in BSON format convertible to an input adapter
21728 @param[in] strict whether to expect the input to be consumed until EOF
21729 (true by default)
21730 @param[in] allow_exceptions whether to throw exceptions in case of a
21731 parse error (optional, true by default)
21732
21733 @return deserialized JSON value; in case of a parse error and
21734 @a allow_exceptions set to `false`, the return value will be
21735 value_t::discarded.
21736
21737 @throw parse_error.114 if an unsupported BSON record type is encountered
21738
21739 @complexity Linear in the size of the input @a i.
21740
21741 @liveexample{The example shows the deserialization of a byte vector in
21742 BSON format to a JSON value.,from_bson}
21743
21744 @sa http://bsonspec.org/spec.html
21745 @sa @ref to_bson(const basic_json&) for the analogous serialization
21746 @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the
21747 related CBOR format
21748 @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
21749 the related MessagePack format
21750 @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
21751 related UBJSON format
21752 */
21753 JSON_HEDLEY_WARN_UNUSED_RESULT
from_bson(detail::input_adapter && i,const bool strict=true,const bool allow_exceptions=true)21754 static basic_json from_bson(detail::input_adapter&& i,
21755 const bool strict = true,
21756 const bool allow_exceptions = true)
21757 {
21758 basic_json result;
21759 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21760 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::bson, &sdp, strict);
21761 return res ? result : basic_json(value_t::discarded);
21762 }
21763
21764 /*!
21765 @copydoc from_bson(detail::input_adapter&&, const bool, const bool)
21766 */
21767 template<typename A1, typename A2,
21768 detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
21769 JSON_HEDLEY_WARN_UNUSED_RESULT
from_bson(A1 && a1,A2 && a2,const bool strict=true,const bool allow_exceptions=true)21770 static basic_json from_bson(A1 && a1, A2 && a2,
21771 const bool strict = true,
21772 const bool allow_exceptions = true)
21773 {
21774 basic_json result;
21775 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
21776 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::bson, &sdp, strict);
21777 return res ? result : basic_json(value_t::discarded);
21778 }
21779
21780
21781
21782 /// @}
21783
21784 //////////////////////////
21785 // JSON Pointer support //
21786 //////////////////////////
21787
21788 /// @name JSON Pointer functions
21789 /// @{
21790
21791 /*!
21792 @brief access specified element via JSON Pointer
21793
21794 Uses a JSON pointer to retrieve a reference to the respective JSON value.
21795 No bound checking is performed. Similar to @ref operator[](const typename
21796 object_t::key_type&), `null` values are created in arrays and objects if
21797 necessary.
21798
21799 In particular:
21800 - If the JSON pointer points to an object key that does not exist, it
21801 is created an filled with a `null` value before a reference to it
21802 is returned.
21803 - If the JSON pointer points to an array index that does not exist, it
21804 is created an filled with a `null` value before a reference to it
21805 is returned. All indices between the current maximum and the given
21806 index are also filled with `null`.
21807 - The special value `-` is treated as a synonym for the index past the
21808 end.
21809
21810 @param[in] ptr a JSON pointer
21811
21812 @return reference to the element pointed to by @a ptr
21813
21814 @complexity Constant.
21815
21816 @throw parse_error.106 if an array index begins with '0'
21817 @throw parse_error.109 if an array index was not a number
21818 @throw out_of_range.404 if the JSON pointer can not be resolved
21819
21820 @liveexample{The behavior is shown in the example.,operatorjson_pointer}
21821
21822 @since version 2.0.0
21823 */
operator [](const json_pointer & ptr)21824 reference operator[](const json_pointer& ptr)
21825 {
21826 return ptr.get_unchecked(this);
21827 }
21828
21829 /*!
21830 @brief access specified element via JSON Pointer
21831
21832 Uses a JSON pointer to retrieve a reference to the respective JSON value.
21833 No bound checking is performed. The function does not change the JSON
21834 value; no `null` values are created. In particular, the the special value
21835 `-` yields an exception.
21836
21837 @param[in] ptr JSON pointer to the desired element
21838
21839 @return const reference to the element pointed to by @a ptr
21840
21841 @complexity Constant.
21842
21843 @throw parse_error.106 if an array index begins with '0'
21844 @throw parse_error.109 if an array index was not a number
21845 @throw out_of_range.402 if the array index '-' is used
21846 @throw out_of_range.404 if the JSON pointer can not be resolved
21847
21848 @liveexample{The behavior is shown in the example.,operatorjson_pointer_const}
21849
21850 @since version 2.0.0
21851 */
operator [](const json_pointer & ptr) const21852 const_reference operator[](const json_pointer& ptr) const
21853 {
21854 return ptr.get_unchecked(this);
21855 }
21856
21857 /*!
21858 @brief access specified element via JSON Pointer
21859
21860 Returns a reference to the element at with specified JSON pointer @a ptr,
21861 with bounds checking.
21862
21863 @param[in] ptr JSON pointer to the desired element
21864
21865 @return reference to the element pointed to by @a ptr
21866
21867 @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
21868 begins with '0'. See example below.
21869
21870 @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
21871 is not a number. See example below.
21872
21873 @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
21874 is out of range. See example below.
21875
21876 @throw out_of_range.402 if the array index '-' is used in the passed JSON
21877 pointer @a ptr. As `at` provides checked access (and no elements are
21878 implicitly inserted), the index '-' is always invalid. See example below.
21879
21880 @throw out_of_range.403 if the JSON pointer describes a key of an object
21881 which cannot be found. See example below.
21882
21883 @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
21884 See example below.
21885
21886 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
21887 changes in the JSON value.
21888
21889 @complexity Constant.
21890
21891 @since version 2.0.0
21892
21893 @liveexample{The behavior is shown in the example.,at_json_pointer}
21894 */
at(const json_pointer & ptr)21895 reference at(const json_pointer& ptr)
21896 {
21897 return ptr.get_checked(this);
21898 }
21899
21900 /*!
21901 @brief access specified element via JSON Pointer
21902
21903 Returns a const reference to the element at with specified JSON pointer @a
21904 ptr, with bounds checking.
21905
21906 @param[in] ptr JSON pointer to the desired element
21907
21908 @return reference to the element pointed to by @a ptr
21909
21910 @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
21911 begins with '0'. See example below.
21912
21913 @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
21914 is not a number. See example below.
21915
21916 @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
21917 is out of range. See example below.
21918
21919 @throw out_of_range.402 if the array index '-' is used in the passed JSON
21920 pointer @a ptr. As `at` provides checked access (and no elements are
21921 implicitly inserted), the index '-' is always invalid. See example below.
21922
21923 @throw out_of_range.403 if the JSON pointer describes a key of an object
21924 which cannot be found. See example below.
21925
21926 @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
21927 See example below.
21928
21929 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
21930 changes in the JSON value.
21931
21932 @complexity Constant.
21933
21934 @since version 2.0.0
21935
21936 @liveexample{The behavior is shown in the example.,at_json_pointer_const}
21937 */
at(const json_pointer & ptr) const21938 const_reference at(const json_pointer& ptr) const
21939 {
21940 return ptr.get_checked(this);
21941 }
21942
21943 /*!
21944 @brief return flattened JSON value
21945
21946 The function creates a JSON object whose keys are JSON pointers (see [RFC
21947 6901](https://tools.ietf.org/html/rfc6901)) and whose values are all
21948 primitive. The original JSON value can be restored using the @ref
21949 unflatten() function.
21950
21951 @return an object that maps JSON pointers to primitive values
21952
21953 @note Empty objects and arrays are flattened to `null` and will not be
21954 reconstructed correctly by the @ref unflatten() function.
21955
21956 @complexity Linear in the size the JSON value.
21957
21958 @liveexample{The following code shows how a JSON object is flattened to an
21959 object whose keys consist of JSON pointers.,flatten}
21960
21961 @sa @ref unflatten() for the reverse function
21962
21963 @since version 2.0.0
21964 */
flatten() const21965 basic_json flatten() const
21966 {
21967 basic_json result(value_t::object);
21968 json_pointer::flatten("", *this, result);
21969 return result;
21970 }
21971
21972 /*!
21973 @brief unflatten a previously flattened JSON value
21974
21975 The function restores the arbitrary nesting of a JSON value that has been
21976 flattened before using the @ref flatten() function. The JSON value must
21977 meet certain constraints:
21978 1. The value must be an object.
21979 2. The keys must be JSON pointers (see
21980 [RFC 6901](https://tools.ietf.org/html/rfc6901))
21981 3. The mapped values must be primitive JSON types.
21982
21983 @return the original JSON from a flattened version
21984
21985 @note Empty objects and arrays are flattened by @ref flatten() to `null`
21986 values and can not unflattened to their original type. Apart from
21987 this example, for a JSON value `j`, the following is always true:
21988 `j == j.flatten().unflatten()`.
21989
21990 @complexity Linear in the size the JSON value.
21991
21992 @throw type_error.314 if value is not an object
21993 @throw type_error.315 if object values are not primitive
21994
21995 @liveexample{The following code shows how a flattened JSON object is
21996 unflattened into the original nested JSON object.,unflatten}
21997
21998 @sa @ref flatten() for the reverse function
21999
22000 @since version 2.0.0
22001 */
unflatten() const22002 basic_json unflatten() const
22003 {
22004 return json_pointer::unflatten(*this);
22005 }
22006
22007 /// @}
22008
22009 //////////////////////////
22010 // JSON Patch functions //
22011 //////////////////////////
22012
22013 /// @name JSON Patch functions
22014 /// @{
22015
22016 /*!
22017 @brief applies a JSON patch
22018
22019 [JSON Patch](http://jsonpatch.com) defines a JSON document structure for
22020 expressing a sequence of operations to apply to a JSON) document. With
22021 this function, a JSON Patch is applied to the current JSON value by
22022 executing all operations from the patch.
22023
22024 @param[in] json_patch JSON patch document
22025 @return patched document
22026
22027 @note The application of a patch is atomic: Either all operations succeed
22028 and the patched document is returned or an exception is thrown. In
22029 any case, the original value is not changed: the patch is applied
22030 to a copy of the value.
22031
22032 @throw parse_error.104 if the JSON patch does not consist of an array of
22033 objects
22034
22035 @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory
22036 attributes are missing); example: `"operation add must have member path"`
22037
22038 @throw out_of_range.401 if an array index is out of range.
22039
22040 @throw out_of_range.403 if a JSON pointer inside the patch could not be
22041 resolved successfully in the current JSON value; example: `"key baz not
22042 found"`
22043
22044 @throw out_of_range.405 if JSON pointer has no parent ("add", "remove",
22045 "move")
22046
22047 @throw other_error.501 if "test" operation was unsuccessful
22048
22049 @complexity Linear in the size of the JSON value and the length of the
22050 JSON patch. As usually only a fraction of the JSON value is affected by
22051 the patch, the complexity can usually be neglected.
22052
22053 @liveexample{The following code shows how a JSON patch is applied to a
22054 value.,patch}
22055
22056 @sa @ref diff -- create a JSON patch by comparing two JSON values
22057
22058 @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
22059 @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901)
22060
22061 @since version 2.0.0
22062 */
patch(const basic_json & json_patch) const22063 basic_json patch(const basic_json& json_patch) const
22064 {
22065 // make a working copy to apply the patch to
22066 basic_json result = *this;
22067
22068 // the valid JSON Patch operations
22069 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
22070
22071 const auto get_op = [](const std::string & op)
22072 {
22073 if (op == "add")
22074 {
22075 return patch_operations::add;
22076 }
22077 if (op == "remove")
22078 {
22079 return patch_operations::remove;
22080 }
22081 if (op == "replace")
22082 {
22083 return patch_operations::replace;
22084 }
22085 if (op == "move")
22086 {
22087 return patch_operations::move;
22088 }
22089 if (op == "copy")
22090 {
22091 return patch_operations::copy;
22092 }
22093 if (op == "test")
22094 {
22095 return patch_operations::test;
22096 }
22097
22098 return patch_operations::invalid;
22099 };
22100
22101 // wrapper for "add" operation; add value at ptr
22102 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
22103 {
22104 // adding to the root of the target document means replacing it
22105 if (ptr.empty())
22106 {
22107 result = val;
22108 return;
22109 }
22110
22111 // make sure the top element of the pointer exists
22112 json_pointer top_pointer = ptr.top();
22113 if (top_pointer != ptr)
22114 {
22115 result.at(top_pointer);
22116 }
22117
22118 // get reference to parent of JSON pointer ptr
22119 const auto last_path = ptr.back();
22120 ptr.pop_back();
22121 basic_json& parent = result[ptr];
22122
22123 switch (parent.m_type)
22124 {
22125 case value_t::null:
22126 case value_t::object:
22127 {
22128 // use operator[] to add value
22129 parent[last_path] = val;
22130 break;
22131 }
22132
22133 case value_t::array:
22134 {
22135 if (last_path == "-")
22136 {
22137 // special case: append to back
22138 parent.push_back(val);
22139 }
22140 else
22141 {
22142 const auto idx = json_pointer::array_index(last_path);
22143 if (JSON_HEDLEY_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
22144 {
22145 // avoid undefined behavior
22146 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
22147 }
22148
22149 // default case: insert add offset
22150 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
22151 }
22152 break;
22153 }
22154
22155 // if there exists a parent it cannot be primitive
22156 default: // LCOV_EXCL_LINE
22157 assert(false); // LCOV_EXCL_LINE
22158 }
22159 };
22160
22161 // wrapper for "remove" operation; remove value at ptr
22162 const auto operation_remove = [&result](json_pointer & ptr)
22163 {
22164 // get reference to parent of JSON pointer ptr
22165 const auto last_path = ptr.back();
22166 ptr.pop_back();
22167 basic_json& parent = result.at(ptr);
22168
22169 // remove child
22170 if (parent.is_object())
22171 {
22172 // perform range check
22173 auto it = parent.find(last_path);
22174 if (JSON_HEDLEY_LIKELY(it != parent.end()))
22175 {
22176 parent.erase(it);
22177 }
22178 else
22179 {
22180 JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found"));
22181 }
22182 }
22183 else if (parent.is_array())
22184 {
22185 // note erase performs range check
22186 parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));
22187 }
22188 };
22189
22190 // type check: top level value must be an array
22191 if (JSON_HEDLEY_UNLIKELY(not json_patch.is_array()))
22192 {
22193 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
22194 }
22195
22196 // iterate and apply the operations
22197 for (const auto& val : json_patch)
22198 {
22199 // wrapper to get a value for an operation
22200 const auto get_value = [&val](const std::string & op,
22201 const std::string & member,
22202 bool string_type) -> basic_json &
22203 {
22204 // find value
22205 auto it = val.m_value.object->find(member);
22206
22207 // context-sensitive error message
22208 const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
22209
22210 // check if desired value is present
22211 if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
22212 {
22213 JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
22214 }
22215
22216 // check if result is of type string
22217 if (JSON_HEDLEY_UNLIKELY(string_type and not it->second.is_string()))
22218 {
22219 JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
22220 }
22221
22222 // no error: return value
22223 return it->second;
22224 };
22225
22226 // type check: every element of the array must be an object
22227 if (JSON_HEDLEY_UNLIKELY(not val.is_object()))
22228 {
22229 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
22230 }
22231
22232 // collect mandatory members
22233 const std::string op = get_value("op", "op", true);
22234 const std::string path = get_value(op, "path", true);
22235 json_pointer ptr(path);
22236
22237 switch (get_op(op))
22238 {
22239 case patch_operations::add:
22240 {
22241 operation_add(ptr, get_value("add", "value", false));
22242 break;
22243 }
22244
22245 case patch_operations::remove:
22246 {
22247 operation_remove(ptr);
22248 break;
22249 }
22250
22251 case patch_operations::replace:
22252 {
22253 // the "path" location must exist - use at()
22254 result.at(ptr) = get_value("replace", "value", false);
22255 break;
22256 }
22257
22258 case patch_operations::move:
22259 {
22260 const std::string from_path = get_value("move", "from", true);
22261 json_pointer from_ptr(from_path);
22262
22263 // the "from" location must exist - use at()
22264 basic_json v = result.at(from_ptr);
22265
22266 // The move operation is functionally identical to a
22267 // "remove" operation on the "from" location, followed
22268 // immediately by an "add" operation at the target
22269 // location with the value that was just removed.
22270 operation_remove(from_ptr);
22271 operation_add(ptr, v);
22272 break;
22273 }
22274
22275 case patch_operations::copy:
22276 {
22277 const std::string from_path = get_value("copy", "from", true);
22278 const json_pointer from_ptr(from_path);
22279
22280 // the "from" location must exist - use at()
22281 basic_json v = result.at(from_ptr);
22282
22283 // The copy is functionally identical to an "add"
22284 // operation at the target location using the value
22285 // specified in the "from" member.
22286 operation_add(ptr, v);
22287 break;
22288 }
22289
22290 case patch_operations::test:
22291 {
22292 bool success = false;
22293 JSON_TRY
22294 {
22295 // check if "value" matches the one at "path"
22296 // the "path" location must exist - use at()
22297 success = (result.at(ptr) == get_value("test", "value", false));
22298 }
22299 JSON_INTERNAL_CATCH (out_of_range&)
22300 {
22301 // ignore out of range errors: success remains false
22302 }
22303
22304 // throw an exception if test fails
22305 if (JSON_HEDLEY_UNLIKELY(not success))
22306 {
22307 JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
22308 }
22309
22310 break;
22311 }
22312
22313 default:
22314 {
22315 // op must be "add", "remove", "replace", "move", "copy", or
22316 // "test"
22317 JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid"));
22318 }
22319 }
22320 }
22321
22322 return result;
22323 }
22324
22325 /*!
22326 @brief creates a diff as a JSON patch
22327
22328 Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can
22329 be changed into the value @a target by calling @ref patch function.
22330
22331 @invariant For two JSON values @a source and @a target, the following code
22332 yields always `true`:
22333 @code {.cpp}
22334 source.patch(diff(source, target)) == target;
22335 @endcode
22336
22337 @note Currently, only `remove`, `add`, and `replace` operations are
22338 generated.
22339
22340 @param[in] source JSON value to compare from
22341 @param[in] target JSON value to compare against
22342 @param[in] path helper value to create JSON pointers
22343
22344 @return a JSON patch to convert the @a source to @a target
22345
22346 @complexity Linear in the lengths of @a source and @a target.
22347
22348 @liveexample{The following code shows how a JSON patch is created as a
22349 diff for two JSON values.,diff}
22350
22351 @sa @ref patch -- apply a JSON patch
22352 @sa @ref merge_patch -- apply a JSON Merge Patch
22353
22354 @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
22355
22356 @since version 2.0.0
22357 */
22358 JSON_HEDLEY_WARN_UNUSED_RESULT
diff(const basic_json & source,const basic_json & target,const std::string & path="")22359 static basic_json diff(const basic_json& source, const basic_json& target,
22360 const std::string& path = "")
22361 {
22362 // the patch
22363 basic_json result(value_t::array);
22364
22365 // if the values are the same, return empty patch
22366 if (source == target)
22367 {
22368 return result;
22369 }
22370
22371 if (source.type() != target.type())
22372 {
22373 // different types: replace value
22374 result.push_back(
22375 {
22376 {"op", "replace"}, {"path", path}, {"value", target}
22377 });
22378 return result;
22379 }
22380
22381 switch (source.type())
22382 {
22383 case value_t::array:
22384 {
22385 // first pass: traverse common elements
22386 std::size_t i = 0;
22387 while (i < source.size() and i < target.size())
22388 {
22389 // recursive call to compare array values at index i
22390 auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
22391 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
22392 ++i;
22393 }
22394
22395 // i now reached the end of at least one array
22396 // in a second pass, traverse the remaining elements
22397
22398 // remove my remaining elements
22399 const auto end_index = static_cast<difference_type>(result.size());
22400 while (i < source.size())
22401 {
22402 // add operations in reverse order to avoid invalid
22403 // indices
22404 result.insert(result.begin() + end_index, object(
22405 {
22406 {"op", "remove"},
22407 {"path", path + "/" + std::to_string(i)}
22408 }));
22409 ++i;
22410 }
22411
22412 // add other remaining elements
22413 while (i < target.size())
22414 {
22415 result.push_back(
22416 {
22417 {"op", "add"},
22418 {"path", path + "/" + std::to_string(i)},
22419 {"value", target[i]}
22420 });
22421 ++i;
22422 }
22423
22424 break;
22425 }
22426
22427 case value_t::object:
22428 {
22429 // first pass: traverse this object's elements
22430 for (auto it = source.cbegin(); it != source.cend(); ++it)
22431 {
22432 // escape the key name to be used in a JSON patch
22433 const auto key = json_pointer::escape(it.key());
22434
22435 if (target.find(it.key()) != target.end())
22436 {
22437 // recursive call to compare object values at key it
22438 auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
22439 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
22440 }
22441 else
22442 {
22443 // found a key that is not in o -> remove it
22444 result.push_back(object(
22445 {
22446 {"op", "remove"}, {"path", path + "/" + key}
22447 }));
22448 }
22449 }
22450
22451 // second pass: traverse other object's elements
22452 for (auto it = target.cbegin(); it != target.cend(); ++it)
22453 {
22454 if (source.find(it.key()) == source.end())
22455 {
22456 // found a key that is not in this -> add it
22457 const auto key = json_pointer::escape(it.key());
22458 result.push_back(
22459 {
22460 {"op", "add"}, {"path", path + "/" + key},
22461 {"value", it.value()}
22462 });
22463 }
22464 }
22465
22466 break;
22467 }
22468
22469 default:
22470 {
22471 // both primitive type: replace value
22472 result.push_back(
22473 {
22474 {"op", "replace"}, {"path", path}, {"value", target}
22475 });
22476 break;
22477 }
22478 }
22479
22480 return result;
22481 }
22482
22483 /// @}
22484
22485 ////////////////////////////////
22486 // JSON Merge Patch functions //
22487 ////////////////////////////////
22488
22489 /// @name JSON Merge Patch functions
22490 /// @{
22491
22492 /*!
22493 @brief applies a JSON Merge Patch
22494
22495 The merge patch format is primarily intended for use with the HTTP PATCH
22496 method as a means of describing a set of modifications to a target
22497 resource's content. This function applies a merge patch to the current
22498 JSON value.
22499
22500 The function implements the following algorithm from Section 2 of
22501 [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396):
22502
22503 ```
22504 define MergePatch(Target, Patch):
22505 if Patch is an Object:
22506 if Target is not an Object:
22507 Target = {} // Ignore the contents and set it to an empty Object
22508 for each Name/Value pair in Patch:
22509 if Value is null:
22510 if Name exists in Target:
22511 remove the Name/Value pair from Target
22512 else:
22513 Target[Name] = MergePatch(Target[Name], Value)
22514 return Target
22515 else:
22516 return Patch
22517 ```
22518
22519 Thereby, `Target` is the current object; that is, the patch is applied to
22520 the current value.
22521
22522 @param[in] apply_patch the patch to apply
22523
22524 @complexity Linear in the lengths of @a patch.
22525
22526 @liveexample{The following code shows how a JSON Merge Patch is applied to
22527 a JSON document.,merge_patch}
22528
22529 @sa @ref patch -- apply a JSON patch
22530 @sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396)
22531
22532 @since version 3.0.0
22533 */
merge_patch(const basic_json & apply_patch)22534 void merge_patch(const basic_json& apply_patch)
22535 {
22536 if (apply_patch.is_object())
22537 {
22538 if (not is_object())
22539 {
22540 *this = object();
22541 }
22542 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
22543 {
22544 if (it.value().is_null())
22545 {
22546 erase(it.key());
22547 }
22548 else
22549 {
22550 operator[](it.key()).merge_patch(it.value());
22551 }
22552 }
22553 }
22554 else
22555 {
22556 *this = apply_patch;
22557 }
22558 }
22559
22560 /// @}
22561 };
22562
22563 /*!
22564 @brief user-defined to_string function for JSON values
22565
22566 This function implements a user-defined to_string for JSON objects.
22567
22568 @param[in] j a JSON object
22569 @return a std::string object
22570 */
22571
22572 NLOHMANN_BASIC_JSON_TPL_DECLARATION
to_string(const NLOHMANN_BASIC_JSON_TPL & j)22573 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
22574 {
22575 return j.dump();
22576 }
22577 } // namespace nlohmann
22578
22579 ///////////////////////
22580 // nonmember support //
22581 ///////////////////////
22582
22583 // specialization of std::swap, and std::hash
22584 namespace std
22585 {
22586
22587 /// hash value for JSON objects
22588 template<>
22589 struct hash<nlohmann::json>
22590 {
22591 /*!
22592 @brief return a hash value for a JSON object
22593
22594 @since version 1.0.0
22595 */
operator ()std::hash22596 std::size_t operator()(const nlohmann::json& j) const
22597 {
22598 // a naive hashing via the string representation
22599 const auto& h = hash<nlohmann::json::string_t>();
22600 return h(j.dump());
22601 }
22602 };
22603
22604 /// specialization for std::less<value_t>
22605 /// @note: do not remove the space after '<',
22606 /// see https://github.com/nlohmann/json/pull/679
22607 template<>
22608 struct less<::nlohmann::detail::value_t>
22609 {
22610 /*!
22611 @brief compare two value_t enum values
22612 @since version 3.0.0
22613 */
operator ()std::less22614 bool operator()(nlohmann::detail::value_t lhs,
22615 nlohmann::detail::value_t rhs) const noexcept
22616 {
22617 return nlohmann::detail::operator<(lhs, rhs);
22618 }
22619 };
22620
22621 /*!
22622 @brief exchanges the values of two JSON objects
22623
22624 @since version 1.0.0
22625 */
22626 template<>
swap(nlohmann::json & j1,nlohmann::json & j2)22627 inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
22628 is_nothrow_move_constructible<nlohmann::json>::value and
22629 is_nothrow_move_assignable<nlohmann::json>::value
22630 )
22631 {
22632 j1.swap(j2);
22633 }
22634
22635 } // namespace std
22636
22637 /*!
22638 @brief user-defined string literal for JSON values
22639
22640 This operator implements a user-defined string literal for JSON objects. It
22641 can be used by adding `"_json"` to a string literal and returns a JSON object
22642 if no parse error occurred.
22643
22644 @param[in] s a string representation of a JSON object
22645 @param[in] n the length of string @a s
22646 @return a JSON object
22647
22648 @since version 1.0.0
22649 */
22650 JSON_HEDLEY_NON_NULL(1)
operator ""_json(const char * s,std::size_t n)22651 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
22652 {
22653 return nlohmann::json::parse(s, s + n);
22654 }
22655
22656 /*!
22657 @brief user-defined string literal for JSON pointer
22658
22659 This operator implements a user-defined string literal for JSON Pointers. It
22660 can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer
22661 object if no parse error occurred.
22662
22663 @param[in] s a string representation of a JSON Pointer
22664 @param[in] n the length of string @a s
22665 @return a JSON pointer object
22666
22667 @since version 2.0.0
22668 */
22669 JSON_HEDLEY_NON_NULL(1)
operator ""_json_pointer(const char * s,std::size_t n)22670 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
22671 {
22672 return nlohmann::json::json_pointer(std::string(s, n));
22673 }
22674
22675 // #include <nlohmann/detail/macro_unscope.hpp>
22676
22677
22678 // restore GCC/clang diagnostic settings
22679 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
22680 #pragma GCC diagnostic pop
22681 #endif
22682 #if defined(__clang__)
22683 #pragma GCC diagnostic pop
22684 #endif
22685
22686 // clean up
22687 #undef JSON_INTERNAL_CATCH
22688 #undef JSON_CATCH
22689 #undef JSON_THROW
22690 #undef JSON_TRY
22691 #undef JSON_HAS_CPP_14
22692 #undef JSON_HAS_CPP_17
22693 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
22694 #undef NLOHMANN_BASIC_JSON_TPL
22695
22696 // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
22697 #undef JSON_HEDLEY_ALWAYS_INLINE
22698 #undef JSON_HEDLEY_ARM_VERSION
22699 #undef JSON_HEDLEY_ARM_VERSION_CHECK
22700 #undef JSON_HEDLEY_ARRAY_PARAM
22701 #undef JSON_HEDLEY_ASSUME
22702 #undef JSON_HEDLEY_BEGIN_C_DECLS
22703 #undef JSON_HEDLEY_C_DECL
22704 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
22705 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
22706 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
22707 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
22708 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
22709 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
22710 #undef JSON_HEDLEY_CLANG_HAS_WARNING
22711 #undef JSON_HEDLEY_COMPCERT_VERSION
22712 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
22713 #undef JSON_HEDLEY_CONCAT
22714 #undef JSON_HEDLEY_CONCAT_EX
22715 #undef JSON_HEDLEY_CONST
22716 #undef JSON_HEDLEY_CONST_CAST
22717 #undef JSON_HEDLEY_CONSTEXPR
22718 #undef JSON_HEDLEY_CPP_CAST
22719 #undef JSON_HEDLEY_CRAY_VERSION
22720 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
22721 #undef JSON_HEDLEY_DEPRECATED
22722 #undef JSON_HEDLEY_DEPRECATED_FOR
22723 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
22724 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
22725 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
22726 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
22727 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
22728 #undef JSON_HEDLEY_DIAGNOSTIC_POP
22729 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
22730 #undef JSON_HEDLEY_DMC_VERSION
22731 #undef JSON_HEDLEY_DMC_VERSION_CHECK
22732 #undef JSON_HEDLEY_EMPTY_BASES
22733 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
22734 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
22735 #undef JSON_HEDLEY_END_C_DECLS
22736 #undef JSON_HEDLEY_FALL_THROUGH
22737 #undef JSON_HEDLEY_FLAGS
22738 #undef JSON_HEDLEY_FLAGS_CAST
22739 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
22740 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
22741 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
22742 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
22743 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
22744 #undef JSON_HEDLEY_GCC_HAS_FEATURE
22745 #undef JSON_HEDLEY_GCC_HAS_WARNING
22746 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
22747 #undef JSON_HEDLEY_GCC_VERSION
22748 #undef JSON_HEDLEY_GCC_VERSION_CHECK
22749 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
22750 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
22751 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
22752 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
22753 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
22754 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
22755 #undef JSON_HEDLEY_GNUC_HAS_WARNING
22756 #undef JSON_HEDLEY_GNUC_VERSION
22757 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
22758 #undef JSON_HEDLEY_HAS_ATTRIBUTE
22759 #undef JSON_HEDLEY_HAS_BUILTIN
22760 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
22761 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
22762 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
22763 #undef JSON_HEDLEY_HAS_EXTENSION
22764 #undef JSON_HEDLEY_HAS_FEATURE
22765 #undef JSON_HEDLEY_HAS_WARNING
22766 #undef JSON_HEDLEY_IAR_VERSION
22767 #undef JSON_HEDLEY_IAR_VERSION_CHECK
22768 #undef JSON_HEDLEY_IBM_VERSION
22769 #undef JSON_HEDLEY_IBM_VERSION_CHECK
22770 #undef JSON_HEDLEY_IMPORT
22771 #undef JSON_HEDLEY_INLINE
22772 #undef JSON_HEDLEY_INTEL_VERSION
22773 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
22774 #undef JSON_HEDLEY_IS_CONSTANT
22775 #undef JSON_HEDLEY_IS_CONSTEXPR_
22776 #undef JSON_HEDLEY_LIKELY
22777 #undef JSON_HEDLEY_MALLOC
22778 #undef JSON_HEDLEY_MESSAGE
22779 #undef JSON_HEDLEY_MSVC_VERSION
22780 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
22781 #undef JSON_HEDLEY_NEVER_INLINE
22782 #undef JSON_HEDLEY_NO_ESCAPE
22783 #undef JSON_HEDLEY_NON_NULL
22784 #undef JSON_HEDLEY_NO_RETURN
22785 #undef JSON_HEDLEY_NO_THROW
22786 #undef JSON_HEDLEY_NULL
22787 #undef JSON_HEDLEY_PELLES_VERSION
22788 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
22789 #undef JSON_HEDLEY_PGI_VERSION
22790 #undef JSON_HEDLEY_PGI_VERSION_CHECK
22791 #undef JSON_HEDLEY_PREDICT
22792 #undef JSON_HEDLEY_PRINTF_FORMAT
22793 #undef JSON_HEDLEY_PRIVATE
22794 #undef JSON_HEDLEY_PUBLIC
22795 #undef JSON_HEDLEY_PURE
22796 #undef JSON_HEDLEY_REINTERPRET_CAST
22797 #undef JSON_HEDLEY_REQUIRE
22798 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
22799 #undef JSON_HEDLEY_REQUIRE_MSG
22800 #undef JSON_HEDLEY_RESTRICT
22801 #undef JSON_HEDLEY_RETURNS_NON_NULL
22802 #undef JSON_HEDLEY_SENTINEL
22803 #undef JSON_HEDLEY_STATIC_ASSERT
22804 #undef JSON_HEDLEY_STATIC_CAST
22805 #undef JSON_HEDLEY_STRINGIFY
22806 #undef JSON_HEDLEY_STRINGIFY_EX
22807 #undef JSON_HEDLEY_SUNPRO_VERSION
22808 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
22809 #undef JSON_HEDLEY_TINYC_VERSION
22810 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
22811 #undef JSON_HEDLEY_TI_VERSION
22812 #undef JSON_HEDLEY_TI_VERSION_CHECK
22813 #undef JSON_HEDLEY_UNAVAILABLE
22814 #undef JSON_HEDLEY_UNLIKELY
22815 #undef JSON_HEDLEY_UNPREDICTABLE
22816 #undef JSON_HEDLEY_UNREACHABLE
22817 #undef JSON_HEDLEY_UNREACHABLE_RETURN
22818 #undef JSON_HEDLEY_VERSION
22819 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
22820 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
22821 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
22822 #undef JSON_HEDLEY_VERSION_ENCODE
22823 #undef JSON_HEDLEY_WARNING
22824 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
22825
22826
22827
22828 #endif // INCLUDE_NLOHMANN_JSON_HPP_
22829