1 /*
2 __ _____ _____ _____
3 __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 3.9.1
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 SPDX-License-Identifier: MIT
9 Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
10
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
28 */
29
30 #ifndef INCLUDE_NLOHMANN_JSON_HPP_
31 #define INCLUDE_NLOHMANN_JSON_HPP_
32
33 #define NLOHMANN_JSON_VERSION_MAJOR 3
34 #define NLOHMANN_JSON_VERSION_MINOR 9
35 #define NLOHMANN_JSON_VERSION_PATCH 1
36
37 #include <algorithm> // all_of, find, for_each
38 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
39 #include <functional> // hash, less
40 #include <initializer_list> // initializer_list
41 #include <iosfwd> // istream, ostream
42 #include <iterator> // random_access_iterator_tag
43 #include <memory> // unique_ptr
44 #include <numeric> // accumulate
45 #include <string> // string, stoi, to_string
46 #include <utility> // declval, forward, move, pair, swap
47 #include <vector> // vector
48
49 // #include <nlohmann/adl_serializer.hpp>
50
51
52 #include <utility>
53
54 // #include <nlohmann/detail/conversions/from_json.hpp>
55
56
57 #include <algorithm> // transform
58 #include <array> // array
59 #include <forward_list> // forward_list
60 #include <iterator> // inserter, front_inserter, end
61 #include <map> // map
62 #include <string> // string
63 #include <tuple> // tuple, make_tuple
64 #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
65 #include <unordered_map> // unordered_map
66 #include <utility> // pair, declval
67 #include <valarray> // valarray
68
69 // #include <nlohmann/detail/exceptions.hpp>
70
71
72 #include <exception> // exception
73 #include <stdexcept> // runtime_error
74 #include <string> // to_string
75
76 // #include <nlohmann/detail/input/position_t.hpp>
77
78
79 #include <cstddef> // size_t
80
81 namespace nlohmann
82 {
83 namespace detail
84 {
85 /// struct to capture the start position of the current token
86 struct position_t
87 {
88 /// the total number of characters read
89 std::size_t chars_read_total = 0;
90 /// the number of characters read in the current line
91 std::size_t chars_read_current_line = 0;
92 /// the number of lines read
93 std::size_t lines_read = 0;
94
95 /// conversion to size_t to preserve SAX interface
operator size_tnlohmann::detail::position_t96 constexpr operator size_t() const
97 {
98 return chars_read_total;
99 }
100 };
101
102 } // namespace detail
103 } // namespace nlohmann
104
105 // #include <nlohmann/detail/macro_scope.hpp>
106
107
108 #include <utility> // pair
109 // #include <nlohmann/thirdparty/hedley/hedley.hpp>
110 /* Hedley - https://nemequ.github.io/hedley
111 * Created by Evan Nemerson <evan@nemerson.com>
112 *
113 * To the extent possible under law, the author(s) have dedicated all
114 * copyright and related and neighboring rights to this software to
115 * the public domain worldwide. This software is distributed without
116 * any warranty.
117 *
118 * For details, see <http://creativecommons.org/publicdomain/zero/1.0/>.
119 * SPDX-License-Identifier: CC0-1.0
120 */
121
122 #if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 13)
123 #if defined(JSON_HEDLEY_VERSION)
124 #undef JSON_HEDLEY_VERSION
125 #endif
126 #define JSON_HEDLEY_VERSION 13
127
128 #if defined(JSON_HEDLEY_STRINGIFY_EX)
129 #undef JSON_HEDLEY_STRINGIFY_EX
130 #endif
131 #define JSON_HEDLEY_STRINGIFY_EX(x) #x
132
133 #if defined(JSON_HEDLEY_STRINGIFY)
134 #undef JSON_HEDLEY_STRINGIFY
135 #endif
136 #define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
137
138 #if defined(JSON_HEDLEY_CONCAT_EX)
139 #undef JSON_HEDLEY_CONCAT_EX
140 #endif
141 #define JSON_HEDLEY_CONCAT_EX(a,b) a##b
142
143 #if defined(JSON_HEDLEY_CONCAT)
144 #undef JSON_HEDLEY_CONCAT
145 #endif
146 #define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
147
148 #if defined(JSON_HEDLEY_CONCAT3_EX)
149 #undef JSON_HEDLEY_CONCAT3_EX
150 #endif
151 #define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
152
153 #if defined(JSON_HEDLEY_CONCAT3)
154 #undef JSON_HEDLEY_CONCAT3
155 #endif
156 #define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
157
158 #if defined(JSON_HEDLEY_VERSION_ENCODE)
159 #undef JSON_HEDLEY_VERSION_ENCODE
160 #endif
161 #define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
162
163 #if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
164 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
165 #endif
166 #define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
167
168 #if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
169 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
170 #endif
171 #define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
172
173 #if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
174 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
175 #endif
176 #define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
177
178 #if defined(JSON_HEDLEY_GNUC_VERSION)
179 #undef JSON_HEDLEY_GNUC_VERSION
180 #endif
181 #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
182 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
183 #elif defined(__GNUC__)
184 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
185 #endif
186
187 #if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
188 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
189 #endif
190 #if defined(JSON_HEDLEY_GNUC_VERSION)
191 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
192 #else
193 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
194 #endif
195
196 #if defined(JSON_HEDLEY_MSVC_VERSION)
197 #undef JSON_HEDLEY_MSVC_VERSION
198 #endif
199 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000)
200 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
201 #elif defined(_MSC_FULL_VER)
202 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
203 #elif defined(_MSC_VER)
204 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
205 #endif
206
207 #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
208 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
209 #endif
210 #if !defined(_MSC_VER)
211 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
212 #elif defined(_MSC_VER) && (_MSC_VER >= 1400)
213 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
214 #elif defined(_MSC_VER) && (_MSC_VER >= 1200)
215 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
216 #else
217 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
218 #endif
219
220 #if defined(JSON_HEDLEY_INTEL_VERSION)
221 #undef JSON_HEDLEY_INTEL_VERSION
222 #endif
223 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE)
224 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
225 #elif defined(__INTEL_COMPILER)
226 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
227 #endif
228
229 #if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
230 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
231 #endif
232 #if defined(JSON_HEDLEY_INTEL_VERSION)
233 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
234 #else
235 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
236 #endif
237
238 #if defined(JSON_HEDLEY_PGI_VERSION)
239 #undef JSON_HEDLEY_PGI_VERSION
240 #endif
241 #if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
242 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
243 #endif
244
245 #if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
246 #undef JSON_HEDLEY_PGI_VERSION_CHECK
247 #endif
248 #if defined(JSON_HEDLEY_PGI_VERSION)
249 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
250 #else
251 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
252 #endif
253
254 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
255 #undef JSON_HEDLEY_SUNPRO_VERSION
256 #endif
257 #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
258 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
259 #elif defined(__SUNPRO_C)
260 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
261 #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
262 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
263 #elif defined(__SUNPRO_CC)
264 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
265 #endif
266
267 #if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
268 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
269 #endif
270 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
271 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
272 #else
273 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
274 #endif
275
276 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
277 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
278 #endif
279 #if defined(__EMSCRIPTEN__)
280 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
281 #endif
282
283 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
284 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
285 #endif
286 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
287 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
288 #else
289 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
290 #endif
291
292 #if defined(JSON_HEDLEY_ARM_VERSION)
293 #undef JSON_HEDLEY_ARM_VERSION
294 #endif
295 #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
296 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
297 #elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
298 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
299 #endif
300
301 #if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
302 #undef JSON_HEDLEY_ARM_VERSION_CHECK
303 #endif
304 #if defined(JSON_HEDLEY_ARM_VERSION)
305 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
306 #else
307 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
308 #endif
309
310 #if defined(JSON_HEDLEY_IBM_VERSION)
311 #undef JSON_HEDLEY_IBM_VERSION
312 #endif
313 #if defined(__ibmxl__)
314 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
315 #elif defined(__xlC__) && defined(__xlC_ver__)
316 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
317 #elif defined(__xlC__)
318 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
319 #endif
320
321 #if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
322 #undef JSON_HEDLEY_IBM_VERSION_CHECK
323 #endif
324 #if defined(JSON_HEDLEY_IBM_VERSION)
325 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
326 #else
327 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
328 #endif
329
330 #if defined(JSON_HEDLEY_TI_VERSION)
331 #undef JSON_HEDLEY_TI_VERSION
332 #endif
333 #if \
334 defined(__TI_COMPILER_VERSION__) && \
335 ( \
336 defined(__TMS470__) || defined(__TI_ARM__) || \
337 defined(__MSP430__) || \
338 defined(__TMS320C2000__) \
339 )
340 #if (__TI_COMPILER_VERSION__ >= 16000000)
341 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
342 #endif
343 #endif
344
345 #if defined(JSON_HEDLEY_TI_VERSION_CHECK)
346 #undef JSON_HEDLEY_TI_VERSION_CHECK
347 #endif
348 #if defined(JSON_HEDLEY_TI_VERSION)
349 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
350 #else
351 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
352 #endif
353
354 #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
355 #undef JSON_HEDLEY_TI_CL2000_VERSION
356 #endif
357 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
358 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
359 #endif
360
361 #if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
362 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
363 #endif
364 #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
365 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
366 #else
367 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
368 #endif
369
370 #if defined(JSON_HEDLEY_TI_CL430_VERSION)
371 #undef JSON_HEDLEY_TI_CL430_VERSION
372 #endif
373 #if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
374 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
375 #endif
376
377 #if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
378 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
379 #endif
380 #if defined(JSON_HEDLEY_TI_CL430_VERSION)
381 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
382 #else
383 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
384 #endif
385
386 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
387 #undef JSON_HEDLEY_TI_ARMCL_VERSION
388 #endif
389 #if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
390 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
391 #endif
392
393 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
394 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
395 #endif
396 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
397 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
398 #else
399 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
400 #endif
401
402 #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
403 #undef JSON_HEDLEY_TI_CL6X_VERSION
404 #endif
405 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
406 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
407 #endif
408
409 #if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
410 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
411 #endif
412 #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
413 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
414 #else
415 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
416 #endif
417
418 #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
419 #undef JSON_HEDLEY_TI_CL7X_VERSION
420 #endif
421 #if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
422 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
423 #endif
424
425 #if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
426 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
427 #endif
428 #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
429 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
430 #else
431 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
432 #endif
433
434 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
435 #undef JSON_HEDLEY_TI_CLPRU_VERSION
436 #endif
437 #if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
438 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
439 #endif
440
441 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
442 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
443 #endif
444 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
445 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
446 #else
447 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
448 #endif
449
450 #if defined(JSON_HEDLEY_CRAY_VERSION)
451 #undef JSON_HEDLEY_CRAY_VERSION
452 #endif
453 #if defined(_CRAYC)
454 #if defined(_RELEASE_PATCHLEVEL)
455 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
456 #else
457 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
458 #endif
459 #endif
460
461 #if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
462 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
463 #endif
464 #if defined(JSON_HEDLEY_CRAY_VERSION)
465 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
466 #else
467 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
468 #endif
469
470 #if defined(JSON_HEDLEY_IAR_VERSION)
471 #undef JSON_HEDLEY_IAR_VERSION
472 #endif
473 #if defined(__IAR_SYSTEMS_ICC__)
474 #if __VER__ > 1000
475 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
476 #else
477 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(VER / 100, __VER__ % 100, 0)
478 #endif
479 #endif
480
481 #if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
482 #undef JSON_HEDLEY_IAR_VERSION_CHECK
483 #endif
484 #if defined(JSON_HEDLEY_IAR_VERSION)
485 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
486 #else
487 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
488 #endif
489
490 #if defined(JSON_HEDLEY_TINYC_VERSION)
491 #undef JSON_HEDLEY_TINYC_VERSION
492 #endif
493 #if defined(__TINYC__)
494 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
495 #endif
496
497 #if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
498 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
499 #endif
500 #if defined(JSON_HEDLEY_TINYC_VERSION)
501 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
502 #else
503 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
504 #endif
505
506 #if defined(JSON_HEDLEY_DMC_VERSION)
507 #undef JSON_HEDLEY_DMC_VERSION
508 #endif
509 #if defined(__DMC__)
510 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
511 #endif
512
513 #if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
514 #undef JSON_HEDLEY_DMC_VERSION_CHECK
515 #endif
516 #if defined(JSON_HEDLEY_DMC_VERSION)
517 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
518 #else
519 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
520 #endif
521
522 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
523 #undef JSON_HEDLEY_COMPCERT_VERSION
524 #endif
525 #if defined(__COMPCERT_VERSION__)
526 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
527 #endif
528
529 #if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
530 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
531 #endif
532 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
533 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
534 #else
535 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
536 #endif
537
538 #if defined(JSON_HEDLEY_PELLES_VERSION)
539 #undef JSON_HEDLEY_PELLES_VERSION
540 #endif
541 #if defined(__POCC__)
542 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
543 #endif
544
545 #if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
546 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
547 #endif
548 #if defined(JSON_HEDLEY_PELLES_VERSION)
549 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
550 #else
551 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
552 #endif
553
554 #if defined(JSON_HEDLEY_GCC_VERSION)
555 #undef JSON_HEDLEY_GCC_VERSION
556 #endif
557 #if \
558 defined(JSON_HEDLEY_GNUC_VERSION) && \
559 !defined(__clang__) && \
560 !defined(JSON_HEDLEY_INTEL_VERSION) && \
561 !defined(JSON_HEDLEY_PGI_VERSION) && \
562 !defined(JSON_HEDLEY_ARM_VERSION) && \
563 !defined(JSON_HEDLEY_TI_VERSION) && \
564 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
565 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
566 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
567 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
568 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
569 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
570 !defined(__COMPCERT__)
571 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
572 #endif
573
574 #if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
575 #undef JSON_HEDLEY_GCC_VERSION_CHECK
576 #endif
577 #if defined(JSON_HEDLEY_GCC_VERSION)
578 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
579 #else
580 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
581 #endif
582
583 #if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
584 #undef JSON_HEDLEY_HAS_ATTRIBUTE
585 #endif
586 #if defined(__has_attribute)
587 #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
588 #else
589 #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
590 #endif
591
592 #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
593 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
594 #endif
595 #if defined(__has_attribute)
596 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute)
597 #else
598 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
599 #endif
600
601 #if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
602 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
603 #endif
604 #if defined(__has_attribute)
605 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute)
606 #else
607 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
608 #endif
609
610 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
611 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
612 #endif
613 #if \
614 defined(__has_cpp_attribute) && \
615 defined(__cplusplus) && \
616 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
617 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
618 #else
619 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
620 #endif
621
622 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
623 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
624 #endif
625 #if !defined(__cplusplus) || !defined(__has_cpp_attribute)
626 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
627 #elif \
628 !defined(JSON_HEDLEY_PGI_VERSION) && \
629 !defined(JSON_HEDLEY_IAR_VERSION) && \
630 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
631 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
632 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
633 #else
634 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
635 #endif
636
637 #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
638 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
639 #endif
640 #if defined(__has_cpp_attribute) && defined(__cplusplus)
641 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
642 #else
643 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
644 #endif
645
646 #if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
647 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
648 #endif
649 #if defined(__has_cpp_attribute) && defined(__cplusplus)
650 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
651 #else
652 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
653 #endif
654
655 #if defined(JSON_HEDLEY_HAS_BUILTIN)
656 #undef JSON_HEDLEY_HAS_BUILTIN
657 #endif
658 #if defined(__has_builtin)
659 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
660 #else
661 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
662 #endif
663
664 #if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
665 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
666 #endif
667 #if defined(__has_builtin)
668 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
669 #else
670 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
671 #endif
672
673 #if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
674 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
675 #endif
676 #if defined(__has_builtin)
677 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
678 #else
679 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
680 #endif
681
682 #if defined(JSON_HEDLEY_HAS_FEATURE)
683 #undef JSON_HEDLEY_HAS_FEATURE
684 #endif
685 #if defined(__has_feature)
686 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
687 #else
688 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
689 #endif
690
691 #if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
692 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
693 #endif
694 #if defined(__has_feature)
695 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
696 #else
697 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
698 #endif
699
700 #if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
701 #undef JSON_HEDLEY_GCC_HAS_FEATURE
702 #endif
703 #if defined(__has_feature)
704 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
705 #else
706 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
707 #endif
708
709 #if defined(JSON_HEDLEY_HAS_EXTENSION)
710 #undef JSON_HEDLEY_HAS_EXTENSION
711 #endif
712 #if defined(__has_extension)
713 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
714 #else
715 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
716 #endif
717
718 #if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
719 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
720 #endif
721 #if defined(__has_extension)
722 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
723 #else
724 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
725 #endif
726
727 #if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
728 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
729 #endif
730 #if defined(__has_extension)
731 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
732 #else
733 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
734 #endif
735
736 #if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
737 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
738 #endif
739 #if defined(__has_declspec_attribute)
740 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
741 #else
742 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
743 #endif
744
745 #if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
746 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
747 #endif
748 #if defined(__has_declspec_attribute)
749 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
750 #else
751 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
752 #endif
753
754 #if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
755 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
756 #endif
757 #if defined(__has_declspec_attribute)
758 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
759 #else
760 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
761 #endif
762
763 #if defined(JSON_HEDLEY_HAS_WARNING)
764 #undef JSON_HEDLEY_HAS_WARNING
765 #endif
766 #if defined(__has_warning)
767 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
768 #else
769 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
770 #endif
771
772 #if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
773 #undef JSON_HEDLEY_GNUC_HAS_WARNING
774 #endif
775 #if defined(__has_warning)
776 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
777 #else
778 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
779 #endif
780
781 #if defined(JSON_HEDLEY_GCC_HAS_WARNING)
782 #undef JSON_HEDLEY_GCC_HAS_WARNING
783 #endif
784 #if defined(__has_warning)
785 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
786 #else
787 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
788 #endif
789
790 /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
791 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
792 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
793 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
794 #endif
795 #if defined(__cplusplus)
796 # if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
797 # if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
798 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
799 JSON_HEDLEY_DIAGNOSTIC_PUSH \
800 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
801 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
802 xpr \
803 JSON_HEDLEY_DIAGNOSTIC_POP
804 # else
805 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
806 JSON_HEDLEY_DIAGNOSTIC_PUSH \
807 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
808 xpr \
809 JSON_HEDLEY_DIAGNOSTIC_POP
810 # endif
811 # endif
812 #endif
813 #if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
814 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
815 #endif
816
817 #if defined(JSON_HEDLEY_CONST_CAST)
818 #undef JSON_HEDLEY_CONST_CAST
819 #endif
820 #if defined(__cplusplus)
821 # define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
822 #elif \
823 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
824 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
825 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
826 # define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
827 JSON_HEDLEY_DIAGNOSTIC_PUSH \
828 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
829 ((T) (expr)); \
830 JSON_HEDLEY_DIAGNOSTIC_POP \
831 }))
832 #else
833 # define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
834 #endif
835
836 #if defined(JSON_HEDLEY_REINTERPRET_CAST)
837 #undef JSON_HEDLEY_REINTERPRET_CAST
838 #endif
839 #if defined(__cplusplus)
840 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
841 #else
842 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
843 #endif
844
845 #if defined(JSON_HEDLEY_STATIC_CAST)
846 #undef JSON_HEDLEY_STATIC_CAST
847 #endif
848 #if defined(__cplusplus)
849 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
850 #else
851 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
852 #endif
853
854 #if defined(JSON_HEDLEY_CPP_CAST)
855 #undef JSON_HEDLEY_CPP_CAST
856 #endif
857 #if defined(__cplusplus)
858 # if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
859 # define JSON_HEDLEY_CPP_CAST(T, expr) \
860 JSON_HEDLEY_DIAGNOSTIC_PUSH \
861 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
862 ((T) (expr)) \
863 JSON_HEDLEY_DIAGNOSTIC_POP
864 # elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
865 # define JSON_HEDLEY_CPP_CAST(T, expr) \
866 JSON_HEDLEY_DIAGNOSTIC_PUSH \
867 _Pragma("diag_suppress=Pe137") \
868 JSON_HEDLEY_DIAGNOSTIC_POP \
869 # else
870 # define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
871 # endif
872 #else
873 # define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
874 #endif
875
876 #if \
877 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
878 defined(__clang__) || \
879 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
880 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
881 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
882 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
883 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
884 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
885 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
886 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
887 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
888 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
889 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
890 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
891 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
892 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
893 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
894 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
895 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
896 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
897 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
898 #else
899 #define JSON_HEDLEY_PRAGMA(value)
900 #endif
901
902 #if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
903 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
904 #endif
905 #if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
906 #undef JSON_HEDLEY_DIAGNOSTIC_POP
907 #endif
908 #if defined(__clang__)
909 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
910 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
911 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
912 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
913 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
914 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
915 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
916 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
917 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
918 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
919 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
920 #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
921 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
922 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
923 #elif \
924 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
925 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
926 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
927 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
928 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
929 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
930 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
931 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
932 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
933 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
934 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
935 #else
936 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
937 #define JSON_HEDLEY_DIAGNOSTIC_POP
938 #endif
939
940 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
941 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
942 #endif
943 #if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
944 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
945 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
946 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
947 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
948 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
949 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
950 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
951 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
952 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
953 #elif \
954 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
955 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
956 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
957 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
958 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
959 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
960 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
961 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
962 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
963 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
964 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
965 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
966 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
967 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
968 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
969 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
970 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
971 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
972 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
973 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
974 #else
975 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
976 #endif
977
978 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
979 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
980 #endif
981 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
982 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
983 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
984 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
985 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
986 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
987 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
988 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
989 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
990 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
991 #elif \
992 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
993 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
994 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
995 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
996 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
997 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
998 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
999 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1000 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1001 #else
1002 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1003 #endif
1004
1005 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1006 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1007 #endif
1008 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1009 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1010 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1011 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1012 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1013 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1014 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1015 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1016 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1017 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1018 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1019 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1020 #elif \
1021 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1022 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1023 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1024 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1025 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1026 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1027 #else
1028 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1029 #endif
1030
1031 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1032 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1033 #endif
1034 #if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1035 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1036 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1037 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1038 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1039 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1040 #else
1041 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1042 #endif
1043
1044 #if defined(JSON_HEDLEY_DEPRECATED)
1045 #undef JSON_HEDLEY_DEPRECATED
1046 #endif
1047 #if defined(JSON_HEDLEY_DEPRECATED_FOR)
1048 #undef JSON_HEDLEY_DEPRECATED_FOR
1049 #endif
1050 #if JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0)
1051 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1052 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1053 #elif defined(__cplusplus) && (__cplusplus >= 201402L)
1054 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1055 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1056 #elif \
1057 JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || \
1058 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1059 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1060 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1061 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1062 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1063 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1064 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1065 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1066 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1067 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1068 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1069 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1070 #elif \
1071 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1072 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1073 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1074 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1075 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1076 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1077 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1078 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1079 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1080 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1081 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1082 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1083 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1084 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1085 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1086 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1087 #elif \
1088 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1089 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0)
1090 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1091 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1092 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1093 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1094 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1095 #else
1096 #define JSON_HEDLEY_DEPRECATED(since)
1097 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1098 #endif
1099
1100 #if defined(JSON_HEDLEY_UNAVAILABLE)
1101 #undef JSON_HEDLEY_UNAVAILABLE
1102 #endif
1103 #if \
1104 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1105 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1106 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1107 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1108 #else
1109 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1110 #endif
1111
1112 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1113 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1114 #endif
1115 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1116 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1117 #endif
1118 #if (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1119 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1120 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1121 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1122 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1123 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1124 #elif \
1125 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1126 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1127 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1128 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1129 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1130 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1131 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1132 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1133 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1134 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1135 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1136 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1137 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1138 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1139 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1140 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1141 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1142 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1143 #elif defined(_Check_return_) /* SAL */
1144 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1145 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1146 #else
1147 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1148 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1149 #endif
1150
1151 #if defined(JSON_HEDLEY_SENTINEL)
1152 #undef JSON_HEDLEY_SENTINEL
1153 #endif
1154 #if \
1155 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1156 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1157 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1158 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0)
1159 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1160 #else
1161 #define JSON_HEDLEY_SENTINEL(position)
1162 #endif
1163
1164 #if defined(JSON_HEDLEY_NO_RETURN)
1165 #undef JSON_HEDLEY_NO_RETURN
1166 #endif
1167 #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1168 #define JSON_HEDLEY_NO_RETURN __noreturn
1169 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1170 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1171 #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1172 #define JSON_HEDLEY_NO_RETURN _Noreturn
1173 #elif defined(__cplusplus) && (__cplusplus >= 201103L)
1174 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1175 #elif \
1176 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1177 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1178 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1179 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1180 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1181 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1182 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1183 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1184 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1185 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1186 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1187 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1188 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1189 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1190 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1191 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1192 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1193 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1194 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1195 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0)
1196 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1197 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1198 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1199 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1200 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1201 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1202 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1203 #else
1204 #define JSON_HEDLEY_NO_RETURN
1205 #endif
1206
1207 #if defined(JSON_HEDLEY_NO_ESCAPE)
1208 #undef JSON_HEDLEY_NO_ESCAPE
1209 #endif
1210 #if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1211 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1212 #else
1213 #define JSON_HEDLEY_NO_ESCAPE
1214 #endif
1215
1216 #if defined(JSON_HEDLEY_UNREACHABLE)
1217 #undef JSON_HEDLEY_UNREACHABLE
1218 #endif
1219 #if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1220 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1221 #endif
1222 #if defined(JSON_HEDLEY_ASSUME)
1223 #undef JSON_HEDLEY_ASSUME
1224 #endif
1225 #if \
1226 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1227 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1228 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1229 #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1230 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1231 #elif \
1232 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1233 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1234 #if defined(__cplusplus)
1235 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1236 #else
1237 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1238 #endif
1239 #endif
1240 #if \
1241 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1242 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1243 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1244 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1245 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5)
1246 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1247 #elif defined(JSON_HEDLEY_ASSUME)
1248 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1249 #endif
1250 #if !defined(JSON_HEDLEY_ASSUME)
1251 #if defined(JSON_HEDLEY_UNREACHABLE)
1252 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1253 #else
1254 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1255 #endif
1256 #endif
1257 #if defined(JSON_HEDLEY_UNREACHABLE)
1258 #if \
1259 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1260 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1261 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1262 #else
1263 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1264 #endif
1265 #else
1266 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1267 #endif
1268 #if !defined(JSON_HEDLEY_UNREACHABLE)
1269 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1270 #endif
1271
1272 JSON_HEDLEY_DIAGNOSTIC_PUSH
1273 #if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1274 #pragma clang diagnostic ignored "-Wpedantic"
1275 #endif
1276 #if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1277 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1278 #endif
1279 #if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1280 #if defined(__clang__)
1281 #pragma clang diagnostic ignored "-Wvariadic-macros"
1282 #elif defined(JSON_HEDLEY_GCC_VERSION)
1283 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1284 #endif
1285 #endif
1286 #if defined(JSON_HEDLEY_NON_NULL)
1287 #undef JSON_HEDLEY_NON_NULL
1288 #endif
1289 #if \
1290 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1291 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1292 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1293 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1294 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1295 #else
1296 #define JSON_HEDLEY_NON_NULL(...)
1297 #endif
1298 JSON_HEDLEY_DIAGNOSTIC_POP
1299
1300 #if defined(JSON_HEDLEY_PRINTF_FORMAT)
1301 #undef JSON_HEDLEY_PRINTF_FORMAT
1302 #endif
1303 #if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1304 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1305 #elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1306 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1307 #elif \
1308 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1309 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1310 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1311 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1312 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1313 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1314 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1315 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1316 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1317 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1318 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1319 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1320 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1321 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1322 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1323 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1324 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1325 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1326 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1327 #else
1328 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1329 #endif
1330
1331 #if defined(JSON_HEDLEY_CONSTEXPR)
1332 #undef JSON_HEDLEY_CONSTEXPR
1333 #endif
1334 #if defined(__cplusplus)
1335 #if __cplusplus >= 201103L
1336 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1337 #endif
1338 #endif
1339 #if !defined(JSON_HEDLEY_CONSTEXPR)
1340 #define JSON_HEDLEY_CONSTEXPR
1341 #endif
1342
1343 #if defined(JSON_HEDLEY_PREDICT)
1344 #undef JSON_HEDLEY_PREDICT
1345 #endif
1346 #if defined(JSON_HEDLEY_LIKELY)
1347 #undef JSON_HEDLEY_LIKELY
1348 #endif
1349 #if defined(JSON_HEDLEY_UNLIKELY)
1350 #undef JSON_HEDLEY_UNLIKELY
1351 #endif
1352 #if defined(JSON_HEDLEY_UNPREDICTABLE)
1353 #undef JSON_HEDLEY_UNPREDICTABLE
1354 #endif
1355 #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1356 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1357 #endif
1358 #if \
1359 JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) || \
1360 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0)
1361 # define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1362 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1363 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1364 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1365 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1366 #elif \
1367 JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) || \
1368 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1369 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1370 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1371 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1372 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1373 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1374 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1375 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1376 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1377 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1378 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1379 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1380 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1381 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0)
1382 # define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1383 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1384 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1385 (__extension__ ({ \
1386 double hedley_probability_ = (probability); \
1387 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1388 }))
1389 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1390 (__extension__ ({ \
1391 double hedley_probability_ = (probability); \
1392 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1393 }))
1394 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1395 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1396 #else
1397 # define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1398 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1399 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1400 # define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1401 # define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1402 #endif
1403 #if !defined(JSON_HEDLEY_UNPREDICTABLE)
1404 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1405 #endif
1406
1407 #if defined(JSON_HEDLEY_MALLOC)
1408 #undef JSON_HEDLEY_MALLOC
1409 #endif
1410 #if \
1411 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1412 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1413 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1414 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1415 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1416 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1417 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1418 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1419 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1420 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1421 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1422 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1423 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1424 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1425 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1426 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1427 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1428 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1429 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1430 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1431 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0)
1432 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1433 #else
1434 #define JSON_HEDLEY_MALLOC
1435 #endif
1436
1437 #if defined(JSON_HEDLEY_PURE)
1438 #undef JSON_HEDLEY_PURE
1439 #endif
1440 #if \
1441 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1442 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1443 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1444 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1445 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1446 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1447 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1448 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1449 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1450 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1451 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1452 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1453 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1454 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1455 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1456 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1457 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1458 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1459 # define JSON_HEDLEY_PURE __attribute__((__pure__))
1460 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1461 # define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1462 #elif defined(__cplusplus) && \
1463 ( \
1464 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1465 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1466 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1467 )
1468 # define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1469 #else
1470 # define JSON_HEDLEY_PURE
1471 #endif
1472
1473 #if defined(JSON_HEDLEY_CONST)
1474 #undef JSON_HEDLEY_CONST
1475 #endif
1476 #if \
1477 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1478 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1479 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1480 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1481 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1482 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1483 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1484 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1485 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1486 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1487 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1488 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1489 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1490 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1491 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1492 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1493 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1494 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1495 #define JSON_HEDLEY_CONST __attribute__((__const__))
1496 #elif \
1497 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1498 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1499 #else
1500 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1501 #endif
1502
1503 #if defined(JSON_HEDLEY_RESTRICT)
1504 #undef JSON_HEDLEY_RESTRICT
1505 #endif
1506 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1507 #define JSON_HEDLEY_RESTRICT restrict
1508 #elif \
1509 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1510 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1511 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1512 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1513 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1514 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1515 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1516 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1517 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1518 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1519 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1520 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1521 defined(__clang__)
1522 #define JSON_HEDLEY_RESTRICT __restrict
1523 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1524 #define JSON_HEDLEY_RESTRICT _Restrict
1525 #else
1526 #define JSON_HEDLEY_RESTRICT
1527 #endif
1528
1529 #if defined(JSON_HEDLEY_INLINE)
1530 #undef JSON_HEDLEY_INLINE
1531 #endif
1532 #if \
1533 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1534 (defined(__cplusplus) && (__cplusplus >= 199711L))
1535 #define JSON_HEDLEY_INLINE inline
1536 #elif \
1537 defined(JSON_HEDLEY_GCC_VERSION) || \
1538 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1539 #define JSON_HEDLEY_INLINE __inline__
1540 #elif \
1541 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1542 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1543 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1544 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1545 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1546 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1547 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1548 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1549 #define JSON_HEDLEY_INLINE __inline
1550 #else
1551 #define JSON_HEDLEY_INLINE
1552 #endif
1553
1554 #if defined(JSON_HEDLEY_ALWAYS_INLINE)
1555 #undef JSON_HEDLEY_ALWAYS_INLINE
1556 #endif
1557 #if \
1558 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1559 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1560 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1561 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1562 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1563 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1564 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1565 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1566 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1567 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1568 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1569 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1570 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1571 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1572 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1573 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1574 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1575 # define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1576 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0)
1577 # define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1578 #elif defined(__cplusplus) && \
1579 ( \
1580 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1581 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1582 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1583 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1584 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1585 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1586 )
1587 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1588 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1589 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1590 #else
1591 # define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1592 #endif
1593
1594 #if defined(JSON_HEDLEY_NEVER_INLINE)
1595 #undef JSON_HEDLEY_NEVER_INLINE
1596 #endif
1597 #if \
1598 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1599 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1600 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1601 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1602 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1603 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1604 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1605 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1606 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1607 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1608 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1609 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1610 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1611 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1612 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1613 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1614 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1615 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1616 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0)
1617 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1618 #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1619 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1620 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1621 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1622 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1623 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1624 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1625 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1626 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1627 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1628 #else
1629 #define JSON_HEDLEY_NEVER_INLINE
1630 #endif
1631
1632 #if defined(JSON_HEDLEY_PRIVATE)
1633 #undef JSON_HEDLEY_PRIVATE
1634 #endif
1635 #if defined(JSON_HEDLEY_PUBLIC)
1636 #undef JSON_HEDLEY_PUBLIC
1637 #endif
1638 #if defined(JSON_HEDLEY_IMPORT)
1639 #undef JSON_HEDLEY_IMPORT
1640 #endif
1641 #if defined(_WIN32) || defined(__CYGWIN__)
1642 # define JSON_HEDLEY_PRIVATE
1643 # define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1644 # define JSON_HEDLEY_IMPORT __declspec(dllimport)
1645 #else
1646 # if \
1647 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1648 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1649 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1650 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1651 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1652 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1653 ( \
1654 defined(__TI_EABI__) && \
1655 ( \
1656 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1657 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1658 ) \
1659 )
1660 # define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1661 # define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1662 # else
1663 # define JSON_HEDLEY_PRIVATE
1664 # define JSON_HEDLEY_PUBLIC
1665 # endif
1666 # define JSON_HEDLEY_IMPORT extern
1667 #endif
1668
1669 #if defined(JSON_HEDLEY_NO_THROW)
1670 #undef JSON_HEDLEY_NO_THROW
1671 #endif
1672 #if \
1673 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
1674 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1675 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1676 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
1677 #elif \
1678 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
1679 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1680 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
1681 #else
1682 #define JSON_HEDLEY_NO_THROW
1683 #endif
1684
1685 #if defined(JSON_HEDLEY_FALL_THROUGH)
1686 #undef JSON_HEDLEY_FALL_THROUGH
1687 #endif
1688 #if \
1689 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
1690 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0)
1691 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
1692 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
1693 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
1694 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
1695 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
1696 #elif defined(__fallthrough) /* SAL */
1697 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
1698 #else
1699 #define JSON_HEDLEY_FALL_THROUGH
1700 #endif
1701
1702 #if defined(JSON_HEDLEY_RETURNS_NON_NULL)
1703 #undef JSON_HEDLEY_RETURNS_NON_NULL
1704 #endif
1705 #if \
1706 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
1707 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
1708 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
1709 #elif defined(_Ret_notnull_) /* SAL */
1710 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
1711 #else
1712 #define JSON_HEDLEY_RETURNS_NON_NULL
1713 #endif
1714
1715 #if defined(JSON_HEDLEY_ARRAY_PARAM)
1716 #undef JSON_HEDLEY_ARRAY_PARAM
1717 #endif
1718 #if \
1719 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
1720 !defined(__STDC_NO_VLA__) && \
1721 !defined(__cplusplus) && \
1722 !defined(JSON_HEDLEY_PGI_VERSION) && \
1723 !defined(JSON_HEDLEY_TINYC_VERSION)
1724 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
1725 #else
1726 #define JSON_HEDLEY_ARRAY_PARAM(name)
1727 #endif
1728
1729 #if defined(JSON_HEDLEY_IS_CONSTANT)
1730 #undef JSON_HEDLEY_IS_CONSTANT
1731 #endif
1732 #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
1733 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
1734 #endif
1735 /* JSON_HEDLEY_IS_CONSTEXPR_ is for
1736 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1737 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1738 #undef JSON_HEDLEY_IS_CONSTEXPR_
1739 #endif
1740 #if \
1741 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
1742 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1743 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1744 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
1745 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1746 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1747 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1748 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
1749 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0)
1750 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
1751 #endif
1752 #if !defined(__cplusplus)
1753 # if \
1754 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
1755 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1756 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1757 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1758 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1759 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1760 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
1761 #if defined(__INTPTR_TYPE__)
1762 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
1763 #else
1764 #include <stdint.h>
1765 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
1766 #endif
1767 # elif \
1768 ( \
1769 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
1770 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
1771 !defined(JSON_HEDLEY_PGI_VERSION) && \
1772 !defined(JSON_HEDLEY_IAR_VERSION)) || \
1773 JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) || \
1774 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
1775 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
1776 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1777 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
1778 #if defined(__INTPTR_TYPE__)
1779 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
1780 #else
1781 #include <stdint.h>
1782 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
1783 #endif
1784 # elif \
1785 defined(JSON_HEDLEY_GCC_VERSION) || \
1786 defined(JSON_HEDLEY_INTEL_VERSION) || \
1787 defined(JSON_HEDLEY_TINYC_VERSION) || \
1788 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
1789 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
1790 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
1791 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
1792 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
1793 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
1794 defined(__clang__)
1795 # define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
1796 sizeof(void) != \
1797 sizeof(*( \
1798 1 ? \
1799 ((void*) ((expr) * 0L) ) : \
1800 ((struct { char v[sizeof(void) * 2]; } *) 1) \
1801 ) \
1802 ) \
1803 )
1804 # endif
1805 #endif
1806 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1807 #if !defined(JSON_HEDLEY_IS_CONSTANT)
1808 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
1809 #endif
1810 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
1811 #else
1812 #if !defined(JSON_HEDLEY_IS_CONSTANT)
1813 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
1814 #endif
1815 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
1816 #endif
1817
1818 #if defined(JSON_HEDLEY_BEGIN_C_DECLS)
1819 #undef JSON_HEDLEY_BEGIN_C_DECLS
1820 #endif
1821 #if defined(JSON_HEDLEY_END_C_DECLS)
1822 #undef JSON_HEDLEY_END_C_DECLS
1823 #endif
1824 #if defined(JSON_HEDLEY_C_DECL)
1825 #undef JSON_HEDLEY_C_DECL
1826 #endif
1827 #if defined(__cplusplus)
1828 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
1829 #define JSON_HEDLEY_END_C_DECLS }
1830 #define JSON_HEDLEY_C_DECL extern "C"
1831 #else
1832 #define JSON_HEDLEY_BEGIN_C_DECLS
1833 #define JSON_HEDLEY_END_C_DECLS
1834 #define JSON_HEDLEY_C_DECL
1835 #endif
1836
1837 #if defined(JSON_HEDLEY_STATIC_ASSERT)
1838 #undef JSON_HEDLEY_STATIC_ASSERT
1839 #endif
1840 #if \
1841 !defined(__cplusplus) && ( \
1842 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
1843 JSON_HEDLEY_HAS_FEATURE(c_static_assert) || \
1844 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
1845 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1846 defined(_Static_assert) \
1847 )
1848 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
1849 #elif \
1850 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
1851 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0)
1852 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
1853 #else
1854 # define JSON_HEDLEY_STATIC_ASSERT(expr, message)
1855 #endif
1856
1857 #if defined(JSON_HEDLEY_NULL)
1858 #undef JSON_HEDLEY_NULL
1859 #endif
1860 #if defined(__cplusplus)
1861 #if __cplusplus >= 201103L
1862 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
1863 #elif defined(NULL)
1864 #define JSON_HEDLEY_NULL NULL
1865 #else
1866 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
1867 #endif
1868 #elif defined(NULL)
1869 #define JSON_HEDLEY_NULL NULL
1870 #else
1871 #define JSON_HEDLEY_NULL ((void*) 0)
1872 #endif
1873
1874 #if defined(JSON_HEDLEY_MESSAGE)
1875 #undef JSON_HEDLEY_MESSAGE
1876 #endif
1877 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1878 # define JSON_HEDLEY_MESSAGE(msg) \
1879 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1880 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
1881 JSON_HEDLEY_PRAGMA(message msg) \
1882 JSON_HEDLEY_DIAGNOSTIC_POP
1883 #elif \
1884 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
1885 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1886 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
1887 #elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
1888 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
1889 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1890 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
1891 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
1892 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
1893 #else
1894 # define JSON_HEDLEY_MESSAGE(msg)
1895 #endif
1896
1897 #if defined(JSON_HEDLEY_WARNING)
1898 #undef JSON_HEDLEY_WARNING
1899 #endif
1900 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1901 # define JSON_HEDLEY_WARNING(msg) \
1902 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1903 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
1904 JSON_HEDLEY_PRAGMA(clang warning msg) \
1905 JSON_HEDLEY_DIAGNOSTIC_POP
1906 #elif \
1907 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
1908 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1909 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1910 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
1911 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1912 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
1913 #else
1914 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
1915 #endif
1916
1917 #if defined(JSON_HEDLEY_REQUIRE)
1918 #undef JSON_HEDLEY_REQUIRE
1919 #endif
1920 #if defined(JSON_HEDLEY_REQUIRE_MSG)
1921 #undef JSON_HEDLEY_REQUIRE_MSG
1922 #endif
1923 #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
1924 # if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
1925 # define JSON_HEDLEY_REQUIRE(expr) \
1926 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1927 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
1928 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
1929 JSON_HEDLEY_DIAGNOSTIC_POP
1930 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
1931 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1932 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
1933 __attribute__((diagnose_if(!(expr), msg, "error"))) \
1934 JSON_HEDLEY_DIAGNOSTIC_POP
1935 # else
1936 # define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
1937 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
1938 # endif
1939 #else
1940 # define JSON_HEDLEY_REQUIRE(expr)
1941 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
1942 #endif
1943
1944 #if defined(JSON_HEDLEY_FLAGS)
1945 #undef JSON_HEDLEY_FLAGS
1946 #endif
1947 #if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum)
1948 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
1949 #endif
1950
1951 #if defined(JSON_HEDLEY_FLAGS_CAST)
1952 #undef JSON_HEDLEY_FLAGS_CAST
1953 #endif
1954 #if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
1955 # define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
1956 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1957 _Pragma("warning(disable:188)") \
1958 ((T) (expr)); \
1959 JSON_HEDLEY_DIAGNOSTIC_POP \
1960 }))
1961 #else
1962 # define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
1963 #endif
1964
1965 #if defined(JSON_HEDLEY_EMPTY_BASES)
1966 #undef JSON_HEDLEY_EMPTY_BASES
1967 #endif
1968 #if JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)
1969 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
1970 #else
1971 #define JSON_HEDLEY_EMPTY_BASES
1972 #endif
1973
1974 /* Remaining macros are deprecated. */
1975
1976 #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
1977 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
1978 #endif
1979 #if defined(__clang__)
1980 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
1981 #else
1982 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1983 #endif
1984
1985 #if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
1986 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
1987 #endif
1988 #define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
1989
1990 #if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
1991 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
1992 #endif
1993 #define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
1994
1995 #if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
1996 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
1997 #endif
1998 #define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
1999
2000 #if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2001 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2002 #endif
2003 #define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2004
2005 #if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2006 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2007 #endif
2008 #define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2009
2010 #if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2011 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2012 #endif
2013 #define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2014
2015 #if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2016 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2017 #endif
2018 #define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2019
2020 #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2021
2022
2023 // This file contains all internal macro definitions
2024 // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2025
2026 // exclude unsupported compilers
2027 #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2028 #if defined(__clang__)
2029 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2030 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2031 #endif
2032 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2033 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2034 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2035 #endif
2036 #endif
2037 #endif
2038
2039 // C++ language standard detection
2040 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2041 #define JSON_HAS_CPP_20
2042 #define JSON_HAS_CPP_17
2043 #define JSON_HAS_CPP_14
2044 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2045 #define JSON_HAS_CPP_17
2046 #define JSON_HAS_CPP_14
2047 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2048 #define JSON_HAS_CPP_14
2049 #endif
2050
2051 // disable float-equal warnings on GCC/clang
2052 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
2053 #pragma GCC diagnostic push
2054 #pragma GCC diagnostic ignored "-Wfloat-equal"
2055 #endif
2056
2057 // disable documentation warnings on clang
2058 #if defined(__clang__)
2059 #pragma GCC diagnostic push
2060 #pragma GCC diagnostic ignored "-Wdocumentation"
2061 #endif
2062
2063 // allow to disable exceptions
2064 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2065 #define JSON_THROW(exception) throw exception
2066 #define JSON_TRY try
2067 #define JSON_CATCH(exception) catch(exception)
2068 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2069 #else
2070 #include <cstdlib>
2071 #define JSON_THROW(exception) std::abort()
2072 #define JSON_TRY if(true)
2073 #define JSON_CATCH(exception) if(false)
2074 #define JSON_INTERNAL_CATCH(exception) if(false)
2075 #endif
2076
2077 // override exception macros
2078 #if defined(JSON_THROW_USER)
2079 #undef JSON_THROW
2080 #define JSON_THROW JSON_THROW_USER
2081 #endif
2082 #if defined(JSON_TRY_USER)
2083 #undef JSON_TRY
2084 #define JSON_TRY JSON_TRY_USER
2085 #endif
2086 #if defined(JSON_CATCH_USER)
2087 #undef JSON_CATCH
2088 #define JSON_CATCH JSON_CATCH_USER
2089 #undef JSON_INTERNAL_CATCH
2090 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2091 #endif
2092 #if defined(JSON_INTERNAL_CATCH_USER)
2093 #undef JSON_INTERNAL_CATCH
2094 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2095 #endif
2096
2097 // allow to override assert
2098 #if !defined(JSON_ASSERT)
2099 #include <cassert> // assert
2100 #define JSON_ASSERT(x) assert(x)
2101 #endif
2102
2103 /*!
2104 @brief macro to briefly define a mapping between an enum and JSON
2105 @def NLOHMANN_JSON_SERIALIZE_ENUM
2106 @since version 3.4.0
2107 */
2108 #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2109 template<typename BasicJsonType> \
2110 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2111 { \
2112 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2113 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2114 auto it = std::find_if(std::begin(m), std::end(m), \
2115 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2116 { \
2117 return ej_pair.first == e; \
2118 }); \
2119 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2120 } \
2121 template<typename BasicJsonType> \
2122 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2123 { \
2124 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2125 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2126 auto it = std::find_if(std::begin(m), std::end(m), \
2127 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2128 { \
2129 return ej_pair.second == j; \
2130 }); \
2131 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2132 }
2133
2134 // Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2135 // may be removed in the future once the class is split.
2136
2137 #define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2138 template<template<typename, typename, typename...> class ObjectType, \
2139 template<typename, typename...> class ArrayType, \
2140 class StringType, class BooleanType, class NumberIntegerType, \
2141 class NumberUnsignedType, class NumberFloatType, \
2142 template<typename> class AllocatorType, \
2143 template<typename, typename = void> class JSONSerializer, \
2144 class BinaryType>
2145
2146 #define NLOHMANN_BASIC_JSON_TPL \
2147 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2148 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2149 AllocatorType, JSONSerializer, BinaryType>
2150
2151 // Macros to simplify conversion from/to types
2152
2153 #define NLOHMANN_JSON_EXPAND( x ) x
2154 #define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
2155 #define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2156 NLOHMANN_JSON_PASTE64, \
2157 NLOHMANN_JSON_PASTE63, \
2158 NLOHMANN_JSON_PASTE62, \
2159 NLOHMANN_JSON_PASTE61, \
2160 NLOHMANN_JSON_PASTE60, \
2161 NLOHMANN_JSON_PASTE59, \
2162 NLOHMANN_JSON_PASTE58, \
2163 NLOHMANN_JSON_PASTE57, \
2164 NLOHMANN_JSON_PASTE56, \
2165 NLOHMANN_JSON_PASTE55, \
2166 NLOHMANN_JSON_PASTE54, \
2167 NLOHMANN_JSON_PASTE53, \
2168 NLOHMANN_JSON_PASTE52, \
2169 NLOHMANN_JSON_PASTE51, \
2170 NLOHMANN_JSON_PASTE50, \
2171 NLOHMANN_JSON_PASTE49, \
2172 NLOHMANN_JSON_PASTE48, \
2173 NLOHMANN_JSON_PASTE47, \
2174 NLOHMANN_JSON_PASTE46, \
2175 NLOHMANN_JSON_PASTE45, \
2176 NLOHMANN_JSON_PASTE44, \
2177 NLOHMANN_JSON_PASTE43, \
2178 NLOHMANN_JSON_PASTE42, \
2179 NLOHMANN_JSON_PASTE41, \
2180 NLOHMANN_JSON_PASTE40, \
2181 NLOHMANN_JSON_PASTE39, \
2182 NLOHMANN_JSON_PASTE38, \
2183 NLOHMANN_JSON_PASTE37, \
2184 NLOHMANN_JSON_PASTE36, \
2185 NLOHMANN_JSON_PASTE35, \
2186 NLOHMANN_JSON_PASTE34, \
2187 NLOHMANN_JSON_PASTE33, \
2188 NLOHMANN_JSON_PASTE32, \
2189 NLOHMANN_JSON_PASTE31, \
2190 NLOHMANN_JSON_PASTE30, \
2191 NLOHMANN_JSON_PASTE29, \
2192 NLOHMANN_JSON_PASTE28, \
2193 NLOHMANN_JSON_PASTE27, \
2194 NLOHMANN_JSON_PASTE26, \
2195 NLOHMANN_JSON_PASTE25, \
2196 NLOHMANN_JSON_PASTE24, \
2197 NLOHMANN_JSON_PASTE23, \
2198 NLOHMANN_JSON_PASTE22, \
2199 NLOHMANN_JSON_PASTE21, \
2200 NLOHMANN_JSON_PASTE20, \
2201 NLOHMANN_JSON_PASTE19, \
2202 NLOHMANN_JSON_PASTE18, \
2203 NLOHMANN_JSON_PASTE17, \
2204 NLOHMANN_JSON_PASTE16, \
2205 NLOHMANN_JSON_PASTE15, \
2206 NLOHMANN_JSON_PASTE14, \
2207 NLOHMANN_JSON_PASTE13, \
2208 NLOHMANN_JSON_PASTE12, \
2209 NLOHMANN_JSON_PASTE11, \
2210 NLOHMANN_JSON_PASTE10, \
2211 NLOHMANN_JSON_PASTE9, \
2212 NLOHMANN_JSON_PASTE8, \
2213 NLOHMANN_JSON_PASTE7, \
2214 NLOHMANN_JSON_PASTE6, \
2215 NLOHMANN_JSON_PASTE5, \
2216 NLOHMANN_JSON_PASTE4, \
2217 NLOHMANN_JSON_PASTE3, \
2218 NLOHMANN_JSON_PASTE2, \
2219 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2220 #define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2221 #define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2222 #define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2223 #define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2224 #define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2225 #define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2226 #define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2227 #define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2228 #define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2229 #define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2230 #define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2231 #define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2232 #define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2233 #define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2234 #define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2235 #define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2236 #define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
2237 #define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
2238 #define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
2239 #define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
2240 #define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
2241 #define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
2242 #define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
2243 #define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
2244 #define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
2245 #define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
2246 #define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
2247 #define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
2248 #define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
2249 #define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2250 #define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
2251 #define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
2252 #define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
2253 #define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
2254 #define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
2255 #define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
2256 #define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
2257 #define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
2258 #define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
2259 #define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
2260 #define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
2261 #define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
2262 #define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
2263 #define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
2264 #define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
2265 #define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
2266 #define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
2267 #define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
2268 #define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
2269 #define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
2270 #define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
2271 #define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
2272 #define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
2273 #define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2274 #define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2275 #define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2276 #define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
2277 #define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
2278 #define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
2279 #define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
2280 #define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
2281 #define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
2282 #define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
2283
2284 #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2285 #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2286
2287 /*!
2288 @brief macro
2289 @def NLOHMANN_DEFINE_TYPE_INTRUSIVE
2290 @since version 3.9.0
2291 */
2292 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2293 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2294 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2295
2296 /*!
2297 @brief macro
2298 @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
2299 @since version 3.9.0
2300 */
2301 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2302 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2303 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2304
2305 #ifndef JSON_USE_IMPLICIT_CONVERSIONS
2306 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2307 #endif
2308
2309 #if JSON_USE_IMPLICIT_CONVERSIONS
2310 #define JSON_EXPLICIT
2311 #else
2312 #define JSON_EXPLICIT explicit
2313 #endif
2314
2315
2316 namespace nlohmann
2317 {
2318 namespace detail
2319 {
2320 ////////////////
2321 // exceptions //
2322 ////////////////
2323
2324 /*!
2325 @brief general exception of the @ref basic_json class
2326
2327 This class is an extension of `std::exception` objects with a member @a id for
2328 exception ids. It is used as the base class for all exceptions thrown by the
2329 @ref basic_json class. This class can hence be used as "wildcard" to catch
2330 exceptions.
2331
2332 Subclasses:
2333 - @ref parse_error for exceptions indicating a parse error
2334 - @ref invalid_iterator for exceptions indicating errors with iterators
2335 - @ref type_error for exceptions indicating executing a member function with
2336 a wrong type
2337 - @ref out_of_range for exceptions indicating access out of the defined range
2338 - @ref other_error for exceptions indicating other library errors
2339
2340 @internal
2341 @note To have nothrow-copy-constructible exceptions, we internally use
2342 `std::runtime_error` which can cope with arbitrary-length error messages.
2343 Intermediate strings are built with static functions and then passed to
2344 the actual constructor.
2345 @endinternal
2346
2347 @liveexample{The following code shows how arbitrary library exceptions can be
2348 caught.,exception}
2349
2350 @since version 3.0.0
2351 */
2352 class exception : public std::exception
2353 {
2354 public:
2355 /// returns the explanatory string
2356 JSON_HEDLEY_RETURNS_NON_NULL
what() const2357 const char* what() const noexcept override
2358 {
2359 return m.what();
2360 }
2361
2362 /// the id of the exception
2363 const int id;
2364
2365 protected:
2366 JSON_HEDLEY_NON_NULL(3)
exception(int id_,const char * what_arg)2367 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
2368
name(const std::string & ename,int id_)2369 static std::string name(const std::string& ename, int id_)
2370 {
2371 return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
2372 }
2373
2374 private:
2375 /// an exception object as storage for error messages
2376 std::runtime_error m;
2377 };
2378
2379 /*!
2380 @brief exception indicating a parse error
2381
2382 This exception is thrown by the library when a parse error occurs. Parse errors
2383 can occur during the deserialization of JSON text, CBOR, MessagePack, as well
2384 as when using JSON Patch.
2385
2386 Member @a byte holds the byte index of the last read character in the input
2387 file.
2388
2389 Exceptions have ids 1xx.
2390
2391 name / id | example message | description
2392 ------------------------------ | --------------- | -------------------------
2393 json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.
2394 json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.
2395 json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.
2396 json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects.
2397 json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors.
2398 json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`.
2399 json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.
2400 json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
2401 json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.
2402 json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.
2403 json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
2404 json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
2405 json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet).
2406 json.exception.parse_error.115 | parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A | A UBJSON high-precision number could not be parsed.
2407
2408 @note For an input with n bytes, 1 is the index of the first character and n+1
2409 is the index of the terminating null byte or the end of file. This also
2410 holds true when reading a byte vector (CBOR or MessagePack).
2411
2412 @liveexample{The following code shows how a `parse_error` exception can be
2413 caught.,parse_error}
2414
2415 @sa - @ref exception for the base class of the library exceptions
2416 @sa - @ref invalid_iterator for exceptions indicating errors with iterators
2417 @sa - @ref type_error for exceptions indicating executing a member function with
2418 a wrong type
2419 @sa - @ref out_of_range for exceptions indicating access out of the defined range
2420 @sa - @ref other_error for exceptions indicating other library errors
2421
2422 @since version 3.0.0
2423 */
2424 class parse_error : public exception
2425 {
2426 public:
2427 /*!
2428 @brief create a parse error exception
2429 @param[in] id_ the id of the exception
2430 @param[in] pos the position where the error occurred (or with
2431 chars_read_total=0 if the position cannot be
2432 determined)
2433 @param[in] what_arg the explanatory string
2434 @return parse_error object
2435 */
create(int id_,const position_t & pos,const std::string & what_arg)2436 static parse_error create(int id_, const position_t& pos, const std::string& what_arg)
2437 {
2438 std::string w = exception::name("parse_error", id_) + "parse error" +
2439 position_string(pos) + ": " + what_arg;
2440 return parse_error(id_, pos.chars_read_total, w.c_str());
2441 }
2442
create(int id_,std::size_t byte_,const std::string & what_arg)2443 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)
2444 {
2445 std::string w = exception::name("parse_error", id_) + "parse error" +
2446 (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
2447 ": " + what_arg;
2448 return parse_error(id_, byte_, w.c_str());
2449 }
2450
2451 /*!
2452 @brief byte index of the parse error
2453
2454 The byte index of the last read character in the input file.
2455
2456 @note For an input with n bytes, 1 is the index of the first character and
2457 n+1 is the index of the terminating null byte or the end of file.
2458 This also holds true when reading a byte vector (CBOR or MessagePack).
2459 */
2460 const std::size_t byte;
2461
2462 private:
parse_error(int id_,std::size_t byte_,const char * what_arg)2463 parse_error(int id_, std::size_t byte_, const char* what_arg)
2464 : exception(id_, what_arg), byte(byte_) {}
2465
position_string(const position_t & pos)2466 static std::string position_string(const position_t& pos)
2467 {
2468 return " at line " + std::to_string(pos.lines_read + 1) +
2469 ", column " + std::to_string(pos.chars_read_current_line);
2470 }
2471 };
2472
2473 /*!
2474 @brief exception indicating errors with iterators
2475
2476 This exception is thrown if iterators passed to a library function do not match
2477 the expected semantics.
2478
2479 Exceptions have ids 2xx.
2480
2481 name / id | example message | description
2482 ----------------------------------- | --------------- | -------------------------
2483 json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
2484 json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
2485 json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.
2486 json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.
2487 json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.
2488 json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.
2489 json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.
2490 json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
2491 json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
2492 json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
2493 json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to.
2494 json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container.
2495 json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered.
2496 json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().
2497
2498 @liveexample{The following code shows how an `invalid_iterator` exception can be
2499 caught.,invalid_iterator}
2500
2501 @sa - @ref exception for the base class of the library exceptions
2502 @sa - @ref parse_error for exceptions indicating a parse error
2503 @sa - @ref type_error for exceptions indicating executing a member function with
2504 a wrong type
2505 @sa - @ref out_of_range for exceptions indicating access out of the defined range
2506 @sa - @ref other_error for exceptions indicating other library errors
2507
2508 @since version 3.0.0
2509 */
2510 class invalid_iterator : public exception
2511 {
2512 public:
create(int id_,const std::string & what_arg)2513 static invalid_iterator create(int id_, const std::string& what_arg)
2514 {
2515 std::string w = exception::name("invalid_iterator", id_) + what_arg;
2516 return invalid_iterator(id_, w.c_str());
2517 }
2518
2519 private:
2520 JSON_HEDLEY_NON_NULL(3)
invalid_iterator(int id_,const char * what_arg)2521 invalid_iterator(int id_, const char* what_arg)
2522 : exception(id_, what_arg) {}
2523 };
2524
2525 /*!
2526 @brief exception indicating executing a member function with a wrong type
2527
2528 This exception is thrown in case of a type error; that is, a library function is
2529 executed on a JSON value whose type does not match the expected semantics.
2530
2531 Exceptions have ids 3xx.
2532
2533 name / id | example message | description
2534 ----------------------------- | --------------- | -------------------------
2535 json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
2536 json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
2537 json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &.
2538 json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
2539 json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
2540 json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
2541 json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.
2542 json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.
2543 json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.
2544 json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.
2545 json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types.
2546 json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.
2547 json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.
2548 json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.
2549 json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.
2550 json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. |
2551 json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) |
2552
2553 @liveexample{The following code shows how a `type_error` exception can be
2554 caught.,type_error}
2555
2556 @sa - @ref exception for the base class of the library exceptions
2557 @sa - @ref parse_error for exceptions indicating a parse error
2558 @sa - @ref invalid_iterator for exceptions indicating errors with iterators
2559 @sa - @ref out_of_range for exceptions indicating access out of the defined range
2560 @sa - @ref other_error for exceptions indicating other library errors
2561
2562 @since version 3.0.0
2563 */
2564 class type_error : public exception
2565 {
2566 public:
create(int id_,const std::string & what_arg)2567 static type_error create(int id_, const std::string& what_arg)
2568 {
2569 std::string w = exception::name("type_error", id_) + what_arg;
2570 return type_error(id_, w.c_str());
2571 }
2572
2573 private:
2574 JSON_HEDLEY_NON_NULL(3)
type_error(int id_,const char * what_arg)2575 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
2576 };
2577
2578 /*!
2579 @brief exception indicating access out of the defined range
2580
2581 This exception is thrown in case a library function is called on an input
2582 parameter that exceeds the expected range, for instance in case of array
2583 indices or nonexisting object keys.
2584
2585 Exceptions have ids 4xx.
2586
2587 name / id | example message | description
2588 ------------------------------- | --------------- | -------------------------
2589 json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.
2590 json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.
2591 json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.
2592 json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
2593 json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
2594 json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
2595 json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. (until version 3.8.0) |
2596 json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
2597 json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |
2598
2599 @liveexample{The following code shows how an `out_of_range` exception can be
2600 caught.,out_of_range}
2601
2602 @sa - @ref exception for the base class of the library exceptions
2603 @sa - @ref parse_error for exceptions indicating a parse error
2604 @sa - @ref invalid_iterator for exceptions indicating errors with iterators
2605 @sa - @ref type_error for exceptions indicating executing a member function with
2606 a wrong type
2607 @sa - @ref other_error for exceptions indicating other library errors
2608
2609 @since version 3.0.0
2610 */
2611 class out_of_range : public exception
2612 {
2613 public:
create(int id_,const std::string & what_arg)2614 static out_of_range create(int id_, const std::string& what_arg)
2615 {
2616 std::string w = exception::name("out_of_range", id_) + what_arg;
2617 return out_of_range(id_, w.c_str());
2618 }
2619
2620 private:
2621 JSON_HEDLEY_NON_NULL(3)
out_of_range(int id_,const char * what_arg)2622 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
2623 };
2624
2625 /*!
2626 @brief exception indicating other library errors
2627
2628 This exception is thrown in case of errors that cannot be classified with the
2629 other exception types.
2630
2631 Exceptions have ids 5xx.
2632
2633 name / id | example message | description
2634 ------------------------------ | --------------- | -------------------------
2635 json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
2636
2637 @sa - @ref exception for the base class of the library exceptions
2638 @sa - @ref parse_error for exceptions indicating a parse error
2639 @sa - @ref invalid_iterator for exceptions indicating errors with iterators
2640 @sa - @ref type_error for exceptions indicating executing a member function with
2641 a wrong type
2642 @sa - @ref out_of_range for exceptions indicating access out of the defined range
2643
2644 @liveexample{The following code shows how an `other_error` exception can be
2645 caught.,other_error}
2646
2647 @since version 3.0.0
2648 */
2649 class other_error : public exception
2650 {
2651 public:
create(int id_,const std::string & what_arg)2652 static other_error create(int id_, const std::string& what_arg)
2653 {
2654 std::string w = exception::name("other_error", id_) + what_arg;
2655 return other_error(id_, w.c_str());
2656 }
2657
2658 private:
2659 JSON_HEDLEY_NON_NULL(3)
other_error(int id_,const char * what_arg)2660 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
2661 };
2662 } // namespace detail
2663 } // namespace nlohmann
2664
2665 // #include <nlohmann/detail/macro_scope.hpp>
2666
2667 // #include <nlohmann/detail/meta/cpp_future.hpp>
2668
2669
2670 #include <cstddef> // size_t
2671 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
2672
2673 namespace nlohmann
2674 {
2675 namespace detail
2676 {
2677 // alias templates to reduce boilerplate
2678 template<bool B, typename T = void>
2679 using enable_if_t = typename std::enable_if<B, T>::type;
2680
2681 template<typename T>
2682 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
2683
2684 // implementation of C++14 index_sequence and affiliates
2685 // source: https://stackoverflow.com/a/32223343
2686 template<std::size_t... Ints>
2687 struct index_sequence
2688 {
2689 using type = index_sequence;
2690 using value_type = std::size_t;
sizenlohmann::detail::index_sequence2691 static constexpr std::size_t size() noexcept
2692 {
2693 return sizeof...(Ints);
2694 }
2695 };
2696
2697 template<class Sequence1, class Sequence2>
2698 struct merge_and_renumber;
2699
2700 template<std::size_t... I1, std::size_t... I2>
2701 struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
2702 : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
2703
2704 template<std::size_t N>
2705 struct make_index_sequence
2706 : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
2707 typename make_index_sequence < N - N / 2 >::type > {};
2708
2709 template<> struct make_index_sequence<0> : index_sequence<> {};
2710 template<> struct make_index_sequence<1> : index_sequence<0> {};
2711
2712 template<typename... Ts>
2713 using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
2714
2715 // dispatch utility (taken from ranges-v3)
2716 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
2717 template<> struct priority_tag<0> {};
2718
2719 // taken from ranges-v3
2720 template<typename T>
2721 struct static_const
2722 {
2723 static constexpr T value{};
2724 };
2725
2726 template<typename T>
2727 constexpr T static_const<T>::value;
2728 } // namespace detail
2729 } // namespace nlohmann
2730
2731 // #include <nlohmann/detail/meta/type_traits.hpp>
2732
2733
2734 #include <limits> // numeric_limits
2735 #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
2736 #include <utility> // declval
2737
2738 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
2739
2740
2741 #include <iterator> // random_access_iterator_tag
2742
2743 // #include <nlohmann/detail/meta/void_t.hpp>
2744
2745
2746 namespace nlohmann
2747 {
2748 namespace detail
2749 {
2750 template<typename ...Ts> struct make_void
2751 {
2752 using type = void;
2753 };
2754 template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
2755 } // namespace detail
2756 } // namespace nlohmann
2757
2758 // #include <nlohmann/detail/meta/cpp_future.hpp>
2759
2760
2761 namespace nlohmann
2762 {
2763 namespace detail
2764 {
2765 template<typename It, typename = void>
2766 struct iterator_types {};
2767
2768 template<typename It>
2769 struct iterator_types <
2770 It,
2771 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
2772 typename It::reference, typename It::iterator_category >>
2773 {
2774 using difference_type = typename It::difference_type;
2775 using value_type = typename It::value_type;
2776 using pointer = typename It::pointer;
2777 using reference = typename It::reference;
2778 using iterator_category = typename It::iterator_category;
2779 };
2780
2781 // This is required as some compilers implement std::iterator_traits in a way that
2782 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
2783 template<typename T, typename = void>
2784 struct iterator_traits
2785 {
2786 };
2787
2788 template<typename T>
2789 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
2790 : iterator_types<T>
2791 {
2792 };
2793
2794 template<typename T>
2795 struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
2796 {
2797 using iterator_category = std::random_access_iterator_tag;
2798 using value_type = T;
2799 using difference_type = ptrdiff_t;
2800 using pointer = T*;
2801 using reference = T&;
2802 };
2803 } // namespace detail
2804 } // namespace nlohmann
2805
2806 // #include <nlohmann/detail/macro_scope.hpp>
2807
2808 // #include <nlohmann/detail/meta/cpp_future.hpp>
2809
2810 // #include <nlohmann/detail/meta/detected.hpp>
2811
2812
2813 #include <type_traits>
2814
2815 // #include <nlohmann/detail/meta/void_t.hpp>
2816
2817
2818 // https://en.cppreference.com/w/cpp/experimental/is_detected
2819 namespace nlohmann
2820 {
2821 namespace detail
2822 {
2823 struct nonesuch
2824 {
2825 nonesuch() = delete;
2826 ~nonesuch() = delete;
2827 nonesuch(nonesuch const&) = delete;
2828 nonesuch(nonesuch const&&) = delete;
2829 void operator=(nonesuch const&) = delete;
2830 void operator=(nonesuch&&) = delete;
2831 };
2832
2833 template<class Default,
2834 class AlwaysVoid,
2835 template<class...> class Op,
2836 class... Args>
2837 struct detector
2838 {
2839 using value_t = std::false_type;
2840 using type = Default;
2841 };
2842
2843 template<class Default, template<class...> class Op, class... Args>
2844 struct detector<Default, void_t<Op<Args...>>, Op, Args...>
2845 {
2846 using value_t = std::true_type;
2847 using type = Op<Args...>;
2848 };
2849
2850 template<template<class...> class Op, class... Args>
2851 using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
2852
2853 template<template<class...> class Op, class... Args>
2854 using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
2855
2856 template<class Default, template<class...> class Op, class... Args>
2857 using detected_or = detector<Default, void, Op, Args...>;
2858
2859 template<class Default, template<class...> class Op, class... Args>
2860 using detected_or_t = typename detected_or<Default, Op, Args...>::type;
2861
2862 template<class Expected, template<class...> class Op, class... Args>
2863 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
2864
2865 template<class To, template<class...> class Op, class... Args>
2866 using is_detected_convertible =
2867 std::is_convertible<detected_t<Op, Args...>, To>;
2868 } // namespace detail
2869 } // namespace nlohmann
2870
2871 // #include <nlohmann/json_fwd.hpp>
2872 #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
2873 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
2874
2875 #include <cstdint> // int64_t, uint64_t
2876 #include <map> // map
2877 #include <memory> // allocator
2878 #include <string> // string
2879 #include <vector> // vector
2880
2881 /*!
2882 @brief namespace for Niels Lohmann
2883 @see https://github.com/nlohmann
2884 @since version 1.0.0
2885 */
2886 namespace nlohmann
2887 {
2888 /*!
2889 @brief default JSONSerializer template argument
2890
2891 This serializer ignores the template arguments and uses ADL
2892 ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
2893 for serialization.
2894 */
2895 template<typename T = void, typename SFINAE = void>
2896 struct adl_serializer;
2897
2898 template<template<typename U, typename V, typename... Args> class ObjectType =
2899 std::map,
2900 template<typename U, typename... Args> class ArrayType = std::vector,
2901 class StringType = std::string, class BooleanType = bool,
2902 class NumberIntegerType = std::int64_t,
2903 class NumberUnsignedType = std::uint64_t,
2904 class NumberFloatType = double,
2905 template<typename U> class AllocatorType = std::allocator,
2906 template<typename T, typename SFINAE = void> class JSONSerializer =
2907 adl_serializer,
2908 class BinaryType = std::vector<std::uint8_t>>
2909 class basic_json;
2910
2911 /*!
2912 @brief JSON Pointer
2913
2914 A JSON pointer defines a string syntax for identifying a specific value
2915 within a JSON document. It can be used with functions `at` and
2916 `operator[]`. Furthermore, JSON pointers are the base for JSON patches.
2917
2918 @sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
2919
2920 @since version 2.0.0
2921 */
2922 template<typename BasicJsonType>
2923 class json_pointer;
2924
2925 /*!
2926 @brief default JSON class
2927
2928 This type is the default specialization of the @ref basic_json class which
2929 uses the standard template types.
2930
2931 @since version 1.0.0
2932 */
2933 using json = basic_json<>;
2934
2935 template<class Key, class T, class IgnoredLess, class Allocator>
2936 struct ordered_map;
2937
2938 /*!
2939 @brief ordered JSON class
2940
2941 This type preserves the insertion order of object keys.
2942
2943 @since version 3.9.0
2944 */
2945 using ordered_json = basic_json<nlohmann::ordered_map>;
2946
2947 } // namespace nlohmann
2948
2949 #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
2950
2951
2952 namespace nlohmann
2953 {
2954 /*!
2955 @brief detail namespace with internal helper functions
2956
2957 This namespace collects functions that should not be exposed,
2958 implementations of some @ref basic_json methods, and meta-programming helpers.
2959
2960 @since version 2.1.0
2961 */
2962 namespace detail
2963 {
2964 /////////////
2965 // helpers //
2966 /////////////
2967
2968 // Note to maintainers:
2969 //
2970 // Every trait in this file expects a non CV-qualified type.
2971 // The only exceptions are in the 'aliases for detected' section
2972 // (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
2973 //
2974 // In this case, T has to be properly CV-qualified to constraint the function arguments
2975 // (e.g. to_json(BasicJsonType&, const T&))
2976
2977 template<typename> struct is_basic_json : std::false_type {};
2978
2979 NLOHMANN_BASIC_JSON_TPL_DECLARATION
2980 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
2981
2982 //////////////////////
2983 // json_ref helpers //
2984 //////////////////////
2985
2986 template<typename>
2987 class json_ref;
2988
2989 template<typename>
2990 struct is_json_ref : std::false_type {};
2991
2992 template<typename T>
2993 struct is_json_ref<json_ref<T>> : std::true_type {};
2994
2995 //////////////////////////
2996 // aliases for detected //
2997 //////////////////////////
2998
2999 template<typename T>
3000 using mapped_type_t = typename T::mapped_type;
3001
3002 template<typename T>
3003 using key_type_t = typename T::key_type;
3004
3005 template<typename T>
3006 using value_type_t = typename T::value_type;
3007
3008 template<typename T>
3009 using difference_type_t = typename T::difference_type;
3010
3011 template<typename T>
3012 using pointer_t = typename T::pointer;
3013
3014 template<typename T>
3015 using reference_t = typename T::reference;
3016
3017 template<typename T>
3018 using iterator_category_t = typename T::iterator_category;
3019
3020 template<typename T>
3021 using iterator_t = typename T::iterator;
3022
3023 template<typename T, typename... Args>
3024 using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3025
3026 template<typename T, typename... Args>
3027 using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3028
3029 template<typename T, typename U>
3030 using get_template_function = decltype(std::declval<T>().template get<U>());
3031
3032 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3033 template<typename BasicJsonType, typename T, typename = void>
3034 struct has_from_json : std::false_type {};
3035
3036 // trait checking if j.get<T> is valid
3037 // use this trait instead of std::is_constructible or std::is_convertible,
3038 // both rely on, or make use of implicit conversions, and thus fail when T
3039 // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3040 template <typename BasicJsonType, typename T>
3041 struct is_getable
3042 {
3043 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3044 };
3045
3046 template<typename BasicJsonType, typename T>
3047 struct has_from_json < BasicJsonType, T,
3048 enable_if_t < !is_basic_json<T>::value >>
3049 {
3050 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3051
3052 static constexpr bool value =
3053 is_detected_exact<void, from_json_function, serializer,
3054 const BasicJsonType&, T&>::value;
3055 };
3056
3057 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
3058 // this overload is used for non-default-constructible user-defined-types
3059 template<typename BasicJsonType, typename T, typename = void>
3060 struct has_non_default_from_json : std::false_type {};
3061
3062 template<typename BasicJsonType, typename T>
3063 struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3064 {
3065 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3066
3067 static constexpr bool value =
3068 is_detected_exact<T, from_json_function, serializer,
3069 const BasicJsonType&>::value;
3070 };
3071
3072 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3073 // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3074 template<typename BasicJsonType, typename T, typename = void>
3075 struct has_to_json : std::false_type {};
3076
3077 template<typename BasicJsonType, typename T>
3078 struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3079 {
3080 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3081
3082 static constexpr bool value =
3083 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3084 T>::value;
3085 };
3086
3087
3088 ///////////////////
3089 // is_ functions //
3090 ///////////////////
3091
3092 template<typename T, typename = void>
3093 struct is_iterator_traits : std::false_type {};
3094
3095 template<typename T>
3096 struct is_iterator_traits<iterator_traits<T>>
3097 {
3098 private:
3099 using traits = iterator_traits<T>;
3100
3101 public:
3102 static constexpr auto value =
3103 is_detected<value_type_t, traits>::value &&
3104 is_detected<difference_type_t, traits>::value &&
3105 is_detected<pointer_t, traits>::value &&
3106 is_detected<iterator_category_t, traits>::value &&
3107 is_detected<reference_t, traits>::value;
3108 };
3109
3110 // source: https://stackoverflow.com/a/37193089/4116453
3111
3112 template<typename T, typename = void>
3113 struct is_complete_type : std::false_type {};
3114
3115 template<typename T>
3116 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3117
3118 template<typename BasicJsonType, typename CompatibleObjectType,
3119 typename = void>
3120 struct is_compatible_object_type_impl : std::false_type {};
3121
3122 template<typename BasicJsonType, typename CompatibleObjectType>
3123 struct is_compatible_object_type_impl <
3124 BasicJsonType, CompatibleObjectType,
3125 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3126 is_detected<key_type_t, CompatibleObjectType>::value >>
3127 {
3128
3129 using object_t = typename BasicJsonType::object_t;
3130
3131 // macOS's is_constructible does not play well with nonesuch...
3132 static constexpr bool value =
3133 std::is_constructible<typename object_t::key_type,
3134 typename CompatibleObjectType::key_type>::value &&
3135 std::is_constructible<typename object_t::mapped_type,
3136 typename CompatibleObjectType::mapped_type>::value;
3137 };
3138
3139 template<typename BasicJsonType, typename CompatibleObjectType>
3140 struct is_compatible_object_type
3141 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3142
3143 template<typename BasicJsonType, typename ConstructibleObjectType,
3144 typename = void>
3145 struct is_constructible_object_type_impl : std::false_type {};
3146
3147 template<typename BasicJsonType, typename ConstructibleObjectType>
3148 struct is_constructible_object_type_impl <
3149 BasicJsonType, ConstructibleObjectType,
3150 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3151 is_detected<key_type_t, ConstructibleObjectType>::value >>
3152 {
3153 using object_t = typename BasicJsonType::object_t;
3154
3155 static constexpr bool value =
3156 (std::is_default_constructible<ConstructibleObjectType>::value &&
3157 (std::is_move_assignable<ConstructibleObjectType>::value ||
3158 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3159 (std::is_constructible<typename ConstructibleObjectType::key_type,
3160 typename object_t::key_type>::value &&
3161 std::is_same <
3162 typename object_t::mapped_type,
3163 typename ConstructibleObjectType::mapped_type >::value)) ||
3164 (has_from_json<BasicJsonType,
3165 typename ConstructibleObjectType::mapped_type>::value ||
3166 has_non_default_from_json <
3167 BasicJsonType,
3168 typename ConstructibleObjectType::mapped_type >::value);
3169 };
3170
3171 template<typename BasicJsonType, typename ConstructibleObjectType>
3172 struct is_constructible_object_type
3173 : is_constructible_object_type_impl<BasicJsonType,
3174 ConstructibleObjectType> {};
3175
3176 template<typename BasicJsonType, typename CompatibleStringType,
3177 typename = void>
3178 struct is_compatible_string_type_impl : std::false_type {};
3179
3180 template<typename BasicJsonType, typename CompatibleStringType>
3181 struct is_compatible_string_type_impl <
3182 BasicJsonType, CompatibleStringType,
3183 enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
3184 value_type_t, CompatibleStringType>::value >>
3185 {
3186 static constexpr auto value =
3187 std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
3188 };
3189
3190 template<typename BasicJsonType, typename ConstructibleStringType>
3191 struct is_compatible_string_type
3192 : is_compatible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
3193
3194 template<typename BasicJsonType, typename ConstructibleStringType,
3195 typename = void>
3196 struct is_constructible_string_type_impl : std::false_type {};
3197
3198 template<typename BasicJsonType, typename ConstructibleStringType>
3199 struct is_constructible_string_type_impl <
3200 BasicJsonType, ConstructibleStringType,
3201 enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
3202 value_type_t, ConstructibleStringType>::value >>
3203 {
3204 static constexpr auto value =
3205 std::is_constructible<ConstructibleStringType,
3206 typename BasicJsonType::string_t>::value;
3207 };
3208
3209 template<typename BasicJsonType, typename ConstructibleStringType>
3210 struct is_constructible_string_type
3211 : is_constructible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
3212
3213 template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3214 struct is_compatible_array_type_impl : std::false_type {};
3215
3216 template<typename BasicJsonType, typename CompatibleArrayType>
3217 struct is_compatible_array_type_impl <
3218 BasicJsonType, CompatibleArrayType,
3219 enable_if_t < is_detected<value_type_t, CompatibleArrayType>::value&&
3220 is_detected<iterator_t, CompatibleArrayType>::value&&
3221 // This is needed because json_reverse_iterator has a ::iterator type...
3222 // Therefore it is detected as a CompatibleArrayType.
3223 // The real fix would be to have an Iterable concept.
3224 !is_iterator_traits <
3225 iterator_traits<CompatibleArrayType >>::value >>
3226 {
3227 static constexpr bool value =
3228 std::is_constructible<BasicJsonType,
3229 typename CompatibleArrayType::value_type>::value;
3230 };
3231
3232 template<typename BasicJsonType, typename CompatibleArrayType>
3233 struct is_compatible_array_type
3234 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3235
3236 template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3237 struct is_constructible_array_type_impl : std::false_type {};
3238
3239 template<typename BasicJsonType, typename ConstructibleArrayType>
3240 struct is_constructible_array_type_impl <
3241 BasicJsonType, ConstructibleArrayType,
3242 enable_if_t<std::is_same<ConstructibleArrayType,
3243 typename BasicJsonType::value_type>::value >>
3244 : std::true_type {};
3245
3246 template<typename BasicJsonType, typename ConstructibleArrayType>
3247 struct is_constructible_array_type_impl <
3248 BasicJsonType, ConstructibleArrayType,
3249 enable_if_t < !std::is_same<ConstructibleArrayType,
3250 typename BasicJsonType::value_type>::value&&
3251 std::is_default_constructible<ConstructibleArrayType>::value&&
3252 (std::is_move_assignable<ConstructibleArrayType>::value ||
3253 std::is_copy_assignable<ConstructibleArrayType>::value)&&
3254 is_detected<value_type_t, ConstructibleArrayType>::value&&
3255 is_detected<iterator_t, ConstructibleArrayType>::value&&
3256 is_complete_type <
3257 detected_t<value_type_t, ConstructibleArrayType >>::value >>
3258 {
3259 static constexpr bool value =
3260 // This is needed because json_reverse_iterator has a ::iterator type,
3261 // furthermore, std::back_insert_iterator (and other iterators) have a
3262 // base class `iterator`... Therefore it is detected as a
3263 // ConstructibleArrayType. The real fix would be to have an Iterable
3264 // concept.
3265 !is_iterator_traits<iterator_traits<ConstructibleArrayType>>::value &&
3266
3267 (std::is_same<typename ConstructibleArrayType::value_type,
3268 typename BasicJsonType::array_t::value_type>::value ||
3269 has_from_json<BasicJsonType,
3270 typename ConstructibleArrayType::value_type>::value ||
3271 has_non_default_from_json <
3272 BasicJsonType, typename ConstructibleArrayType::value_type >::value);
3273 };
3274
3275 template<typename BasicJsonType, typename ConstructibleArrayType>
3276 struct is_constructible_array_type
3277 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3278
3279 template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3280 typename = void>
3281 struct is_compatible_integer_type_impl : std::false_type {};
3282
3283 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3284 struct is_compatible_integer_type_impl <
3285 RealIntegerType, CompatibleNumberIntegerType,
3286 enable_if_t < std::is_integral<RealIntegerType>::value&&
3287 std::is_integral<CompatibleNumberIntegerType>::value&&
3288 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
3289 {
3290 // is there an assert somewhere on overflows?
3291 using RealLimits = std::numeric_limits<RealIntegerType>;
3292 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3293
3294 static constexpr auto value =
3295 std::is_constructible<RealIntegerType,
3296 CompatibleNumberIntegerType>::value &&
3297 CompatibleLimits::is_integer &&
3298 RealLimits::is_signed == CompatibleLimits::is_signed;
3299 };
3300
3301 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3302 struct is_compatible_integer_type
3303 : is_compatible_integer_type_impl<RealIntegerType,
3304 CompatibleNumberIntegerType> {};
3305
3306 template<typename BasicJsonType, typename CompatibleType, typename = void>
3307 struct is_compatible_type_impl: std::false_type {};
3308
3309 template<typename BasicJsonType, typename CompatibleType>
3310 struct is_compatible_type_impl <
3311 BasicJsonType, CompatibleType,
3312 enable_if_t<is_complete_type<CompatibleType>::value >>
3313 {
3314 static constexpr bool value =
3315 has_to_json<BasicJsonType, CompatibleType>::value;
3316 };
3317
3318 template<typename BasicJsonType, typename CompatibleType>
3319 struct is_compatible_type
3320 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3321
3322 // https://en.cppreference.com/w/cpp/types/conjunction
3323 template<class...> struct conjunction : std::true_type { };
3324 template<class B1> struct conjunction<B1> : B1 { };
3325 template<class B1, class... Bn>
3326 struct conjunction<B1, Bn...>
3327 : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
3328
3329 template<typename T1, typename T2>
3330 struct is_constructible_tuple : std::false_type {};
3331
3332 template<typename T1, typename... Args>
3333 struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<std::is_constructible<T1, Args>...> {};
3334 } // namespace detail
3335 } // namespace nlohmann
3336
3337 // #include <nlohmann/detail/value_t.hpp>
3338
3339
3340 #include <array> // array
3341 #include <cstddef> // size_t
3342 #include <cstdint> // uint8_t
3343 #include <string> // string
3344
3345 namespace nlohmann
3346 {
3347 namespace detail
3348 {
3349 ///////////////////////////
3350 // JSON type enumeration //
3351 ///////////////////////////
3352
3353 /*!
3354 @brief the JSON type enumeration
3355
3356 This enumeration collects the different JSON types. It is internally used to
3357 distinguish the stored values, and the functions @ref basic_json::is_null(),
3358 @ref basic_json::is_object(), @ref basic_json::is_array(),
3359 @ref basic_json::is_string(), @ref basic_json::is_boolean(),
3360 @ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
3361 @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
3362 @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
3363 @ref basic_json::is_structured() rely on it.
3364
3365 @note There are three enumeration entries (number_integer, number_unsigned, and
3366 number_float), because the library distinguishes these three types for numbers:
3367 @ref basic_json::number_unsigned_t is used for unsigned integers,
3368 @ref basic_json::number_integer_t is used for signed integers, and
3369 @ref basic_json::number_float_t is used for floating-point numbers or to
3370 approximate integers which do not fit in the limits of their respective type.
3371
3372 @sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON
3373 value with the default value for a given type
3374
3375 @since version 1.0.0
3376 */
3377 enum class value_t : std::uint8_t
3378 {
3379 null, ///< null value
3380 object, ///< object (unordered set of name/value pairs)
3381 array, ///< array (ordered collection of values)
3382 string, ///< string value
3383 boolean, ///< boolean value
3384 number_integer, ///< number value (signed integer)
3385 number_unsigned, ///< number value (unsigned integer)
3386 number_float, ///< number value (floating-point)
3387 binary, ///< binary array (ordered collection of bytes)
3388 discarded ///< discarded by the parser callback function
3389 };
3390
3391 /*!
3392 @brief comparison operator for JSON types
3393
3394 Returns an ordering that is similar to Python:
3395 - order: null < boolean < number < object < array < string < binary
3396 - furthermore, each type is not smaller than itself
3397 - discarded values are not comparable
3398 - binary is represented as a b"" string in python and directly comparable to a
3399 string; however, making a binary array directly comparable with a string would
3400 be surprising behavior in a JSON file.
3401
3402 @since version 1.0.0
3403 */
operator <(const value_t lhs,const value_t rhs)3404 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3405 {
3406 static constexpr std::array<std::uint8_t, 9> order = {{
3407 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
3408 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
3409 6 /* binary */
3410 }
3411 };
3412
3413 const auto l_index = static_cast<std::size_t>(lhs);
3414 const auto r_index = static_cast<std::size_t>(rhs);
3415 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
3416 }
3417 } // namespace detail
3418 } // namespace nlohmann
3419
3420
3421 namespace nlohmann
3422 {
3423 namespace detail
3424 {
3425 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename std::nullptr_t & n)3426 void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
3427 {
3428 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
3429 {
3430 JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
3431 }
3432 n = nullptr;
3433 }
3434
3435 // overloads for basic_json template parameters
3436 template < typename BasicJsonType, typename ArithmeticType,
3437 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
3438 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
3439 int > = 0 >
get_arithmetic_value(const BasicJsonType & j,ArithmeticType & val)3440 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
3441 {
3442 switch (static_cast<value_t>(j))
3443 {
3444 case value_t::number_unsigned:
3445 {
3446 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
3447 break;
3448 }
3449 case value_t::number_integer:
3450 {
3451 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
3452 break;
3453 }
3454 case value_t::number_float:
3455 {
3456 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
3457 break;
3458 }
3459
3460 default:
3461 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
3462 }
3463 }
3464
3465 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::boolean_t & b)3466 void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
3467 {
3468 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
3469 {
3470 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
3471 }
3472 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
3473 }
3474
3475 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::string_t & s)3476 void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
3477 {
3478 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
3479 {
3480 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
3481 }
3482 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
3483 }
3484
3485 template <
3486 typename BasicJsonType, typename ConstructibleStringType,
3487 enable_if_t <
3488 is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value&&
3489 !std::is_same<typename BasicJsonType::string_t,
3490 ConstructibleStringType>::value,
3491 int > = 0 >
from_json(const BasicJsonType & j,ConstructibleStringType & s)3492 void from_json(const BasicJsonType& j, ConstructibleStringType& s)
3493 {
3494 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
3495 {
3496 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
3497 }
3498
3499 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
3500 }
3501
3502 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::number_float_t & val)3503 void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
3504 {
3505 get_arithmetic_value(j, val);
3506 }
3507
3508 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::number_unsigned_t & val)3509 void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
3510 {
3511 get_arithmetic_value(j, val);
3512 }
3513
3514 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::number_integer_t & val)3515 void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
3516 {
3517 get_arithmetic_value(j, val);
3518 }
3519
3520 template<typename BasicJsonType, typename EnumType,
3521 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
from_json(const BasicJsonType & j,EnumType & e)3522 void from_json(const BasicJsonType& j, EnumType& e)
3523 {
3524 typename std::underlying_type<EnumType>::type val;
3525 get_arithmetic_value(j, val);
3526 e = static_cast<EnumType>(val);
3527 }
3528
3529 // forward_list doesn't have an insert method
3530 template<typename BasicJsonType, typename T, typename Allocator,
3531 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
from_json(const BasicJsonType & j,std::forward_list<T,Allocator> & l)3532 void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
3533 {
3534 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3535 {
3536 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
3537 }
3538 l.clear();
3539 std::transform(j.rbegin(), j.rend(),
3540 std::front_inserter(l), [](const BasicJsonType & i)
3541 {
3542 return i.template get<T>();
3543 });
3544 }
3545
3546 // valarray doesn't have an insert method
3547 template<typename BasicJsonType, typename T,
3548 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
from_json(const BasicJsonType & j,std::valarray<T> & l)3549 void from_json(const BasicJsonType& j, std::valarray<T>& l)
3550 {
3551 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3552 {
3553 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
3554 }
3555 l.resize(j.size());
3556 std::transform(j.begin(), j.end(), std::begin(l),
3557 [](const BasicJsonType & elem)
3558 {
3559 return elem.template get<T>();
3560 });
3561 }
3562
3563 template<typename BasicJsonType, typename T, std::size_t N>
from_json(const BasicJsonType & j,T (& arr)[N])3564 auto from_json(const BasicJsonType& j, T (&arr)[N])
3565 -> decltype(j.template get<T>(), void())
3566 {
3567 for (std::size_t i = 0; i < N; ++i)
3568 {
3569 arr[i] = j.at(i).template get<T>();
3570 }
3571 }
3572
3573 template<typename BasicJsonType>
from_json_array_impl(const BasicJsonType & j,typename BasicJsonType::array_t & arr,priority_tag<3>)3574 void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
3575 {
3576 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
3577 }
3578
3579 template<typename BasicJsonType, typename T, std::size_t N>
from_json_array_impl(const BasicJsonType & j,std::array<T,N> & arr,priority_tag<2>)3580 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
3581 priority_tag<2> /*unused*/)
3582 -> decltype(j.template get<T>(), void())
3583 {
3584 for (std::size_t i = 0; i < N; ++i)
3585 {
3586 arr[i] = j.at(i).template get<T>();
3587 }
3588 }
3589
3590 template<typename BasicJsonType, typename ConstructibleArrayType>
from_json_array_impl(const BasicJsonType & j,ConstructibleArrayType & arr,priority_tag<1>)3591 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
3592 -> decltype(
3593 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
3594 j.template get<typename ConstructibleArrayType::value_type>(),
3595 void())
3596 {
3597 using std::end;
3598
3599 ConstructibleArrayType ret;
3600 ret.reserve(j.size());
3601 std::transform(j.begin(), j.end(),
3602 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
3603 {
3604 // get<BasicJsonType>() returns *this, this won't call a from_json
3605 // method when value_type is BasicJsonType
3606 return i.template get<typename ConstructibleArrayType::value_type>();
3607 });
3608 arr = std::move(ret);
3609 }
3610
3611 template<typename BasicJsonType, typename ConstructibleArrayType>
from_json_array_impl(const BasicJsonType & j,ConstructibleArrayType & arr,priority_tag<0>)3612 void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
3613 priority_tag<0> /*unused*/)
3614 {
3615 using std::end;
3616
3617 ConstructibleArrayType ret;
3618 std::transform(
3619 j.begin(), j.end(), std::inserter(ret, end(ret)),
3620 [](const BasicJsonType & i)
3621 {
3622 // get<BasicJsonType>() returns *this, this won't call a from_json
3623 // method when value_type is BasicJsonType
3624 return i.template get<typename ConstructibleArrayType::value_type>();
3625 });
3626 arr = std::move(ret);
3627 }
3628
3629 template < typename BasicJsonType, typename ConstructibleArrayType,
3630 enable_if_t <
3631 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
3632 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
3633 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3634 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
3635 !is_basic_json<ConstructibleArrayType>::value,
3636 int > = 0 >
from_json(const BasicJsonType & j,ConstructibleArrayType & arr)3637 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
3638 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
3639 j.template get<typename ConstructibleArrayType::value_type>(),
3640 void())
3641 {
3642 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3643 {
3644 JSON_THROW(type_error::create(302, "type must be array, but is " +
3645 std::string(j.type_name())));
3646 }
3647
3648 from_json_array_impl(j, arr, priority_tag<3> {});
3649 }
3650
3651 template<typename BasicJsonType>
from_json(const BasicJsonType & j,typename BasicJsonType::binary_t & bin)3652 void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
3653 {
3654 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
3655 {
3656 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name())));
3657 }
3658
3659 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
3660 }
3661
3662 template<typename BasicJsonType, typename ConstructibleObjectType,
3663 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
from_json(const BasicJsonType & j,ConstructibleObjectType & obj)3664 void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
3665 {
3666 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
3667 {
3668 JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
3669 }
3670
3671 ConstructibleObjectType ret;
3672 auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
3673 using value_type = typename ConstructibleObjectType::value_type;
3674 std::transform(
3675 inner_object->begin(), inner_object->end(),
3676 std::inserter(ret, ret.begin()),
3677 [](typename BasicJsonType::object_t::value_type const & p)
3678 {
3679 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
3680 });
3681 obj = std::move(ret);
3682 }
3683
3684 // overload for arithmetic types, not chosen for basic_json template arguments
3685 // (BooleanType, etc..); note: Is it really necessary to provide explicit
3686 // overloads for boolean_t etc. in case of a custom BooleanType which is not
3687 // an arithmetic type?
3688 template < typename BasicJsonType, typename ArithmeticType,
3689 enable_if_t <
3690 std::is_arithmetic<ArithmeticType>::value&&
3691 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
3692 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
3693 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
3694 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
3695 int > = 0 >
from_json(const BasicJsonType & j,ArithmeticType & val)3696 void from_json(const BasicJsonType& j, ArithmeticType& val)
3697 {
3698 switch (static_cast<value_t>(j))
3699 {
3700 case value_t::number_unsigned:
3701 {
3702 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
3703 break;
3704 }
3705 case value_t::number_integer:
3706 {
3707 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
3708 break;
3709 }
3710 case value_t::number_float:
3711 {
3712 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
3713 break;
3714 }
3715 case value_t::boolean:
3716 {
3717 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
3718 break;
3719 }
3720
3721 default:
3722 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
3723 }
3724 }
3725
3726 template<typename BasicJsonType, typename A1, typename A2>
from_json(const BasicJsonType & j,std::pair<A1,A2> & p)3727 void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
3728 {
3729 p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
3730 }
3731
3732 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
from_json_tuple_impl(const BasicJsonType & j,Tuple & t,index_sequence<Idx...>)3733 void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...> /*unused*/)
3734 {
3735 t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
3736 }
3737
3738 template<typename BasicJsonType, typename... Args>
from_json(const BasicJsonType & j,std::tuple<Args...> & t)3739 void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
3740 {
3741 from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
3742 }
3743
3744 template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
3745 typename = enable_if_t < !std::is_constructible <
3746 typename BasicJsonType::string_t, Key >::value >>
from_json(const BasicJsonType & j,std::map<Key,Value,Compare,Allocator> & m)3747 void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
3748 {
3749 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3750 {
3751 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
3752 }
3753 m.clear();
3754 for (const auto& p : j)
3755 {
3756 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
3757 {
3758 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
3759 }
3760 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
3761 }
3762 }
3763
3764 template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
3765 typename = enable_if_t < !std::is_constructible <
3766 typename BasicJsonType::string_t, Key >::value >>
from_json(const BasicJsonType & j,std::unordered_map<Key,Value,Hash,KeyEqual,Allocator> & m)3767 void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
3768 {
3769 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
3770 {
3771 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
3772 }
3773 m.clear();
3774 for (const auto& p : j)
3775 {
3776 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
3777 {
3778 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
3779 }
3780 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
3781 }
3782 }
3783
3784 struct from_json_fn
3785 {
3786 template<typename BasicJsonType, typename T>
operator ()nlohmann::detail::from_json_fn3787 auto operator()(const BasicJsonType& j, T& val) const
3788 noexcept(noexcept(from_json(j, val)))
3789 -> decltype(from_json(j, val), void())
3790 {
3791 return from_json(j, val);
3792 }
3793 };
3794 } // namespace detail
3795
3796 /// namespace to hold default `from_json` function
3797 /// to see why this is required:
3798 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
3799 namespace
3800 {
3801 constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
3802 } // namespace
3803 } // namespace nlohmann
3804
3805 // #include <nlohmann/detail/conversions/to_json.hpp>
3806
3807
3808 #include <algorithm> // copy
3809 #include <iterator> // begin, end
3810 #include <string> // string
3811 #include <tuple> // tuple, get
3812 #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
3813 #include <utility> // move, forward, declval, pair
3814 #include <valarray> // valarray
3815 #include <vector> // vector
3816
3817 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
3818
3819
3820 #include <cstddef> // size_t
3821 #include <iterator> // input_iterator_tag
3822 #include <string> // string, to_string
3823 #include <tuple> // tuple_size, get, tuple_element
3824
3825 // #include <nlohmann/detail/meta/type_traits.hpp>
3826
3827 // #include <nlohmann/detail/value_t.hpp>
3828
3829
3830 namespace nlohmann
3831 {
3832 namespace detail
3833 {
3834 template<typename string_type>
int_to_string(string_type & target,std::size_t value)3835 void int_to_string( string_type& target, std::size_t value )
3836 {
3837 // For ADL
3838 using std::to_string;
3839 target = to_string(value);
3840 }
3841 template<typename IteratorType> class iteration_proxy_value
3842 {
3843 public:
3844 using difference_type = std::ptrdiff_t;
3845 using value_type = iteration_proxy_value;
3846 using pointer = value_type * ;
3847 using reference = value_type & ;
3848 using iterator_category = std::input_iterator_tag;
3849 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
3850
3851 private:
3852 /// the iterator
3853 IteratorType anchor;
3854 /// an index for arrays (used to create key names)
3855 std::size_t array_index = 0;
3856 /// last stringified array index
3857 mutable std::size_t array_index_last = 0;
3858 /// a string representation of the array index
3859 mutable string_type array_index_str = "0";
3860 /// an empty string (to return a reference for primitive values)
3861 const string_type empty_str = "";
3862
3863 public:
iteration_proxy_value(IteratorType it)3864 explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {}
3865
3866 /// dereference operator (needed for range-based for)
operator *()3867 iteration_proxy_value& operator*()
3868 {
3869 return *this;
3870 }
3871
3872 /// increment operator (needed for range-based for)
operator ++()3873 iteration_proxy_value& operator++()
3874 {
3875 ++anchor;
3876 ++array_index;
3877
3878 return *this;
3879 }
3880
3881 /// equality operator (needed for InputIterator)
operator ==(const iteration_proxy_value & o) const3882 bool operator==(const iteration_proxy_value& o) const
3883 {
3884 return anchor == o.anchor;
3885 }
3886
3887 /// inequality operator (needed for range-based for)
operator !=(const iteration_proxy_value & o) const3888 bool operator!=(const iteration_proxy_value& o) const
3889 {
3890 return anchor != o.anchor;
3891 }
3892
3893 /// return key of the iterator
key() const3894 const string_type& key() const
3895 {
3896 JSON_ASSERT(anchor.m_object != nullptr);
3897
3898 switch (anchor.m_object->type())
3899 {
3900 // use integer array index as key
3901 case value_t::array:
3902 {
3903 if (array_index != array_index_last)
3904 {
3905 int_to_string( array_index_str, array_index );
3906 array_index_last = array_index;
3907 }
3908 return array_index_str;
3909 }
3910
3911 // use key from the object
3912 case value_t::object:
3913 return anchor.key();
3914
3915 // use an empty key for all primitive types
3916 default:
3917 return empty_str;
3918 }
3919 }
3920
3921 /// return value of the iterator
value() const3922 typename IteratorType::reference value() const
3923 {
3924 return anchor.value();
3925 }
3926 };
3927
3928 /// proxy class for the items() function
3929 template<typename IteratorType> class iteration_proxy
3930 {
3931 private:
3932 /// the container to iterate
3933 typename IteratorType::reference container;
3934
3935 public:
3936 /// construct iteration proxy from a container
iteration_proxy(typename IteratorType::reference cont)3937 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
3938 : container(cont) {}
3939
3940 /// return iterator begin (needed for range-based for)
begin()3941 iteration_proxy_value<IteratorType> begin() noexcept
3942 {
3943 return iteration_proxy_value<IteratorType>(container.begin());
3944 }
3945
3946 /// return iterator end (needed for range-based for)
end()3947 iteration_proxy_value<IteratorType> end() noexcept
3948 {
3949 return iteration_proxy_value<IteratorType>(container.end());
3950 }
3951 };
3952 // Structured Bindings Support
3953 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
3954 // And see https://github.com/nlohmann/json/pull/1391
3955 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
get(const nlohmann::detail::iteration_proxy_value<IteratorType> & i)3956 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
3957 {
3958 return i.key();
3959 }
3960 // Structured Bindings Support
3961 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
3962 // And see https://github.com/nlohmann/json/pull/1391
3963 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
get(const nlohmann::detail::iteration_proxy_value<IteratorType> & i)3964 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
3965 {
3966 return i.value();
3967 }
3968 } // namespace detail
3969 } // namespace nlohmann
3970
3971 // The Addition to the STD Namespace is required to add
3972 // Structured Bindings Support to the iteration_proxy_value class
3973 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
3974 // And see https://github.com/nlohmann/json/pull/1391
3975 namespace std
3976 {
3977 #if defined(__clang__)
3978 // Fix: https://github.com/nlohmann/json/issues/1401
3979 #pragma clang diagnostic push
3980 #pragma clang diagnostic ignored "-Wmismatched-tags"
3981 #endif
3982 template<typename IteratorType>
3983 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
3984 : public std::integral_constant<std::size_t, 2> {};
3985
3986 template<std::size_t N, typename IteratorType>
3987 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
3988 {
3989 public:
3990 using type = decltype(
3991 get<N>(std::declval <
3992 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
3993 };
3994 #if defined(__clang__)
3995 #pragma clang diagnostic pop
3996 #endif
3997 } // namespace std
3998
3999 // #include <nlohmann/detail/meta/cpp_future.hpp>
4000
4001 // #include <nlohmann/detail/meta/type_traits.hpp>
4002
4003 // #include <nlohmann/detail/value_t.hpp>
4004
4005
4006 namespace nlohmann
4007 {
4008 namespace detail
4009 {
4010 //////////////////
4011 // constructors //
4012 //////////////////
4013
4014 template<value_t> struct external_constructor;
4015
4016 template<>
4017 struct external_constructor<value_t::boolean>
4018 {
4019 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor4020 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
4021 {
4022 j.m_type = value_t::boolean;
4023 j.m_value = b;
4024 j.assert_invariant();
4025 }
4026 };
4027
4028 template<>
4029 struct external_constructor<value_t::string>
4030 {
4031 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor4032 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
4033 {
4034 j.m_type = value_t::string;
4035 j.m_value = s;
4036 j.assert_invariant();
4037 }
4038
4039 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor4040 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
4041 {
4042 j.m_type = value_t::string;
4043 j.m_value = std::move(s);
4044 j.assert_invariant();
4045 }
4046
4047 template < typename BasicJsonType, typename CompatibleStringType,
4048 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
4049 int > = 0 >
constructnlohmann::detail::external_constructor4050 static void construct(BasicJsonType& j, const CompatibleStringType& str)
4051 {
4052 j.m_type = value_t::string;
4053 j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
4054 j.assert_invariant();
4055 }
4056 };
4057
4058 template<>
4059 struct external_constructor<value_t::binary>
4060 {
4061 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor4062 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
4063 {
4064 j.m_type = value_t::binary;
4065 typename BasicJsonType::binary_t value{b};
4066 j.m_value = value;
4067 j.assert_invariant();
4068 }
4069
4070 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor4071 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
4072 {
4073 j.m_type = value_t::binary;
4074 typename BasicJsonType::binary_t value{std::move(b)};
4075 j.m_value = value;
4076 j.assert_invariant();
4077 }
4078 };
4079
4080 template<>
4081 struct external_constructor<value_t::number_float>
4082 {
4083 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor4084 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
4085 {
4086 j.m_type = value_t::number_float;
4087 j.m_value = val;
4088 j.assert_invariant();
4089 }
4090 };
4091
4092 template<>
4093 struct external_constructor<value_t::number_unsigned>
4094 {
4095 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor4096 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
4097 {
4098 j.m_type = value_t::number_unsigned;
4099 j.m_value = val;
4100 j.assert_invariant();
4101 }
4102 };
4103
4104 template<>
4105 struct external_constructor<value_t::number_integer>
4106 {
4107 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor4108 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
4109 {
4110 j.m_type = value_t::number_integer;
4111 j.m_value = val;
4112 j.assert_invariant();
4113 }
4114 };
4115
4116 template<>
4117 struct external_constructor<value_t::array>
4118 {
4119 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor4120 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
4121 {
4122 j.m_type = value_t::array;
4123 j.m_value = arr;
4124 j.assert_invariant();
4125 }
4126
4127 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor4128 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
4129 {
4130 j.m_type = value_t::array;
4131 j.m_value = std::move(arr);
4132 j.assert_invariant();
4133 }
4134
4135 template < typename BasicJsonType, typename CompatibleArrayType,
4136 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
4137 int > = 0 >
constructnlohmann::detail::external_constructor4138 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
4139 {
4140 using std::begin;
4141 using std::end;
4142 j.m_type = value_t::array;
4143 j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
4144 j.assert_invariant();
4145 }
4146
4147 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor4148 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
4149 {
4150 j.m_type = value_t::array;
4151 j.m_value = value_t::array;
4152 j.m_value.array->reserve(arr.size());
4153 for (const bool x : arr)
4154 {
4155 j.m_value.array->push_back(x);
4156 }
4157 j.assert_invariant();
4158 }
4159
4160 template<typename BasicJsonType, typename T,
4161 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
constructnlohmann::detail::external_constructor4162 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
4163 {
4164 j.m_type = value_t::array;
4165 j.m_value = value_t::array;
4166 j.m_value.array->resize(arr.size());
4167 if (arr.size() > 0)
4168 {
4169 std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
4170 }
4171 j.assert_invariant();
4172 }
4173 };
4174
4175 template<>
4176 struct external_constructor<value_t::object>
4177 {
4178 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor4179 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
4180 {
4181 j.m_type = value_t::object;
4182 j.m_value = obj;
4183 j.assert_invariant();
4184 }
4185
4186 template<typename BasicJsonType>
constructnlohmann::detail::external_constructor4187 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
4188 {
4189 j.m_type = value_t::object;
4190 j.m_value = std::move(obj);
4191 j.assert_invariant();
4192 }
4193
4194 template < typename BasicJsonType, typename CompatibleObjectType,
4195 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
constructnlohmann::detail::external_constructor4196 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
4197 {
4198 using std::begin;
4199 using std::end;
4200
4201 j.m_type = value_t::object;
4202 j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
4203 j.assert_invariant();
4204 }
4205 };
4206
4207 /////////////
4208 // to_json //
4209 /////////////
4210
4211 template<typename BasicJsonType, typename T,
4212 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
to_json(BasicJsonType & j,T b)4213 void to_json(BasicJsonType& j, T b) noexcept
4214 {
4215 external_constructor<value_t::boolean>::construct(j, b);
4216 }
4217
4218 template<typename BasicJsonType, typename CompatibleString,
4219 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
to_json(BasicJsonType & j,const CompatibleString & s)4220 void to_json(BasicJsonType& j, const CompatibleString& s)
4221 {
4222 external_constructor<value_t::string>::construct(j, s);
4223 }
4224
4225 template<typename BasicJsonType>
to_json(BasicJsonType & j,typename BasicJsonType::string_t && s)4226 void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
4227 {
4228 external_constructor<value_t::string>::construct(j, std::move(s));
4229 }
4230
4231 template<typename BasicJsonType, typename FloatType,
4232 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
to_json(BasicJsonType & j,FloatType val)4233 void to_json(BasicJsonType& j, FloatType val) noexcept
4234 {
4235 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
4236 }
4237
4238 template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
4239 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
to_json(BasicJsonType & j,CompatibleNumberUnsignedType val)4240 void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
4241 {
4242 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
4243 }
4244
4245 template<typename BasicJsonType, typename CompatibleNumberIntegerType,
4246 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
to_json(BasicJsonType & j,CompatibleNumberIntegerType val)4247 void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
4248 {
4249 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
4250 }
4251
4252 template<typename BasicJsonType, typename EnumType,
4253 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
to_json(BasicJsonType & j,EnumType e)4254 void to_json(BasicJsonType& j, EnumType e) noexcept
4255 {
4256 using underlying_type = typename std::underlying_type<EnumType>::type;
4257 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
4258 }
4259
4260 template<typename BasicJsonType>
to_json(BasicJsonType & j,const std::vector<bool> & e)4261 void to_json(BasicJsonType& j, const std::vector<bool>& e)
4262 {
4263 external_constructor<value_t::array>::construct(j, e);
4264 }
4265
4266 template < typename BasicJsonType, typename CompatibleArrayType,
4267 enable_if_t < is_compatible_array_type<BasicJsonType,
4268 CompatibleArrayType>::value&&
4269 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
4270 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
4271 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
4272 !is_basic_json<CompatibleArrayType>::value,
4273 int > = 0 >
to_json(BasicJsonType & j,const CompatibleArrayType & arr)4274 void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
4275 {
4276 external_constructor<value_t::array>::construct(j, arr);
4277 }
4278
4279 template<typename BasicJsonType>
to_json(BasicJsonType & j,const typename BasicJsonType::binary_t & bin)4280 void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
4281 {
4282 external_constructor<value_t::binary>::construct(j, bin);
4283 }
4284
4285 template<typename BasicJsonType, typename T,
4286 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
to_json(BasicJsonType & j,const std::valarray<T> & arr)4287 void to_json(BasicJsonType& j, const std::valarray<T>& arr)
4288 {
4289 external_constructor<value_t::array>::construct(j, std::move(arr));
4290 }
4291
4292 template<typename BasicJsonType>
to_json(BasicJsonType & j,typename BasicJsonType::array_t && arr)4293 void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
4294 {
4295 external_constructor<value_t::array>::construct(j, std::move(arr));
4296 }
4297
4298 template < typename BasicJsonType, typename CompatibleObjectType,
4299 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
to_json(BasicJsonType & j,const CompatibleObjectType & obj)4300 void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
4301 {
4302 external_constructor<value_t::object>::construct(j, obj);
4303 }
4304
4305 template<typename BasicJsonType>
to_json(BasicJsonType & j,typename BasicJsonType::object_t && obj)4306 void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
4307 {
4308 external_constructor<value_t::object>::construct(j, std::move(obj));
4309 }
4310
4311 template <
4312 typename BasicJsonType, typename T, std::size_t N,
4313 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
4314 const T(&)[N]>::value,
4315 int > = 0 >
to_json(BasicJsonType & j,const T (& arr)[N])4316 void to_json(BasicJsonType& j, const T(&arr)[N])
4317 {
4318 external_constructor<value_t::array>::construct(j, arr);
4319 }
4320
4321 template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
to_json(BasicJsonType & j,const std::pair<T1,T2> & p)4322 void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
4323 {
4324 j = { p.first, p.second };
4325 }
4326
4327 // for https://github.com/nlohmann/json/pull/1134
4328 template<typename BasicJsonType, typename T,
4329 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
to_json(BasicJsonType & j,const T & b)4330 void to_json(BasicJsonType& j, const T& b)
4331 {
4332 j = { {b.key(), b.value()} };
4333 }
4334
4335 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
to_json_tuple_impl(BasicJsonType & j,const Tuple & t,index_sequence<Idx...>)4336 void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
4337 {
4338 j = { std::get<Idx>(t)... };
4339 }
4340
4341 template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
to_json(BasicJsonType & j,const T & t)4342 void to_json(BasicJsonType& j, const T& t)
4343 {
4344 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
4345 }
4346
4347 struct to_json_fn
4348 {
4349 template<typename BasicJsonType, typename T>
operator ()nlohmann::detail::to_json_fn4350 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
4351 -> decltype(to_json(j, std::forward<T>(val)), void())
4352 {
4353 return to_json(j, std::forward<T>(val));
4354 }
4355 };
4356 } // namespace detail
4357
4358 /// namespace to hold default `to_json` function
4359 namespace
4360 {
4361 constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
4362 } // namespace
4363 } // namespace nlohmann
4364
4365
4366 namespace nlohmann
4367 {
4368
4369 template<typename, typename>
4370 struct adl_serializer
4371 {
4372 /*!
4373 @brief convert a JSON value to any value type
4374
4375 This function is usually called by the `get()` function of the
4376 @ref basic_json class (either explicit or via conversion operators).
4377
4378 @param[in] j JSON value to read from
4379 @param[in,out] val value to write to
4380 */
4381 template<typename BasicJsonType, typename ValueType>
from_jsonnlohmann::adl_serializer4382 static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(
4383 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
4384 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
4385 {
4386 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
4387 }
4388
4389 /*!
4390 @brief convert any value type to a JSON value
4391
4392 This function is usually called by the constructors of the @ref basic_json
4393 class.
4394
4395 @param[in,out] j JSON value to write to
4396 @param[in] val value to read from
4397 */
4398 template<typename BasicJsonType, typename ValueType>
to_jsonnlohmann::adl_serializer4399 static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
4400 noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
4401 -> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)), void())
4402 {
4403 ::nlohmann::to_json(j, std::forward<ValueType>(val));
4404 }
4405 };
4406
4407 } // namespace nlohmann
4408
4409 // #include <nlohmann/byte_container_with_subtype.hpp>
4410
4411
4412 #include <cstdint> // uint8_t
4413 #include <tuple> // tie
4414 #include <utility> // move
4415
4416 namespace nlohmann
4417 {
4418
4419 /*!
4420 @brief an internal type for a backed binary type
4421
4422 This type extends the template parameter @a BinaryType provided to `basic_json`
4423 with a subtype used by BSON and MessagePack. This type exists so that the user
4424 does not have to specify a type themselves with a specific naming scheme in
4425 order to override the binary type.
4426
4427 @tparam BinaryType container to store bytes (`std::vector<std::uint8_t>` by
4428 default)
4429
4430 @since version 3.8.0
4431 */
4432 template<typename BinaryType>
4433 class byte_container_with_subtype : public BinaryType
4434 {
4435 public:
4436 /// the type of the underlying container
4437 using container_type = BinaryType;
4438
byte_container_with_subtype()4439 byte_container_with_subtype() noexcept(noexcept(container_type()))
4440 : container_type()
4441 {}
4442
byte_container_with_subtype(const container_type & b)4443 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
4444 : container_type(b)
4445 {}
4446
byte_container_with_subtype(container_type && b)4447 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
4448 : container_type(std::move(b))
4449 {}
4450
byte_container_with_subtype(const container_type & b,std::uint8_t subtype)4451 byte_container_with_subtype(const container_type& b, std::uint8_t subtype) noexcept(noexcept(container_type(b)))
4452 : container_type(b)
4453 , m_subtype(subtype)
4454 , m_has_subtype(true)
4455 {}
4456
byte_container_with_subtype(container_type && b,std::uint8_t subtype)4457 byte_container_with_subtype(container_type&& b, std::uint8_t subtype) noexcept(noexcept(container_type(std::move(b))))
4458 : container_type(std::move(b))
4459 , m_subtype(subtype)
4460 , m_has_subtype(true)
4461 {}
4462
operator ==(const byte_container_with_subtype & rhs) const4463 bool operator==(const byte_container_with_subtype& rhs) const
4464 {
4465 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
4466 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
4467 }
4468
operator !=(const byte_container_with_subtype & rhs) const4469 bool operator!=(const byte_container_with_subtype& rhs) const
4470 {
4471 return !(rhs == *this);
4472 }
4473
4474 /*!
4475 @brief sets the binary subtype
4476
4477 Sets the binary subtype of the value, also flags a binary JSON value as
4478 having a subtype, which has implications for serialization.
4479
4480 @complexity Constant.
4481
4482 @exceptionsafety No-throw guarantee: this member function never throws
4483 exceptions.
4484
4485 @sa @ref subtype() -- return the binary subtype
4486 @sa @ref clear_subtype() -- clears the binary subtype
4487 @sa @ref has_subtype() -- returns whether or not the binary value has a
4488 subtype
4489
4490 @since version 3.8.0
4491 */
set_subtype(std::uint8_t subtype)4492 void set_subtype(std::uint8_t subtype) noexcept
4493 {
4494 m_subtype = subtype;
4495 m_has_subtype = true;
4496 }
4497
4498 /*!
4499 @brief return the binary subtype
4500
4501 Returns the numerical subtype of the value if it has a subtype. If it does
4502 not have a subtype, this function will return size_t(-1) as a sentinel
4503 value.
4504
4505 @return the numerical subtype of the binary value
4506
4507 @complexity Constant.
4508
4509 @exceptionsafety No-throw guarantee: this member function never throws
4510 exceptions.
4511
4512 @sa @ref set_subtype() -- sets the binary subtype
4513 @sa @ref clear_subtype() -- clears the binary subtype
4514 @sa @ref has_subtype() -- returns whether or not the binary value has a
4515 subtype
4516
4517 @since version 3.8.0
4518 */
subtype() const4519 constexpr std::uint8_t subtype() const noexcept
4520 {
4521 return m_subtype;
4522 }
4523
4524 /*!
4525 @brief return whether the value has a subtype
4526
4527 @return whether the value has a subtype
4528
4529 @complexity Constant.
4530
4531 @exceptionsafety No-throw guarantee: this member function never throws
4532 exceptions.
4533
4534 @sa @ref subtype() -- return the binary subtype
4535 @sa @ref set_subtype() -- sets the binary subtype
4536 @sa @ref clear_subtype() -- clears the binary subtype
4537
4538 @since version 3.8.0
4539 */
has_subtype() const4540 constexpr bool has_subtype() const noexcept
4541 {
4542 return m_has_subtype;
4543 }
4544
4545 /*!
4546 @brief clears the binary subtype
4547
4548 Clears the binary subtype and flags the value as not having a subtype, which
4549 has implications for serialization; for instance MessagePack will prefer the
4550 bin family over the ext family.
4551
4552 @complexity Constant.
4553
4554 @exceptionsafety No-throw guarantee: this member function never throws
4555 exceptions.
4556
4557 @sa @ref subtype() -- return the binary subtype
4558 @sa @ref set_subtype() -- sets the binary subtype
4559 @sa @ref has_subtype() -- returns whether or not the binary value has a
4560 subtype
4561
4562 @since version 3.8.0
4563 */
clear_subtype()4564 void clear_subtype() noexcept
4565 {
4566 m_subtype = 0;
4567 m_has_subtype = false;
4568 }
4569
4570 private:
4571 std::uint8_t m_subtype = 0;
4572 bool m_has_subtype = false;
4573 };
4574
4575 } // namespace nlohmann
4576
4577 // #include <nlohmann/detail/conversions/from_json.hpp>
4578
4579 // #include <nlohmann/detail/conversions/to_json.hpp>
4580
4581 // #include <nlohmann/detail/exceptions.hpp>
4582
4583 // #include <nlohmann/detail/hash.hpp>
4584
4585
4586 #include <cstddef> // size_t, uint8_t
4587 #include <functional> // hash
4588
4589 namespace nlohmann
4590 {
4591 namespace detail
4592 {
4593
4594 // boost::hash_combine
combine(std::size_t seed,std::size_t h)4595 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
4596 {
4597 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
4598 return seed;
4599 }
4600
4601 /*!
4602 @brief hash a JSON value
4603
4604 The hash function tries to rely on std::hash where possible. Furthermore, the
4605 type of the JSON value is taken into account to have different hash values for
4606 null, 0, 0U, and false, etc.
4607
4608 @tparam BasicJsonType basic_json specialization
4609 @param j JSON value to hash
4610 @return hash value of j
4611 */
4612 template<typename BasicJsonType>
hash(const BasicJsonType & j)4613 std::size_t hash(const BasicJsonType& j)
4614 {
4615 using string_t = typename BasicJsonType::string_t;
4616 using number_integer_t = typename BasicJsonType::number_integer_t;
4617 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4618 using number_float_t = typename BasicJsonType::number_float_t;
4619
4620 const auto type = static_cast<std::size_t>(j.type());
4621 switch (j.type())
4622 {
4623 case BasicJsonType::value_t::null:
4624 case BasicJsonType::value_t::discarded:
4625 {
4626 return combine(type, 0);
4627 }
4628
4629 case BasicJsonType::value_t::object:
4630 {
4631 auto seed = combine(type, j.size());
4632 for (const auto& element : j.items())
4633 {
4634 const auto h = std::hash<string_t> {}(element.key());
4635 seed = combine(seed, h);
4636 seed = combine(seed, hash(element.value()));
4637 }
4638 return seed;
4639 }
4640
4641 case BasicJsonType::value_t::array:
4642 {
4643 auto seed = combine(type, j.size());
4644 for (const auto& element : j)
4645 {
4646 seed = combine(seed, hash(element));
4647 }
4648 return seed;
4649 }
4650
4651 case BasicJsonType::value_t::string:
4652 {
4653 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
4654 return combine(type, h);
4655 }
4656
4657 case BasicJsonType::value_t::boolean:
4658 {
4659 const auto h = std::hash<bool> {}(j.template get<bool>());
4660 return combine(type, h);
4661 }
4662
4663 case BasicJsonType::value_t::number_integer:
4664 {
4665 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
4666 return combine(type, h);
4667 }
4668
4669 case nlohmann::detail::value_t::number_unsigned:
4670 {
4671 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
4672 return combine(type, h);
4673 }
4674
4675 case nlohmann::detail::value_t::number_float:
4676 {
4677 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
4678 return combine(type, h);
4679 }
4680
4681 case nlohmann::detail::value_t::binary:
4682 {
4683 auto seed = combine(type, j.get_binary().size());
4684 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
4685 seed = combine(seed, h);
4686 seed = combine(seed, j.get_binary().subtype());
4687 for (const auto byte : j.get_binary())
4688 {
4689 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
4690 }
4691 return seed;
4692 }
4693
4694 default: // LCOV_EXCL_LINE
4695 JSON_ASSERT(false); // LCOV_EXCL_LINE
4696 }
4697 }
4698
4699 } // namespace detail
4700 } // namespace nlohmann
4701
4702 // #include <nlohmann/detail/input/binary_reader.hpp>
4703
4704
4705 #include <algorithm> // generate_n
4706 #include <array> // array
4707 #include <cmath> // ldexp
4708 #include <cstddef> // size_t
4709 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
4710 #include <cstdio> // snprintf
4711 #include <cstring> // memcpy
4712 #include <iterator> // back_inserter
4713 #include <limits> // numeric_limits
4714 #include <string> // char_traits, string
4715 #include <utility> // make_pair, move
4716
4717 // #include <nlohmann/detail/exceptions.hpp>
4718
4719 // #include <nlohmann/detail/input/input_adapters.hpp>
4720
4721
4722 #include <array> // array
4723 #include <cstddef> // size_t
4724 #include <cstdio> //FILE *
4725 #include <cstring> // strlen
4726 #include <istream> // istream
4727 #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
4728 #include <memory> // shared_ptr, make_shared, addressof
4729 #include <numeric> // accumulate
4730 #include <string> // string, char_traits
4731 #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
4732 #include <utility> // pair, declval
4733
4734 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
4735
4736 // #include <nlohmann/detail/macro_scope.hpp>
4737
4738
4739 namespace nlohmann
4740 {
4741 namespace detail
4742 {
4743 /// the supported input formats
4744 enum class input_format_t { json, cbor, msgpack, ubjson, bson };
4745
4746 ////////////////////
4747 // input adapters //
4748 ////////////////////
4749
4750 /*!
4751 Input adapter for stdio file access. This adapter read only 1 byte and do not use any
4752 buffer. This adapter is a very low level adapter.
4753 */
4754 class file_input_adapter
4755 {
4756 public:
4757 using char_type = char;
4758
4759 JSON_HEDLEY_NON_NULL(2)
file_input_adapter(std::FILE * f)4760 explicit file_input_adapter(std::FILE* f) noexcept
4761 : m_file(f)
4762 {}
4763
4764 // make class move-only
4765 file_input_adapter(const file_input_adapter&) = delete;
4766 file_input_adapter(file_input_adapter&&) = default;
4767 file_input_adapter& operator=(const file_input_adapter&) = delete;
4768 file_input_adapter& operator=(file_input_adapter&&) = delete;
4769
get_character()4770 std::char_traits<char>::int_type get_character() noexcept
4771 {
4772 return std::fgetc(m_file);
4773 }
4774
4775 private:
4776 /// the file pointer to read from
4777 std::FILE* m_file;
4778 };
4779
4780
4781 /*!
4782 Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
4783 beginning of input. Does not support changing the underlying std::streambuf
4784 in mid-input. Maintains underlying std::istream and std::streambuf to support
4785 subsequent use of standard std::istream operations to process any input
4786 characters following those used in parsing the JSON input. Clears the
4787 std::istream flags; any input errors (e.g., EOF) will be detected by the first
4788 subsequent call for input from the std::istream.
4789 */
4790 class input_stream_adapter
4791 {
4792 public:
4793 using char_type = char;
4794
~input_stream_adapter()4795 ~input_stream_adapter()
4796 {
4797 // clear stream flags; we use underlying streambuf I/O, do not
4798 // maintain ifstream flags, except eof
4799 if (is != nullptr)
4800 {
4801 is->clear(is->rdstate() & std::ios::eofbit);
4802 }
4803 }
4804
input_stream_adapter(std::istream & i)4805 explicit input_stream_adapter(std::istream& i)
4806 : is(&i), sb(i.rdbuf())
4807 {}
4808
4809 // delete because of pointer members
4810 input_stream_adapter(const input_stream_adapter&) = delete;
4811 input_stream_adapter& operator=(input_stream_adapter&) = delete;
4812 input_stream_adapter& operator=(input_stream_adapter&& rhs) = delete;
4813
input_stream_adapter(input_stream_adapter && rhs)4814 input_stream_adapter(input_stream_adapter&& rhs) noexcept : is(rhs.is), sb(rhs.sb)
4815 {
4816 rhs.is = nullptr;
4817 rhs.sb = nullptr;
4818 }
4819
4820 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
4821 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
4822 // end up as the same value, eg. 0xFFFFFFFF.
get_character()4823 std::char_traits<char>::int_type get_character()
4824 {
4825 auto res = sb->sbumpc();
4826 // set eof manually, as we don't use the istream interface.
4827 if (JSON_HEDLEY_UNLIKELY(res == EOF))
4828 {
4829 is->clear(is->rdstate() | std::ios::eofbit);
4830 }
4831 return res;
4832 }
4833
4834 private:
4835 /// the associated input stream
4836 std::istream* is = nullptr;
4837 std::streambuf* sb = nullptr;
4838 };
4839
4840 // General-purpose iterator-based adapter. It might not be as fast as
4841 // theoretically possible for some containers, but it is extremely versatile.
4842 template<typename IteratorType>
4843 class iterator_input_adapter
4844 {
4845 public:
4846 using char_type = typename std::iterator_traits<IteratorType>::value_type;
4847
iterator_input_adapter(IteratorType first,IteratorType last)4848 iterator_input_adapter(IteratorType first, IteratorType last)
4849 : current(std::move(first)), end(std::move(last)) {}
4850
get_character()4851 typename std::char_traits<char_type>::int_type get_character()
4852 {
4853 if (JSON_HEDLEY_LIKELY(current != end))
4854 {
4855 auto result = std::char_traits<char_type>::to_int_type(*current);
4856 std::advance(current, 1);
4857 return result;
4858 }
4859 else
4860 {
4861 return std::char_traits<char_type>::eof();
4862 }
4863 }
4864
4865 private:
4866 IteratorType current;
4867 IteratorType end;
4868
4869 template<typename BaseInputAdapter, size_t T>
4870 friend struct wide_string_input_helper;
4871
empty() const4872 bool empty() const
4873 {
4874 return current == end;
4875 }
4876
4877 };
4878
4879
4880 template<typename BaseInputAdapter, size_t T>
4881 struct wide_string_input_helper;
4882
4883 template<typename BaseInputAdapter>
4884 struct wide_string_input_helper<BaseInputAdapter, 4>
4885 {
4886 // UTF-32
fill_buffernlohmann::detail::wide_string_input_helper4887 static void fill_buffer(BaseInputAdapter& input,
4888 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
4889 size_t& utf8_bytes_index,
4890 size_t& utf8_bytes_filled)
4891 {
4892 utf8_bytes_index = 0;
4893
4894 if (JSON_HEDLEY_UNLIKELY(input.empty()))
4895 {
4896 utf8_bytes[0] = std::char_traits<char>::eof();
4897 utf8_bytes_filled = 1;
4898 }
4899 else
4900 {
4901 // get the current character
4902 const auto wc = input.get_character();
4903
4904 // UTF-32 to UTF-8 encoding
4905 if (wc < 0x80)
4906 {
4907 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
4908 utf8_bytes_filled = 1;
4909 }
4910 else if (wc <= 0x7FF)
4911 {
4912 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
4913 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
4914 utf8_bytes_filled = 2;
4915 }
4916 else if (wc <= 0xFFFF)
4917 {
4918 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
4919 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
4920 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
4921 utf8_bytes_filled = 3;
4922 }
4923 else if (wc <= 0x10FFFF)
4924 {
4925 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
4926 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
4927 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
4928 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
4929 utf8_bytes_filled = 4;
4930 }
4931 else
4932 {
4933 // unknown character
4934 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
4935 utf8_bytes_filled = 1;
4936 }
4937 }
4938 }
4939 };
4940
4941 template<typename BaseInputAdapter>
4942 struct wide_string_input_helper<BaseInputAdapter, 2>
4943 {
4944 // UTF-16
fill_buffernlohmann::detail::wide_string_input_helper4945 static void fill_buffer(BaseInputAdapter& input,
4946 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
4947 size_t& utf8_bytes_index,
4948 size_t& utf8_bytes_filled)
4949 {
4950 utf8_bytes_index = 0;
4951
4952 if (JSON_HEDLEY_UNLIKELY(input.empty()))
4953 {
4954 utf8_bytes[0] = std::char_traits<char>::eof();
4955 utf8_bytes_filled = 1;
4956 }
4957 else
4958 {
4959 // get the current character
4960 const auto wc = input.get_character();
4961
4962 // UTF-16 to UTF-8 encoding
4963 if (wc < 0x80)
4964 {
4965 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
4966 utf8_bytes_filled = 1;
4967 }
4968 else if (wc <= 0x7FF)
4969 {
4970 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
4971 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
4972 utf8_bytes_filled = 2;
4973 }
4974 else if (0xD800 > wc || wc >= 0xE000)
4975 {
4976 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
4977 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
4978 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
4979 utf8_bytes_filled = 3;
4980 }
4981 else
4982 {
4983 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
4984 {
4985 const auto wc2 = static_cast<unsigned int>(input.get_character());
4986 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
4987 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
4988 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
4989 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
4990 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
4991 utf8_bytes_filled = 4;
4992 }
4993 else
4994 {
4995 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
4996 utf8_bytes_filled = 1;
4997 }
4998 }
4999 }
5000 }
5001 };
5002
5003 // Wraps another input apdater to convert wide character types into individual bytes.
5004 template<typename BaseInputAdapter, typename WideCharType>
5005 class wide_string_input_adapter
5006 {
5007 public:
5008 using char_type = char;
5009
wide_string_input_adapter(BaseInputAdapter base)5010 wide_string_input_adapter(BaseInputAdapter base)
5011 : base_adapter(base) {}
5012
get_character()5013 typename std::char_traits<char>::int_type get_character() noexcept
5014 {
5015 // check if buffer needs to be filled
5016 if (utf8_bytes_index == utf8_bytes_filled)
5017 {
5018 fill_buffer<sizeof(WideCharType)>();
5019
5020 JSON_ASSERT(utf8_bytes_filled > 0);
5021 JSON_ASSERT(utf8_bytes_index == 0);
5022 }
5023
5024 // use buffer
5025 JSON_ASSERT(utf8_bytes_filled > 0);
5026 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
5027 return utf8_bytes[utf8_bytes_index++];
5028 }
5029
5030 private:
5031 BaseInputAdapter base_adapter;
5032
5033 template<size_t T>
fill_buffer()5034 void fill_buffer()
5035 {
5036 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
5037 }
5038
5039 /// a buffer for UTF-8 bytes
5040 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
5041
5042 /// index to the utf8_codes array for the next valid byte
5043 std::size_t utf8_bytes_index = 0;
5044 /// number of valid bytes in the utf8_codes array
5045 std::size_t utf8_bytes_filled = 0;
5046 };
5047
5048
5049 template<typename IteratorType, typename Enable = void>
5050 struct iterator_input_adapter_factory
5051 {
5052 using iterator_type = IteratorType;
5053 using char_type = typename std::iterator_traits<iterator_type>::value_type;
5054 using adapter_type = iterator_input_adapter<iterator_type>;
5055
createnlohmann::detail::iterator_input_adapter_factory5056 static adapter_type create(IteratorType first, IteratorType last)
5057 {
5058 return adapter_type(std::move(first), std::move(last));
5059 }
5060 };
5061
5062 template<typename T>
5063 struct is_iterator_of_multibyte
5064 {
5065 using value_type = typename std::iterator_traits<T>::value_type;
5066 enum
5067 {
5068 value = sizeof(value_type) > 1
5069 };
5070 };
5071
5072 template<typename IteratorType>
5073 struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
5074 {
5075 using iterator_type = IteratorType;
5076 using char_type = typename std::iterator_traits<iterator_type>::value_type;
5077 using base_adapter_type = iterator_input_adapter<iterator_type>;
5078 using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
5079
createnlohmann::detail::iterator_input_adapter_factory5080 static adapter_type create(IteratorType first, IteratorType last)
5081 {
5082 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
5083 }
5084 };
5085
5086 // General purpose iterator-based input
5087 template<typename IteratorType>
input_adapter(IteratorType first,IteratorType last)5088 typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
5089 {
5090 using factory_type = iterator_input_adapter_factory<IteratorType>;
5091 return factory_type::create(first, last);
5092 }
5093
5094 // Convenience shorthand from container to iterator
5095 template<typename ContainerType>
input_adapter(const ContainerType & container)5096 auto input_adapter(const ContainerType& container) -> decltype(input_adapter(begin(container), end(container)))
5097 {
5098 // Enable ADL
5099 using std::begin;
5100 using std::end;
5101
5102 return input_adapter(begin(container), end(container));
5103 }
5104
5105 // Special cases with fast paths
input_adapter(std::FILE * file)5106 inline file_input_adapter input_adapter(std::FILE* file)
5107 {
5108 return file_input_adapter(file);
5109 }
5110
input_adapter(std::istream & stream)5111 inline input_stream_adapter input_adapter(std::istream& stream)
5112 {
5113 return input_stream_adapter(stream);
5114 }
5115
input_adapter(std::istream && stream)5116 inline input_stream_adapter input_adapter(std::istream&& stream)
5117 {
5118 return input_stream_adapter(stream);
5119 }
5120
5121 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
5122
5123 // Null-delimited strings, and the like.
5124 template < typename CharT,
5125 typename std::enable_if <
5126 std::is_pointer<CharT>::value&&
5127 !std::is_array<CharT>::value&&
5128 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
5129 sizeof(typename std::remove_pointer<CharT>::type) == 1,
5130 int >::type = 0 >
input_adapter(CharT b)5131 contiguous_bytes_input_adapter input_adapter(CharT b)
5132 {
5133 auto length = std::strlen(reinterpret_cast<const char*>(b));
5134 const auto* ptr = reinterpret_cast<const char*>(b);
5135 return input_adapter(ptr, ptr + length);
5136 }
5137
5138 template<typename T, std::size_t N>
input_adapter(T (& array)[N])5139 auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N))
5140 {
5141 return input_adapter(array, array + N);
5142 }
5143
5144 // This class only handles inputs of input_buffer_adapter type.
5145 // It's required so that expressions like {ptr, len} can be implicitely casted
5146 // to the correct adapter.
5147 class span_input_adapter
5148 {
5149 public:
5150 template < typename CharT,
5151 typename std::enable_if <
5152 std::is_pointer<CharT>::value&&
5153 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
5154 sizeof(typename std::remove_pointer<CharT>::type) == 1,
5155 int >::type = 0 >
span_input_adapter(CharT b,std::size_t l)5156 span_input_adapter(CharT b, std::size_t l)
5157 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
5158
5159 template<class IteratorType,
5160 typename std::enable_if<
5161 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
5162 int>::type = 0>
span_input_adapter(IteratorType first,IteratorType last)5163 span_input_adapter(IteratorType first, IteratorType last)
5164 : ia(input_adapter(first, last)) {}
5165
get()5166 contiguous_bytes_input_adapter&& get()
5167 {
5168 return std::move(ia);
5169 }
5170
5171 private:
5172 contiguous_bytes_input_adapter ia;
5173 };
5174 } // namespace detail
5175 } // namespace nlohmann
5176
5177 // #include <nlohmann/detail/input/json_sax.hpp>
5178
5179
5180 #include <cstddef>
5181 #include <string> // string
5182 #include <utility> // move
5183 #include <vector> // vector
5184
5185 // #include <nlohmann/detail/exceptions.hpp>
5186
5187 // #include <nlohmann/detail/macro_scope.hpp>
5188
5189
5190 namespace nlohmann
5191 {
5192
5193 /*!
5194 @brief SAX interface
5195
5196 This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
5197 Each function is called in different situations while the input is parsed. The
5198 boolean return value informs the parser whether to continue processing the
5199 input.
5200 */
5201 template<typename BasicJsonType>
5202 struct json_sax
5203 {
5204 using number_integer_t = typename BasicJsonType::number_integer_t;
5205 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5206 using number_float_t = typename BasicJsonType::number_float_t;
5207 using string_t = typename BasicJsonType::string_t;
5208 using binary_t = typename BasicJsonType::binary_t;
5209
5210 /*!
5211 @brief a null value was read
5212 @return whether parsing should proceed
5213 */
5214 virtual bool null() = 0;
5215
5216 /*!
5217 @brief a boolean value was read
5218 @param[in] val boolean value
5219 @return whether parsing should proceed
5220 */
5221 virtual bool boolean(bool val) = 0;
5222
5223 /*!
5224 @brief an integer number was read
5225 @param[in] val integer value
5226 @return whether parsing should proceed
5227 */
5228 virtual bool number_integer(number_integer_t val) = 0;
5229
5230 /*!
5231 @brief an unsigned integer number was read
5232 @param[in] val unsigned integer value
5233 @return whether parsing should proceed
5234 */
5235 virtual bool number_unsigned(number_unsigned_t val) = 0;
5236
5237 /*!
5238 @brief an floating-point number was read
5239 @param[in] val floating-point value
5240 @param[in] s raw token value
5241 @return whether parsing should proceed
5242 */
5243 virtual bool number_float(number_float_t val, const string_t& s) = 0;
5244
5245 /*!
5246 @brief a string was read
5247 @param[in] val string value
5248 @return whether parsing should proceed
5249 @note It is safe to move the passed string.
5250 */
5251 virtual bool string(string_t& val) = 0;
5252
5253 /*!
5254 @brief a binary string was read
5255 @param[in] val binary value
5256 @return whether parsing should proceed
5257 @note It is safe to move the passed binary.
5258 */
5259 virtual bool binary(binary_t& val) = 0;
5260
5261 /*!
5262 @brief the beginning of an object was read
5263 @param[in] elements number of object elements or -1 if unknown
5264 @return whether parsing should proceed
5265 @note binary formats may report the number of elements
5266 */
5267 virtual bool start_object(std::size_t elements) = 0;
5268
5269 /*!
5270 @brief an object key was read
5271 @param[in] val object key
5272 @return whether parsing should proceed
5273 @note It is safe to move the passed string.
5274 */
5275 virtual bool key(string_t& val) = 0;
5276
5277 /*!
5278 @brief the end of an object was read
5279 @return whether parsing should proceed
5280 */
5281 virtual bool end_object() = 0;
5282
5283 /*!
5284 @brief the beginning of an array was read
5285 @param[in] elements number of array elements or -1 if unknown
5286 @return whether parsing should proceed
5287 @note binary formats may report the number of elements
5288 */
5289 virtual bool start_array(std::size_t elements) = 0;
5290
5291 /*!
5292 @brief the end of an array was read
5293 @return whether parsing should proceed
5294 */
5295 virtual bool end_array() = 0;
5296
5297 /*!
5298 @brief a parse error occurred
5299 @param[in] position the position in the input where the error occurs
5300 @param[in] last_token the last read token
5301 @param[in] ex an exception object describing the error
5302 @return whether parsing should proceed (must return false)
5303 */
5304 virtual bool parse_error(std::size_t position,
5305 const std::string& last_token,
5306 const detail::exception& ex) = 0;
5307
5308 virtual ~json_sax() = default;
5309 };
5310
5311
5312 namespace detail
5313 {
5314 /*!
5315 @brief SAX implementation to create a JSON value from SAX events
5316
5317 This class implements the @ref json_sax interface and processes the SAX events
5318 to create a JSON value which makes it basically a DOM parser. The structure or
5319 hierarchy of the JSON value is managed by the stack `ref_stack` which contains
5320 a pointer to the respective array or object for each recursion depth.
5321
5322 After successful parsing, the value that is passed by reference to the
5323 constructor contains the parsed value.
5324
5325 @tparam BasicJsonType the JSON type
5326 */
5327 template<typename BasicJsonType>
5328 class json_sax_dom_parser
5329 {
5330 public:
5331 using number_integer_t = typename BasicJsonType::number_integer_t;
5332 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5333 using number_float_t = typename BasicJsonType::number_float_t;
5334 using string_t = typename BasicJsonType::string_t;
5335 using binary_t = typename BasicJsonType::binary_t;
5336
5337 /*!
5338 @param[in, out] r reference to a JSON value that is manipulated while
5339 parsing
5340 @param[in] allow_exceptions_ whether parse errors yield exceptions
5341 */
json_sax_dom_parser(BasicJsonType & r,const bool allow_exceptions_=true)5342 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
5343 : root(r), allow_exceptions(allow_exceptions_)
5344 {}
5345
5346 // make class move-only
5347 json_sax_dom_parser(const json_sax_dom_parser&) = delete;
5348 json_sax_dom_parser(json_sax_dom_parser&&) = default;
5349 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
5350 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default;
5351 ~json_sax_dom_parser() = default;
5352
null()5353 bool null()
5354 {
5355 handle_value(nullptr);
5356 return true;
5357 }
5358
boolean(bool val)5359 bool boolean(bool val)
5360 {
5361 handle_value(val);
5362 return true;
5363 }
5364
number_integer(number_integer_t val)5365 bool number_integer(number_integer_t val)
5366 {
5367 handle_value(val);
5368 return true;
5369 }
5370
number_unsigned(number_unsigned_t val)5371 bool number_unsigned(number_unsigned_t val)
5372 {
5373 handle_value(val);
5374 return true;
5375 }
5376
number_float(number_float_t val,const string_t &)5377 bool number_float(number_float_t val, const string_t& /*unused*/)
5378 {
5379 handle_value(val);
5380 return true;
5381 }
5382
string(string_t & val)5383 bool string(string_t& val)
5384 {
5385 handle_value(val);
5386 return true;
5387 }
5388
binary(binary_t & val)5389 bool binary(binary_t& val)
5390 {
5391 handle_value(std::move(val));
5392 return true;
5393 }
5394
start_object(std::size_t len)5395 bool start_object(std::size_t len)
5396 {
5397 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
5398
5399 if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
5400 {
5401 JSON_THROW(out_of_range::create(408,
5402 "excessive object size: " + std::to_string(len)));
5403 }
5404
5405 return true;
5406 }
5407
key(string_t & val)5408 bool key(string_t& val)
5409 {
5410 // add null at given key and store the reference for later
5411 object_element = &(ref_stack.back()->m_value.object->operator[](val));
5412 return true;
5413 }
5414
end_object()5415 bool end_object()
5416 {
5417 ref_stack.pop_back();
5418 return true;
5419 }
5420
start_array(std::size_t len)5421 bool start_array(std::size_t len)
5422 {
5423 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
5424
5425 if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
5426 {
5427 JSON_THROW(out_of_range::create(408,
5428 "excessive array size: " + std::to_string(len)));
5429 }
5430
5431 return true;
5432 }
5433
end_array()5434 bool end_array()
5435 {
5436 ref_stack.pop_back();
5437 return true;
5438 }
5439
5440 template<class Exception>
parse_error(std::size_t,const std::string &,const Exception & ex)5441 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
5442 const Exception& ex)
5443 {
5444 errored = true;
5445 static_cast<void>(ex);
5446 if (allow_exceptions)
5447 {
5448 JSON_THROW(ex);
5449 }
5450 return false;
5451 }
5452
is_errored() const5453 constexpr bool is_errored() const
5454 {
5455 return errored;
5456 }
5457
5458 private:
5459 /*!
5460 @invariant If the ref stack is empty, then the passed value will be the new
5461 root.
5462 @invariant If the ref stack contains a value, then it is an array or an
5463 object to which we can add elements
5464 */
5465 template<typename Value>
5466 JSON_HEDLEY_RETURNS_NON_NULL
handle_value(Value && v)5467 BasicJsonType* handle_value(Value&& v)
5468 {
5469 if (ref_stack.empty())
5470 {
5471 root = BasicJsonType(std::forward<Value>(v));
5472 return &root;
5473 }
5474
5475 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
5476
5477 if (ref_stack.back()->is_array())
5478 {
5479 ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
5480 return &(ref_stack.back()->m_value.array->back());
5481 }
5482
5483 JSON_ASSERT(ref_stack.back()->is_object());
5484 JSON_ASSERT(object_element);
5485 *object_element = BasicJsonType(std::forward<Value>(v));
5486 return object_element;
5487 }
5488
5489 /// the parsed JSON value
5490 BasicJsonType& root;
5491 /// stack to model hierarchy of values
5492 std::vector<BasicJsonType*> ref_stack {};
5493 /// helper to hold the reference for the next object element
5494 BasicJsonType* object_element = nullptr;
5495 /// whether a syntax error occurred
5496 bool errored = false;
5497 /// whether to throw exceptions in case of errors
5498 const bool allow_exceptions = true;
5499 };
5500
5501 template<typename BasicJsonType>
5502 class json_sax_dom_callback_parser
5503 {
5504 public:
5505 using number_integer_t = typename BasicJsonType::number_integer_t;
5506 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5507 using number_float_t = typename BasicJsonType::number_float_t;
5508 using string_t = typename BasicJsonType::string_t;
5509 using binary_t = typename BasicJsonType::binary_t;
5510 using parser_callback_t = typename BasicJsonType::parser_callback_t;
5511 using parse_event_t = typename BasicJsonType::parse_event_t;
5512
json_sax_dom_callback_parser(BasicJsonType & r,const parser_callback_t cb,const bool allow_exceptions_=true)5513 json_sax_dom_callback_parser(BasicJsonType& r,
5514 const parser_callback_t cb,
5515 const bool allow_exceptions_ = true)
5516 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
5517 {
5518 keep_stack.push_back(true);
5519 }
5520
5521 // make class move-only
5522 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
5523 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default;
5524 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
5525 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default;
5526 ~json_sax_dom_callback_parser() = default;
5527
null()5528 bool null()
5529 {
5530 handle_value(nullptr);
5531 return true;
5532 }
5533
boolean(bool val)5534 bool boolean(bool val)
5535 {
5536 handle_value(val);
5537 return true;
5538 }
5539
number_integer(number_integer_t val)5540 bool number_integer(number_integer_t val)
5541 {
5542 handle_value(val);
5543 return true;
5544 }
5545
number_unsigned(number_unsigned_t val)5546 bool number_unsigned(number_unsigned_t val)
5547 {
5548 handle_value(val);
5549 return true;
5550 }
5551
number_float(number_float_t val,const string_t &)5552 bool number_float(number_float_t val, const string_t& /*unused*/)
5553 {
5554 handle_value(val);
5555 return true;
5556 }
5557
string(string_t & val)5558 bool string(string_t& val)
5559 {
5560 handle_value(val);
5561 return true;
5562 }
5563
binary(binary_t & val)5564 bool binary(binary_t& val)
5565 {
5566 handle_value(std::move(val));
5567 return true;
5568 }
5569
start_object(std::size_t len)5570 bool start_object(std::size_t len)
5571 {
5572 // check callback for object start
5573 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
5574 keep_stack.push_back(keep);
5575
5576 auto val = handle_value(BasicJsonType::value_t::object, true);
5577 ref_stack.push_back(val.second);
5578
5579 // check object limit
5580 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
5581 {
5582 JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len)));
5583 }
5584
5585 return true;
5586 }
5587
key(string_t & val)5588 bool key(string_t& val)
5589 {
5590 BasicJsonType k = BasicJsonType(val);
5591
5592 // check callback for key
5593 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
5594 key_keep_stack.push_back(keep);
5595
5596 // add discarded value at given key and store the reference for later
5597 if (keep && ref_stack.back())
5598 {
5599 object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
5600 }
5601
5602 return true;
5603 }
5604
end_object()5605 bool end_object()
5606 {
5607 if (ref_stack.back() && !callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
5608 {
5609 // discard object
5610 *ref_stack.back() = discarded;
5611 }
5612
5613 JSON_ASSERT(!ref_stack.empty());
5614 JSON_ASSERT(!keep_stack.empty());
5615 ref_stack.pop_back();
5616 keep_stack.pop_back();
5617
5618 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
5619 {
5620 // remove discarded value
5621 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
5622 {
5623 if (it->is_discarded())
5624 {
5625 ref_stack.back()->erase(it);
5626 break;
5627 }
5628 }
5629 }
5630
5631 return true;
5632 }
5633
start_array(std::size_t len)5634 bool start_array(std::size_t len)
5635 {
5636 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
5637 keep_stack.push_back(keep);
5638
5639 auto val = handle_value(BasicJsonType::value_t::array, true);
5640 ref_stack.push_back(val.second);
5641
5642 // check array limit
5643 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
5644 {
5645 JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len)));
5646 }
5647
5648 return true;
5649 }
5650
end_array()5651 bool end_array()
5652 {
5653 bool keep = true;
5654
5655 if (ref_stack.back())
5656 {
5657 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
5658 if (!keep)
5659 {
5660 // discard array
5661 *ref_stack.back() = discarded;
5662 }
5663 }
5664
5665 JSON_ASSERT(!ref_stack.empty());
5666 JSON_ASSERT(!keep_stack.empty());
5667 ref_stack.pop_back();
5668 keep_stack.pop_back();
5669
5670 // remove discarded value
5671 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
5672 {
5673 ref_stack.back()->m_value.array->pop_back();
5674 }
5675
5676 return true;
5677 }
5678
5679 template<class Exception>
parse_error(std::size_t,const std::string &,const Exception & ex)5680 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
5681 const Exception& ex)
5682 {
5683 errored = true;
5684 static_cast<void>(ex);
5685 if (allow_exceptions)
5686 {
5687 JSON_THROW(ex);
5688 }
5689 return false;
5690 }
5691
is_errored() const5692 constexpr bool is_errored() const
5693 {
5694 return errored;
5695 }
5696
5697 private:
5698 /*!
5699 @param[in] v value to add to the JSON value we build during parsing
5700 @param[in] skip_callback whether we should skip calling the callback
5701 function; this is required after start_array() and
5702 start_object() SAX events, because otherwise we would call the
5703 callback function with an empty array or object, respectively.
5704
5705 @invariant If the ref stack is empty, then the passed value will be the new
5706 root.
5707 @invariant If the ref stack contains a value, then it is an array or an
5708 object to which we can add elements
5709
5710 @return pair of boolean (whether value should be kept) and pointer (to the
5711 passed value in the ref_stack hierarchy; nullptr if not kept)
5712 */
5713 template<typename Value>
handle_value(Value && v,const bool skip_callback=false)5714 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
5715 {
5716 JSON_ASSERT(!keep_stack.empty());
5717
5718 // do not handle this value if we know it would be added to a discarded
5719 // container
5720 if (!keep_stack.back())
5721 {
5722 return {false, nullptr};
5723 }
5724
5725 // create value
5726 auto value = BasicJsonType(std::forward<Value>(v));
5727
5728 // check callback
5729 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
5730
5731 // do not handle this value if we just learnt it shall be discarded
5732 if (!keep)
5733 {
5734 return {false, nullptr};
5735 }
5736
5737 if (ref_stack.empty())
5738 {
5739 root = std::move(value);
5740 return {true, &root};
5741 }
5742
5743 // skip this value if we already decided to skip the parent
5744 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
5745 if (!ref_stack.back())
5746 {
5747 return {false, nullptr};
5748 }
5749
5750 // we now only expect arrays and objects
5751 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
5752
5753 // array
5754 if (ref_stack.back()->is_array())
5755 {
5756 ref_stack.back()->m_value.array->push_back(std::move(value));
5757 return {true, &(ref_stack.back()->m_value.array->back())};
5758 }
5759
5760 // object
5761 JSON_ASSERT(ref_stack.back()->is_object());
5762 // check if we should store an element for the current key
5763 JSON_ASSERT(!key_keep_stack.empty());
5764 const bool store_element = key_keep_stack.back();
5765 key_keep_stack.pop_back();
5766
5767 if (!store_element)
5768 {
5769 return {false, nullptr};
5770 }
5771
5772 JSON_ASSERT(object_element);
5773 *object_element = std::move(value);
5774 return {true, object_element};
5775 }
5776
5777 /// the parsed JSON value
5778 BasicJsonType& root;
5779 /// stack to model hierarchy of values
5780 std::vector<BasicJsonType*> ref_stack {};
5781 /// stack to manage which values to keep
5782 std::vector<bool> keep_stack {};
5783 /// stack to manage which object keys to keep
5784 std::vector<bool> key_keep_stack {};
5785 /// helper to hold the reference for the next object element
5786 BasicJsonType* object_element = nullptr;
5787 /// whether a syntax error occurred
5788 bool errored = false;
5789 /// callback function
5790 const parser_callback_t callback = nullptr;
5791 /// whether to throw exceptions in case of errors
5792 const bool allow_exceptions = true;
5793 /// a discarded value for the callback
5794 BasicJsonType discarded = BasicJsonType::value_t::discarded;
5795 };
5796
5797 template<typename BasicJsonType>
5798 class json_sax_acceptor
5799 {
5800 public:
5801 using number_integer_t = typename BasicJsonType::number_integer_t;
5802 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5803 using number_float_t = typename BasicJsonType::number_float_t;
5804 using string_t = typename BasicJsonType::string_t;
5805 using binary_t = typename BasicJsonType::binary_t;
5806
null()5807 bool null()
5808 {
5809 return true;
5810 }
5811
boolean(bool)5812 bool boolean(bool /*unused*/)
5813 {
5814 return true;
5815 }
5816
number_integer(number_integer_t)5817 bool number_integer(number_integer_t /*unused*/)
5818 {
5819 return true;
5820 }
5821
number_unsigned(number_unsigned_t)5822 bool number_unsigned(number_unsigned_t /*unused*/)
5823 {
5824 return true;
5825 }
5826
number_float(number_float_t,const string_t &)5827 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
5828 {
5829 return true;
5830 }
5831
string(string_t &)5832 bool string(string_t& /*unused*/)
5833 {
5834 return true;
5835 }
5836
binary(binary_t &)5837 bool binary(binary_t& /*unused*/)
5838 {
5839 return true;
5840 }
5841
start_object(std::size_t=std::size_t (-1))5842 bool start_object(std::size_t /*unused*/ = std::size_t(-1))
5843 {
5844 return true;
5845 }
5846
key(string_t &)5847 bool key(string_t& /*unused*/)
5848 {
5849 return true;
5850 }
5851
end_object()5852 bool end_object()
5853 {
5854 return true;
5855 }
5856
start_array(std::size_t=std::size_t (-1))5857 bool start_array(std::size_t /*unused*/ = std::size_t(-1))
5858 {
5859 return true;
5860 }
5861
end_array()5862 bool end_array()
5863 {
5864 return true;
5865 }
5866
parse_error(std::size_t,const std::string &,const detail::exception &)5867 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
5868 {
5869 return false;
5870 }
5871 };
5872 } // namespace detail
5873
5874 } // namespace nlohmann
5875
5876 // #include <nlohmann/detail/input/lexer.hpp>
5877
5878
5879 #include <array> // array
5880 #include <clocale> // localeconv
5881 #include <cstddef> // size_t
5882 #include <cstdio> // snprintf
5883 #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
5884 #include <initializer_list> // initializer_list
5885 #include <string> // char_traits, string
5886 #include <utility> // move
5887 #include <vector> // vector
5888
5889 // #include <nlohmann/detail/input/input_adapters.hpp>
5890
5891 // #include <nlohmann/detail/input/position_t.hpp>
5892
5893 // #include <nlohmann/detail/macro_scope.hpp>
5894
5895
5896 namespace nlohmann
5897 {
5898 namespace detail
5899 {
5900 ///////////
5901 // lexer //
5902 ///////////
5903
5904 template<typename BasicJsonType>
5905 class lexer_base
5906 {
5907 public:
5908 /// token types for the parser
5909 enum class token_type
5910 {
5911 uninitialized, ///< indicating the scanner is uninitialized
5912 literal_true, ///< the `true` literal
5913 literal_false, ///< the `false` literal
5914 literal_null, ///< the `null` literal
5915 value_string, ///< a string -- use get_string() for actual value
5916 value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
5917 value_integer, ///< a signed integer -- use get_number_integer() for actual value
5918 value_float, ///< an floating point number -- use get_number_float() for actual value
5919 begin_array, ///< the character for array begin `[`
5920 begin_object, ///< the character for object begin `{`
5921 end_array, ///< the character for array end `]`
5922 end_object, ///< the character for object end `}`
5923 name_separator, ///< the name separator `:`
5924 value_separator, ///< the value separator `,`
5925 parse_error, ///< indicating a parse error
5926 end_of_input, ///< indicating the end of the input buffer
5927 literal_or_value ///< a literal or the begin of a value (only for diagnostics)
5928 };
5929
5930 /// return name of values of type token_type (only used for errors)
5931 JSON_HEDLEY_RETURNS_NON_NULL
5932 JSON_HEDLEY_CONST
token_type_name(const token_type t)5933 static const char* token_type_name(const token_type t) noexcept
5934 {
5935 switch (t)
5936 {
5937 case token_type::uninitialized:
5938 return "<uninitialized>";
5939 case token_type::literal_true:
5940 return "true literal";
5941 case token_type::literal_false:
5942 return "false literal";
5943 case token_type::literal_null:
5944 return "null literal";
5945 case token_type::value_string:
5946 return "string literal";
5947 case token_type::value_unsigned:
5948 case token_type::value_integer:
5949 case token_type::value_float:
5950 return "number literal";
5951 case token_type::begin_array:
5952 return "'['";
5953 case token_type::begin_object:
5954 return "'{'";
5955 case token_type::end_array:
5956 return "']'";
5957 case token_type::end_object:
5958 return "'}'";
5959 case token_type::name_separator:
5960 return "':'";
5961 case token_type::value_separator:
5962 return "','";
5963 case token_type::parse_error:
5964 return "<parse error>";
5965 case token_type::end_of_input:
5966 return "end of input";
5967 case token_type::literal_or_value:
5968 return "'[', '{', or a literal";
5969 // LCOV_EXCL_START
5970 default: // catch non-enum values
5971 return "unknown token";
5972 // LCOV_EXCL_STOP
5973 }
5974 }
5975 };
5976 /*!
5977 @brief lexical analysis
5978
5979 This class organizes the lexical analysis during JSON deserialization.
5980 */
5981 template<typename BasicJsonType, typename InputAdapterType>
5982 class lexer : public lexer_base<BasicJsonType>
5983 {
5984 using number_integer_t = typename BasicJsonType::number_integer_t;
5985 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5986 using number_float_t = typename BasicJsonType::number_float_t;
5987 using string_t = typename BasicJsonType::string_t;
5988 using char_type = typename InputAdapterType::char_type;
5989 using char_int_type = typename std::char_traits<char_type>::int_type;
5990
5991 public:
5992 using token_type = typename lexer_base<BasicJsonType>::token_type;
5993
lexer(InputAdapterType && adapter,bool ignore_comments_=false)5994 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false)
5995 : ia(std::move(adapter))
5996 , ignore_comments(ignore_comments_)
5997 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
5998 {}
5999
6000 // delete because of pointer members
6001 lexer(const lexer&) = delete;
6002 lexer(lexer&&) = default;
6003 lexer& operator=(lexer&) = delete;
6004 lexer& operator=(lexer&&) = default;
6005 ~lexer() = default;
6006
6007 private:
6008 /////////////////////
6009 // locales
6010 /////////////////////
6011
6012 /// return the locale-dependent decimal point
6013 JSON_HEDLEY_PURE
get_decimal_point()6014 static char get_decimal_point() noexcept
6015 {
6016 const auto* loc = localeconv();
6017 JSON_ASSERT(loc != nullptr);
6018 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
6019 }
6020
6021 /////////////////////
6022 // scan functions
6023 /////////////////////
6024
6025 /*!
6026 @brief get codepoint from 4 hex characters following `\u`
6027
6028 For input "\u c1 c2 c3 c4" the codepoint is:
6029 (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
6030 = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
6031
6032 Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
6033 must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
6034 conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
6035 between the ASCII value of the character and the desired integer value.
6036
6037 @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
6038 non-hex character)
6039 */
get_codepoint()6040 int get_codepoint()
6041 {
6042 // this function only makes sense after reading `\u`
6043 JSON_ASSERT(current == 'u');
6044 int codepoint = 0;
6045
6046 const auto factors = { 12u, 8u, 4u, 0u };
6047 for (const auto factor : factors)
6048 {
6049 get();
6050
6051 if (current >= '0' && current <= '9')
6052 {
6053 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
6054 }
6055 else if (current >= 'A' && current <= 'F')
6056 {
6057 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
6058 }
6059 else if (current >= 'a' && current <= 'f')
6060 {
6061 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
6062 }
6063 else
6064 {
6065 return -1;
6066 }
6067 }
6068
6069 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
6070 return codepoint;
6071 }
6072
6073 /*!
6074 @brief check if the next byte(s) are inside a given range
6075
6076 Adds the current byte and, for each passed range, reads a new byte and
6077 checks if it is inside the range. If a violation was detected, set up an
6078 error message and return false. Otherwise, return true.
6079
6080 @param[in] ranges list of integers; interpreted as list of pairs of
6081 inclusive lower and upper bound, respectively
6082
6083 @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
6084 1, 2, or 3 pairs. This precondition is enforced by an assertion.
6085
6086 @return true if and only if no range violation was detected
6087 */
next_byte_in_range(std::initializer_list<char_int_type> ranges)6088 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
6089 {
6090 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
6091 add(current);
6092
6093 for (auto range = ranges.begin(); range != ranges.end(); ++range)
6094 {
6095 get();
6096 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
6097 {
6098 add(current);
6099 }
6100 else
6101 {
6102 error_message = "invalid string: ill-formed UTF-8 byte";
6103 return false;
6104 }
6105 }
6106
6107 return true;
6108 }
6109
6110 /*!
6111 @brief scan a string literal
6112
6113 This function scans a string according to Sect. 7 of RFC 7159. While
6114 scanning, bytes are escaped and copied into buffer token_buffer. Then the
6115 function returns successfully, token_buffer is *not* null-terminated (as it
6116 may contain \0 bytes), and token_buffer.size() is the number of bytes in the
6117 string.
6118
6119 @return token_type::value_string if string could be successfully scanned,
6120 token_type::parse_error otherwise
6121
6122 @note In case of errors, variable error_message contains a textual
6123 description.
6124 */
scan_string()6125 token_type scan_string()
6126 {
6127 // reset token_buffer (ignore opening quote)
6128 reset();
6129
6130 // we entered the function by reading an open quote
6131 JSON_ASSERT(current == '\"');
6132
6133 while (true)
6134 {
6135 // get next character
6136 switch (get())
6137 {
6138 // end of file while parsing string
6139 case std::char_traits<char_type>::eof():
6140 {
6141 error_message = "invalid string: missing closing quote";
6142 return token_type::parse_error;
6143 }
6144
6145 // closing quote
6146 case '\"':
6147 {
6148 return token_type::value_string;
6149 }
6150
6151 // escapes
6152 case '\\':
6153 {
6154 switch (get())
6155 {
6156 // quotation mark
6157 case '\"':
6158 add('\"');
6159 break;
6160 // reverse solidus
6161 case '\\':
6162 add('\\');
6163 break;
6164 // solidus
6165 case '/':
6166 add('/');
6167 break;
6168 // backspace
6169 case 'b':
6170 add('\b');
6171 break;
6172 // form feed
6173 case 'f':
6174 add('\f');
6175 break;
6176 // line feed
6177 case 'n':
6178 add('\n');
6179 break;
6180 // carriage return
6181 case 'r':
6182 add('\r');
6183 break;
6184 // tab
6185 case 't':
6186 add('\t');
6187 break;
6188
6189 // unicode escapes
6190 case 'u':
6191 {
6192 const int codepoint1 = get_codepoint();
6193 int codepoint = codepoint1; // start with codepoint1
6194
6195 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
6196 {
6197 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
6198 return token_type::parse_error;
6199 }
6200
6201 // check if code point is a high surrogate
6202 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
6203 {
6204 // expect next \uxxxx entry
6205 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
6206 {
6207 const int codepoint2 = get_codepoint();
6208
6209 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
6210 {
6211 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
6212 return token_type::parse_error;
6213 }
6214
6215 // check if codepoint2 is a low surrogate
6216 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
6217 {
6218 // overwrite codepoint
6219 codepoint = static_cast<int>(
6220 // high surrogate occupies the most significant 22 bits
6221 (static_cast<unsigned int>(codepoint1) << 10u)
6222 // low surrogate occupies the least significant 15 bits
6223 + static_cast<unsigned int>(codepoint2)
6224 // there is still the 0xD800, 0xDC00 and 0x10000 noise
6225 // in the result so we have to subtract with:
6226 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6227 - 0x35FDC00u);
6228 }
6229 else
6230 {
6231 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
6232 return token_type::parse_error;
6233 }
6234 }
6235 else
6236 {
6237 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
6238 return token_type::parse_error;
6239 }
6240 }
6241 else
6242 {
6243 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
6244 {
6245 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
6246 return token_type::parse_error;
6247 }
6248 }
6249
6250 // result of the above calculation yields a proper codepoint
6251 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
6252
6253 // translate codepoint into bytes
6254 if (codepoint < 0x80)
6255 {
6256 // 1-byte characters: 0xxxxxxx (ASCII)
6257 add(static_cast<char_int_type>(codepoint));
6258 }
6259 else if (codepoint <= 0x7FF)
6260 {
6261 // 2-byte characters: 110xxxxx 10xxxxxx
6262 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
6263 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6264 }
6265 else if (codepoint <= 0xFFFF)
6266 {
6267 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6268 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
6269 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
6270 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6271 }
6272 else
6273 {
6274 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6275 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
6276 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
6277 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
6278 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
6279 }
6280
6281 break;
6282 }
6283
6284 // other characters after escape
6285 default:
6286 error_message = "invalid string: forbidden character after backslash";
6287 return token_type::parse_error;
6288 }
6289
6290 break;
6291 }
6292
6293 // invalid control characters
6294 case 0x00:
6295 {
6296 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
6297 return token_type::parse_error;
6298 }
6299
6300 case 0x01:
6301 {
6302 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
6303 return token_type::parse_error;
6304 }
6305
6306 case 0x02:
6307 {
6308 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
6309 return token_type::parse_error;
6310 }
6311
6312 case 0x03:
6313 {
6314 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
6315 return token_type::parse_error;
6316 }
6317
6318 case 0x04:
6319 {
6320 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
6321 return token_type::parse_error;
6322 }
6323
6324 case 0x05:
6325 {
6326 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
6327 return token_type::parse_error;
6328 }
6329
6330 case 0x06:
6331 {
6332 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
6333 return token_type::parse_error;
6334 }
6335
6336 case 0x07:
6337 {
6338 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
6339 return token_type::parse_error;
6340 }
6341
6342 case 0x08:
6343 {
6344 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
6345 return token_type::parse_error;
6346 }
6347
6348 case 0x09:
6349 {
6350 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
6351 return token_type::parse_error;
6352 }
6353
6354 case 0x0A:
6355 {
6356 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
6357 return token_type::parse_error;
6358 }
6359
6360 case 0x0B:
6361 {
6362 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
6363 return token_type::parse_error;
6364 }
6365
6366 case 0x0C:
6367 {
6368 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
6369 return token_type::parse_error;
6370 }
6371
6372 case 0x0D:
6373 {
6374 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
6375 return token_type::parse_error;
6376 }
6377
6378 case 0x0E:
6379 {
6380 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
6381 return token_type::parse_error;
6382 }
6383
6384 case 0x0F:
6385 {
6386 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
6387 return token_type::parse_error;
6388 }
6389
6390 case 0x10:
6391 {
6392 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
6393 return token_type::parse_error;
6394 }
6395
6396 case 0x11:
6397 {
6398 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
6399 return token_type::parse_error;
6400 }
6401
6402 case 0x12:
6403 {
6404 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
6405 return token_type::parse_error;
6406 }
6407
6408 case 0x13:
6409 {
6410 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
6411 return token_type::parse_error;
6412 }
6413
6414 case 0x14:
6415 {
6416 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
6417 return token_type::parse_error;
6418 }
6419
6420 case 0x15:
6421 {
6422 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
6423 return token_type::parse_error;
6424 }
6425
6426 case 0x16:
6427 {
6428 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
6429 return token_type::parse_error;
6430 }
6431
6432 case 0x17:
6433 {
6434 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
6435 return token_type::parse_error;
6436 }
6437
6438 case 0x18:
6439 {
6440 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
6441 return token_type::parse_error;
6442 }
6443
6444 case 0x19:
6445 {
6446 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
6447 return token_type::parse_error;
6448 }
6449
6450 case 0x1A:
6451 {
6452 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
6453 return token_type::parse_error;
6454 }
6455
6456 case 0x1B:
6457 {
6458 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
6459 return token_type::parse_error;
6460 }
6461
6462 case 0x1C:
6463 {
6464 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
6465 return token_type::parse_error;
6466 }
6467
6468 case 0x1D:
6469 {
6470 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
6471 return token_type::parse_error;
6472 }
6473
6474 case 0x1E:
6475 {
6476 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
6477 return token_type::parse_error;
6478 }
6479
6480 case 0x1F:
6481 {
6482 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
6483 return token_type::parse_error;
6484 }
6485
6486 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
6487 case 0x20:
6488 case 0x21:
6489 case 0x23:
6490 case 0x24:
6491 case 0x25:
6492 case 0x26:
6493 case 0x27:
6494 case 0x28:
6495 case 0x29:
6496 case 0x2A:
6497 case 0x2B:
6498 case 0x2C:
6499 case 0x2D:
6500 case 0x2E:
6501 case 0x2F:
6502 case 0x30:
6503 case 0x31:
6504 case 0x32:
6505 case 0x33:
6506 case 0x34:
6507 case 0x35:
6508 case 0x36:
6509 case 0x37:
6510 case 0x38:
6511 case 0x39:
6512 case 0x3A:
6513 case 0x3B:
6514 case 0x3C:
6515 case 0x3D:
6516 case 0x3E:
6517 case 0x3F:
6518 case 0x40:
6519 case 0x41:
6520 case 0x42:
6521 case 0x43:
6522 case 0x44:
6523 case 0x45:
6524 case 0x46:
6525 case 0x47:
6526 case 0x48:
6527 case 0x49:
6528 case 0x4A:
6529 case 0x4B:
6530 case 0x4C:
6531 case 0x4D:
6532 case 0x4E:
6533 case 0x4F:
6534 case 0x50:
6535 case 0x51:
6536 case 0x52:
6537 case 0x53:
6538 case 0x54:
6539 case 0x55:
6540 case 0x56:
6541 case 0x57:
6542 case 0x58:
6543 case 0x59:
6544 case 0x5A:
6545 case 0x5B:
6546 case 0x5D:
6547 case 0x5E:
6548 case 0x5F:
6549 case 0x60:
6550 case 0x61:
6551 case 0x62:
6552 case 0x63:
6553 case 0x64:
6554 case 0x65:
6555 case 0x66:
6556 case 0x67:
6557 case 0x68:
6558 case 0x69:
6559 case 0x6A:
6560 case 0x6B:
6561 case 0x6C:
6562 case 0x6D:
6563 case 0x6E:
6564 case 0x6F:
6565 case 0x70:
6566 case 0x71:
6567 case 0x72:
6568 case 0x73:
6569 case 0x74:
6570 case 0x75:
6571 case 0x76:
6572 case 0x77:
6573 case 0x78:
6574 case 0x79:
6575 case 0x7A:
6576 case 0x7B:
6577 case 0x7C:
6578 case 0x7D:
6579 case 0x7E:
6580 case 0x7F:
6581 {
6582 add(current);
6583 break;
6584 }
6585
6586 // U+0080..U+07FF: bytes C2..DF 80..BF
6587 case 0xC2:
6588 case 0xC3:
6589 case 0xC4:
6590 case 0xC5:
6591 case 0xC6:
6592 case 0xC7:
6593 case 0xC8:
6594 case 0xC9:
6595 case 0xCA:
6596 case 0xCB:
6597 case 0xCC:
6598 case 0xCD:
6599 case 0xCE:
6600 case 0xCF:
6601 case 0xD0:
6602 case 0xD1:
6603 case 0xD2:
6604 case 0xD3:
6605 case 0xD4:
6606 case 0xD5:
6607 case 0xD6:
6608 case 0xD7:
6609 case 0xD8:
6610 case 0xD9:
6611 case 0xDA:
6612 case 0xDB:
6613 case 0xDC:
6614 case 0xDD:
6615 case 0xDE:
6616 case 0xDF:
6617 {
6618 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
6619 {
6620 return token_type::parse_error;
6621 }
6622 break;
6623 }
6624
6625 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
6626 case 0xE0:
6627 {
6628 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
6629 {
6630 return token_type::parse_error;
6631 }
6632 break;
6633 }
6634
6635 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
6636 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
6637 case 0xE1:
6638 case 0xE2:
6639 case 0xE3:
6640 case 0xE4:
6641 case 0xE5:
6642 case 0xE6:
6643 case 0xE7:
6644 case 0xE8:
6645 case 0xE9:
6646 case 0xEA:
6647 case 0xEB:
6648 case 0xEC:
6649 case 0xEE:
6650 case 0xEF:
6651 {
6652 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
6653 {
6654 return token_type::parse_error;
6655 }
6656 break;
6657 }
6658
6659 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
6660 case 0xED:
6661 {
6662 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
6663 {
6664 return token_type::parse_error;
6665 }
6666 break;
6667 }
6668
6669 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
6670 case 0xF0:
6671 {
6672 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
6673 {
6674 return token_type::parse_error;
6675 }
6676 break;
6677 }
6678
6679 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
6680 case 0xF1:
6681 case 0xF2:
6682 case 0xF3:
6683 {
6684 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
6685 {
6686 return token_type::parse_error;
6687 }
6688 break;
6689 }
6690
6691 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
6692 case 0xF4:
6693 {
6694 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
6695 {
6696 return token_type::parse_error;
6697 }
6698 break;
6699 }
6700
6701 // remaining bytes (80..C1 and F5..FF) are ill-formed
6702 default:
6703 {
6704 error_message = "invalid string: ill-formed UTF-8 byte";
6705 return token_type::parse_error;
6706 }
6707 }
6708 }
6709 }
6710
6711 /*!
6712 * @brief scan a comment
6713 * @return whether comment could be scanned successfully
6714 */
scan_comment()6715 bool scan_comment()
6716 {
6717 switch (get())
6718 {
6719 // single-line comments skip input until a newline or EOF is read
6720 case '/':
6721 {
6722 while (true)
6723 {
6724 switch (get())
6725 {
6726 case '\n':
6727 case '\r':
6728 case std::char_traits<char_type>::eof():
6729 case '\0':
6730 return true;
6731
6732 default:
6733 break;
6734 }
6735 }
6736 }
6737
6738 // multi-line comments skip input until */ is read
6739 case '*':
6740 {
6741 while (true)
6742 {
6743 switch (get())
6744 {
6745 case std::char_traits<char_type>::eof():
6746 case '\0':
6747 {
6748 error_message = "invalid comment; missing closing '*/'";
6749 return false;
6750 }
6751
6752 case '*':
6753 {
6754 switch (get())
6755 {
6756 case '/':
6757 return true;
6758
6759 default:
6760 {
6761 unget();
6762 continue;
6763 }
6764 }
6765 }
6766
6767 default:
6768 continue;
6769 }
6770 }
6771 }
6772
6773 // unexpected character after reading '/'
6774 default:
6775 {
6776 error_message = "invalid comment; expecting '/' or '*' after '/'";
6777 return false;
6778 }
6779 }
6780 }
6781
6782 JSON_HEDLEY_NON_NULL(2)
strtof(float & f,const char * str,char ** endptr)6783 static void strtof(float& f, const char* str, char** endptr) noexcept
6784 {
6785 f = std::strtof(str, endptr);
6786 }
6787
6788 JSON_HEDLEY_NON_NULL(2)
strtof(double & f,const char * str,char ** endptr)6789 static void strtof(double& f, const char* str, char** endptr) noexcept
6790 {
6791 f = std::strtod(str, endptr);
6792 }
6793
6794 JSON_HEDLEY_NON_NULL(2)
strtof(long double & f,const char * str,char ** endptr)6795 static void strtof(long double& f, const char* str, char** endptr) noexcept
6796 {
6797 f = std::strtold(str, endptr);
6798 }
6799
6800 /*!
6801 @brief scan a number literal
6802
6803 This function scans a string according to Sect. 6 of RFC 7159.
6804
6805 The function is realized with a deterministic finite state machine derived
6806 from the grammar described in RFC 7159. Starting in state "init", the
6807 input is read and used to determined the next state. Only state "done"
6808 accepts the number. State "error" is a trap state to model errors. In the
6809 table below, "anything" means any character but the ones listed before.
6810
6811 state | 0 | 1-9 | e E | + | - | . | anything
6812 ---------|----------|----------|----------|---------|---------|----------|-----------
6813 init | zero | any1 | [error] | [error] | minus | [error] | [error]
6814 minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
6815 zero | done | done | exponent | done | done | decimal1 | done
6816 any1 | any1 | any1 | exponent | done | done | decimal1 | done
6817 decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error]
6818 decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
6819 exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
6820 sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
6821 any2 | any2 | any2 | done | done | done | done | done
6822
6823 The state machine is realized with one label per state (prefixed with
6824 "scan_number_") and `goto` statements between them. The state machine
6825 contains cycles, but any cycle can be left when EOF is read. Therefore,
6826 the function is guaranteed to terminate.
6827
6828 During scanning, the read bytes are stored in token_buffer. This string is
6829 then converted to a signed integer, an unsigned integer, or a
6830 floating-point number.
6831
6832 @return token_type::value_unsigned, token_type::value_integer, or
6833 token_type::value_float if number could be successfully scanned,
6834 token_type::parse_error otherwise
6835
6836 @note The scanner is independent of the current locale. Internally, the
6837 locale's decimal point is used instead of `.` to work with the
6838 locale-dependent converters.
6839 */
scan_number()6840 token_type scan_number() // lgtm [cpp/use-of-goto]
6841 {
6842 // reset token_buffer to store the number's bytes
6843 reset();
6844
6845 // the type of the parsed number; initially set to unsigned; will be
6846 // changed if minus sign, decimal point or exponent is read
6847 token_type number_type = token_type::value_unsigned;
6848
6849 // state (init): we just found out we need to scan a number
6850 switch (current)
6851 {
6852 case '-':
6853 {
6854 add(current);
6855 goto scan_number_minus;
6856 }
6857
6858 case '0':
6859 {
6860 add(current);
6861 goto scan_number_zero;
6862 }
6863
6864 case '1':
6865 case '2':
6866 case '3':
6867 case '4':
6868 case '5':
6869 case '6':
6870 case '7':
6871 case '8':
6872 case '9':
6873 {
6874 add(current);
6875 goto scan_number_any1;
6876 }
6877
6878 // all other characters are rejected outside scan_number()
6879 default: // LCOV_EXCL_LINE
6880 JSON_ASSERT(false); // LCOV_EXCL_LINE
6881 }
6882
6883 scan_number_minus:
6884 // state: we just parsed a leading minus sign
6885 number_type = token_type::value_integer;
6886 switch (get())
6887 {
6888 case '0':
6889 {
6890 add(current);
6891 goto scan_number_zero;
6892 }
6893
6894 case '1':
6895 case '2':
6896 case '3':
6897 case '4':
6898 case '5':
6899 case '6':
6900 case '7':
6901 case '8':
6902 case '9':
6903 {
6904 add(current);
6905 goto scan_number_any1;
6906 }
6907
6908 default:
6909 {
6910 error_message = "invalid number; expected digit after '-'";
6911 return token_type::parse_error;
6912 }
6913 }
6914
6915 scan_number_zero:
6916 // state: we just parse a zero (maybe with a leading minus sign)
6917 switch (get())
6918 {
6919 case '.':
6920 {
6921 add(decimal_point_char);
6922 goto scan_number_decimal1;
6923 }
6924
6925 case 'e':
6926 case 'E':
6927 {
6928 add(current);
6929 goto scan_number_exponent;
6930 }
6931
6932 default:
6933 goto scan_number_done;
6934 }
6935
6936 scan_number_any1:
6937 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
6938 switch (get())
6939 {
6940 case '0':
6941 case '1':
6942 case '2':
6943 case '3':
6944 case '4':
6945 case '5':
6946 case '6':
6947 case '7':
6948 case '8':
6949 case '9':
6950 {
6951 add(current);
6952 goto scan_number_any1;
6953 }
6954
6955 case '.':
6956 {
6957 add(decimal_point_char);
6958 goto scan_number_decimal1;
6959 }
6960
6961 case 'e':
6962 case 'E':
6963 {
6964 add(current);
6965 goto scan_number_exponent;
6966 }
6967
6968 default:
6969 goto scan_number_done;
6970 }
6971
6972 scan_number_decimal1:
6973 // state: we just parsed a decimal point
6974 number_type = token_type::value_float;
6975 switch (get())
6976 {
6977 case '0':
6978 case '1':
6979 case '2':
6980 case '3':
6981 case '4':
6982 case '5':
6983 case '6':
6984 case '7':
6985 case '8':
6986 case '9':
6987 {
6988 add(current);
6989 goto scan_number_decimal2;
6990 }
6991
6992 default:
6993 {
6994 error_message = "invalid number; expected digit after '.'";
6995 return token_type::parse_error;
6996 }
6997 }
6998
6999 scan_number_decimal2:
7000 // we just parsed at least one number after a decimal point
7001 switch (get())
7002 {
7003 case '0':
7004 case '1':
7005 case '2':
7006 case '3':
7007 case '4':
7008 case '5':
7009 case '6':
7010 case '7':
7011 case '8':
7012 case '9':
7013 {
7014 add(current);
7015 goto scan_number_decimal2;
7016 }
7017
7018 case 'e':
7019 case 'E':
7020 {
7021 add(current);
7022 goto scan_number_exponent;
7023 }
7024
7025 default:
7026 goto scan_number_done;
7027 }
7028
7029 scan_number_exponent:
7030 // we just parsed an exponent
7031 number_type = token_type::value_float;
7032 switch (get())
7033 {
7034 case '+':
7035 case '-':
7036 {
7037 add(current);
7038 goto scan_number_sign;
7039 }
7040
7041 case '0':
7042 case '1':
7043 case '2':
7044 case '3':
7045 case '4':
7046 case '5':
7047 case '6':
7048 case '7':
7049 case '8':
7050 case '9':
7051 {
7052 add(current);
7053 goto scan_number_any2;
7054 }
7055
7056 default:
7057 {
7058 error_message =
7059 "invalid number; expected '+', '-', or digit after exponent";
7060 return token_type::parse_error;
7061 }
7062 }
7063
7064 scan_number_sign:
7065 // we just parsed an exponent sign
7066 switch (get())
7067 {
7068 case '0':
7069 case '1':
7070 case '2':
7071 case '3':
7072 case '4':
7073 case '5':
7074 case '6':
7075 case '7':
7076 case '8':
7077 case '9':
7078 {
7079 add(current);
7080 goto scan_number_any2;
7081 }
7082
7083 default:
7084 {
7085 error_message = "invalid number; expected digit after exponent sign";
7086 return token_type::parse_error;
7087 }
7088 }
7089
7090 scan_number_any2:
7091 // we just parsed a number after the exponent or exponent sign
7092 switch (get())
7093 {
7094 case '0':
7095 case '1':
7096 case '2':
7097 case '3':
7098 case '4':
7099 case '5':
7100 case '6':
7101 case '7':
7102 case '8':
7103 case '9':
7104 {
7105 add(current);
7106 goto scan_number_any2;
7107 }
7108
7109 default:
7110 goto scan_number_done;
7111 }
7112
7113 scan_number_done:
7114 // unget the character after the number (we only read it to know that
7115 // we are done scanning a number)
7116 unget();
7117
7118 char* endptr = nullptr;
7119 errno = 0;
7120
7121 // try to parse integers first and fall back to floats
7122 if (number_type == token_type::value_unsigned)
7123 {
7124 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
7125
7126 // we checked the number format before
7127 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7128
7129 if (errno == 0)
7130 {
7131 value_unsigned = static_cast<number_unsigned_t>(x);
7132 if (value_unsigned == x)
7133 {
7134 return token_type::value_unsigned;
7135 }
7136 }
7137 }
7138 else if (number_type == token_type::value_integer)
7139 {
7140 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
7141
7142 // we checked the number format before
7143 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7144
7145 if (errno == 0)
7146 {
7147 value_integer = static_cast<number_integer_t>(x);
7148 if (value_integer == x)
7149 {
7150 return token_type::value_integer;
7151 }
7152 }
7153 }
7154
7155 // this code is reached if we parse a floating-point number or if an
7156 // integer conversion above failed
7157 strtof(value_float, token_buffer.data(), &endptr);
7158
7159 // we checked the number format before
7160 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
7161
7162 return token_type::value_float;
7163 }
7164
7165 /*!
7166 @param[in] literal_text the literal text to expect
7167 @param[in] length the length of the passed literal text
7168 @param[in] return_type the token type to return on success
7169 */
7170 JSON_HEDLEY_NON_NULL(2)
scan_literal(const char_type * literal_text,const std::size_t length,token_type return_type)7171 token_type scan_literal(const char_type* literal_text, const std::size_t length,
7172 token_type return_type)
7173 {
7174 JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
7175 for (std::size_t i = 1; i < length; ++i)
7176 {
7177 if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
7178 {
7179 error_message = "invalid literal";
7180 return token_type::parse_error;
7181 }
7182 }
7183 return return_type;
7184 }
7185
7186 /////////////////////
7187 // input management
7188 /////////////////////
7189
7190 /// reset token_buffer; current character is beginning of token
reset()7191 void reset() noexcept
7192 {
7193 token_buffer.clear();
7194 token_string.clear();
7195 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
7196 }
7197
7198 /*
7199 @brief get next character from the input
7200
7201 This function provides the interface to the used input adapter. It does
7202 not throw in case the input reached EOF, but returns a
7203 `std::char_traits<char>::eof()` in that case. Stores the scanned characters
7204 for use in error messages.
7205
7206 @return character read from the input
7207 */
get()7208 char_int_type get()
7209 {
7210 ++position.chars_read_total;
7211 ++position.chars_read_current_line;
7212
7213 if (next_unget)
7214 {
7215 // just reset the next_unget variable and work with current
7216 next_unget = false;
7217 }
7218 else
7219 {
7220 current = ia.get_character();
7221 }
7222
7223 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
7224 {
7225 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
7226 }
7227
7228 if (current == '\n')
7229 {
7230 ++position.lines_read;
7231 position.chars_read_current_line = 0;
7232 }
7233
7234 return current;
7235 }
7236
7237 /*!
7238 @brief unget current character (read it again on next get)
7239
7240 We implement unget by setting variable next_unget to true. The input is not
7241 changed - we just simulate ungetting by modifying chars_read_total,
7242 chars_read_current_line, and token_string. The next call to get() will
7243 behave as if the unget character is read again.
7244 */
unget()7245 void unget()
7246 {
7247 next_unget = true;
7248
7249 --position.chars_read_total;
7250
7251 // in case we "unget" a newline, we have to also decrement the lines_read
7252 if (position.chars_read_current_line == 0)
7253 {
7254 if (position.lines_read > 0)
7255 {
7256 --position.lines_read;
7257 }
7258 }
7259 else
7260 {
7261 --position.chars_read_current_line;
7262 }
7263
7264 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
7265 {
7266 JSON_ASSERT(!token_string.empty());
7267 token_string.pop_back();
7268 }
7269 }
7270
7271 /// add a character to token_buffer
add(char_int_type c)7272 void add(char_int_type c)
7273 {
7274 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
7275 }
7276
7277 public:
7278 /////////////////////
7279 // value getters
7280 /////////////////////
7281
7282 /// return integer value
get_number_integer() const7283 constexpr number_integer_t get_number_integer() const noexcept
7284 {
7285 return value_integer;
7286 }
7287
7288 /// return unsigned integer value
get_number_unsigned() const7289 constexpr number_unsigned_t get_number_unsigned() const noexcept
7290 {
7291 return value_unsigned;
7292 }
7293
7294 /// return floating-point value
get_number_float() const7295 constexpr number_float_t get_number_float() const noexcept
7296 {
7297 return value_float;
7298 }
7299
7300 /// return current string value (implicitly resets the token; useful only once)
get_string()7301 string_t& get_string()
7302 {
7303 return token_buffer;
7304 }
7305
7306 /////////////////////
7307 // diagnostics
7308 /////////////////////
7309
7310 /// return position of last read token
get_position() const7311 constexpr position_t get_position() const noexcept
7312 {
7313 return position;
7314 }
7315
7316 /// return the last read token (for errors only). Will never contain EOF
7317 /// (an arbitrary value that is not a valid char value, often -1), because
7318 /// 255 may legitimately occur. May contain NUL, which should be escaped.
get_token_string() const7319 std::string get_token_string() const
7320 {
7321 // escape control characters
7322 std::string result;
7323 for (const auto c : token_string)
7324 {
7325 if (static_cast<unsigned char>(c) <= '\x1F')
7326 {
7327 // escape control characters
7328 std::array<char, 9> cs{{}};
7329 (std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c));
7330 result += cs.data();
7331 }
7332 else
7333 {
7334 // add character as is
7335 result.push_back(static_cast<std::string::value_type>(c));
7336 }
7337 }
7338
7339 return result;
7340 }
7341
7342 /// return syntax error message
7343 JSON_HEDLEY_RETURNS_NON_NULL
get_error_message() const7344 constexpr const char* get_error_message() const noexcept
7345 {
7346 return error_message;
7347 }
7348
7349 /////////////////////
7350 // actual scanner
7351 /////////////////////
7352
7353 /*!
7354 @brief skip the UTF-8 byte order mark
7355 @return true iff there is no BOM or the correct BOM has been skipped
7356 */
skip_bom()7357 bool skip_bom()
7358 {
7359 if (get() == 0xEF)
7360 {
7361 // check if we completely parse the BOM
7362 return get() == 0xBB && get() == 0xBF;
7363 }
7364
7365 // the first character is not the beginning of the BOM; unget it to
7366 // process is later
7367 unget();
7368 return true;
7369 }
7370
skip_whitespace()7371 void skip_whitespace()
7372 {
7373 do
7374 {
7375 get();
7376 }
7377 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
7378 }
7379
scan()7380 token_type scan()
7381 {
7382 // initially, skip the BOM
7383 if (position.chars_read_total == 0 && !skip_bom())
7384 {
7385 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
7386 return token_type::parse_error;
7387 }
7388
7389 // read next character and ignore whitespace
7390 skip_whitespace();
7391
7392 // ignore comments
7393 while (ignore_comments && current == '/')
7394 {
7395 if (!scan_comment())
7396 {
7397 return token_type::parse_error;
7398 }
7399
7400 // skip following whitespace
7401 skip_whitespace();
7402 }
7403
7404 switch (current)
7405 {
7406 // structural characters
7407 case '[':
7408 return token_type::begin_array;
7409 case ']':
7410 return token_type::end_array;
7411 case '{':
7412 return token_type::begin_object;
7413 case '}':
7414 return token_type::end_object;
7415 case ':':
7416 return token_type::name_separator;
7417 case ',':
7418 return token_type::value_separator;
7419
7420 // literals
7421 case 't':
7422 {
7423 std::array<char_type, 4> true_literal = {{'t', 'r', 'u', 'e'}};
7424 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
7425 }
7426 case 'f':
7427 {
7428 std::array<char_type, 5> false_literal = {{'f', 'a', 'l', 's', 'e'}};
7429 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
7430 }
7431 case 'n':
7432 {
7433 std::array<char_type, 4> null_literal = {{'n', 'u', 'l', 'l'}};
7434 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
7435 }
7436
7437 // string
7438 case '\"':
7439 return scan_string();
7440
7441 // number
7442 case '-':
7443 case '0':
7444 case '1':
7445 case '2':
7446 case '3':
7447 case '4':
7448 case '5':
7449 case '6':
7450 case '7':
7451 case '8':
7452 case '9':
7453 return scan_number();
7454
7455 // end of input (the null byte is needed when parsing from
7456 // string literals)
7457 case '\0':
7458 case std::char_traits<char_type>::eof():
7459 return token_type::end_of_input;
7460
7461 // error
7462 default:
7463 error_message = "invalid literal";
7464 return token_type::parse_error;
7465 }
7466 }
7467
7468 private:
7469 /// input adapter
7470 InputAdapterType ia;
7471
7472 /// whether comments should be ignored (true) or signaled as errors (false)
7473 const bool ignore_comments = false;
7474
7475 /// the current character
7476 char_int_type current = std::char_traits<char_type>::eof();
7477
7478 /// whether the next get() call should just return current
7479 bool next_unget = false;
7480
7481 /// the start position of the current token
7482 position_t position {};
7483
7484 /// raw input token string (for error messages)
7485 std::vector<char_type> token_string {};
7486
7487 /// buffer for variable-length tokens (numbers, strings)
7488 string_t token_buffer {};
7489
7490 /// a description of occurred lexer errors
7491 const char* error_message = "";
7492
7493 // number values
7494 number_integer_t value_integer = 0;
7495 number_unsigned_t value_unsigned = 0;
7496 number_float_t value_float = 0;
7497
7498 /// the decimal point
7499 const char_int_type decimal_point_char = '.';
7500 };
7501 } // namespace detail
7502 } // namespace nlohmann
7503
7504 // #include <nlohmann/detail/macro_scope.hpp>
7505
7506 // #include <nlohmann/detail/meta/is_sax.hpp>
7507
7508
7509 #include <cstdint> // size_t
7510 #include <utility> // declval
7511 #include <string> // string
7512
7513 // #include <nlohmann/detail/meta/detected.hpp>
7514
7515 // #include <nlohmann/detail/meta/type_traits.hpp>
7516
7517
7518 namespace nlohmann
7519 {
7520 namespace detail
7521 {
7522 template<typename T>
7523 using null_function_t = decltype(std::declval<T&>().null());
7524
7525 template<typename T>
7526 using boolean_function_t =
7527 decltype(std::declval<T&>().boolean(std::declval<bool>()));
7528
7529 template<typename T, typename Integer>
7530 using number_integer_function_t =
7531 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
7532
7533 template<typename T, typename Unsigned>
7534 using number_unsigned_function_t =
7535 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
7536
7537 template<typename T, typename Float, typename String>
7538 using number_float_function_t = decltype(std::declval<T&>().number_float(
7539 std::declval<Float>(), std::declval<const String&>()));
7540
7541 template<typename T, typename String>
7542 using string_function_t =
7543 decltype(std::declval<T&>().string(std::declval<String&>()));
7544
7545 template<typename T, typename Binary>
7546 using binary_function_t =
7547 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
7548
7549 template<typename T>
7550 using start_object_function_t =
7551 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
7552
7553 template<typename T, typename String>
7554 using key_function_t =
7555 decltype(std::declval<T&>().key(std::declval<String&>()));
7556
7557 template<typename T>
7558 using end_object_function_t = decltype(std::declval<T&>().end_object());
7559
7560 template<typename T>
7561 using start_array_function_t =
7562 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
7563
7564 template<typename T>
7565 using end_array_function_t = decltype(std::declval<T&>().end_array());
7566
7567 template<typename T, typename Exception>
7568 using parse_error_function_t = decltype(std::declval<T&>().parse_error(
7569 std::declval<std::size_t>(), std::declval<const std::string&>(),
7570 std::declval<const Exception&>()));
7571
7572 template<typename SAX, typename BasicJsonType>
7573 struct is_sax
7574 {
7575 private:
7576 static_assert(is_basic_json<BasicJsonType>::value,
7577 "BasicJsonType must be of type basic_json<...>");
7578
7579 using number_integer_t = typename BasicJsonType::number_integer_t;
7580 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7581 using number_float_t = typename BasicJsonType::number_float_t;
7582 using string_t = typename BasicJsonType::string_t;
7583 using binary_t = typename BasicJsonType::binary_t;
7584 using exception_t = typename BasicJsonType::exception;
7585
7586 public:
7587 static constexpr bool value =
7588 is_detected_exact<bool, null_function_t, SAX>::value &&
7589 is_detected_exact<bool, boolean_function_t, SAX>::value &&
7590 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
7591 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
7592 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
7593 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
7594 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
7595 is_detected_exact<bool, start_object_function_t, SAX>::value &&
7596 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
7597 is_detected_exact<bool, end_object_function_t, SAX>::value &&
7598 is_detected_exact<bool, start_array_function_t, SAX>::value &&
7599 is_detected_exact<bool, end_array_function_t, SAX>::value &&
7600 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
7601 };
7602
7603 template<typename SAX, typename BasicJsonType>
7604 struct is_sax_static_asserts
7605 {
7606 private:
7607 static_assert(is_basic_json<BasicJsonType>::value,
7608 "BasicJsonType must be of type basic_json<...>");
7609
7610 using number_integer_t = typename BasicJsonType::number_integer_t;
7611 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7612 using number_float_t = typename BasicJsonType::number_float_t;
7613 using string_t = typename BasicJsonType::string_t;
7614 using binary_t = typename BasicJsonType::binary_t;
7615 using exception_t = typename BasicJsonType::exception;
7616
7617 public:
7618 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
7619 "Missing/invalid function: bool null()");
7620 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
7621 "Missing/invalid function: bool boolean(bool)");
7622 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
7623 "Missing/invalid function: bool boolean(bool)");
7624 static_assert(
7625 is_detected_exact<bool, number_integer_function_t, SAX,
7626 number_integer_t>::value,
7627 "Missing/invalid function: bool number_integer(number_integer_t)");
7628 static_assert(
7629 is_detected_exact<bool, number_unsigned_function_t, SAX,
7630 number_unsigned_t>::value,
7631 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
7632 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
7633 number_float_t, string_t>::value,
7634 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
7635 static_assert(
7636 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
7637 "Missing/invalid function: bool string(string_t&)");
7638 static_assert(
7639 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
7640 "Missing/invalid function: bool binary(binary_t&)");
7641 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
7642 "Missing/invalid function: bool start_object(std::size_t)");
7643 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
7644 "Missing/invalid function: bool key(string_t&)");
7645 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
7646 "Missing/invalid function: bool end_object()");
7647 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
7648 "Missing/invalid function: bool start_array(std::size_t)");
7649 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
7650 "Missing/invalid function: bool end_array()");
7651 static_assert(
7652 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
7653 "Missing/invalid function: bool parse_error(std::size_t, const "
7654 "std::string&, const exception&)");
7655 };
7656 } // namespace detail
7657 } // namespace nlohmann
7658
7659 // #include <nlohmann/detail/value_t.hpp>
7660
7661
7662 namespace nlohmann
7663 {
7664 namespace detail
7665 {
7666
7667 /// how to treat CBOR tags
7668 enum class cbor_tag_handler_t
7669 {
7670 error, ///< throw a parse_error exception in case of a tag
7671 ignore ///< ignore tags
7672 };
7673
7674 /*!
7675 @brief determine system byte order
7676
7677 @return true if and only if system's byte order is little endian
7678
7679 @note from https://stackoverflow.com/a/1001328/266378
7680 */
little_endianess(int num=1)7681 static inline bool little_endianess(int num = 1) noexcept
7682 {
7683 return *reinterpret_cast<char*>(&num) == 1;
7684 }
7685
7686
7687 ///////////////////
7688 // binary reader //
7689 ///////////////////
7690
7691 /*!
7692 @brief deserialization of CBOR, MessagePack, and UBJSON values
7693 */
7694 template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
7695 class binary_reader
7696 {
7697 using number_integer_t = typename BasicJsonType::number_integer_t;
7698 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7699 using number_float_t = typename BasicJsonType::number_float_t;
7700 using string_t = typename BasicJsonType::string_t;
7701 using binary_t = typename BasicJsonType::binary_t;
7702 using json_sax_t = SAX;
7703 using char_type = typename InputAdapterType::char_type;
7704 using char_int_type = typename std::char_traits<char_type>::int_type;
7705
7706 public:
7707 /*!
7708 @brief create a binary reader
7709
7710 @param[in] adapter input adapter to read from
7711 */
binary_reader(InputAdapterType && adapter)7712 explicit binary_reader(InputAdapterType&& adapter) : ia(std::move(adapter))
7713 {
7714 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
7715 }
7716
7717 // make class move-only
7718 binary_reader(const binary_reader&) = delete;
7719 binary_reader(binary_reader&&) = default;
7720 binary_reader& operator=(const binary_reader&) = delete;
7721 binary_reader& operator=(binary_reader&&) = default;
7722 ~binary_reader() = default;
7723
7724 /*!
7725 @param[in] format the binary format to parse
7726 @param[in] sax_ a SAX event processor
7727 @param[in] strict whether to expect the input to be consumed completed
7728 @param[in] tag_handler how to treat CBOR tags
7729
7730 @return
7731 */
7732 JSON_HEDLEY_NON_NULL(3)
sax_parse(const input_format_t format,json_sax_t * sax_,const bool strict=true,const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)7733 bool sax_parse(const input_format_t format,
7734 json_sax_t* sax_,
7735 const bool strict = true,
7736 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
7737 {
7738 sax = sax_;
7739 bool result = false;
7740
7741 switch (format)
7742 {
7743 case input_format_t::bson:
7744 result = parse_bson_internal();
7745 break;
7746
7747 case input_format_t::cbor:
7748 result = parse_cbor_internal(true, tag_handler);
7749 break;
7750
7751 case input_format_t::msgpack:
7752 result = parse_msgpack_internal();
7753 break;
7754
7755 case input_format_t::ubjson:
7756 result = parse_ubjson_internal();
7757 break;
7758
7759 default: // LCOV_EXCL_LINE
7760 JSON_ASSERT(false); // LCOV_EXCL_LINE
7761 }
7762
7763 // strict mode: next byte must be EOF
7764 if (result && strict)
7765 {
7766 if (format == input_format_t::ubjson)
7767 {
7768 get_ignore_noop();
7769 }
7770 else
7771 {
7772 get();
7773 }
7774
7775 if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
7776 {
7777 return sax->parse_error(chars_read, get_token_string(),
7778 parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value")));
7779 }
7780 }
7781
7782 return result;
7783 }
7784
7785 private:
7786 //////////
7787 // BSON //
7788 //////////
7789
7790 /*!
7791 @brief Reads in a BSON-object and passes it to the SAX-parser.
7792 @return whether a valid BSON-value was passed to the SAX parser
7793 */
parse_bson_internal()7794 bool parse_bson_internal()
7795 {
7796 std::int32_t document_size{};
7797 get_number<std::int32_t, true>(input_format_t::bson, document_size);
7798
7799 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
7800 {
7801 return false;
7802 }
7803
7804 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
7805 {
7806 return false;
7807 }
7808
7809 return sax->end_object();
7810 }
7811
7812 /*!
7813 @brief Parses a C-style string from the BSON input.
7814 @param[in, out] result A reference to the string variable where the read
7815 string is to be stored.
7816 @return `true` if the \x00-byte indicating the end of the string was
7817 encountered before the EOF; false` indicates an unexpected EOF.
7818 */
get_bson_cstr(string_t & result)7819 bool get_bson_cstr(string_t& result)
7820 {
7821 auto out = std::back_inserter(result);
7822 while (true)
7823 {
7824 get();
7825 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
7826 {
7827 return false;
7828 }
7829 if (current == 0x00)
7830 {
7831 return true;
7832 }
7833 *out++ = static_cast<typename string_t::value_type>(current);
7834 }
7835 }
7836
7837 /*!
7838 @brief Parses a zero-terminated string of length @a len from the BSON
7839 input.
7840 @param[in] len The length (including the zero-byte at the end) of the
7841 string to be read.
7842 @param[in, out] result A reference to the string variable where the read
7843 string is to be stored.
7844 @tparam NumberType The type of the length @a len
7845 @pre len >= 1
7846 @return `true` if the string was successfully parsed
7847 */
7848 template<typename NumberType>
get_bson_string(const NumberType len,string_t & result)7849 bool get_bson_string(const NumberType len, string_t& result)
7850 {
7851 if (JSON_HEDLEY_UNLIKELY(len < 1))
7852 {
7853 auto last_token = get_token_string();
7854 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string")));
7855 }
7856
7857 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
7858 }
7859
7860 /*!
7861 @brief Parses a byte array input of length @a len from the BSON input.
7862 @param[in] len The length of the byte array to be read.
7863 @param[in, out] result A reference to the binary variable where the read
7864 array is to be stored.
7865 @tparam NumberType The type of the length @a len
7866 @pre len >= 0
7867 @return `true` if the byte array was successfully parsed
7868 */
7869 template<typename NumberType>
get_bson_binary(const NumberType len,binary_t & result)7870 bool get_bson_binary(const NumberType len, binary_t& result)
7871 {
7872 if (JSON_HEDLEY_UNLIKELY(len < 0))
7873 {
7874 auto last_token = get_token_string();
7875 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary")));
7876 }
7877
7878 // All BSON binary values have a subtype
7879 std::uint8_t subtype{};
7880 get_number<std::uint8_t>(input_format_t::bson, subtype);
7881 result.set_subtype(subtype);
7882
7883 return get_binary(input_format_t::bson, len, result);
7884 }
7885
7886 /*!
7887 @brief Read a BSON document element of the given @a element_type.
7888 @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
7889 @param[in] element_type_parse_position The position in the input stream,
7890 where the `element_type` was read.
7891 @warning Not all BSON element types are supported yet. An unsupported
7892 @a element_type will give rise to a parse_error.114:
7893 Unsupported BSON record type 0x...
7894 @return whether a valid BSON-object/array was passed to the SAX parser
7895 */
parse_bson_element_internal(const char_int_type element_type,const std::size_t element_type_parse_position)7896 bool parse_bson_element_internal(const char_int_type element_type,
7897 const std::size_t element_type_parse_position)
7898 {
7899 switch (element_type)
7900 {
7901 case 0x01: // double
7902 {
7903 double number{};
7904 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
7905 }
7906
7907 case 0x02: // string
7908 {
7909 std::int32_t len{};
7910 string_t value;
7911 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
7912 }
7913
7914 case 0x03: // object
7915 {
7916 return parse_bson_internal();
7917 }
7918
7919 case 0x04: // array
7920 {
7921 return parse_bson_array();
7922 }
7923
7924 case 0x05: // binary
7925 {
7926 std::int32_t len{};
7927 binary_t value;
7928 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
7929 }
7930
7931 case 0x08: // boolean
7932 {
7933 return sax->boolean(get() != 0);
7934 }
7935
7936 case 0x0A: // null
7937 {
7938 return sax->null();
7939 }
7940
7941 case 0x10: // int32
7942 {
7943 std::int32_t value{};
7944 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
7945 }
7946
7947 case 0x12: // int64
7948 {
7949 std::int64_t value{};
7950 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
7951 }
7952
7953 default: // anything else not supported (yet)
7954 {
7955 std::array<char, 3> cr{{}};
7956 (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type));
7957 return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data())));
7958 }
7959 }
7960 }
7961
7962 /*!
7963 @brief Read a BSON element list (as specified in the BSON-spec)
7964
7965 The same binary layout is used for objects and arrays, hence it must be
7966 indicated with the argument @a is_array which one is expected
7967 (true --> array, false --> object).
7968
7969 @param[in] is_array Determines if the element list being read is to be
7970 treated as an object (@a is_array == false), or as an
7971 array (@a is_array == true).
7972 @return whether a valid BSON-object/array was passed to the SAX parser
7973 */
parse_bson_element_list(const bool is_array)7974 bool parse_bson_element_list(const bool is_array)
7975 {
7976 string_t key;
7977
7978 while (auto element_type = get())
7979 {
7980 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
7981 {
7982 return false;
7983 }
7984
7985 const std::size_t element_type_parse_position = chars_read;
7986 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
7987 {
7988 return false;
7989 }
7990
7991 if (!is_array && !sax->key(key))
7992 {
7993 return false;
7994 }
7995
7996 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
7997 {
7998 return false;
7999 }
8000
8001 // get_bson_cstr only appends
8002 key.clear();
8003 }
8004
8005 return true;
8006 }
8007
8008 /*!
8009 @brief Reads an array from the BSON input and passes it to the SAX-parser.
8010 @return whether a valid BSON-array was passed to the SAX parser
8011 */
parse_bson_array()8012 bool parse_bson_array()
8013 {
8014 std::int32_t document_size{};
8015 get_number<std::int32_t, true>(input_format_t::bson, document_size);
8016
8017 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
8018 {
8019 return false;
8020 }
8021
8022 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
8023 {
8024 return false;
8025 }
8026
8027 return sax->end_array();
8028 }
8029
8030 //////////
8031 // CBOR //
8032 //////////
8033
8034 /*!
8035 @param[in] get_char whether a new character should be retrieved from the
8036 input (true) or whether the last read character should
8037 be considered instead (false)
8038 @param[in] tag_handler how CBOR tags should be treated
8039
8040 @return whether a valid CBOR value was passed to the SAX parser
8041 */
parse_cbor_internal(const bool get_char,const cbor_tag_handler_t tag_handler)8042 bool parse_cbor_internal(const bool get_char,
8043 const cbor_tag_handler_t tag_handler)
8044 {
8045 switch (get_char ? get() : current)
8046 {
8047 // EOF
8048 case std::char_traits<char_type>::eof():
8049 return unexpect_eof(input_format_t::cbor, "value");
8050
8051 // Integer 0x00..0x17 (0..23)
8052 case 0x00:
8053 case 0x01:
8054 case 0x02:
8055 case 0x03:
8056 case 0x04:
8057 case 0x05:
8058 case 0x06:
8059 case 0x07:
8060 case 0x08:
8061 case 0x09:
8062 case 0x0A:
8063 case 0x0B:
8064 case 0x0C:
8065 case 0x0D:
8066 case 0x0E:
8067 case 0x0F:
8068 case 0x10:
8069 case 0x11:
8070 case 0x12:
8071 case 0x13:
8072 case 0x14:
8073 case 0x15:
8074 case 0x16:
8075 case 0x17:
8076 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
8077
8078 case 0x18: // Unsigned integer (one-byte uint8_t follows)
8079 {
8080 std::uint8_t number{};
8081 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8082 }
8083
8084 case 0x19: // Unsigned integer (two-byte uint16_t follows)
8085 {
8086 std::uint16_t number{};
8087 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8088 }
8089
8090 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
8091 {
8092 std::uint32_t number{};
8093 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8094 }
8095
8096 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
8097 {
8098 std::uint64_t number{};
8099 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
8100 }
8101
8102 // Negative integer -1-0x00..-1-0x17 (-1..-24)
8103 case 0x20:
8104 case 0x21:
8105 case 0x22:
8106 case 0x23:
8107 case 0x24:
8108 case 0x25:
8109 case 0x26:
8110 case 0x27:
8111 case 0x28:
8112 case 0x29:
8113 case 0x2A:
8114 case 0x2B:
8115 case 0x2C:
8116 case 0x2D:
8117 case 0x2E:
8118 case 0x2F:
8119 case 0x30:
8120 case 0x31:
8121 case 0x32:
8122 case 0x33:
8123 case 0x34:
8124 case 0x35:
8125 case 0x36:
8126 case 0x37:
8127 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
8128
8129 case 0x38: // Negative integer (one-byte uint8_t follows)
8130 {
8131 std::uint8_t number{};
8132 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8133 }
8134
8135 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
8136 {
8137 std::uint16_t number{};
8138 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8139 }
8140
8141 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
8142 {
8143 std::uint32_t number{};
8144 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
8145 }
8146
8147 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
8148 {
8149 std::uint64_t number{};
8150 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
8151 - static_cast<number_integer_t>(number));
8152 }
8153
8154 // Binary data (0x00..0x17 bytes follow)
8155 case 0x40:
8156 case 0x41:
8157 case 0x42:
8158 case 0x43:
8159 case 0x44:
8160 case 0x45:
8161 case 0x46:
8162 case 0x47:
8163 case 0x48:
8164 case 0x49:
8165 case 0x4A:
8166 case 0x4B:
8167 case 0x4C:
8168 case 0x4D:
8169 case 0x4E:
8170 case 0x4F:
8171 case 0x50:
8172 case 0x51:
8173 case 0x52:
8174 case 0x53:
8175 case 0x54:
8176 case 0x55:
8177 case 0x56:
8178 case 0x57:
8179 case 0x58: // Binary data (one-byte uint8_t for n follows)
8180 case 0x59: // Binary data (two-byte uint16_t for n follow)
8181 case 0x5A: // Binary data (four-byte uint32_t for n follow)
8182 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
8183 case 0x5F: // Binary data (indefinite length)
8184 {
8185 binary_t b;
8186 return get_cbor_binary(b) && sax->binary(b);
8187 }
8188
8189 // UTF-8 string (0x00..0x17 bytes follow)
8190 case 0x60:
8191 case 0x61:
8192 case 0x62:
8193 case 0x63:
8194 case 0x64:
8195 case 0x65:
8196 case 0x66:
8197 case 0x67:
8198 case 0x68:
8199 case 0x69:
8200 case 0x6A:
8201 case 0x6B:
8202 case 0x6C:
8203 case 0x6D:
8204 case 0x6E:
8205 case 0x6F:
8206 case 0x70:
8207 case 0x71:
8208 case 0x72:
8209 case 0x73:
8210 case 0x74:
8211 case 0x75:
8212 case 0x76:
8213 case 0x77:
8214 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
8215 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
8216 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
8217 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
8218 case 0x7F: // UTF-8 string (indefinite length)
8219 {
8220 string_t s;
8221 return get_cbor_string(s) && sax->string(s);
8222 }
8223
8224 // array (0x00..0x17 data items follow)
8225 case 0x80:
8226 case 0x81:
8227 case 0x82:
8228 case 0x83:
8229 case 0x84:
8230 case 0x85:
8231 case 0x86:
8232 case 0x87:
8233 case 0x88:
8234 case 0x89:
8235 case 0x8A:
8236 case 0x8B:
8237 case 0x8C:
8238 case 0x8D:
8239 case 0x8E:
8240 case 0x8F:
8241 case 0x90:
8242 case 0x91:
8243 case 0x92:
8244 case 0x93:
8245 case 0x94:
8246 case 0x95:
8247 case 0x96:
8248 case 0x97:
8249 return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
8250
8251 case 0x98: // array (one-byte uint8_t for n follows)
8252 {
8253 std::uint8_t len{};
8254 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8255 }
8256
8257 case 0x99: // array (two-byte uint16_t for n follow)
8258 {
8259 std::uint16_t len{};
8260 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8261 }
8262
8263 case 0x9A: // array (four-byte uint32_t for n follow)
8264 {
8265 std::uint32_t len{};
8266 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8267 }
8268
8269 case 0x9B: // array (eight-byte uint64_t for n follow)
8270 {
8271 std::uint64_t len{};
8272 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
8273 }
8274
8275 case 0x9F: // array (indefinite length)
8276 return get_cbor_array(std::size_t(-1), tag_handler);
8277
8278 // map (0x00..0x17 pairs of data items follow)
8279 case 0xA0:
8280 case 0xA1:
8281 case 0xA2:
8282 case 0xA3:
8283 case 0xA4:
8284 case 0xA5:
8285 case 0xA6:
8286 case 0xA7:
8287 case 0xA8:
8288 case 0xA9:
8289 case 0xAA:
8290 case 0xAB:
8291 case 0xAC:
8292 case 0xAD:
8293 case 0xAE:
8294 case 0xAF:
8295 case 0xB0:
8296 case 0xB1:
8297 case 0xB2:
8298 case 0xB3:
8299 case 0xB4:
8300 case 0xB5:
8301 case 0xB6:
8302 case 0xB7:
8303 return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
8304
8305 case 0xB8: // map (one-byte uint8_t for n follows)
8306 {
8307 std::uint8_t len{};
8308 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8309 }
8310
8311 case 0xB9: // map (two-byte uint16_t for n follow)
8312 {
8313 std::uint16_t len{};
8314 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8315 }
8316
8317 case 0xBA: // map (four-byte uint32_t for n follow)
8318 {
8319 std::uint32_t len{};
8320 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8321 }
8322
8323 case 0xBB: // map (eight-byte uint64_t for n follow)
8324 {
8325 std::uint64_t len{};
8326 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
8327 }
8328
8329 case 0xBF: // map (indefinite length)
8330 return get_cbor_object(std::size_t(-1), tag_handler);
8331
8332 case 0xC6: // tagged item
8333 case 0xC7:
8334 case 0xC8:
8335 case 0xC9:
8336 case 0xCA:
8337 case 0xCB:
8338 case 0xCC:
8339 case 0xCD:
8340 case 0xCE:
8341 case 0xCF:
8342 case 0xD0:
8343 case 0xD1:
8344 case 0xD2:
8345 case 0xD3:
8346 case 0xD4:
8347 case 0xD8: // tagged item (1 bytes follow)
8348 case 0xD9: // tagged item (2 bytes follow)
8349 case 0xDA: // tagged item (4 bytes follow)
8350 case 0xDB: // tagged item (8 bytes follow)
8351 {
8352 switch (tag_handler)
8353 {
8354 case cbor_tag_handler_t::error:
8355 {
8356 auto last_token = get_token_string();
8357 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value")));
8358 }
8359
8360 case cbor_tag_handler_t::ignore:
8361 {
8362 switch (current)
8363 {
8364 case 0xD8:
8365 {
8366 std::uint8_t len{};
8367 get_number(input_format_t::cbor, len);
8368 break;
8369 }
8370 case 0xD9:
8371 {
8372 std::uint16_t len{};
8373 get_number(input_format_t::cbor, len);
8374 break;
8375 }
8376 case 0xDA:
8377 {
8378 std::uint32_t len{};
8379 get_number(input_format_t::cbor, len);
8380 break;
8381 }
8382 case 0xDB:
8383 {
8384 std::uint64_t len{};
8385 get_number(input_format_t::cbor, len);
8386 break;
8387 }
8388 default:
8389 break;
8390 }
8391 return parse_cbor_internal(true, tag_handler);
8392 }
8393
8394 default: // LCOV_EXCL_LINE
8395 JSON_ASSERT(false); // LCOV_EXCL_LINE
8396 }
8397 }
8398
8399 case 0xF4: // false
8400 return sax->boolean(false);
8401
8402 case 0xF5: // true
8403 return sax->boolean(true);
8404
8405 case 0xF6: // null
8406 return sax->null();
8407
8408 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
8409 {
8410 const auto byte1_raw = get();
8411 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
8412 {
8413 return false;
8414 }
8415 const auto byte2_raw = get();
8416 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
8417 {
8418 return false;
8419 }
8420
8421 const auto byte1 = static_cast<unsigned char>(byte1_raw);
8422 const auto byte2 = static_cast<unsigned char>(byte2_raw);
8423
8424 // code from RFC 7049, Appendix D, Figure 3:
8425 // As half-precision floating-point numbers were only added
8426 // to IEEE 754 in 2008, today's programming platforms often
8427 // still only have limited support for them. It is very
8428 // easy to include at least decoding support for them even
8429 // without such support. An example of a small decoder for
8430 // half-precision floating-point numbers in the C language
8431 // is shown in Fig. 3.
8432 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
8433 const double val = [&half]
8434 {
8435 const int exp = (half >> 10u) & 0x1Fu;
8436 const unsigned int mant = half & 0x3FFu;
8437 JSON_ASSERT(0 <= exp&& exp <= 32);
8438 JSON_ASSERT(mant <= 1024);
8439 switch (exp)
8440 {
8441 case 0:
8442 return std::ldexp(mant, -24);
8443 case 31:
8444 return (mant == 0)
8445 ? std::numeric_limits<double>::infinity()
8446 : std::numeric_limits<double>::quiet_NaN();
8447 default:
8448 return std::ldexp(mant + 1024, exp - 25);
8449 }
8450 }();
8451 return sax->number_float((half & 0x8000u) != 0
8452 ? static_cast<number_float_t>(-val)
8453 : static_cast<number_float_t>(val), "");
8454 }
8455
8456 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
8457 {
8458 float number{};
8459 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
8460 }
8461
8462 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
8463 {
8464 double number{};
8465 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
8466 }
8467
8468 default: // anything else (0xFF is handled inside the other types)
8469 {
8470 auto last_token = get_token_string();
8471 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value")));
8472 }
8473 }
8474 }
8475
8476 /*!
8477 @brief reads a CBOR string
8478
8479 This function first reads starting bytes to determine the expected
8480 string length and then copies this number of bytes into a string.
8481 Additionally, CBOR's strings with indefinite lengths are supported.
8482
8483 @param[out] result created string
8484
8485 @return whether string creation completed
8486 */
get_cbor_string(string_t & result)8487 bool get_cbor_string(string_t& result)
8488 {
8489 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
8490 {
8491 return false;
8492 }
8493
8494 switch (current)
8495 {
8496 // UTF-8 string (0x00..0x17 bytes follow)
8497 case 0x60:
8498 case 0x61:
8499 case 0x62:
8500 case 0x63:
8501 case 0x64:
8502 case 0x65:
8503 case 0x66:
8504 case 0x67:
8505 case 0x68:
8506 case 0x69:
8507 case 0x6A:
8508 case 0x6B:
8509 case 0x6C:
8510 case 0x6D:
8511 case 0x6E:
8512 case 0x6F:
8513 case 0x70:
8514 case 0x71:
8515 case 0x72:
8516 case 0x73:
8517 case 0x74:
8518 case 0x75:
8519 case 0x76:
8520 case 0x77:
8521 {
8522 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
8523 }
8524
8525 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
8526 {
8527 std::uint8_t len{};
8528 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
8529 }
8530
8531 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
8532 {
8533 std::uint16_t len{};
8534 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
8535 }
8536
8537 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
8538 {
8539 std::uint32_t len{};
8540 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
8541 }
8542
8543 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
8544 {
8545 std::uint64_t len{};
8546 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
8547 }
8548
8549 case 0x7F: // UTF-8 string (indefinite length)
8550 {
8551 while (get() != 0xFF)
8552 {
8553 string_t chunk;
8554 if (!get_cbor_string(chunk))
8555 {
8556 return false;
8557 }
8558 result.append(chunk);
8559 }
8560 return true;
8561 }
8562
8563 default:
8564 {
8565 auto last_token = get_token_string();
8566 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string")));
8567 }
8568 }
8569 }
8570
8571 /*!
8572 @brief reads a CBOR byte array
8573
8574 This function first reads starting bytes to determine the expected
8575 byte array length and then copies this number of bytes into the byte array.
8576 Additionally, CBOR's byte arrays with indefinite lengths are supported.
8577
8578 @param[out] result created byte array
8579
8580 @return whether byte array creation completed
8581 */
get_cbor_binary(binary_t & result)8582 bool get_cbor_binary(binary_t& result)
8583 {
8584 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
8585 {
8586 return false;
8587 }
8588
8589 switch (current)
8590 {
8591 // Binary data (0x00..0x17 bytes follow)
8592 case 0x40:
8593 case 0x41:
8594 case 0x42:
8595 case 0x43:
8596 case 0x44:
8597 case 0x45:
8598 case 0x46:
8599 case 0x47:
8600 case 0x48:
8601 case 0x49:
8602 case 0x4A:
8603 case 0x4B:
8604 case 0x4C:
8605 case 0x4D:
8606 case 0x4E:
8607 case 0x4F:
8608 case 0x50:
8609 case 0x51:
8610 case 0x52:
8611 case 0x53:
8612 case 0x54:
8613 case 0x55:
8614 case 0x56:
8615 case 0x57:
8616 {
8617 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
8618 }
8619
8620 case 0x58: // Binary data (one-byte uint8_t for n follows)
8621 {
8622 std::uint8_t len{};
8623 return get_number(input_format_t::cbor, len) &&
8624 get_binary(input_format_t::cbor, len, result);
8625 }
8626
8627 case 0x59: // Binary data (two-byte uint16_t for n follow)
8628 {
8629 std::uint16_t len{};
8630 return get_number(input_format_t::cbor, len) &&
8631 get_binary(input_format_t::cbor, len, result);
8632 }
8633
8634 case 0x5A: // Binary data (four-byte uint32_t for n follow)
8635 {
8636 std::uint32_t len{};
8637 return get_number(input_format_t::cbor, len) &&
8638 get_binary(input_format_t::cbor, len, result);
8639 }
8640
8641 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
8642 {
8643 std::uint64_t len{};
8644 return get_number(input_format_t::cbor, len) &&
8645 get_binary(input_format_t::cbor, len, result);
8646 }
8647
8648 case 0x5F: // Binary data (indefinite length)
8649 {
8650 while (get() != 0xFF)
8651 {
8652 binary_t chunk;
8653 if (!get_cbor_binary(chunk))
8654 {
8655 return false;
8656 }
8657 result.insert(result.end(), chunk.begin(), chunk.end());
8658 }
8659 return true;
8660 }
8661
8662 default:
8663 {
8664 auto last_token = get_token_string();
8665 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary")));
8666 }
8667 }
8668 }
8669
8670 /*!
8671 @param[in] len the length of the array or std::size_t(-1) for an
8672 array of indefinite size
8673 @param[in] tag_handler how CBOR tags should be treated
8674 @return whether array creation completed
8675 */
get_cbor_array(const std::size_t len,const cbor_tag_handler_t tag_handler)8676 bool get_cbor_array(const std::size_t len,
8677 const cbor_tag_handler_t tag_handler)
8678 {
8679 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
8680 {
8681 return false;
8682 }
8683
8684 if (len != std::size_t(-1))
8685 {
8686 for (std::size_t i = 0; i < len; ++i)
8687 {
8688 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
8689 {
8690 return false;
8691 }
8692 }
8693 }
8694 else
8695 {
8696 while (get() != 0xFF)
8697 {
8698 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
8699 {
8700 return false;
8701 }
8702 }
8703 }
8704
8705 return sax->end_array();
8706 }
8707
8708 /*!
8709 @param[in] len the length of the object or std::size_t(-1) for an
8710 object of indefinite size
8711 @param[in] tag_handler how CBOR tags should be treated
8712 @return whether object creation completed
8713 */
get_cbor_object(const std::size_t len,const cbor_tag_handler_t tag_handler)8714 bool get_cbor_object(const std::size_t len,
8715 const cbor_tag_handler_t tag_handler)
8716 {
8717 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
8718 {
8719 return false;
8720 }
8721
8722 string_t key;
8723 if (len != std::size_t(-1))
8724 {
8725 for (std::size_t i = 0; i < len; ++i)
8726 {
8727 get();
8728 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
8729 {
8730 return false;
8731 }
8732
8733 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
8734 {
8735 return false;
8736 }
8737 key.clear();
8738 }
8739 }
8740 else
8741 {
8742 while (get() != 0xFF)
8743 {
8744 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
8745 {
8746 return false;
8747 }
8748
8749 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
8750 {
8751 return false;
8752 }
8753 key.clear();
8754 }
8755 }
8756
8757 return sax->end_object();
8758 }
8759
8760 /////////////
8761 // MsgPack //
8762 /////////////
8763
8764 /*!
8765 @return whether a valid MessagePack value was passed to the SAX parser
8766 */
parse_msgpack_internal()8767 bool parse_msgpack_internal()
8768 {
8769 switch (get())
8770 {
8771 // EOF
8772 case std::char_traits<char_type>::eof():
8773 return unexpect_eof(input_format_t::msgpack, "value");
8774
8775 // positive fixint
8776 case 0x00:
8777 case 0x01:
8778 case 0x02:
8779 case 0x03:
8780 case 0x04:
8781 case 0x05:
8782 case 0x06:
8783 case 0x07:
8784 case 0x08:
8785 case 0x09:
8786 case 0x0A:
8787 case 0x0B:
8788 case 0x0C:
8789 case 0x0D:
8790 case 0x0E:
8791 case 0x0F:
8792 case 0x10:
8793 case 0x11:
8794 case 0x12:
8795 case 0x13:
8796 case 0x14:
8797 case 0x15:
8798 case 0x16:
8799 case 0x17:
8800 case 0x18:
8801 case 0x19:
8802 case 0x1A:
8803 case 0x1B:
8804 case 0x1C:
8805 case 0x1D:
8806 case 0x1E:
8807 case 0x1F:
8808 case 0x20:
8809 case 0x21:
8810 case 0x22:
8811 case 0x23:
8812 case 0x24:
8813 case 0x25:
8814 case 0x26:
8815 case 0x27:
8816 case 0x28:
8817 case 0x29:
8818 case 0x2A:
8819 case 0x2B:
8820 case 0x2C:
8821 case 0x2D:
8822 case 0x2E:
8823 case 0x2F:
8824 case 0x30:
8825 case 0x31:
8826 case 0x32:
8827 case 0x33:
8828 case 0x34:
8829 case 0x35:
8830 case 0x36:
8831 case 0x37:
8832 case 0x38:
8833 case 0x39:
8834 case 0x3A:
8835 case 0x3B:
8836 case 0x3C:
8837 case 0x3D:
8838 case 0x3E:
8839 case 0x3F:
8840 case 0x40:
8841 case 0x41:
8842 case 0x42:
8843 case 0x43:
8844 case 0x44:
8845 case 0x45:
8846 case 0x46:
8847 case 0x47:
8848 case 0x48:
8849 case 0x49:
8850 case 0x4A:
8851 case 0x4B:
8852 case 0x4C:
8853 case 0x4D:
8854 case 0x4E:
8855 case 0x4F:
8856 case 0x50:
8857 case 0x51:
8858 case 0x52:
8859 case 0x53:
8860 case 0x54:
8861 case 0x55:
8862 case 0x56:
8863 case 0x57:
8864 case 0x58:
8865 case 0x59:
8866 case 0x5A:
8867 case 0x5B:
8868 case 0x5C:
8869 case 0x5D:
8870 case 0x5E:
8871 case 0x5F:
8872 case 0x60:
8873 case 0x61:
8874 case 0x62:
8875 case 0x63:
8876 case 0x64:
8877 case 0x65:
8878 case 0x66:
8879 case 0x67:
8880 case 0x68:
8881 case 0x69:
8882 case 0x6A:
8883 case 0x6B:
8884 case 0x6C:
8885 case 0x6D:
8886 case 0x6E:
8887 case 0x6F:
8888 case 0x70:
8889 case 0x71:
8890 case 0x72:
8891 case 0x73:
8892 case 0x74:
8893 case 0x75:
8894 case 0x76:
8895 case 0x77:
8896 case 0x78:
8897 case 0x79:
8898 case 0x7A:
8899 case 0x7B:
8900 case 0x7C:
8901 case 0x7D:
8902 case 0x7E:
8903 case 0x7F:
8904 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
8905
8906 // fixmap
8907 case 0x80:
8908 case 0x81:
8909 case 0x82:
8910 case 0x83:
8911 case 0x84:
8912 case 0x85:
8913 case 0x86:
8914 case 0x87:
8915 case 0x88:
8916 case 0x89:
8917 case 0x8A:
8918 case 0x8B:
8919 case 0x8C:
8920 case 0x8D:
8921 case 0x8E:
8922 case 0x8F:
8923 return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
8924
8925 // fixarray
8926 case 0x90:
8927 case 0x91:
8928 case 0x92:
8929 case 0x93:
8930 case 0x94:
8931 case 0x95:
8932 case 0x96:
8933 case 0x97:
8934 case 0x98:
8935 case 0x99:
8936 case 0x9A:
8937 case 0x9B:
8938 case 0x9C:
8939 case 0x9D:
8940 case 0x9E:
8941 case 0x9F:
8942 return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
8943
8944 // fixstr
8945 case 0xA0:
8946 case 0xA1:
8947 case 0xA2:
8948 case 0xA3:
8949 case 0xA4:
8950 case 0xA5:
8951 case 0xA6:
8952 case 0xA7:
8953 case 0xA8:
8954 case 0xA9:
8955 case 0xAA:
8956 case 0xAB:
8957 case 0xAC:
8958 case 0xAD:
8959 case 0xAE:
8960 case 0xAF:
8961 case 0xB0:
8962 case 0xB1:
8963 case 0xB2:
8964 case 0xB3:
8965 case 0xB4:
8966 case 0xB5:
8967 case 0xB6:
8968 case 0xB7:
8969 case 0xB8:
8970 case 0xB9:
8971 case 0xBA:
8972 case 0xBB:
8973 case 0xBC:
8974 case 0xBD:
8975 case 0xBE:
8976 case 0xBF:
8977 case 0xD9: // str 8
8978 case 0xDA: // str 16
8979 case 0xDB: // str 32
8980 {
8981 string_t s;
8982 return get_msgpack_string(s) && sax->string(s);
8983 }
8984
8985 case 0xC0: // nil
8986 return sax->null();
8987
8988 case 0xC2: // false
8989 return sax->boolean(false);
8990
8991 case 0xC3: // true
8992 return sax->boolean(true);
8993
8994 case 0xC4: // bin 8
8995 case 0xC5: // bin 16
8996 case 0xC6: // bin 32
8997 case 0xC7: // ext 8
8998 case 0xC8: // ext 16
8999 case 0xC9: // ext 32
9000 case 0xD4: // fixext 1
9001 case 0xD5: // fixext 2
9002 case 0xD6: // fixext 4
9003 case 0xD7: // fixext 8
9004 case 0xD8: // fixext 16
9005 {
9006 binary_t b;
9007 return get_msgpack_binary(b) && sax->binary(b);
9008 }
9009
9010 case 0xCA: // float 32
9011 {
9012 float number{};
9013 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
9014 }
9015
9016 case 0xCB: // float 64
9017 {
9018 double number{};
9019 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
9020 }
9021
9022 case 0xCC: // uint 8
9023 {
9024 std::uint8_t number{};
9025 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9026 }
9027
9028 case 0xCD: // uint 16
9029 {
9030 std::uint16_t number{};
9031 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9032 }
9033
9034 case 0xCE: // uint 32
9035 {
9036 std::uint32_t number{};
9037 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9038 }
9039
9040 case 0xCF: // uint 64
9041 {
9042 std::uint64_t number{};
9043 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
9044 }
9045
9046 case 0xD0: // int 8
9047 {
9048 std::int8_t number{};
9049 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9050 }
9051
9052 case 0xD1: // int 16
9053 {
9054 std::int16_t number{};
9055 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9056 }
9057
9058 case 0xD2: // int 32
9059 {
9060 std::int32_t number{};
9061 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9062 }
9063
9064 case 0xD3: // int 64
9065 {
9066 std::int64_t number{};
9067 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
9068 }
9069
9070 case 0xDC: // array 16
9071 {
9072 std::uint16_t len{};
9073 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
9074 }
9075
9076 case 0xDD: // array 32
9077 {
9078 std::uint32_t len{};
9079 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
9080 }
9081
9082 case 0xDE: // map 16
9083 {
9084 std::uint16_t len{};
9085 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
9086 }
9087
9088 case 0xDF: // map 32
9089 {
9090 std::uint32_t len{};
9091 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
9092 }
9093
9094 // negative fixint
9095 case 0xE0:
9096 case 0xE1:
9097 case 0xE2:
9098 case 0xE3:
9099 case 0xE4:
9100 case 0xE5:
9101 case 0xE6:
9102 case 0xE7:
9103 case 0xE8:
9104 case 0xE9:
9105 case 0xEA:
9106 case 0xEB:
9107 case 0xEC:
9108 case 0xED:
9109 case 0xEE:
9110 case 0xEF:
9111 case 0xF0:
9112 case 0xF1:
9113 case 0xF2:
9114 case 0xF3:
9115 case 0xF4:
9116 case 0xF5:
9117 case 0xF6:
9118 case 0xF7:
9119 case 0xF8:
9120 case 0xF9:
9121 case 0xFA:
9122 case 0xFB:
9123 case 0xFC:
9124 case 0xFD:
9125 case 0xFE:
9126 case 0xFF:
9127 return sax->number_integer(static_cast<std::int8_t>(current));
9128
9129 default: // anything else
9130 {
9131 auto last_token = get_token_string();
9132 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value")));
9133 }
9134 }
9135 }
9136
9137 /*!
9138 @brief reads a MessagePack string
9139
9140 This function first reads starting bytes to determine the expected
9141 string length and then copies this number of bytes into a string.
9142
9143 @param[out] result created string
9144
9145 @return whether string creation completed
9146 */
get_msgpack_string(string_t & result)9147 bool get_msgpack_string(string_t& result)
9148 {
9149 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
9150 {
9151 return false;
9152 }
9153
9154 switch (current)
9155 {
9156 // fixstr
9157 case 0xA0:
9158 case 0xA1:
9159 case 0xA2:
9160 case 0xA3:
9161 case 0xA4:
9162 case 0xA5:
9163 case 0xA6:
9164 case 0xA7:
9165 case 0xA8:
9166 case 0xA9:
9167 case 0xAA:
9168 case 0xAB:
9169 case 0xAC:
9170 case 0xAD:
9171 case 0xAE:
9172 case 0xAF:
9173 case 0xB0:
9174 case 0xB1:
9175 case 0xB2:
9176 case 0xB3:
9177 case 0xB4:
9178 case 0xB5:
9179 case 0xB6:
9180 case 0xB7:
9181 case 0xB8:
9182 case 0xB9:
9183 case 0xBA:
9184 case 0xBB:
9185 case 0xBC:
9186 case 0xBD:
9187 case 0xBE:
9188 case 0xBF:
9189 {
9190 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
9191 }
9192
9193 case 0xD9: // str 8
9194 {
9195 std::uint8_t len{};
9196 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9197 }
9198
9199 case 0xDA: // str 16
9200 {
9201 std::uint16_t len{};
9202 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9203 }
9204
9205 case 0xDB: // str 32
9206 {
9207 std::uint32_t len{};
9208 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
9209 }
9210
9211 default:
9212 {
9213 auto last_token = get_token_string();
9214 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string")));
9215 }
9216 }
9217 }
9218
9219 /*!
9220 @brief reads a MessagePack byte array
9221
9222 This function first reads starting bytes to determine the expected
9223 byte array length and then copies this number of bytes into a byte array.
9224
9225 @param[out] result created byte array
9226
9227 @return whether byte array creation completed
9228 */
get_msgpack_binary(binary_t & result)9229 bool get_msgpack_binary(binary_t& result)
9230 {
9231 // helper function to set the subtype
9232 auto assign_and_return_true = [&result](std::int8_t subtype)
9233 {
9234 result.set_subtype(static_cast<std::uint8_t>(subtype));
9235 return true;
9236 };
9237
9238 switch (current)
9239 {
9240 case 0xC4: // bin 8
9241 {
9242 std::uint8_t len{};
9243 return get_number(input_format_t::msgpack, len) &&
9244 get_binary(input_format_t::msgpack, len, result);
9245 }
9246
9247 case 0xC5: // bin 16
9248 {
9249 std::uint16_t len{};
9250 return get_number(input_format_t::msgpack, len) &&
9251 get_binary(input_format_t::msgpack, len, result);
9252 }
9253
9254 case 0xC6: // bin 32
9255 {
9256 std::uint32_t len{};
9257 return get_number(input_format_t::msgpack, len) &&
9258 get_binary(input_format_t::msgpack, len, result);
9259 }
9260
9261 case 0xC7: // ext 8
9262 {
9263 std::uint8_t len{};
9264 std::int8_t subtype{};
9265 return get_number(input_format_t::msgpack, len) &&
9266 get_number(input_format_t::msgpack, subtype) &&
9267 get_binary(input_format_t::msgpack, len, result) &&
9268 assign_and_return_true(subtype);
9269 }
9270
9271 case 0xC8: // ext 16
9272 {
9273 std::uint16_t len{};
9274 std::int8_t subtype{};
9275 return get_number(input_format_t::msgpack, len) &&
9276 get_number(input_format_t::msgpack, subtype) &&
9277 get_binary(input_format_t::msgpack, len, result) &&
9278 assign_and_return_true(subtype);
9279 }
9280
9281 case 0xC9: // ext 32
9282 {
9283 std::uint32_t len{};
9284 std::int8_t subtype{};
9285 return get_number(input_format_t::msgpack, len) &&
9286 get_number(input_format_t::msgpack, subtype) &&
9287 get_binary(input_format_t::msgpack, len, result) &&
9288 assign_and_return_true(subtype);
9289 }
9290
9291 case 0xD4: // fixext 1
9292 {
9293 std::int8_t subtype{};
9294 return get_number(input_format_t::msgpack, subtype) &&
9295 get_binary(input_format_t::msgpack, 1, result) &&
9296 assign_and_return_true(subtype);
9297 }
9298
9299 case 0xD5: // fixext 2
9300 {
9301 std::int8_t subtype{};
9302 return get_number(input_format_t::msgpack, subtype) &&
9303 get_binary(input_format_t::msgpack, 2, result) &&
9304 assign_and_return_true(subtype);
9305 }
9306
9307 case 0xD6: // fixext 4
9308 {
9309 std::int8_t subtype{};
9310 return get_number(input_format_t::msgpack, subtype) &&
9311 get_binary(input_format_t::msgpack, 4, result) &&
9312 assign_and_return_true(subtype);
9313 }
9314
9315 case 0xD7: // fixext 8
9316 {
9317 std::int8_t subtype{};
9318 return get_number(input_format_t::msgpack, subtype) &&
9319 get_binary(input_format_t::msgpack, 8, result) &&
9320 assign_and_return_true(subtype);
9321 }
9322
9323 case 0xD8: // fixext 16
9324 {
9325 std::int8_t subtype{};
9326 return get_number(input_format_t::msgpack, subtype) &&
9327 get_binary(input_format_t::msgpack, 16, result) &&
9328 assign_and_return_true(subtype);
9329 }
9330
9331 default: // LCOV_EXCL_LINE
9332 return false; // LCOV_EXCL_LINE
9333 }
9334 }
9335
9336 /*!
9337 @param[in] len the length of the array
9338 @return whether array creation completed
9339 */
get_msgpack_array(const std::size_t len)9340 bool get_msgpack_array(const std::size_t len)
9341 {
9342 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
9343 {
9344 return false;
9345 }
9346
9347 for (std::size_t i = 0; i < len; ++i)
9348 {
9349 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
9350 {
9351 return false;
9352 }
9353 }
9354
9355 return sax->end_array();
9356 }
9357
9358 /*!
9359 @param[in] len the length of the object
9360 @return whether object creation completed
9361 */
get_msgpack_object(const std::size_t len)9362 bool get_msgpack_object(const std::size_t len)
9363 {
9364 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
9365 {
9366 return false;
9367 }
9368
9369 string_t key;
9370 for (std::size_t i = 0; i < len; ++i)
9371 {
9372 get();
9373 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
9374 {
9375 return false;
9376 }
9377
9378 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
9379 {
9380 return false;
9381 }
9382 key.clear();
9383 }
9384
9385 return sax->end_object();
9386 }
9387
9388 ////////////
9389 // UBJSON //
9390 ////////////
9391
9392 /*!
9393 @param[in] get_char whether a new character should be retrieved from the
9394 input (true, default) or whether the last read
9395 character should be considered instead
9396
9397 @return whether a valid UBJSON value was passed to the SAX parser
9398 */
parse_ubjson_internal(const bool get_char=true)9399 bool parse_ubjson_internal(const bool get_char = true)
9400 {
9401 return get_ubjson_value(get_char ? get_ignore_noop() : current);
9402 }
9403
9404 /*!
9405 @brief reads a UBJSON string
9406
9407 This function is either called after reading the 'S' byte explicitly
9408 indicating a string, or in case of an object key where the 'S' byte can be
9409 left out.
9410
9411 @param[out] result created string
9412 @param[in] get_char whether a new character should be retrieved from the
9413 input (true, default) or whether the last read
9414 character should be considered instead
9415
9416 @return whether string creation completed
9417 */
get_ubjson_string(string_t & result,const bool get_char=true)9418 bool get_ubjson_string(string_t& result, const bool get_char = true)
9419 {
9420 if (get_char)
9421 {
9422 get(); // TODO(niels): may we ignore N here?
9423 }
9424
9425 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
9426 {
9427 return false;
9428 }
9429
9430 switch (current)
9431 {
9432 case 'U':
9433 {
9434 std::uint8_t len{};
9435 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
9436 }
9437
9438 case 'i':
9439 {
9440 std::int8_t len{};
9441 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
9442 }
9443
9444 case 'I':
9445 {
9446 std::int16_t len{};
9447 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
9448 }
9449
9450 case 'l':
9451 {
9452 std::int32_t len{};
9453 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
9454 }
9455
9456 case 'L':
9457 {
9458 std::int64_t len{};
9459 return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
9460 }
9461
9462 default:
9463 auto last_token = get_token_string();
9464 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string")));
9465 }
9466 }
9467
9468 /*!
9469 @param[out] result determined size
9470 @return whether size determination completed
9471 */
get_ubjson_size_value(std::size_t & result)9472 bool get_ubjson_size_value(std::size_t& result)
9473 {
9474 switch (get_ignore_noop())
9475 {
9476 case 'U':
9477 {
9478 std::uint8_t number{};
9479 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
9480 {
9481 return false;
9482 }
9483 result = static_cast<std::size_t>(number);
9484 return true;
9485 }
9486
9487 case 'i':
9488 {
9489 std::int8_t number{};
9490 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
9491 {
9492 return false;
9493 }
9494 result = static_cast<std::size_t>(number);
9495 return true;
9496 }
9497
9498 case 'I':
9499 {
9500 std::int16_t number{};
9501 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
9502 {
9503 return false;
9504 }
9505 result = static_cast<std::size_t>(number);
9506 return true;
9507 }
9508
9509 case 'l':
9510 {
9511 std::int32_t number{};
9512 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
9513 {
9514 return false;
9515 }
9516 result = static_cast<std::size_t>(number);
9517 return true;
9518 }
9519
9520 case 'L':
9521 {
9522 std::int64_t number{};
9523 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
9524 {
9525 return false;
9526 }
9527 result = static_cast<std::size_t>(number);
9528 return true;
9529 }
9530
9531 default:
9532 {
9533 auto last_token = get_token_string();
9534 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size")));
9535 }
9536 }
9537 }
9538
9539 /*!
9540 @brief determine the type and size for a container
9541
9542 In the optimized UBJSON format, a type and a size can be provided to allow
9543 for a more compact representation.
9544
9545 @param[out] result pair of the size and the type
9546
9547 @return whether pair creation completed
9548 */
get_ubjson_size_type(std::pair<std::size_t,char_int_type> & result)9549 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result)
9550 {
9551 result.first = string_t::npos; // size
9552 result.second = 0; // type
9553
9554 get_ignore_noop();
9555
9556 if (current == '$')
9557 {
9558 result.second = get(); // must not ignore 'N', because 'N' maybe the type
9559 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type")))
9560 {
9561 return false;
9562 }
9563
9564 get_ignore_noop();
9565 if (JSON_HEDLEY_UNLIKELY(current != '#'))
9566 {
9567 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
9568 {
9569 return false;
9570 }
9571 auto last_token = get_token_string();
9572 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size")));
9573 }
9574
9575 return get_ubjson_size_value(result.first);
9576 }
9577
9578 if (current == '#')
9579 {
9580 return get_ubjson_size_value(result.first);
9581 }
9582
9583 return true;
9584 }
9585
9586 /*!
9587 @param prefix the previously read or set type prefix
9588 @return whether value creation completed
9589 */
get_ubjson_value(const char_int_type prefix)9590 bool get_ubjson_value(const char_int_type prefix)
9591 {
9592 switch (prefix)
9593 {
9594 case std::char_traits<char_type>::eof(): // EOF
9595 return unexpect_eof(input_format_t::ubjson, "value");
9596
9597 case 'T': // true
9598 return sax->boolean(true);
9599 case 'F': // false
9600 return sax->boolean(false);
9601
9602 case 'Z': // null
9603 return sax->null();
9604
9605 case 'U':
9606 {
9607 std::uint8_t number{};
9608 return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number);
9609 }
9610
9611 case 'i':
9612 {
9613 std::int8_t number{};
9614 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
9615 }
9616
9617 case 'I':
9618 {
9619 std::int16_t number{};
9620 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
9621 }
9622
9623 case 'l':
9624 {
9625 std::int32_t number{};
9626 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
9627 }
9628
9629 case 'L':
9630 {
9631 std::int64_t number{};
9632 return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
9633 }
9634
9635 case 'd':
9636 {
9637 float number{};
9638 return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9639 }
9640
9641 case 'D':
9642 {
9643 double number{};
9644 return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9645 }
9646
9647 case 'H':
9648 {
9649 return get_ubjson_high_precision_number();
9650 }
9651
9652 case 'C': // char
9653 {
9654 get();
9655 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char")))
9656 {
9657 return false;
9658 }
9659 if (JSON_HEDLEY_UNLIKELY(current > 127))
9660 {
9661 auto last_token = get_token_string();
9662 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char")));
9663 }
9664 string_t s(1, static_cast<typename string_t::value_type>(current));
9665 return sax->string(s);
9666 }
9667
9668 case 'S': // string
9669 {
9670 string_t s;
9671 return get_ubjson_string(s) && sax->string(s);
9672 }
9673
9674 case '[': // array
9675 return get_ubjson_array();
9676
9677 case '{': // object
9678 return get_ubjson_object();
9679
9680 default: // anything else
9681 {
9682 auto last_token = get_token_string();
9683 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value")));
9684 }
9685 }
9686 }
9687
9688 /*!
9689 @return whether array creation completed
9690 */
get_ubjson_array()9691 bool get_ubjson_array()
9692 {
9693 std::pair<std::size_t, char_int_type> size_and_type;
9694 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
9695 {
9696 return false;
9697 }
9698
9699 if (size_and_type.first != string_t::npos)
9700 {
9701 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
9702 {
9703 return false;
9704 }
9705
9706 if (size_and_type.second != 0)
9707 {
9708 if (size_and_type.second != 'N')
9709 {
9710 for (std::size_t i = 0; i < size_and_type.first; ++i)
9711 {
9712 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
9713 {
9714 return false;
9715 }
9716 }
9717 }
9718 }
9719 else
9720 {
9721 for (std::size_t i = 0; i < size_and_type.first; ++i)
9722 {
9723 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
9724 {
9725 return false;
9726 }
9727 }
9728 }
9729 }
9730 else
9731 {
9732 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
9733 {
9734 return false;
9735 }
9736
9737 while (current != ']')
9738 {
9739 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
9740 {
9741 return false;
9742 }
9743 get_ignore_noop();
9744 }
9745 }
9746
9747 return sax->end_array();
9748 }
9749
9750 /*!
9751 @return whether object creation completed
9752 */
get_ubjson_object()9753 bool get_ubjson_object()
9754 {
9755 std::pair<std::size_t, char_int_type> size_and_type;
9756 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
9757 {
9758 return false;
9759 }
9760
9761 string_t key;
9762 if (size_and_type.first != string_t::npos)
9763 {
9764 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
9765 {
9766 return false;
9767 }
9768
9769 if (size_and_type.second != 0)
9770 {
9771 for (std::size_t i = 0; i < size_and_type.first; ++i)
9772 {
9773 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
9774 {
9775 return false;
9776 }
9777 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
9778 {
9779 return false;
9780 }
9781 key.clear();
9782 }
9783 }
9784 else
9785 {
9786 for (std::size_t i = 0; i < size_and_type.first; ++i)
9787 {
9788 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
9789 {
9790 return false;
9791 }
9792 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
9793 {
9794 return false;
9795 }
9796 key.clear();
9797 }
9798 }
9799 }
9800 else
9801 {
9802 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
9803 {
9804 return false;
9805 }
9806
9807 while (current != '}')
9808 {
9809 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
9810 {
9811 return false;
9812 }
9813 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
9814 {
9815 return false;
9816 }
9817 get_ignore_noop();
9818 key.clear();
9819 }
9820 }
9821
9822 return sax->end_object();
9823 }
9824
9825 // Note, no reader for UBJSON binary types is implemented because they do
9826 // not exist
9827
get_ubjson_high_precision_number()9828 bool get_ubjson_high_precision_number()
9829 {
9830 // get size of following number string
9831 std::size_t size{};
9832 auto res = get_ubjson_size_value(size);
9833 if (JSON_HEDLEY_UNLIKELY(!res))
9834 {
9835 return res;
9836 }
9837
9838 // get number string
9839 std::vector<char> number_vector;
9840 for (std::size_t i = 0; i < size; ++i)
9841 {
9842 get();
9843 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number")))
9844 {
9845 return false;
9846 }
9847 number_vector.push_back(static_cast<char>(current));
9848 }
9849
9850 // parse number string
9851 auto number_ia = detail::input_adapter(std::forward<decltype(number_vector)>(number_vector));
9852 auto number_lexer = detail::lexer<BasicJsonType, decltype(number_ia)>(std::move(number_ia), false);
9853 const auto result_number = number_lexer.scan();
9854 const auto number_string = number_lexer.get_token_string();
9855 const auto result_remainder = number_lexer.scan();
9856
9857 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
9858
9859 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
9860 {
9861 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number")));
9862 }
9863
9864 switch (result_number)
9865 {
9866 case token_type::value_integer:
9867 return sax->number_integer(number_lexer.get_number_integer());
9868 case token_type::value_unsigned:
9869 return sax->number_unsigned(number_lexer.get_number_unsigned());
9870 case token_type::value_float:
9871 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
9872 default:
9873 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number")));
9874 }
9875 }
9876
9877 ///////////////////////
9878 // Utility functions //
9879 ///////////////////////
9880
9881 /*!
9882 @brief get next character from the input
9883
9884 This function provides the interface to the used input adapter. It does
9885 not throw in case the input reached EOF, but returns a -'ve valued
9886 `std::char_traits<char_type>::eof()` in that case.
9887
9888 @return character read from the input
9889 */
get()9890 char_int_type get()
9891 {
9892 ++chars_read;
9893 return current = ia.get_character();
9894 }
9895
9896 /*!
9897 @return character read from the input after ignoring all 'N' entries
9898 */
get_ignore_noop()9899 char_int_type get_ignore_noop()
9900 {
9901 do
9902 {
9903 get();
9904 }
9905 while (current == 'N');
9906
9907 return current;
9908 }
9909
9910 /*
9911 @brief read a number from the input
9912
9913 @tparam NumberType the type of the number
9914 @param[in] format the current format (for diagnostics)
9915 @param[out] result number of type @a NumberType
9916
9917 @return whether conversion completed
9918
9919 @note This function needs to respect the system's endianess, because
9920 bytes in CBOR, MessagePack, and UBJSON are stored in network order
9921 (big endian) and therefore need reordering on little endian systems.
9922 */
9923 template<typename NumberType, bool InputIsLittleEndian = false>
get_number(const input_format_t format,NumberType & result)9924 bool get_number(const input_format_t format, NumberType& result)
9925 {
9926 // step 1: read input into array with system's byte order
9927 std::array<std::uint8_t, sizeof(NumberType)> vec;
9928 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
9929 {
9930 get();
9931 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
9932 {
9933 return false;
9934 }
9935
9936 // reverse byte order prior to conversion if necessary
9937 if (is_little_endian != InputIsLittleEndian)
9938 {
9939 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
9940 }
9941 else
9942 {
9943 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
9944 }
9945 }
9946
9947 // step 2: convert array into number of type T and return
9948 std::memcpy(&result, vec.data(), sizeof(NumberType));
9949 return true;
9950 }
9951
9952 /*!
9953 @brief create a string by reading characters from the input
9954
9955 @tparam NumberType the type of the number
9956 @param[in] format the current format (for diagnostics)
9957 @param[in] len number of characters to read
9958 @param[out] result string created by reading @a len bytes
9959
9960 @return whether string creation completed
9961
9962 @note We can not reserve @a len bytes for the result, because @a len
9963 may be too large. Usually, @ref unexpect_eof() detects the end of
9964 the input before we run out of string memory.
9965 */
9966 template<typename NumberType>
get_string(const input_format_t format,const NumberType len,string_t & result)9967 bool get_string(const input_format_t format,
9968 const NumberType len,
9969 string_t& result)
9970 {
9971 bool success = true;
9972 for (NumberType i = 0; i < len; i++)
9973 {
9974 get();
9975 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
9976 {
9977 success = false;
9978 break;
9979 }
9980 result.push_back(static_cast<typename string_t::value_type>(current));
9981 };
9982 return success;
9983 }
9984
9985 /*!
9986 @brief create a byte array by reading bytes from the input
9987
9988 @tparam NumberType the type of the number
9989 @param[in] format the current format (for diagnostics)
9990 @param[in] len number of bytes to read
9991 @param[out] result byte array created by reading @a len bytes
9992
9993 @return whether byte array creation completed
9994
9995 @note We can not reserve @a len bytes for the result, because @a len
9996 may be too large. Usually, @ref unexpect_eof() detects the end of
9997 the input before we run out of memory.
9998 */
9999 template<typename NumberType>
get_binary(const input_format_t format,const NumberType len,binary_t & result)10000 bool get_binary(const input_format_t format,
10001 const NumberType len,
10002 binary_t& result)
10003 {
10004 bool success = true;
10005 for (NumberType i = 0; i < len; i++)
10006 {
10007 get();
10008 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
10009 {
10010 success = false;
10011 break;
10012 }
10013 result.push_back(static_cast<std::uint8_t>(current));
10014 }
10015 return success;
10016 }
10017
10018 /*!
10019 @param[in] format the current format (for diagnostics)
10020 @param[in] context further context information (for diagnostics)
10021 @return whether the last read character is not EOF
10022 */
10023 JSON_HEDLEY_NON_NULL(3)
unexpect_eof(const input_format_t format,const char * context) const10024 bool unexpect_eof(const input_format_t format, const char* context) const
10025 {
10026 if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
10027 {
10028 return sax->parse_error(chars_read, "<end of file>",
10029 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context)));
10030 }
10031 return true;
10032 }
10033
10034 /*!
10035 @return a string representation of the last read byte
10036 */
get_token_string() const10037 std::string get_token_string() const
10038 {
10039 std::array<char, 3> cr{{}};
10040 (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current));
10041 return std::string{cr.data()};
10042 }
10043
10044 /*!
10045 @param[in] format the current format
10046 @param[in] detail a detailed error message
10047 @param[in] context further context information
10048 @return a message string to use in the parse_error exceptions
10049 */
exception_message(const input_format_t format,const std::string & detail,const std::string & context) const10050 std::string exception_message(const input_format_t format,
10051 const std::string& detail,
10052 const std::string& context) const
10053 {
10054 std::string error_msg = "syntax error while parsing ";
10055
10056 switch (format)
10057 {
10058 case input_format_t::cbor:
10059 error_msg += "CBOR";
10060 break;
10061
10062 case input_format_t::msgpack:
10063 error_msg += "MessagePack";
10064 break;
10065
10066 case input_format_t::ubjson:
10067 error_msg += "UBJSON";
10068 break;
10069
10070 case input_format_t::bson:
10071 error_msg += "BSON";
10072 break;
10073
10074 default: // LCOV_EXCL_LINE
10075 JSON_ASSERT(false); // LCOV_EXCL_LINE
10076 }
10077
10078 return error_msg + " " + context + ": " + detail;
10079 }
10080
10081 private:
10082 /// input adapter
10083 InputAdapterType ia;
10084
10085 /// the current character
10086 char_int_type current = std::char_traits<char_type>::eof();
10087
10088 /// the number of characters read
10089 std::size_t chars_read = 0;
10090
10091 /// whether we can assume little endianess
10092 const bool is_little_endian = little_endianess();
10093
10094 /// the SAX parser
10095 json_sax_t* sax = nullptr;
10096 };
10097 } // namespace detail
10098 } // namespace nlohmann
10099
10100 // #include <nlohmann/detail/input/input_adapters.hpp>
10101
10102 // #include <nlohmann/detail/input/lexer.hpp>
10103
10104 // #include <nlohmann/detail/input/parser.hpp>
10105
10106
10107 #include <cmath> // isfinite
10108 #include <cstdint> // uint8_t
10109 #include <functional> // function
10110 #include <string> // string
10111 #include <utility> // move
10112 #include <vector> // vector
10113
10114 // #include <nlohmann/detail/exceptions.hpp>
10115
10116 // #include <nlohmann/detail/input/input_adapters.hpp>
10117
10118 // #include <nlohmann/detail/input/json_sax.hpp>
10119
10120 // #include <nlohmann/detail/input/lexer.hpp>
10121
10122 // #include <nlohmann/detail/macro_scope.hpp>
10123
10124 // #include <nlohmann/detail/meta/is_sax.hpp>
10125
10126 // #include <nlohmann/detail/value_t.hpp>
10127
10128
10129 namespace nlohmann
10130 {
10131 namespace detail
10132 {
10133 ////////////
10134 // parser //
10135 ////////////
10136
10137 enum class parse_event_t : uint8_t
10138 {
10139 /// the parser read `{` and started to process a JSON object
10140 object_start,
10141 /// the parser read `}` and finished processing a JSON object
10142 object_end,
10143 /// the parser read `[` and started to process a JSON array
10144 array_start,
10145 /// the parser read `]` and finished processing a JSON array
10146 array_end,
10147 /// the parser read a key of a value in an object
10148 key,
10149 /// the parser finished reading a JSON value
10150 value
10151 };
10152
10153 template<typename BasicJsonType>
10154 using parser_callback_t =
10155 std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
10156
10157 /*!
10158 @brief syntax analysis
10159
10160 This class implements a recursive descent parser.
10161 */
10162 template<typename BasicJsonType, typename InputAdapterType>
10163 class parser
10164 {
10165 using number_integer_t = typename BasicJsonType::number_integer_t;
10166 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
10167 using number_float_t = typename BasicJsonType::number_float_t;
10168 using string_t = typename BasicJsonType::string_t;
10169 using lexer_t = lexer<BasicJsonType, InputAdapterType>;
10170 using token_type = typename lexer_t::token_type;
10171
10172 public:
10173 /// a parser reading from an input adapter
parser(InputAdapterType && adapter,const parser_callback_t<BasicJsonType> cb=nullptr,const bool allow_exceptions_=true,const bool skip_comments=false)10174 explicit parser(InputAdapterType&& adapter,
10175 const parser_callback_t<BasicJsonType> cb = nullptr,
10176 const bool allow_exceptions_ = true,
10177 const bool skip_comments = false)
10178 : callback(cb)
10179 , m_lexer(std::move(adapter), skip_comments)
10180 , allow_exceptions(allow_exceptions_)
10181 {
10182 // read first token
10183 get_token();
10184 }
10185
10186 /*!
10187 @brief public parser interface
10188
10189 @param[in] strict whether to expect the last token to be EOF
10190 @param[in,out] result parsed JSON value
10191
10192 @throw parse_error.101 in case of an unexpected token
10193 @throw parse_error.102 if to_unicode fails or surrogate error
10194 @throw parse_error.103 if to_unicode fails
10195 */
parse(const bool strict,BasicJsonType & result)10196 void parse(const bool strict, BasicJsonType& result)
10197 {
10198 if (callback)
10199 {
10200 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
10201 sax_parse_internal(&sdp);
10202 result.assert_invariant();
10203
10204 // in strict mode, input must be completely read
10205 if (strict && (get_token() != token_type::end_of_input))
10206 {
10207 sdp.parse_error(m_lexer.get_position(),
10208 m_lexer.get_token_string(),
10209 parse_error::create(101, m_lexer.get_position(),
10210 exception_message(token_type::end_of_input, "value")));
10211 }
10212
10213 // in case of an error, return discarded value
10214 if (sdp.is_errored())
10215 {
10216 result = value_t::discarded;
10217 return;
10218 }
10219
10220 // set top-level value to null if it was discarded by the callback
10221 // function
10222 if (result.is_discarded())
10223 {
10224 result = nullptr;
10225 }
10226 }
10227 else
10228 {
10229 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
10230 sax_parse_internal(&sdp);
10231 result.assert_invariant();
10232
10233 // in strict mode, input must be completely read
10234 if (strict && (get_token() != token_type::end_of_input))
10235 {
10236 sdp.parse_error(m_lexer.get_position(),
10237 m_lexer.get_token_string(),
10238 parse_error::create(101, m_lexer.get_position(),
10239 exception_message(token_type::end_of_input, "value")));
10240 }
10241
10242 // in case of an error, return discarded value
10243 if (sdp.is_errored())
10244 {
10245 result = value_t::discarded;
10246 return;
10247 }
10248 }
10249 }
10250
10251 /*!
10252 @brief public accept interface
10253
10254 @param[in] strict whether to expect the last token to be EOF
10255 @return whether the input is a proper JSON text
10256 */
accept(const bool strict=true)10257 bool accept(const bool strict = true)
10258 {
10259 json_sax_acceptor<BasicJsonType> sax_acceptor;
10260 return sax_parse(&sax_acceptor, strict);
10261 }
10262
10263 template<typename SAX>
10264 JSON_HEDLEY_NON_NULL(2)
sax_parse(SAX * sax,const bool strict=true)10265 bool sax_parse(SAX* sax, const bool strict = true)
10266 {
10267 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
10268 const bool result = sax_parse_internal(sax);
10269
10270 // strict mode: next byte must be EOF
10271 if (result && strict && (get_token() != token_type::end_of_input))
10272 {
10273 return sax->parse_error(m_lexer.get_position(),
10274 m_lexer.get_token_string(),
10275 parse_error::create(101, m_lexer.get_position(),
10276 exception_message(token_type::end_of_input, "value")));
10277 }
10278
10279 return result;
10280 }
10281
10282 private:
10283 template<typename SAX>
10284 JSON_HEDLEY_NON_NULL(2)
sax_parse_internal(SAX * sax)10285 bool sax_parse_internal(SAX* sax)
10286 {
10287 // stack to remember the hierarchy of structured values we are parsing
10288 // true = array; false = object
10289 std::vector<bool> states;
10290 // value to avoid a goto (see comment where set to true)
10291 bool skip_to_state_evaluation = false;
10292
10293 while (true)
10294 {
10295 if (!skip_to_state_evaluation)
10296 {
10297 // invariant: get_token() was called before each iteration
10298 switch (last_token)
10299 {
10300 case token_type::begin_object:
10301 {
10302 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
10303 {
10304 return false;
10305 }
10306
10307 // closing } -> we are done
10308 if (get_token() == token_type::end_object)
10309 {
10310 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
10311 {
10312 return false;
10313 }
10314 break;
10315 }
10316
10317 // parse key
10318 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
10319 {
10320 return sax->parse_error(m_lexer.get_position(),
10321 m_lexer.get_token_string(),
10322 parse_error::create(101, m_lexer.get_position(),
10323 exception_message(token_type::value_string, "object key")));
10324 }
10325 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
10326 {
10327 return false;
10328 }
10329
10330 // parse separator (:)
10331 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
10332 {
10333 return sax->parse_error(m_lexer.get_position(),
10334 m_lexer.get_token_string(),
10335 parse_error::create(101, m_lexer.get_position(),
10336 exception_message(token_type::name_separator, "object separator")));
10337 }
10338
10339 // remember we are now inside an object
10340 states.push_back(false);
10341
10342 // parse values
10343 get_token();
10344 continue;
10345 }
10346
10347 case token_type::begin_array:
10348 {
10349 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
10350 {
10351 return false;
10352 }
10353
10354 // closing ] -> we are done
10355 if (get_token() == token_type::end_array)
10356 {
10357 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
10358 {
10359 return false;
10360 }
10361 break;
10362 }
10363
10364 // remember we are now inside an array
10365 states.push_back(true);
10366
10367 // parse values (no need to call get_token)
10368 continue;
10369 }
10370
10371 case token_type::value_float:
10372 {
10373 const auto res = m_lexer.get_number_float();
10374
10375 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
10376 {
10377 return sax->parse_error(m_lexer.get_position(),
10378 m_lexer.get_token_string(),
10379 out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
10380 }
10381
10382 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
10383 {
10384 return false;
10385 }
10386
10387 break;
10388 }
10389
10390 case token_type::literal_false:
10391 {
10392 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
10393 {
10394 return false;
10395 }
10396 break;
10397 }
10398
10399 case token_type::literal_null:
10400 {
10401 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
10402 {
10403 return false;
10404 }
10405 break;
10406 }
10407
10408 case token_type::literal_true:
10409 {
10410 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
10411 {
10412 return false;
10413 }
10414 break;
10415 }
10416
10417 case token_type::value_integer:
10418 {
10419 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
10420 {
10421 return false;
10422 }
10423 break;
10424 }
10425
10426 case token_type::value_string:
10427 {
10428 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
10429 {
10430 return false;
10431 }
10432 break;
10433 }
10434
10435 case token_type::value_unsigned:
10436 {
10437 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
10438 {
10439 return false;
10440 }
10441 break;
10442 }
10443
10444 case token_type::parse_error:
10445 {
10446 // using "uninitialized" to avoid "expected" message
10447 return sax->parse_error(m_lexer.get_position(),
10448 m_lexer.get_token_string(),
10449 parse_error::create(101, m_lexer.get_position(),
10450 exception_message(token_type::uninitialized, "value")));
10451 }
10452
10453 default: // the last token was unexpected
10454 {
10455 return sax->parse_error(m_lexer.get_position(),
10456 m_lexer.get_token_string(),
10457 parse_error::create(101, m_lexer.get_position(),
10458 exception_message(token_type::literal_or_value, "value")));
10459 }
10460 }
10461 }
10462 else
10463 {
10464 skip_to_state_evaluation = false;
10465 }
10466
10467 // we reached this line after we successfully parsed a value
10468 if (states.empty())
10469 {
10470 // empty stack: we reached the end of the hierarchy: done
10471 return true;
10472 }
10473
10474 if (states.back()) // array
10475 {
10476 // comma -> next value
10477 if (get_token() == token_type::value_separator)
10478 {
10479 // parse a new value
10480 get_token();
10481 continue;
10482 }
10483
10484 // closing ]
10485 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
10486 {
10487 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
10488 {
10489 return false;
10490 }
10491
10492 // We are done with this array. Before we can parse a
10493 // new value, we need to evaluate the new state first.
10494 // By setting skip_to_state_evaluation to false, we
10495 // are effectively jumping to the beginning of this if.
10496 JSON_ASSERT(!states.empty());
10497 states.pop_back();
10498 skip_to_state_evaluation = true;
10499 continue;
10500 }
10501
10502 return sax->parse_error(m_lexer.get_position(),
10503 m_lexer.get_token_string(),
10504 parse_error::create(101, m_lexer.get_position(),
10505 exception_message(token_type::end_array, "array")));
10506 }
10507 else // object
10508 {
10509 // comma -> next value
10510 if (get_token() == token_type::value_separator)
10511 {
10512 // parse key
10513 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
10514 {
10515 return sax->parse_error(m_lexer.get_position(),
10516 m_lexer.get_token_string(),
10517 parse_error::create(101, m_lexer.get_position(),
10518 exception_message(token_type::value_string, "object key")));
10519 }
10520
10521 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
10522 {
10523 return false;
10524 }
10525
10526 // parse separator (:)
10527 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
10528 {
10529 return sax->parse_error(m_lexer.get_position(),
10530 m_lexer.get_token_string(),
10531 parse_error::create(101, m_lexer.get_position(),
10532 exception_message(token_type::name_separator, "object separator")));
10533 }
10534
10535 // parse values
10536 get_token();
10537 continue;
10538 }
10539
10540 // closing }
10541 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
10542 {
10543 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
10544 {
10545 return false;
10546 }
10547
10548 // We are done with this object. Before we can parse a
10549 // new value, we need to evaluate the new state first.
10550 // By setting skip_to_state_evaluation to false, we
10551 // are effectively jumping to the beginning of this if.
10552 JSON_ASSERT(!states.empty());
10553 states.pop_back();
10554 skip_to_state_evaluation = true;
10555 continue;
10556 }
10557
10558 return sax->parse_error(m_lexer.get_position(),
10559 m_lexer.get_token_string(),
10560 parse_error::create(101, m_lexer.get_position(),
10561 exception_message(token_type::end_object, "object")));
10562 }
10563 }
10564 }
10565
10566 /// get next token from lexer
get_token()10567 token_type get_token()
10568 {
10569 return last_token = m_lexer.scan();
10570 }
10571
exception_message(const token_type expected,const std::string & context)10572 std::string exception_message(const token_type expected, const std::string& context)
10573 {
10574 std::string error_msg = "syntax error ";
10575
10576 if (!context.empty())
10577 {
10578 error_msg += "while parsing " + context + " ";
10579 }
10580
10581 error_msg += "- ";
10582
10583 if (last_token == token_type::parse_error)
10584 {
10585 error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
10586 m_lexer.get_token_string() + "'";
10587 }
10588 else
10589 {
10590 error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
10591 }
10592
10593 if (expected != token_type::uninitialized)
10594 {
10595 error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
10596 }
10597
10598 return error_msg;
10599 }
10600
10601 private:
10602 /// callback function
10603 const parser_callback_t<BasicJsonType> callback = nullptr;
10604 /// the type of the last read token
10605 token_type last_token = token_type::uninitialized;
10606 /// the lexer
10607 lexer_t m_lexer;
10608 /// whether to throw exceptions in case of errors
10609 const bool allow_exceptions = true;
10610 };
10611 } // namespace detail
10612 } // namespace nlohmann
10613
10614 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
10615
10616
10617 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
10618
10619
10620 #include <cstddef> // ptrdiff_t
10621 #include <limits> // numeric_limits
10622
10623 namespace nlohmann
10624 {
10625 namespace detail
10626 {
10627 /*
10628 @brief an iterator for primitive JSON types
10629
10630 This class models an iterator for primitive JSON types (boolean, number,
10631 string). It's only purpose is to allow the iterator/const_iterator classes
10632 to "iterate" over primitive values. Internally, the iterator is modeled by
10633 a `difference_type` variable. Value begin_value (`0`) models the begin,
10634 end_value (`1`) models past the end.
10635 */
10636 class primitive_iterator_t
10637 {
10638 private:
10639 using difference_type = std::ptrdiff_t;
10640 static constexpr difference_type begin_value = 0;
10641 static constexpr difference_type end_value = begin_value + 1;
10642
10643 /// iterator as signed integer type
10644 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
10645
10646 public:
get_value() const10647 constexpr difference_type get_value() const noexcept
10648 {
10649 return m_it;
10650 }
10651
10652 /// set iterator to a defined beginning
set_begin()10653 void set_begin() noexcept
10654 {
10655 m_it = begin_value;
10656 }
10657
10658 /// set iterator to a defined past the end
set_end()10659 void set_end() noexcept
10660 {
10661 m_it = end_value;
10662 }
10663
10664 /// return whether the iterator can be dereferenced
is_begin() const10665 constexpr bool is_begin() const noexcept
10666 {
10667 return m_it == begin_value;
10668 }
10669
10670 /// return whether the iterator is at end
is_end() const10671 constexpr bool is_end() const noexcept
10672 {
10673 return m_it == end_value;
10674 }
10675
operator ==(primitive_iterator_t lhs,primitive_iterator_t rhs)10676 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
10677 {
10678 return lhs.m_it == rhs.m_it;
10679 }
10680
operator <(primitive_iterator_t lhs,primitive_iterator_t rhs)10681 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
10682 {
10683 return lhs.m_it < rhs.m_it;
10684 }
10685
operator +(difference_type n)10686 primitive_iterator_t operator+(difference_type n) noexcept
10687 {
10688 auto result = *this;
10689 result += n;
10690 return result;
10691 }
10692
operator -(primitive_iterator_t lhs,primitive_iterator_t rhs)10693 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
10694 {
10695 return lhs.m_it - rhs.m_it;
10696 }
10697
operator ++()10698 primitive_iterator_t& operator++() noexcept
10699 {
10700 ++m_it;
10701 return *this;
10702 }
10703
operator ++(int)10704 primitive_iterator_t const operator++(int) noexcept
10705 {
10706 auto result = *this;
10707 ++m_it;
10708 return result;
10709 }
10710
operator --()10711 primitive_iterator_t& operator--() noexcept
10712 {
10713 --m_it;
10714 return *this;
10715 }
10716
operator --(int)10717 primitive_iterator_t const operator--(int) noexcept
10718 {
10719 auto result = *this;
10720 --m_it;
10721 return result;
10722 }
10723
operator +=(difference_type n)10724 primitive_iterator_t& operator+=(difference_type n) noexcept
10725 {
10726 m_it += n;
10727 return *this;
10728 }
10729
operator -=(difference_type n)10730 primitive_iterator_t& operator-=(difference_type n) noexcept
10731 {
10732 m_it -= n;
10733 return *this;
10734 }
10735 };
10736 } // namespace detail
10737 } // namespace nlohmann
10738
10739
10740 namespace nlohmann
10741 {
10742 namespace detail
10743 {
10744 /*!
10745 @brief an iterator value
10746
10747 @note This structure could easily be a union, but MSVC currently does not allow
10748 unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
10749 */
10750 template<typename BasicJsonType> struct internal_iterator
10751 {
10752 /// iterator for JSON objects
10753 typename BasicJsonType::object_t::iterator object_iterator {};
10754 /// iterator for JSON arrays
10755 typename BasicJsonType::array_t::iterator array_iterator {};
10756 /// generic iterator for all other types
10757 primitive_iterator_t primitive_iterator {};
10758 };
10759 } // namespace detail
10760 } // namespace nlohmann
10761
10762 // #include <nlohmann/detail/iterators/iter_impl.hpp>
10763
10764
10765 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
10766 #include <type_traits> // conditional, is_const, remove_const
10767
10768 // #include <nlohmann/detail/exceptions.hpp>
10769
10770 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
10771
10772 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
10773
10774 // #include <nlohmann/detail/macro_scope.hpp>
10775
10776 // #include <nlohmann/detail/meta/cpp_future.hpp>
10777
10778 // #include <nlohmann/detail/meta/type_traits.hpp>
10779
10780 // #include <nlohmann/detail/value_t.hpp>
10781
10782
10783 namespace nlohmann
10784 {
10785 namespace detail
10786 {
10787 // forward declare, to be able to friend it later on
10788 template<typename IteratorType> class iteration_proxy;
10789 template<typename IteratorType> class iteration_proxy_value;
10790
10791 /*!
10792 @brief a template for a bidirectional iterator for the @ref basic_json class
10793 This class implements a both iterators (iterator and const_iterator) for the
10794 @ref basic_json class.
10795 @note An iterator is called *initialized* when a pointer to a JSON value has
10796 been set (e.g., by a constructor or a copy assignment). If the iterator is
10797 default-constructed, it is *uninitialized* and most methods are undefined.
10798 **The library uses assertions to detect calls on uninitialized iterators.**
10799 @requirement The class satisfies the following concept requirements:
10800 -
10801 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
10802 The iterator that can be moved can be moved in both directions (i.e.
10803 incremented and decremented).
10804 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional
10805 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
10806 */
10807 template<typename BasicJsonType>
10808 class iter_impl
10809 {
10810 /// allow basic_json to access private members
10811 friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
10812 friend BasicJsonType;
10813 friend iteration_proxy<iter_impl>;
10814 friend iteration_proxy_value<iter_impl>;
10815
10816 using object_t = typename BasicJsonType::object_t;
10817 using array_t = typename BasicJsonType::array_t;
10818 // make sure BasicJsonType is basic_json or const basic_json
10819 static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
10820 "iter_impl only accepts (const) basic_json");
10821
10822 public:
10823
10824 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
10825 /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
10826 /// A user-defined iterator should provide publicly accessible typedefs named
10827 /// iterator_category, value_type, difference_type, pointer, and reference.
10828 /// Note that value_type is required to be non-const, even for constant iterators.
10829 using iterator_category = std::bidirectional_iterator_tag;
10830
10831 /// the type of the values when the iterator is dereferenced
10832 using value_type = typename BasicJsonType::value_type;
10833 /// a type to represent differences between iterators
10834 using difference_type = typename BasicJsonType::difference_type;
10835 /// defines a pointer to the type iterated over (value_type)
10836 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
10837 typename BasicJsonType::const_pointer,
10838 typename BasicJsonType::pointer>::type;
10839 /// defines a reference to the type iterated over (value_type)
10840 using reference =
10841 typename std::conditional<std::is_const<BasicJsonType>::value,
10842 typename BasicJsonType::const_reference,
10843 typename BasicJsonType::reference>::type;
10844
10845 /// default constructor
10846 iter_impl() = default;
10847
10848 /*!
10849 @brief constructor for a given JSON instance
10850 @param[in] object pointer to a JSON object for this iterator
10851 @pre object != nullptr
10852 @post The iterator is initialized; i.e. `m_object != nullptr`.
10853 */
iter_impl(pointer object)10854 explicit iter_impl(pointer object) noexcept : m_object(object)
10855 {
10856 JSON_ASSERT(m_object != nullptr);
10857
10858 switch (m_object->m_type)
10859 {
10860 case value_t::object:
10861 {
10862 m_it.object_iterator = typename object_t::iterator();
10863 break;
10864 }
10865
10866 case value_t::array:
10867 {
10868 m_it.array_iterator = typename array_t::iterator();
10869 break;
10870 }
10871
10872 default:
10873 {
10874 m_it.primitive_iterator = primitive_iterator_t();
10875 break;
10876 }
10877 }
10878 }
10879
10880 /*!
10881 @note The conventional copy constructor and copy assignment are implicitly
10882 defined. Combined with the following converting constructor and
10883 assignment, they support: (1) copy from iterator to iterator, (2)
10884 copy from const iterator to const iterator, and (3) conversion from
10885 iterator to const iterator. However conversion from const iterator
10886 to iterator is not defined.
10887 */
10888
10889 /*!
10890 @brief const copy constructor
10891 @param[in] other const iterator to copy from
10892 @note This copy constructor had to be defined explicitly to circumvent a bug
10893 occurring on msvc v19.0 compiler (VS 2015) debug build. For more
10894 information refer to: https://github.com/nlohmann/json/issues/1608
10895 */
iter_impl(const iter_impl<const BasicJsonType> & other)10896 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
10897 : m_object(other.m_object), m_it(other.m_it)
10898 {}
10899
10900 /*!
10901 @brief converting assignment
10902 @param[in] other const iterator to copy from
10903 @return const/non-const iterator
10904 @note It is not checked whether @a other is initialized.
10905 */
operator =(const iter_impl<const BasicJsonType> & other)10906 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
10907 {
10908 m_object = other.m_object;
10909 m_it = other.m_it;
10910 return *this;
10911 }
10912
10913 /*!
10914 @brief converting constructor
10915 @param[in] other non-const iterator to copy from
10916 @note It is not checked whether @a other is initialized.
10917 */
iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type> & other)10918 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
10919 : m_object(other.m_object), m_it(other.m_it)
10920 {}
10921
10922 /*!
10923 @brief converting assignment
10924 @param[in] other non-const iterator to copy from
10925 @return const/non-const iterator
10926 @note It is not checked whether @a other is initialized.
10927 */
operator =(const iter_impl<typename std::remove_const<BasicJsonType>::type> & other)10928 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
10929 {
10930 m_object = other.m_object;
10931 m_it = other.m_it;
10932 return *this;
10933 }
10934
10935 private:
10936 /*!
10937 @brief set the iterator to the first value
10938 @pre The iterator is initialized; i.e. `m_object != nullptr`.
10939 */
set_begin()10940 void set_begin() noexcept
10941 {
10942 JSON_ASSERT(m_object != nullptr);
10943
10944 switch (m_object->m_type)
10945 {
10946 case value_t::object:
10947 {
10948 m_it.object_iterator = m_object->m_value.object->begin();
10949 break;
10950 }
10951
10952 case value_t::array:
10953 {
10954 m_it.array_iterator = m_object->m_value.array->begin();
10955 break;
10956 }
10957
10958 case value_t::null:
10959 {
10960 // set to end so begin()==end() is true: null is empty
10961 m_it.primitive_iterator.set_end();
10962 break;
10963 }
10964
10965 default:
10966 {
10967 m_it.primitive_iterator.set_begin();
10968 break;
10969 }
10970 }
10971 }
10972
10973 /*!
10974 @brief set the iterator past the last value
10975 @pre The iterator is initialized; i.e. `m_object != nullptr`.
10976 */
set_end()10977 void set_end() noexcept
10978 {
10979 JSON_ASSERT(m_object != nullptr);
10980
10981 switch (m_object->m_type)
10982 {
10983 case value_t::object:
10984 {
10985 m_it.object_iterator = m_object->m_value.object->end();
10986 break;
10987 }
10988
10989 case value_t::array:
10990 {
10991 m_it.array_iterator = m_object->m_value.array->end();
10992 break;
10993 }
10994
10995 default:
10996 {
10997 m_it.primitive_iterator.set_end();
10998 break;
10999 }
11000 }
11001 }
11002
11003 public:
11004 /*!
11005 @brief return a reference to the value pointed to by the iterator
11006 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11007 */
operator *() const11008 reference operator*() const
11009 {
11010 JSON_ASSERT(m_object != nullptr);
11011
11012 switch (m_object->m_type)
11013 {
11014 case value_t::object:
11015 {
11016 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
11017 return m_it.object_iterator->second;
11018 }
11019
11020 case value_t::array:
11021 {
11022 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
11023 return *m_it.array_iterator;
11024 }
11025
11026 case value_t::null:
11027 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
11028
11029 default:
11030 {
11031 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
11032 {
11033 return *m_object;
11034 }
11035
11036 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
11037 }
11038 }
11039 }
11040
11041 /*!
11042 @brief dereference the iterator
11043 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11044 */
operator ->() const11045 pointer operator->() const
11046 {
11047 JSON_ASSERT(m_object != nullptr);
11048
11049 switch (m_object->m_type)
11050 {
11051 case value_t::object:
11052 {
11053 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
11054 return &(m_it.object_iterator->second);
11055 }
11056
11057 case value_t::array:
11058 {
11059 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
11060 return &*m_it.array_iterator;
11061 }
11062
11063 default:
11064 {
11065 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
11066 {
11067 return m_object;
11068 }
11069
11070 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
11071 }
11072 }
11073 }
11074
11075 /*!
11076 @brief post-increment (it++)
11077 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11078 */
operator ++(int)11079 iter_impl const operator++(int)
11080 {
11081 auto result = *this;
11082 ++(*this);
11083 return result;
11084 }
11085
11086 /*!
11087 @brief pre-increment (++it)
11088 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11089 */
operator ++()11090 iter_impl& operator++()
11091 {
11092 JSON_ASSERT(m_object != nullptr);
11093
11094 switch (m_object->m_type)
11095 {
11096 case value_t::object:
11097 {
11098 std::advance(m_it.object_iterator, 1);
11099 break;
11100 }
11101
11102 case value_t::array:
11103 {
11104 std::advance(m_it.array_iterator, 1);
11105 break;
11106 }
11107
11108 default:
11109 {
11110 ++m_it.primitive_iterator;
11111 break;
11112 }
11113 }
11114
11115 return *this;
11116 }
11117
11118 /*!
11119 @brief post-decrement (it--)
11120 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11121 */
operator --(int)11122 iter_impl const operator--(int)
11123 {
11124 auto result = *this;
11125 --(*this);
11126 return result;
11127 }
11128
11129 /*!
11130 @brief pre-decrement (--it)
11131 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11132 */
operator --()11133 iter_impl& operator--()
11134 {
11135 JSON_ASSERT(m_object != nullptr);
11136
11137 switch (m_object->m_type)
11138 {
11139 case value_t::object:
11140 {
11141 std::advance(m_it.object_iterator, -1);
11142 break;
11143 }
11144
11145 case value_t::array:
11146 {
11147 std::advance(m_it.array_iterator, -1);
11148 break;
11149 }
11150
11151 default:
11152 {
11153 --m_it.primitive_iterator;
11154 break;
11155 }
11156 }
11157
11158 return *this;
11159 }
11160
11161 /*!
11162 @brief comparison: equal
11163 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11164 */
operator ==(const iter_impl & other) const11165 bool operator==(const iter_impl& other) const
11166 {
11167 // if objects are not the same, the comparison is undefined
11168 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
11169 {
11170 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
11171 }
11172
11173 JSON_ASSERT(m_object != nullptr);
11174
11175 switch (m_object->m_type)
11176 {
11177 case value_t::object:
11178 return (m_it.object_iterator == other.m_it.object_iterator);
11179
11180 case value_t::array:
11181 return (m_it.array_iterator == other.m_it.array_iterator);
11182
11183 default:
11184 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
11185 }
11186 }
11187
11188 /*!
11189 @brief comparison: not equal
11190 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11191 */
operator !=(const iter_impl & other) const11192 bool operator!=(const iter_impl& other) const
11193 {
11194 return !operator==(other);
11195 }
11196
11197 /*!
11198 @brief comparison: smaller
11199 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11200 */
operator <(const iter_impl & other) const11201 bool operator<(const iter_impl& other) const
11202 {
11203 // if objects are not the same, the comparison is undefined
11204 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
11205 {
11206 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
11207 }
11208
11209 JSON_ASSERT(m_object != nullptr);
11210
11211 switch (m_object->m_type)
11212 {
11213 case value_t::object:
11214 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
11215
11216 case value_t::array:
11217 return (m_it.array_iterator < other.m_it.array_iterator);
11218
11219 default:
11220 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
11221 }
11222 }
11223
11224 /*!
11225 @brief comparison: less than or equal
11226 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11227 */
operator <=(const iter_impl & other) const11228 bool operator<=(const iter_impl& other) const
11229 {
11230 return !other.operator < (*this);
11231 }
11232
11233 /*!
11234 @brief comparison: greater than
11235 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11236 */
operator >(const iter_impl & other) const11237 bool operator>(const iter_impl& other) const
11238 {
11239 return !operator<=(other);
11240 }
11241
11242 /*!
11243 @brief comparison: greater than or equal
11244 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11245 */
operator >=(const iter_impl & other) const11246 bool operator>=(const iter_impl& other) const
11247 {
11248 return !operator<(other);
11249 }
11250
11251 /*!
11252 @brief add to iterator
11253 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11254 */
operator +=(difference_type i)11255 iter_impl& operator+=(difference_type i)
11256 {
11257 JSON_ASSERT(m_object != nullptr);
11258
11259 switch (m_object->m_type)
11260 {
11261 case value_t::object:
11262 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
11263
11264 case value_t::array:
11265 {
11266 std::advance(m_it.array_iterator, i);
11267 break;
11268 }
11269
11270 default:
11271 {
11272 m_it.primitive_iterator += i;
11273 break;
11274 }
11275 }
11276
11277 return *this;
11278 }
11279
11280 /*!
11281 @brief subtract from iterator
11282 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11283 */
operator -=(difference_type i)11284 iter_impl& operator-=(difference_type i)
11285 {
11286 return operator+=(-i);
11287 }
11288
11289 /*!
11290 @brief add to iterator
11291 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11292 */
operator +(difference_type i) const11293 iter_impl operator+(difference_type i) const
11294 {
11295 auto result = *this;
11296 result += i;
11297 return result;
11298 }
11299
11300 /*!
11301 @brief addition of distance and iterator
11302 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11303 */
operator +(difference_type i,const iter_impl & it)11304 friend iter_impl operator+(difference_type i, const iter_impl& it)
11305 {
11306 auto result = it;
11307 result += i;
11308 return result;
11309 }
11310
11311 /*!
11312 @brief subtract from iterator
11313 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11314 */
operator -(difference_type i) const11315 iter_impl operator-(difference_type i) const
11316 {
11317 auto result = *this;
11318 result -= i;
11319 return result;
11320 }
11321
11322 /*!
11323 @brief return difference
11324 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11325 */
operator -(const iter_impl & other) const11326 difference_type operator-(const iter_impl& other) const
11327 {
11328 JSON_ASSERT(m_object != nullptr);
11329
11330 switch (m_object->m_type)
11331 {
11332 case value_t::object:
11333 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
11334
11335 case value_t::array:
11336 return m_it.array_iterator - other.m_it.array_iterator;
11337
11338 default:
11339 return m_it.primitive_iterator - other.m_it.primitive_iterator;
11340 }
11341 }
11342
11343 /*!
11344 @brief access to successor
11345 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11346 */
operator [](difference_type n) const11347 reference operator[](difference_type n) const
11348 {
11349 JSON_ASSERT(m_object != nullptr);
11350
11351 switch (m_object->m_type)
11352 {
11353 case value_t::object:
11354 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
11355
11356 case value_t::array:
11357 return *std::next(m_it.array_iterator, n);
11358
11359 case value_t::null:
11360 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
11361
11362 default:
11363 {
11364 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
11365 {
11366 return *m_object;
11367 }
11368
11369 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
11370 }
11371 }
11372 }
11373
11374 /*!
11375 @brief return the key of an object iterator
11376 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11377 */
key() const11378 const typename object_t::key_type& key() const
11379 {
11380 JSON_ASSERT(m_object != nullptr);
11381
11382 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
11383 {
11384 return m_it.object_iterator->first;
11385 }
11386
11387 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
11388 }
11389
11390 /*!
11391 @brief return the value of an iterator
11392 @pre The iterator is initialized; i.e. `m_object != nullptr`.
11393 */
value() const11394 reference value() const
11395 {
11396 return operator*();
11397 }
11398
11399 private:
11400 /// associated JSON instance
11401 pointer m_object = nullptr;
11402 /// the actual iterator of the associated instance
11403 internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
11404 };
11405 } // namespace detail
11406 } // namespace nlohmann
11407
11408 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
11409
11410 // #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
11411
11412
11413 #include <cstddef> // ptrdiff_t
11414 #include <iterator> // reverse_iterator
11415 #include <utility> // declval
11416
11417 namespace nlohmann
11418 {
11419 namespace detail
11420 {
11421 //////////////////////
11422 // reverse_iterator //
11423 //////////////////////
11424
11425 /*!
11426 @brief a template for a reverse iterator class
11427
11428 @tparam Base the base iterator type to reverse. Valid types are @ref
11429 iterator (to create @ref reverse_iterator) and @ref const_iterator (to
11430 create @ref const_reverse_iterator).
11431
11432 @requirement The class satisfies the following concept requirements:
11433 -
11434 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
11435 The iterator that can be moved can be moved in both directions (i.e.
11436 incremented and decremented).
11437 - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
11438 It is possible to write to the pointed-to element (only if @a Base is
11439 @ref iterator).
11440
11441 @since version 1.0.0
11442 */
11443 template<typename Base>
11444 class json_reverse_iterator : public std::reverse_iterator<Base>
11445 {
11446 public:
11447 using difference_type = std::ptrdiff_t;
11448 /// shortcut to the reverse iterator adapter
11449 using base_iterator = std::reverse_iterator<Base>;
11450 /// the reference type for the pointed-to element
11451 using reference = typename Base::reference;
11452
11453 /// create reverse iterator from iterator
json_reverse_iterator(const typename base_iterator::iterator_type & it)11454 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
11455 : base_iterator(it) {}
11456
11457 /// create reverse iterator from base class
json_reverse_iterator(const base_iterator & it)11458 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
11459
11460 /// post-increment (it++)
operator ++(int)11461 json_reverse_iterator const operator++(int)
11462 {
11463 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
11464 }
11465
11466 /// pre-increment (++it)
operator ++()11467 json_reverse_iterator& operator++()
11468 {
11469 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
11470 }
11471
11472 /// post-decrement (it--)
operator --(int)11473 json_reverse_iterator const operator--(int)
11474 {
11475 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
11476 }
11477
11478 /// pre-decrement (--it)
operator --()11479 json_reverse_iterator& operator--()
11480 {
11481 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
11482 }
11483
11484 /// add to iterator
operator +=(difference_type i)11485 json_reverse_iterator& operator+=(difference_type i)
11486 {
11487 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
11488 }
11489
11490 /// add to iterator
operator +(difference_type i) const11491 json_reverse_iterator operator+(difference_type i) const
11492 {
11493 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
11494 }
11495
11496 /// subtract from iterator
operator -(difference_type i) const11497 json_reverse_iterator operator-(difference_type i) const
11498 {
11499 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
11500 }
11501
11502 /// return difference
operator -(const json_reverse_iterator & other) const11503 difference_type operator-(const json_reverse_iterator& other) const
11504 {
11505 return base_iterator(*this) - base_iterator(other);
11506 }
11507
11508 /// access to successor
operator [](difference_type n) const11509 reference operator[](difference_type n) const
11510 {
11511 return *(this->operator+(n));
11512 }
11513
11514 /// return the key of an object iterator
key() const11515 auto key() const -> decltype(std::declval<Base>().key())
11516 {
11517 auto it = --this->base();
11518 return it.key();
11519 }
11520
11521 /// return the value of an iterator
value() const11522 reference value() const
11523 {
11524 auto it = --this->base();
11525 return it.operator * ();
11526 }
11527 };
11528 } // namespace detail
11529 } // namespace nlohmann
11530
11531 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
11532
11533 // #include <nlohmann/detail/json_pointer.hpp>
11534
11535
11536 #include <algorithm> // all_of
11537 #include <cctype> // isdigit
11538 #include <limits> // max
11539 #include <numeric> // accumulate
11540 #include <string> // string
11541 #include <utility> // move
11542 #include <vector> // vector
11543
11544 // #include <nlohmann/detail/exceptions.hpp>
11545
11546 // #include <nlohmann/detail/macro_scope.hpp>
11547
11548 // #include <nlohmann/detail/value_t.hpp>
11549
11550
11551 namespace nlohmann
11552 {
11553 template<typename BasicJsonType>
11554 class json_pointer
11555 {
11556 // allow basic_json to access private members
11557 NLOHMANN_BASIC_JSON_TPL_DECLARATION
11558 friend class basic_json;
11559
11560 public:
11561 /*!
11562 @brief create JSON pointer
11563
11564 Create a JSON pointer according to the syntax described in
11565 [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).
11566
11567 @param[in] s string representing the JSON pointer; if omitted, the empty
11568 string is assumed which references the whole JSON value
11569
11570 @throw parse_error.107 if the given JSON pointer @a s is nonempty and does
11571 not begin with a slash (`/`); see example below
11572
11573 @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is
11574 not followed by `0` (representing `~`) or `1` (representing `/`); see
11575 example below
11576
11577 @liveexample{The example shows the construction several valid JSON pointers
11578 as well as the exceptional behavior.,json_pointer}
11579
11580 @since version 2.0.0
11581 */
json_pointer(const std::string & s="")11582 explicit json_pointer(const std::string& s = "")
11583 : reference_tokens(split(s))
11584 {}
11585
11586 /*!
11587 @brief return a string representation of the JSON pointer
11588
11589 @invariant For each JSON pointer `ptr`, it holds:
11590 @code {.cpp}
11591 ptr == json_pointer(ptr.to_string());
11592 @endcode
11593
11594 @return a string representation of the JSON pointer
11595
11596 @liveexample{The example shows the result of `to_string`.,json_pointer__to_string}
11597
11598 @since version 2.0.0
11599 */
to_string() const11600 std::string to_string() const
11601 {
11602 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
11603 std::string{},
11604 [](const std::string & a, const std::string & b)
11605 {
11606 return a + "/" + escape(b);
11607 });
11608 }
11609
11610 /// @copydoc to_string()
operator std::string() const11611 operator std::string() const
11612 {
11613 return to_string();
11614 }
11615
11616 /*!
11617 @brief append another JSON pointer at the end of this JSON pointer
11618
11619 @param[in] ptr JSON pointer to append
11620 @return JSON pointer with @a ptr appended
11621
11622 @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
11623
11624 @complexity Linear in the length of @a ptr.
11625
11626 @sa @ref operator/=(std::string) to append a reference token
11627 @sa @ref operator/=(std::size_t) to append an array index
11628 @sa @ref operator/(const json_pointer&, const json_pointer&) for a binary operator
11629
11630 @since version 3.6.0
11631 */
operator /=(const json_pointer & ptr)11632 json_pointer& operator/=(const json_pointer& ptr)
11633 {
11634 reference_tokens.insert(reference_tokens.end(),
11635 ptr.reference_tokens.begin(),
11636 ptr.reference_tokens.end());
11637 return *this;
11638 }
11639
11640 /*!
11641 @brief append an unescaped reference token at the end of this JSON pointer
11642
11643 @param[in] token reference token to append
11644 @return JSON pointer with @a token appended without escaping @a token
11645
11646 @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
11647
11648 @complexity Amortized constant.
11649
11650 @sa @ref operator/=(const json_pointer&) to append a JSON pointer
11651 @sa @ref operator/=(std::size_t) to append an array index
11652 @sa @ref operator/(const json_pointer&, std::size_t) for a binary operator
11653
11654 @since version 3.6.0
11655 */
operator /=(std::string token)11656 json_pointer& operator/=(std::string token)
11657 {
11658 push_back(std::move(token));
11659 return *this;
11660 }
11661
11662 /*!
11663 @brief append an array index at the end of this JSON pointer
11664
11665 @param[in] array_idx array index to append
11666 @return JSON pointer with @a array_idx appended
11667
11668 @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
11669
11670 @complexity Amortized constant.
11671
11672 @sa @ref operator/=(const json_pointer&) to append a JSON pointer
11673 @sa @ref operator/=(std::string) to append a reference token
11674 @sa @ref operator/(const json_pointer&, std::string) for a binary operator
11675
11676 @since version 3.6.0
11677 */
operator /=(std::size_t array_idx)11678 json_pointer& operator/=(std::size_t array_idx)
11679 {
11680 return *this /= std::to_string(array_idx);
11681 }
11682
11683 /*!
11684 @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
11685
11686 @param[in] lhs JSON pointer
11687 @param[in] rhs JSON pointer
11688 @return a new JSON pointer with @a rhs appended to @a lhs
11689
11690 @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
11691
11692 @complexity Linear in the length of @a lhs and @a rhs.
11693
11694 @sa @ref operator/=(const json_pointer&) to append a JSON pointer
11695
11696 @since version 3.6.0
11697 */
operator /(const json_pointer & lhs,const json_pointer & rhs)11698 friend json_pointer operator/(const json_pointer& lhs,
11699 const json_pointer& rhs)
11700 {
11701 return json_pointer(lhs) /= rhs;
11702 }
11703
11704 /*!
11705 @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
11706
11707 @param[in] ptr JSON pointer
11708 @param[in] token reference token
11709 @return a new JSON pointer with unescaped @a token appended to @a ptr
11710
11711 @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
11712
11713 @complexity Linear in the length of @a ptr.
11714
11715 @sa @ref operator/=(std::string) to append a reference token
11716
11717 @since version 3.6.0
11718 */
operator /(const json_pointer & ptr,std::string token)11719 friend json_pointer operator/(const json_pointer& ptr, std::string token)
11720 {
11721 return json_pointer(ptr) /= std::move(token);
11722 }
11723
11724 /*!
11725 @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
11726
11727 @param[in] ptr JSON pointer
11728 @param[in] array_idx array index
11729 @return a new JSON pointer with @a array_idx appended to @a ptr
11730
11731 @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
11732
11733 @complexity Linear in the length of @a ptr.
11734
11735 @sa @ref operator/=(std::size_t) to append an array index
11736
11737 @since version 3.6.0
11738 */
operator /(const json_pointer & ptr,std::size_t array_idx)11739 friend json_pointer operator/(const json_pointer& ptr, std::size_t array_idx)
11740 {
11741 return json_pointer(ptr) /= array_idx;
11742 }
11743
11744 /*!
11745 @brief returns the parent of this JSON pointer
11746
11747 @return parent of this JSON pointer; in case this JSON pointer is the root,
11748 the root itself is returned
11749
11750 @complexity Linear in the length of the JSON pointer.
11751
11752 @liveexample{The example shows the result of `parent_pointer` for different
11753 JSON Pointers.,json_pointer__parent_pointer}
11754
11755 @since version 3.6.0
11756 */
parent_pointer() const11757 json_pointer parent_pointer() const
11758 {
11759 if (empty())
11760 {
11761 return *this;
11762 }
11763
11764 json_pointer res = *this;
11765 res.pop_back();
11766 return res;
11767 }
11768
11769 /*!
11770 @brief remove last reference token
11771
11772 @pre not `empty()`
11773
11774 @liveexample{The example shows the usage of `pop_back`.,json_pointer__pop_back}
11775
11776 @complexity Constant.
11777
11778 @throw out_of_range.405 if JSON pointer has no parent
11779
11780 @since version 3.6.0
11781 */
pop_back()11782 void pop_back()
11783 {
11784 if (JSON_HEDLEY_UNLIKELY(empty()))
11785 {
11786 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
11787 }
11788
11789 reference_tokens.pop_back();
11790 }
11791
11792 /*!
11793 @brief return last reference token
11794
11795 @pre not `empty()`
11796 @return last reference token
11797
11798 @liveexample{The example shows the usage of `back`.,json_pointer__back}
11799
11800 @complexity Constant.
11801
11802 @throw out_of_range.405 if JSON pointer has no parent
11803
11804 @since version 3.6.0
11805 */
back() const11806 const std::string& back() const
11807 {
11808 if (JSON_HEDLEY_UNLIKELY(empty()))
11809 {
11810 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
11811 }
11812
11813 return reference_tokens.back();
11814 }
11815
11816 /*!
11817 @brief append an unescaped token at the end of the reference pointer
11818
11819 @param[in] token token to add
11820
11821 @complexity Amortized constant.
11822
11823 @liveexample{The example shows the result of `push_back` for different
11824 JSON Pointers.,json_pointer__push_back}
11825
11826 @since version 3.6.0
11827 */
push_back(const std::string & token)11828 void push_back(const std::string& token)
11829 {
11830 reference_tokens.push_back(token);
11831 }
11832
11833 /// @copydoc push_back(const std::string&)
push_back(std::string && token)11834 void push_back(std::string&& token)
11835 {
11836 reference_tokens.push_back(std::move(token));
11837 }
11838
11839 /*!
11840 @brief return whether pointer points to the root document
11841
11842 @return true iff the JSON pointer points to the root document
11843
11844 @complexity Constant.
11845
11846 @exceptionsafety No-throw guarantee: this function never throws exceptions.
11847
11848 @liveexample{The example shows the result of `empty` for different JSON
11849 Pointers.,json_pointer__empty}
11850
11851 @since version 3.6.0
11852 */
empty() const11853 bool empty() const noexcept
11854 {
11855 return reference_tokens.empty();
11856 }
11857
11858 private:
11859 /*!
11860 @param[in] s reference token to be converted into an array index
11861
11862 @return integer representation of @a s
11863
11864 @throw parse_error.106 if an array index begins with '0'
11865 @throw parse_error.109 if an array index begins not with a digit
11866 @throw out_of_range.404 if string @a s could not be converted to an integer
11867 @throw out_of_range.410 if an array index exceeds size_type
11868 */
array_index(const std::string & s)11869 static typename BasicJsonType::size_type array_index(const std::string& s)
11870 {
11871 using size_type = typename BasicJsonType::size_type;
11872
11873 // error condition (cf. RFC 6901, Sect. 4)
11874 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
11875 {
11876 JSON_THROW(detail::parse_error::create(106, 0,
11877 "array index '" + s +
11878 "' must not begin with '0'"));
11879 }
11880
11881 // error condition (cf. RFC 6901, Sect. 4)
11882 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
11883 {
11884 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number"));
11885 }
11886
11887 std::size_t processed_chars = 0;
11888 unsigned long long res = 0;
11889 JSON_TRY
11890 {
11891 res = std::stoull(s, &processed_chars);
11892 }
11893 JSON_CATCH(std::out_of_range&)
11894 {
11895 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
11896 }
11897
11898 // check if the string was completely read
11899 if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
11900 {
11901 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
11902 }
11903
11904 // only triggered on special platforms (like 32bit), see also
11905 // https://github.com/nlohmann/json/pull/2203
11906 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))
11907 {
11908 JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE
11909 }
11910
11911 return static_cast<size_type>(res);
11912 }
11913
top() const11914 json_pointer top() const
11915 {
11916 if (JSON_HEDLEY_UNLIKELY(empty()))
11917 {
11918 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
11919 }
11920
11921 json_pointer result = *this;
11922 result.reference_tokens = {reference_tokens[0]};
11923 return result;
11924 }
11925
11926 /*!
11927 @brief create and return a reference to the pointed to value
11928
11929 @complexity Linear in the number of reference tokens.
11930
11931 @throw parse_error.109 if array index is not a number
11932 @throw type_error.313 if value cannot be unflattened
11933 */
get_and_create(BasicJsonType & j) const11934 BasicJsonType& get_and_create(BasicJsonType& j) const
11935 {
11936 auto result = &j;
11937
11938 // in case no reference tokens exist, return a reference to the JSON value
11939 // j which will be overwritten by a primitive value
11940 for (const auto& reference_token : reference_tokens)
11941 {
11942 switch (result->type())
11943 {
11944 case detail::value_t::null:
11945 {
11946 if (reference_token == "0")
11947 {
11948 // start a new array if reference token is 0
11949 result = &result->operator[](0);
11950 }
11951 else
11952 {
11953 // start a new object otherwise
11954 result = &result->operator[](reference_token);
11955 }
11956 break;
11957 }
11958
11959 case detail::value_t::object:
11960 {
11961 // create an entry in the object
11962 result = &result->operator[](reference_token);
11963 break;
11964 }
11965
11966 case detail::value_t::array:
11967 {
11968 // create an entry in the array
11969 result = &result->operator[](array_index(reference_token));
11970 break;
11971 }
11972
11973 /*
11974 The following code is only reached if there exists a reference
11975 token _and_ the current value is primitive. In this case, we have
11976 an error situation, because primitive values may only occur as
11977 single value; that is, with an empty list of reference tokens.
11978 */
11979 default:
11980 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
11981 }
11982 }
11983
11984 return *result;
11985 }
11986
11987 /*!
11988 @brief return a reference to the pointed to value
11989
11990 @note This version does not throw if a value is not present, but tries to
11991 create nested values instead. For instance, calling this function
11992 with pointer `"/this/that"` on a null value is equivalent to calling
11993 `operator[]("this").operator[]("that")` on that value, effectively
11994 changing the null value to an object.
11995
11996 @param[in] ptr a JSON value
11997
11998 @return reference to the JSON value pointed to by the JSON pointer
11999
12000 @complexity Linear in the length of the JSON pointer.
12001
12002 @throw parse_error.106 if an array index begins with '0'
12003 @throw parse_error.109 if an array index was not a number
12004 @throw out_of_range.404 if the JSON pointer can not be resolved
12005 */
get_unchecked(BasicJsonType * ptr) const12006 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
12007 {
12008 for (const auto& reference_token : reference_tokens)
12009 {
12010 // convert null values to arrays or objects before continuing
12011 if (ptr->is_null())
12012 {
12013 // check if reference token is a number
12014 const bool nums =
12015 std::all_of(reference_token.begin(), reference_token.end(),
12016 [](const unsigned char x)
12017 {
12018 return std::isdigit(x);
12019 });
12020
12021 // change value to array for numbers or "-" or to object otherwise
12022 *ptr = (nums || reference_token == "-")
12023 ? detail::value_t::array
12024 : detail::value_t::object;
12025 }
12026
12027 switch (ptr->type())
12028 {
12029 case detail::value_t::object:
12030 {
12031 // use unchecked object access
12032 ptr = &ptr->operator[](reference_token);
12033 break;
12034 }
12035
12036 case detail::value_t::array:
12037 {
12038 if (reference_token == "-")
12039 {
12040 // explicitly treat "-" as index beyond the end
12041 ptr = &ptr->operator[](ptr->m_value.array->size());
12042 }
12043 else
12044 {
12045 // convert array index to number; unchecked access
12046 ptr = &ptr->operator[](array_index(reference_token));
12047 }
12048 break;
12049 }
12050
12051 default:
12052 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12053 }
12054 }
12055
12056 return *ptr;
12057 }
12058
12059 /*!
12060 @throw parse_error.106 if an array index begins with '0'
12061 @throw parse_error.109 if an array index was not a number
12062 @throw out_of_range.402 if the array index '-' is used
12063 @throw out_of_range.404 if the JSON pointer can not be resolved
12064 */
get_checked(BasicJsonType * ptr) const12065 BasicJsonType& get_checked(BasicJsonType* ptr) const
12066 {
12067 for (const auto& reference_token : reference_tokens)
12068 {
12069 switch (ptr->type())
12070 {
12071 case detail::value_t::object:
12072 {
12073 // note: at performs range check
12074 ptr = &ptr->at(reference_token);
12075 break;
12076 }
12077
12078 case detail::value_t::array:
12079 {
12080 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12081 {
12082 // "-" always fails the range check
12083 JSON_THROW(detail::out_of_range::create(402,
12084 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12085 ") is out of range"));
12086 }
12087
12088 // note: at performs range check
12089 ptr = &ptr->at(array_index(reference_token));
12090 break;
12091 }
12092
12093 default:
12094 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12095 }
12096 }
12097
12098 return *ptr;
12099 }
12100
12101 /*!
12102 @brief return a const reference to the pointed to value
12103
12104 @param[in] ptr a JSON value
12105
12106 @return const reference to the JSON value pointed to by the JSON
12107 pointer
12108
12109 @throw parse_error.106 if an array index begins with '0'
12110 @throw parse_error.109 if an array index was not a number
12111 @throw out_of_range.402 if the array index '-' is used
12112 @throw out_of_range.404 if the JSON pointer can not be resolved
12113 */
get_unchecked(const BasicJsonType * ptr) const12114 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
12115 {
12116 for (const auto& reference_token : reference_tokens)
12117 {
12118 switch (ptr->type())
12119 {
12120 case detail::value_t::object:
12121 {
12122 // use unchecked object access
12123 ptr = &ptr->operator[](reference_token);
12124 break;
12125 }
12126
12127 case detail::value_t::array:
12128 {
12129 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12130 {
12131 // "-" cannot be used for const access
12132 JSON_THROW(detail::out_of_range::create(402,
12133 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12134 ") is out of range"));
12135 }
12136
12137 // use unchecked array access
12138 ptr = &ptr->operator[](array_index(reference_token));
12139 break;
12140 }
12141
12142 default:
12143 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12144 }
12145 }
12146
12147 return *ptr;
12148 }
12149
12150 /*!
12151 @throw parse_error.106 if an array index begins with '0'
12152 @throw parse_error.109 if an array index was not a number
12153 @throw out_of_range.402 if the array index '-' is used
12154 @throw out_of_range.404 if the JSON pointer can not be resolved
12155 */
get_checked(const BasicJsonType * ptr) const12156 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
12157 {
12158 for (const auto& reference_token : reference_tokens)
12159 {
12160 switch (ptr->type())
12161 {
12162 case detail::value_t::object:
12163 {
12164 // note: at performs range check
12165 ptr = &ptr->at(reference_token);
12166 break;
12167 }
12168
12169 case detail::value_t::array:
12170 {
12171 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12172 {
12173 // "-" always fails the range check
12174 JSON_THROW(detail::out_of_range::create(402,
12175 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12176 ") is out of range"));
12177 }
12178
12179 // note: at performs range check
12180 ptr = &ptr->at(array_index(reference_token));
12181 break;
12182 }
12183
12184 default:
12185 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12186 }
12187 }
12188
12189 return *ptr;
12190 }
12191
12192 /*!
12193 @throw parse_error.106 if an array index begins with '0'
12194 @throw parse_error.109 if an array index was not a number
12195 */
contains(const BasicJsonType * ptr) const12196 bool contains(const BasicJsonType* ptr) const
12197 {
12198 for (const auto& reference_token : reference_tokens)
12199 {
12200 switch (ptr->type())
12201 {
12202 case detail::value_t::object:
12203 {
12204 if (!ptr->contains(reference_token))
12205 {
12206 // we did not find the key in the object
12207 return false;
12208 }
12209
12210 ptr = &ptr->operator[](reference_token);
12211 break;
12212 }
12213
12214 case detail::value_t::array:
12215 {
12216 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
12217 {
12218 // "-" always fails the range check
12219 return false;
12220 }
12221 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
12222 {
12223 // invalid char
12224 return false;
12225 }
12226 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
12227 {
12228 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
12229 {
12230 // first char should be between '1' and '9'
12231 return false;
12232 }
12233 for (std::size_t i = 1; i < reference_token.size(); i++)
12234 {
12235 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
12236 {
12237 // other char should be between '0' and '9'
12238 return false;
12239 }
12240 }
12241 }
12242
12243 const auto idx = array_index(reference_token);
12244 if (idx >= ptr->size())
12245 {
12246 // index out of range
12247 return false;
12248 }
12249
12250 ptr = &ptr->operator[](idx);
12251 break;
12252 }
12253
12254 default:
12255 {
12256 // we do not expect primitive values if there is still a
12257 // reference token to process
12258 return false;
12259 }
12260 }
12261 }
12262
12263 // no reference token left means we found a primitive value
12264 return true;
12265 }
12266
12267 /*!
12268 @brief split the string input to reference tokens
12269
12270 @note This function is only called by the json_pointer constructor.
12271 All exceptions below are documented there.
12272
12273 @throw parse_error.107 if the pointer is not empty or begins with '/'
12274 @throw parse_error.108 if character '~' is not followed by '0' or '1'
12275 */
split(const std::string & reference_string)12276 static std::vector<std::string> split(const std::string& reference_string)
12277 {
12278 std::vector<std::string> result;
12279
12280 // special case: empty reference string -> no reference tokens
12281 if (reference_string.empty())
12282 {
12283 return result;
12284 }
12285
12286 // check if nonempty reference string begins with slash
12287 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
12288 {
12289 JSON_THROW(detail::parse_error::create(107, 1,
12290 "JSON pointer must be empty or begin with '/' - was: '" +
12291 reference_string + "'"));
12292 }
12293
12294 // extract the reference tokens:
12295 // - slash: position of the last read slash (or end of string)
12296 // - start: position after the previous slash
12297 for (
12298 // search for the first slash after the first character
12299 std::size_t slash = reference_string.find_first_of('/', 1),
12300 // set the beginning of the first reference token
12301 start = 1;
12302 // we can stop if start == 0 (if slash == std::string::npos)
12303 start != 0;
12304 // set the beginning of the next reference token
12305 // (will eventually be 0 if slash == std::string::npos)
12306 start = (slash == std::string::npos) ? 0 : slash + 1,
12307 // find next slash
12308 slash = reference_string.find_first_of('/', start))
12309 {
12310 // use the text between the beginning of the reference token
12311 // (start) and the last slash (slash).
12312 auto reference_token = reference_string.substr(start, slash - start);
12313
12314 // check reference tokens are properly escaped
12315 for (std::size_t pos = reference_token.find_first_of('~');
12316 pos != std::string::npos;
12317 pos = reference_token.find_first_of('~', pos + 1))
12318 {
12319 JSON_ASSERT(reference_token[pos] == '~');
12320
12321 // ~ must be followed by 0 or 1
12322 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
12323 (reference_token[pos + 1] != '0' &&
12324 reference_token[pos + 1] != '1')))
12325 {
12326 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
12327 }
12328 }
12329
12330 // finally, store the reference token
12331 unescape(reference_token);
12332 result.push_back(reference_token);
12333 }
12334
12335 return result;
12336 }
12337
12338 /*!
12339 @brief replace all occurrences of a substring by another string
12340
12341 @param[in,out] s the string to manipulate; changed so that all
12342 occurrences of @a f are replaced with @a t
12343 @param[in] f the substring to replace with @a t
12344 @param[in] t the string to replace @a f
12345
12346 @pre The search string @a f must not be empty. **This precondition is
12347 enforced with an assertion.**
12348
12349 @since version 2.0.0
12350 */
replace_substring(std::string & s,const std::string & f,const std::string & t)12351 static void replace_substring(std::string& s, const std::string& f,
12352 const std::string& t)
12353 {
12354 JSON_ASSERT(!f.empty());
12355 for (auto pos = s.find(f); // find first occurrence of f
12356 pos != std::string::npos; // make sure f was found
12357 s.replace(pos, f.size(), t), // replace with t, and
12358 pos = s.find(f, pos + t.size())) // find next occurrence of f
12359 {}
12360 }
12361
12362 /// escape "~" to "~0" and "/" to "~1"
escape(std::string s)12363 static std::string escape(std::string s)
12364 {
12365 replace_substring(s, "~", "~0");
12366 replace_substring(s, "/", "~1");
12367 return s;
12368 }
12369
12370 /// unescape "~1" to tilde and "~0" to slash (order is important!)
unescape(std::string & s)12371 static void unescape(std::string& s)
12372 {
12373 replace_substring(s, "~1", "/");
12374 replace_substring(s, "~0", "~");
12375 }
12376
12377 /*!
12378 @param[in] reference_string the reference string to the current value
12379 @param[in] value the value to consider
12380 @param[in,out] result the result object to insert values to
12381
12382 @note Empty objects or arrays are flattened to `null`.
12383 */
flatten(const std::string & reference_string,const BasicJsonType & value,BasicJsonType & result)12384 static void flatten(const std::string& reference_string,
12385 const BasicJsonType& value,
12386 BasicJsonType& result)
12387 {
12388 switch (value.type())
12389 {
12390 case detail::value_t::array:
12391 {
12392 if (value.m_value.array->empty())
12393 {
12394 // flatten empty array as null
12395 result[reference_string] = nullptr;
12396 }
12397 else
12398 {
12399 // iterate array and use index as reference string
12400 for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
12401 {
12402 flatten(reference_string + "/" + std::to_string(i),
12403 value.m_value.array->operator[](i), result);
12404 }
12405 }
12406 break;
12407 }
12408
12409 case detail::value_t::object:
12410 {
12411 if (value.m_value.object->empty())
12412 {
12413 // flatten empty object as null
12414 result[reference_string] = nullptr;
12415 }
12416 else
12417 {
12418 // iterate object and use keys as reference string
12419 for (const auto& element : *value.m_value.object)
12420 {
12421 flatten(reference_string + "/" + escape(element.first), element.second, result);
12422 }
12423 }
12424 break;
12425 }
12426
12427 default:
12428 {
12429 // add primitive value with its reference string
12430 result[reference_string] = value;
12431 break;
12432 }
12433 }
12434 }
12435
12436 /*!
12437 @param[in] value flattened JSON
12438
12439 @return unflattened JSON
12440
12441 @throw parse_error.109 if array index is not a number
12442 @throw type_error.314 if value is not an object
12443 @throw type_error.315 if object values are not primitive
12444 @throw type_error.313 if value cannot be unflattened
12445 */
12446 static BasicJsonType
unflatten(const BasicJsonType & value)12447 unflatten(const BasicJsonType& value)
12448 {
12449 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
12450 {
12451 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
12452 }
12453
12454 BasicJsonType result;
12455
12456 // iterate the JSON object values
12457 for (const auto& element : *value.m_value.object)
12458 {
12459 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
12460 {
12461 JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
12462 }
12463
12464 // assign value to reference pointed to by JSON pointer; Note that if
12465 // the JSON pointer is "" (i.e., points to the whole value), function
12466 // get_and_create returns a reference to result itself. An assignment
12467 // will then create a primitive value.
12468 json_pointer(element.first).get_and_create(result) = element.second;
12469 }
12470
12471 return result;
12472 }
12473
12474 /*!
12475 @brief compares two JSON pointers for equality
12476
12477 @param[in] lhs JSON pointer to compare
12478 @param[in] rhs JSON pointer to compare
12479 @return whether @a lhs is equal to @a rhs
12480
12481 @complexity Linear in the length of the JSON pointer
12482
12483 @exceptionsafety No-throw guarantee: this function never throws exceptions.
12484 */
operator ==(json_pointer const & lhs,json_pointer const & rhs)12485 friend bool operator==(json_pointer const& lhs,
12486 json_pointer const& rhs) noexcept
12487 {
12488 return lhs.reference_tokens == rhs.reference_tokens;
12489 }
12490
12491 /*!
12492 @brief compares two JSON pointers for inequality
12493
12494 @param[in] lhs JSON pointer to compare
12495 @param[in] rhs JSON pointer to compare
12496 @return whether @a lhs is not equal @a rhs
12497
12498 @complexity Linear in the length of the JSON pointer
12499
12500 @exceptionsafety No-throw guarantee: this function never throws exceptions.
12501 */
operator !=(json_pointer const & lhs,json_pointer const & rhs)12502 friend bool operator!=(json_pointer const& lhs,
12503 json_pointer const& rhs) noexcept
12504 {
12505 return !(lhs == rhs);
12506 }
12507
12508 /// the reference tokens
12509 std::vector<std::string> reference_tokens;
12510 };
12511 } // namespace nlohmann
12512
12513 // #include <nlohmann/detail/json_ref.hpp>
12514
12515
12516 #include <initializer_list>
12517 #include <utility>
12518
12519 // #include <nlohmann/detail/meta/type_traits.hpp>
12520
12521
12522 namespace nlohmann
12523 {
12524 namespace detail
12525 {
12526 template<typename BasicJsonType>
12527 class json_ref
12528 {
12529 public:
12530 using value_type = BasicJsonType;
12531
json_ref(value_type && value)12532 json_ref(value_type&& value)
12533 : owned_value(std::move(value))
12534 , value_ref(&owned_value)
12535 , is_rvalue(true)
12536 {}
12537
json_ref(const value_type & value)12538 json_ref(const value_type& value)
12539 : value_ref(const_cast<value_type*>(&value))
12540 , is_rvalue(false)
12541 {}
12542
json_ref(std::initializer_list<json_ref> init)12543 json_ref(std::initializer_list<json_ref> init)
12544 : owned_value(init)
12545 , value_ref(&owned_value)
12546 , is_rvalue(true)
12547 {}
12548
12549 template <
12550 class... Args,
12551 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
json_ref(Args &&...args)12552 json_ref(Args && ... args)
12553 : owned_value(std::forward<Args>(args)...)
12554 , value_ref(&owned_value)
12555 , is_rvalue(true)
12556 {}
12557
12558 // class should be movable only
12559 json_ref(json_ref&&) = default;
12560 json_ref(const json_ref&) = delete;
12561 json_ref& operator=(const json_ref&) = delete;
12562 json_ref& operator=(json_ref&&) = delete;
12563 ~json_ref() = default;
12564
moved_or_copied() const12565 value_type moved_or_copied() const
12566 {
12567 if (is_rvalue)
12568 {
12569 return std::move(*value_ref);
12570 }
12571 return *value_ref;
12572 }
12573
operator *() const12574 value_type const& operator*() const
12575 {
12576 return *static_cast<value_type const*>(value_ref);
12577 }
12578
operator ->() const12579 value_type const* operator->() const
12580 {
12581 return static_cast<value_type const*>(value_ref);
12582 }
12583
12584 private:
12585 mutable value_type owned_value = nullptr;
12586 value_type* value_ref = nullptr;
12587 const bool is_rvalue = true;
12588 };
12589 } // namespace detail
12590 } // namespace nlohmann
12591
12592 // #include <nlohmann/detail/macro_scope.hpp>
12593
12594 // #include <nlohmann/detail/meta/cpp_future.hpp>
12595
12596 // #include <nlohmann/detail/meta/type_traits.hpp>
12597
12598 // #include <nlohmann/detail/output/binary_writer.hpp>
12599
12600
12601 #include <algorithm> // reverse
12602 #include <array> // array
12603 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
12604 #include <cstring> // memcpy
12605 #include <limits> // numeric_limits
12606 #include <string> // string
12607 #include <cmath> // isnan, isinf
12608
12609 // #include <nlohmann/detail/input/binary_reader.hpp>
12610
12611 // #include <nlohmann/detail/macro_scope.hpp>
12612
12613 // #include <nlohmann/detail/output/output_adapters.hpp>
12614
12615
12616 #include <algorithm> // copy
12617 #include <cstddef> // size_t
12618 #include <ios> // streamsize
12619 #include <iterator> // back_inserter
12620 #include <memory> // shared_ptr, make_shared
12621 #include <ostream> // basic_ostream
12622 #include <string> // basic_string
12623 #include <vector> // vector
12624 // #include <nlohmann/detail/macro_scope.hpp>
12625
12626
12627 namespace nlohmann
12628 {
12629 namespace detail
12630 {
12631 /// abstract output adapter interface
12632 template<typename CharType> struct output_adapter_protocol
12633 {
12634 virtual void write_character(CharType c) = 0;
12635 virtual void write_characters(const CharType* s, std::size_t length) = 0;
12636 virtual ~output_adapter_protocol() = default;
12637 };
12638
12639 /// a type to simplify interfaces
12640 template<typename CharType>
12641 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
12642
12643 /// output adapter for byte vectors
12644 template<typename CharType>
12645 class output_vector_adapter : public output_adapter_protocol<CharType>
12646 {
12647 public:
output_vector_adapter(std::vector<CharType> & vec)12648 explicit output_vector_adapter(std::vector<CharType>& vec) noexcept
12649 : v(vec)
12650 {}
12651
write_character(CharType c)12652 void write_character(CharType c) override
12653 {
12654 v.push_back(c);
12655 }
12656
12657 JSON_HEDLEY_NON_NULL(2)
write_characters(const CharType * s,std::size_t length)12658 void write_characters(const CharType* s, std::size_t length) override
12659 {
12660 std::copy(s, s + length, std::back_inserter(v));
12661 }
12662
12663 private:
12664 std::vector<CharType>& v;
12665 };
12666
12667 /// output adapter for output streams
12668 template<typename CharType>
12669 class output_stream_adapter : public output_adapter_protocol<CharType>
12670 {
12671 public:
output_stream_adapter(std::basic_ostream<CharType> & s)12672 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
12673 : stream(s)
12674 {}
12675
write_character(CharType c)12676 void write_character(CharType c) override
12677 {
12678 stream.put(c);
12679 }
12680
12681 JSON_HEDLEY_NON_NULL(2)
write_characters(const CharType * s,std::size_t length)12682 void write_characters(const CharType* s, std::size_t length) override
12683 {
12684 stream.write(s, static_cast<std::streamsize>(length));
12685 }
12686
12687 private:
12688 std::basic_ostream<CharType>& stream;
12689 };
12690
12691 /// output adapter for basic_string
12692 template<typename CharType, typename StringType = std::basic_string<CharType>>
12693 class output_string_adapter : public output_adapter_protocol<CharType>
12694 {
12695 public:
output_string_adapter(StringType & s)12696 explicit output_string_adapter(StringType& s) noexcept
12697 : str(s)
12698 {}
12699
write_character(CharType c)12700 void write_character(CharType c) override
12701 {
12702 str.push_back(c);
12703 }
12704
12705 JSON_HEDLEY_NON_NULL(2)
write_characters(const CharType * s,std::size_t length)12706 void write_characters(const CharType* s, std::size_t length) override
12707 {
12708 str.append(s, length);
12709 }
12710
12711 private:
12712 StringType& str;
12713 };
12714
12715 template<typename CharType, typename StringType = std::basic_string<CharType>>
12716 class output_adapter
12717 {
12718 public:
output_adapter(std::vector<CharType> & vec)12719 output_adapter(std::vector<CharType>& vec)
12720 : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
12721
output_adapter(std::basic_ostream<CharType> & s)12722 output_adapter(std::basic_ostream<CharType>& s)
12723 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
12724
output_adapter(StringType & s)12725 output_adapter(StringType& s)
12726 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
12727
operator output_adapter_t<CharType>()12728 operator output_adapter_t<CharType>()
12729 {
12730 return oa;
12731 }
12732
12733 private:
12734 output_adapter_t<CharType> oa = nullptr;
12735 };
12736 } // namespace detail
12737 } // namespace nlohmann
12738
12739
12740 namespace nlohmann
12741 {
12742 namespace detail
12743 {
12744 ///////////////////
12745 // binary writer //
12746 ///////////////////
12747
12748 /*!
12749 @brief serialization to CBOR and MessagePack values
12750 */
12751 template<typename BasicJsonType, typename CharType>
12752 class binary_writer
12753 {
12754 using string_t = typename BasicJsonType::string_t;
12755 using binary_t = typename BasicJsonType::binary_t;
12756 using number_float_t = typename BasicJsonType::number_float_t;
12757
12758 public:
12759 /*!
12760 @brief create a binary writer
12761
12762 @param[in] adapter output adapter to write to
12763 */
binary_writer(output_adapter_t<CharType> adapter)12764 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
12765 {
12766 JSON_ASSERT(oa);
12767 }
12768
12769 /*!
12770 @param[in] j JSON value to serialize
12771 @pre j.type() == value_t::object
12772 */
write_bson(const BasicJsonType & j)12773 void write_bson(const BasicJsonType& j)
12774 {
12775 switch (j.type())
12776 {
12777 case value_t::object:
12778 {
12779 write_bson_object(*j.m_value.object);
12780 break;
12781 }
12782
12783 default:
12784 {
12785 JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name())));
12786 }
12787 }
12788 }
12789
12790 /*!
12791 @param[in] j JSON value to serialize
12792 */
write_cbor(const BasicJsonType & j)12793 void write_cbor(const BasicJsonType& j)
12794 {
12795 switch (j.type())
12796 {
12797 case value_t::null:
12798 {
12799 oa->write_character(to_char_type(0xF6));
12800 break;
12801 }
12802
12803 case value_t::boolean:
12804 {
12805 oa->write_character(j.m_value.boolean
12806 ? to_char_type(0xF5)
12807 : to_char_type(0xF4));
12808 break;
12809 }
12810
12811 case value_t::number_integer:
12812 {
12813 if (j.m_value.number_integer >= 0)
12814 {
12815 // CBOR does not differentiate between positive signed
12816 // integers and unsigned integers. Therefore, we used the
12817 // code from the value_t::number_unsigned case here.
12818 if (j.m_value.number_integer <= 0x17)
12819 {
12820 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
12821 }
12822 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
12823 {
12824 oa->write_character(to_char_type(0x18));
12825 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
12826 }
12827 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
12828 {
12829 oa->write_character(to_char_type(0x19));
12830 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
12831 }
12832 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
12833 {
12834 oa->write_character(to_char_type(0x1A));
12835 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
12836 }
12837 else
12838 {
12839 oa->write_character(to_char_type(0x1B));
12840 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
12841 }
12842 }
12843 else
12844 {
12845 // The conversions below encode the sign in the first
12846 // byte, and the value is converted to a positive number.
12847 const auto positive_number = -1 - j.m_value.number_integer;
12848 if (j.m_value.number_integer >= -24)
12849 {
12850 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
12851 }
12852 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
12853 {
12854 oa->write_character(to_char_type(0x38));
12855 write_number(static_cast<std::uint8_t>(positive_number));
12856 }
12857 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
12858 {
12859 oa->write_character(to_char_type(0x39));
12860 write_number(static_cast<std::uint16_t>(positive_number));
12861 }
12862 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
12863 {
12864 oa->write_character(to_char_type(0x3A));
12865 write_number(static_cast<std::uint32_t>(positive_number));
12866 }
12867 else
12868 {
12869 oa->write_character(to_char_type(0x3B));
12870 write_number(static_cast<std::uint64_t>(positive_number));
12871 }
12872 }
12873 break;
12874 }
12875
12876 case value_t::number_unsigned:
12877 {
12878 if (j.m_value.number_unsigned <= 0x17)
12879 {
12880 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
12881 }
12882 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
12883 {
12884 oa->write_character(to_char_type(0x18));
12885 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
12886 }
12887 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
12888 {
12889 oa->write_character(to_char_type(0x19));
12890 write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
12891 }
12892 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
12893 {
12894 oa->write_character(to_char_type(0x1A));
12895 write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
12896 }
12897 else
12898 {
12899 oa->write_character(to_char_type(0x1B));
12900 write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
12901 }
12902 break;
12903 }
12904
12905 case value_t::number_float:
12906 {
12907 if (std::isnan(j.m_value.number_float))
12908 {
12909 // NaN is 0xf97e00 in CBOR
12910 oa->write_character(to_char_type(0xF9));
12911 oa->write_character(to_char_type(0x7E));
12912 oa->write_character(to_char_type(0x00));
12913 }
12914 else if (std::isinf(j.m_value.number_float))
12915 {
12916 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
12917 oa->write_character(to_char_type(0xf9));
12918 oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
12919 oa->write_character(to_char_type(0x00));
12920 }
12921 else
12922 {
12923 write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
12924 }
12925 break;
12926 }
12927
12928 case value_t::string:
12929 {
12930 // step 1: write control byte and the string length
12931 const auto N = j.m_value.string->size();
12932 if (N <= 0x17)
12933 {
12934 write_number(static_cast<std::uint8_t>(0x60 + N));
12935 }
12936 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
12937 {
12938 oa->write_character(to_char_type(0x78));
12939 write_number(static_cast<std::uint8_t>(N));
12940 }
12941 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
12942 {
12943 oa->write_character(to_char_type(0x79));
12944 write_number(static_cast<std::uint16_t>(N));
12945 }
12946 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
12947 {
12948 oa->write_character(to_char_type(0x7A));
12949 write_number(static_cast<std::uint32_t>(N));
12950 }
12951 // LCOV_EXCL_START
12952 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
12953 {
12954 oa->write_character(to_char_type(0x7B));
12955 write_number(static_cast<std::uint64_t>(N));
12956 }
12957 // LCOV_EXCL_STOP
12958
12959 // step 2: write the string
12960 oa->write_characters(
12961 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
12962 j.m_value.string->size());
12963 break;
12964 }
12965
12966 case value_t::array:
12967 {
12968 // step 1: write control byte and the array size
12969 const auto N = j.m_value.array->size();
12970 if (N <= 0x17)
12971 {
12972 write_number(static_cast<std::uint8_t>(0x80 + N));
12973 }
12974 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
12975 {
12976 oa->write_character(to_char_type(0x98));
12977 write_number(static_cast<std::uint8_t>(N));
12978 }
12979 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
12980 {
12981 oa->write_character(to_char_type(0x99));
12982 write_number(static_cast<std::uint16_t>(N));
12983 }
12984 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
12985 {
12986 oa->write_character(to_char_type(0x9A));
12987 write_number(static_cast<std::uint32_t>(N));
12988 }
12989 // LCOV_EXCL_START
12990 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
12991 {
12992 oa->write_character(to_char_type(0x9B));
12993 write_number(static_cast<std::uint64_t>(N));
12994 }
12995 // LCOV_EXCL_STOP
12996
12997 // step 2: write each element
12998 for (const auto& el : *j.m_value.array)
12999 {
13000 write_cbor(el);
13001 }
13002 break;
13003 }
13004
13005 case value_t::binary:
13006 {
13007 if (j.m_value.binary->has_subtype())
13008 {
13009 write_number(static_cast<std::uint8_t>(0xd8));
13010 write_number(j.m_value.binary->subtype());
13011 }
13012
13013 // step 1: write control byte and the binary array size
13014 const auto N = j.m_value.binary->size();
13015 if (N <= 0x17)
13016 {
13017 write_number(static_cast<std::uint8_t>(0x40 + N));
13018 }
13019 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13020 {
13021 oa->write_character(to_char_type(0x58));
13022 write_number(static_cast<std::uint8_t>(N));
13023 }
13024 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13025 {
13026 oa->write_character(to_char_type(0x59));
13027 write_number(static_cast<std::uint16_t>(N));
13028 }
13029 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13030 {
13031 oa->write_character(to_char_type(0x5A));
13032 write_number(static_cast<std::uint32_t>(N));
13033 }
13034 // LCOV_EXCL_START
13035 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13036 {
13037 oa->write_character(to_char_type(0x5B));
13038 write_number(static_cast<std::uint64_t>(N));
13039 }
13040 // LCOV_EXCL_STOP
13041
13042 // step 2: write each element
13043 oa->write_characters(
13044 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13045 N);
13046
13047 break;
13048 }
13049
13050 case value_t::object:
13051 {
13052 // step 1: write control byte and the object size
13053 const auto N = j.m_value.object->size();
13054 if (N <= 0x17)
13055 {
13056 write_number(static_cast<std::uint8_t>(0xA0 + N));
13057 }
13058 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13059 {
13060 oa->write_character(to_char_type(0xB8));
13061 write_number(static_cast<std::uint8_t>(N));
13062 }
13063 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13064 {
13065 oa->write_character(to_char_type(0xB9));
13066 write_number(static_cast<std::uint16_t>(N));
13067 }
13068 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13069 {
13070 oa->write_character(to_char_type(0xBA));
13071 write_number(static_cast<std::uint32_t>(N));
13072 }
13073 // LCOV_EXCL_START
13074 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
13075 {
13076 oa->write_character(to_char_type(0xBB));
13077 write_number(static_cast<std::uint64_t>(N));
13078 }
13079 // LCOV_EXCL_STOP
13080
13081 // step 2: write each element
13082 for (const auto& el : *j.m_value.object)
13083 {
13084 write_cbor(el.first);
13085 write_cbor(el.second);
13086 }
13087 break;
13088 }
13089
13090 default:
13091 break;
13092 }
13093 }
13094
13095 /*!
13096 @param[in] j JSON value to serialize
13097 */
write_msgpack(const BasicJsonType & j)13098 void write_msgpack(const BasicJsonType& j)
13099 {
13100 switch (j.type())
13101 {
13102 case value_t::null: // nil
13103 {
13104 oa->write_character(to_char_type(0xC0));
13105 break;
13106 }
13107
13108 case value_t::boolean: // true and false
13109 {
13110 oa->write_character(j.m_value.boolean
13111 ? to_char_type(0xC3)
13112 : to_char_type(0xC2));
13113 break;
13114 }
13115
13116 case value_t::number_integer:
13117 {
13118 if (j.m_value.number_integer >= 0)
13119 {
13120 // MessagePack does not differentiate between positive
13121 // signed integers and unsigned integers. Therefore, we used
13122 // the code from the value_t::number_unsigned case here.
13123 if (j.m_value.number_unsigned < 128)
13124 {
13125 // positive fixnum
13126 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13127 }
13128 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
13129 {
13130 // uint 8
13131 oa->write_character(to_char_type(0xCC));
13132 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13133 }
13134 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
13135 {
13136 // uint 16
13137 oa->write_character(to_char_type(0xCD));
13138 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13139 }
13140 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
13141 {
13142 // uint 32
13143 oa->write_character(to_char_type(0xCE));
13144 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13145 }
13146 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
13147 {
13148 // uint 64
13149 oa->write_character(to_char_type(0xCF));
13150 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13151 }
13152 }
13153 else
13154 {
13155 if (j.m_value.number_integer >= -32)
13156 {
13157 // negative fixnum
13158 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
13159 }
13160 else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
13161 j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
13162 {
13163 // int 8
13164 oa->write_character(to_char_type(0xD0));
13165 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
13166 }
13167 else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
13168 j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
13169 {
13170 // int 16
13171 oa->write_character(to_char_type(0xD1));
13172 write_number(static_cast<std::int16_t>(j.m_value.number_integer));
13173 }
13174 else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
13175 j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
13176 {
13177 // int 32
13178 oa->write_character(to_char_type(0xD2));
13179 write_number(static_cast<std::int32_t>(j.m_value.number_integer));
13180 }
13181 else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
13182 j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
13183 {
13184 // int 64
13185 oa->write_character(to_char_type(0xD3));
13186 write_number(static_cast<std::int64_t>(j.m_value.number_integer));
13187 }
13188 }
13189 break;
13190 }
13191
13192 case value_t::number_unsigned:
13193 {
13194 if (j.m_value.number_unsigned < 128)
13195 {
13196 // positive fixnum
13197 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13198 }
13199 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
13200 {
13201 // uint 8
13202 oa->write_character(to_char_type(0xCC));
13203 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
13204 }
13205 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
13206 {
13207 // uint 16
13208 oa->write_character(to_char_type(0xCD));
13209 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
13210 }
13211 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
13212 {
13213 // uint 32
13214 oa->write_character(to_char_type(0xCE));
13215 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
13216 }
13217 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
13218 {
13219 // uint 64
13220 oa->write_character(to_char_type(0xCF));
13221 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
13222 }
13223 break;
13224 }
13225
13226 case value_t::number_float:
13227 {
13228 write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
13229 break;
13230 }
13231
13232 case value_t::string:
13233 {
13234 // step 1: write control byte and the string length
13235 const auto N = j.m_value.string->size();
13236 if (N <= 31)
13237 {
13238 // fixstr
13239 write_number(static_cast<std::uint8_t>(0xA0 | N));
13240 }
13241 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
13242 {
13243 // str 8
13244 oa->write_character(to_char_type(0xD9));
13245 write_number(static_cast<std::uint8_t>(N));
13246 }
13247 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13248 {
13249 // str 16
13250 oa->write_character(to_char_type(0xDA));
13251 write_number(static_cast<std::uint16_t>(N));
13252 }
13253 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13254 {
13255 // str 32
13256 oa->write_character(to_char_type(0xDB));
13257 write_number(static_cast<std::uint32_t>(N));
13258 }
13259
13260 // step 2: write the string
13261 oa->write_characters(
13262 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
13263 j.m_value.string->size());
13264 break;
13265 }
13266
13267 case value_t::array:
13268 {
13269 // step 1: write control byte and the array size
13270 const auto N = j.m_value.array->size();
13271 if (N <= 15)
13272 {
13273 // fixarray
13274 write_number(static_cast<std::uint8_t>(0x90 | N));
13275 }
13276 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13277 {
13278 // array 16
13279 oa->write_character(to_char_type(0xDC));
13280 write_number(static_cast<std::uint16_t>(N));
13281 }
13282 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13283 {
13284 // array 32
13285 oa->write_character(to_char_type(0xDD));
13286 write_number(static_cast<std::uint32_t>(N));
13287 }
13288
13289 // step 2: write each element
13290 for (const auto& el : *j.m_value.array)
13291 {
13292 write_msgpack(el);
13293 }
13294 break;
13295 }
13296
13297 case value_t::binary:
13298 {
13299 // step 0: determine if the binary type has a set subtype to
13300 // determine whether or not to use the ext or fixext types
13301 const bool use_ext = j.m_value.binary->has_subtype();
13302
13303 // step 1: write control byte and the byte string length
13304 const auto N = j.m_value.binary->size();
13305 if (N <= (std::numeric_limits<std::uint8_t>::max)())
13306 {
13307 std::uint8_t output_type{};
13308 bool fixed = true;
13309 if (use_ext)
13310 {
13311 switch (N)
13312 {
13313 case 1:
13314 output_type = 0xD4; // fixext 1
13315 break;
13316 case 2:
13317 output_type = 0xD5; // fixext 2
13318 break;
13319 case 4:
13320 output_type = 0xD6; // fixext 4
13321 break;
13322 case 8:
13323 output_type = 0xD7; // fixext 8
13324 break;
13325 case 16:
13326 output_type = 0xD8; // fixext 16
13327 break;
13328 default:
13329 output_type = 0xC7; // ext 8
13330 fixed = false;
13331 break;
13332 }
13333
13334 }
13335 else
13336 {
13337 output_type = 0xC4; // bin 8
13338 fixed = false;
13339 }
13340
13341 oa->write_character(to_char_type(output_type));
13342 if (!fixed)
13343 {
13344 write_number(static_cast<std::uint8_t>(N));
13345 }
13346 }
13347 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13348 {
13349 std::uint8_t output_type = use_ext
13350 ? 0xC8 // ext 16
13351 : 0xC5; // bin 16
13352
13353 oa->write_character(to_char_type(output_type));
13354 write_number(static_cast<std::uint16_t>(N));
13355 }
13356 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13357 {
13358 std::uint8_t output_type = use_ext
13359 ? 0xC9 // ext 32
13360 : 0xC6; // bin 32
13361
13362 oa->write_character(to_char_type(output_type));
13363 write_number(static_cast<std::uint32_t>(N));
13364 }
13365
13366 // step 1.5: if this is an ext type, write the subtype
13367 if (use_ext)
13368 {
13369 write_number(static_cast<std::int8_t>(j.m_value.binary->subtype()));
13370 }
13371
13372 // step 2: write the byte string
13373 oa->write_characters(
13374 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13375 N);
13376
13377 break;
13378 }
13379
13380 case value_t::object:
13381 {
13382 // step 1: write control byte and the object size
13383 const auto N = j.m_value.object->size();
13384 if (N <= 15)
13385 {
13386 // fixmap
13387 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
13388 }
13389 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
13390 {
13391 // map 16
13392 oa->write_character(to_char_type(0xDE));
13393 write_number(static_cast<std::uint16_t>(N));
13394 }
13395 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
13396 {
13397 // map 32
13398 oa->write_character(to_char_type(0xDF));
13399 write_number(static_cast<std::uint32_t>(N));
13400 }
13401
13402 // step 2: write each element
13403 for (const auto& el : *j.m_value.object)
13404 {
13405 write_msgpack(el.first);
13406 write_msgpack(el.second);
13407 }
13408 break;
13409 }
13410
13411 default:
13412 break;
13413 }
13414 }
13415
13416 /*!
13417 @param[in] j JSON value to serialize
13418 @param[in] use_count whether to use '#' prefixes (optimized format)
13419 @param[in] use_type whether to use '$' prefixes (optimized format)
13420 @param[in] add_prefix whether prefixes need to be used for this value
13421 */
write_ubjson(const BasicJsonType & j,const bool use_count,const bool use_type,const bool add_prefix=true)13422 void write_ubjson(const BasicJsonType& j, const bool use_count,
13423 const bool use_type, const bool add_prefix = true)
13424 {
13425 switch (j.type())
13426 {
13427 case value_t::null:
13428 {
13429 if (add_prefix)
13430 {
13431 oa->write_character(to_char_type('Z'));
13432 }
13433 break;
13434 }
13435
13436 case value_t::boolean:
13437 {
13438 if (add_prefix)
13439 {
13440 oa->write_character(j.m_value.boolean
13441 ? to_char_type('T')
13442 : to_char_type('F'));
13443 }
13444 break;
13445 }
13446
13447 case value_t::number_integer:
13448 {
13449 write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
13450 break;
13451 }
13452
13453 case value_t::number_unsigned:
13454 {
13455 write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
13456 break;
13457 }
13458
13459 case value_t::number_float:
13460 {
13461 write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
13462 break;
13463 }
13464
13465 case value_t::string:
13466 {
13467 if (add_prefix)
13468 {
13469 oa->write_character(to_char_type('S'));
13470 }
13471 write_number_with_ubjson_prefix(j.m_value.string->size(), true);
13472 oa->write_characters(
13473 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
13474 j.m_value.string->size());
13475 break;
13476 }
13477
13478 case value_t::array:
13479 {
13480 if (add_prefix)
13481 {
13482 oa->write_character(to_char_type('['));
13483 }
13484
13485 bool prefix_required = true;
13486 if (use_type && !j.m_value.array->empty())
13487 {
13488 JSON_ASSERT(use_count);
13489 const CharType first_prefix = ubjson_prefix(j.front());
13490 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
13491 [this, first_prefix](const BasicJsonType & v)
13492 {
13493 return ubjson_prefix(v) == first_prefix;
13494 });
13495
13496 if (same_prefix)
13497 {
13498 prefix_required = false;
13499 oa->write_character(to_char_type('$'));
13500 oa->write_character(first_prefix);
13501 }
13502 }
13503
13504 if (use_count)
13505 {
13506 oa->write_character(to_char_type('#'));
13507 write_number_with_ubjson_prefix(j.m_value.array->size(), true);
13508 }
13509
13510 for (const auto& el : *j.m_value.array)
13511 {
13512 write_ubjson(el, use_count, use_type, prefix_required);
13513 }
13514
13515 if (!use_count)
13516 {
13517 oa->write_character(to_char_type(']'));
13518 }
13519
13520 break;
13521 }
13522
13523 case value_t::binary:
13524 {
13525 if (add_prefix)
13526 {
13527 oa->write_character(to_char_type('['));
13528 }
13529
13530 if (use_type && !j.m_value.binary->empty())
13531 {
13532 JSON_ASSERT(use_count);
13533 oa->write_character(to_char_type('$'));
13534 oa->write_character('U');
13535 }
13536
13537 if (use_count)
13538 {
13539 oa->write_character(to_char_type('#'));
13540 write_number_with_ubjson_prefix(j.m_value.binary->size(), true);
13541 }
13542
13543 if (use_type)
13544 {
13545 oa->write_characters(
13546 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
13547 j.m_value.binary->size());
13548 }
13549 else
13550 {
13551 for (size_t i = 0; i < j.m_value.binary->size(); ++i)
13552 {
13553 oa->write_character(to_char_type('U'));
13554 oa->write_character(j.m_value.binary->data()[i]);
13555 }
13556 }
13557
13558 if (!use_count)
13559 {
13560 oa->write_character(to_char_type(']'));
13561 }
13562
13563 break;
13564 }
13565
13566 case value_t::object:
13567 {
13568 if (add_prefix)
13569 {
13570 oa->write_character(to_char_type('{'));
13571 }
13572
13573 bool prefix_required = true;
13574 if (use_type && !j.m_value.object->empty())
13575 {
13576 JSON_ASSERT(use_count);
13577 const CharType first_prefix = ubjson_prefix(j.front());
13578 const bool same_prefix = std::all_of(j.begin(), j.end(),
13579 [this, first_prefix](const BasicJsonType & v)
13580 {
13581 return ubjson_prefix(v) == first_prefix;
13582 });
13583
13584 if (same_prefix)
13585 {
13586 prefix_required = false;
13587 oa->write_character(to_char_type('$'));
13588 oa->write_character(first_prefix);
13589 }
13590 }
13591
13592 if (use_count)
13593 {
13594 oa->write_character(to_char_type('#'));
13595 write_number_with_ubjson_prefix(j.m_value.object->size(), true);
13596 }
13597
13598 for (const auto& el : *j.m_value.object)
13599 {
13600 write_number_with_ubjson_prefix(el.first.size(), true);
13601 oa->write_characters(
13602 reinterpret_cast<const CharType*>(el.first.c_str()),
13603 el.first.size());
13604 write_ubjson(el.second, use_count, use_type, prefix_required);
13605 }
13606
13607 if (!use_count)
13608 {
13609 oa->write_character(to_char_type('}'));
13610 }
13611
13612 break;
13613 }
13614
13615 default:
13616 break;
13617 }
13618 }
13619
13620 private:
13621 //////////
13622 // BSON //
13623 //////////
13624
13625 /*!
13626 @return The size of a BSON document entry header, including the id marker
13627 and the entry name size (and its null-terminator).
13628 */
calc_bson_entry_header_size(const string_t & name)13629 static std::size_t calc_bson_entry_header_size(const string_t& name)
13630 {
13631 const auto it = name.find(static_cast<typename string_t::value_type>(0));
13632 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
13633 {
13634 JSON_THROW(out_of_range::create(409,
13635 "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")"));
13636 }
13637
13638 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
13639 }
13640
13641 /*!
13642 @brief Writes the given @a element_type and @a name to the output adapter
13643 */
write_bson_entry_header(const string_t & name,const std::uint8_t element_type)13644 void write_bson_entry_header(const string_t& name,
13645 const std::uint8_t element_type)
13646 {
13647 oa->write_character(to_char_type(element_type)); // boolean
13648 oa->write_characters(
13649 reinterpret_cast<const CharType*>(name.c_str()),
13650 name.size() + 1u);
13651 }
13652
13653 /*!
13654 @brief Writes a BSON element with key @a name and boolean value @a value
13655 */
write_bson_boolean(const string_t & name,const bool value)13656 void write_bson_boolean(const string_t& name,
13657 const bool value)
13658 {
13659 write_bson_entry_header(name, 0x08);
13660 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
13661 }
13662
13663 /*!
13664 @brief Writes a BSON element with key @a name and double value @a value
13665 */
write_bson_double(const string_t & name,const double value)13666 void write_bson_double(const string_t& name,
13667 const double value)
13668 {
13669 write_bson_entry_header(name, 0x01);
13670 write_number<double, true>(value);
13671 }
13672
13673 /*!
13674 @return The size of the BSON-encoded string in @a value
13675 */
calc_bson_string_size(const string_t & value)13676 static std::size_t calc_bson_string_size(const string_t& value)
13677 {
13678 return sizeof(std::int32_t) + value.size() + 1ul;
13679 }
13680
13681 /*!
13682 @brief Writes a BSON element with key @a name and string value @a value
13683 */
write_bson_string(const string_t & name,const string_t & value)13684 void write_bson_string(const string_t& name,
13685 const string_t& value)
13686 {
13687 write_bson_entry_header(name, 0x02);
13688
13689 write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
13690 oa->write_characters(
13691 reinterpret_cast<const CharType*>(value.c_str()),
13692 value.size() + 1);
13693 }
13694
13695 /*!
13696 @brief Writes a BSON element with key @a name and null value
13697 */
write_bson_null(const string_t & name)13698 void write_bson_null(const string_t& name)
13699 {
13700 write_bson_entry_header(name, 0x0A);
13701 }
13702
13703 /*!
13704 @return The size of the BSON-encoded integer @a value
13705 */
calc_bson_integer_size(const std::int64_t value)13706 static std::size_t calc_bson_integer_size(const std::int64_t value)
13707 {
13708 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
13709 ? sizeof(std::int32_t)
13710 : sizeof(std::int64_t);
13711 }
13712
13713 /*!
13714 @brief Writes a BSON element with key @a name and integer @a value
13715 */
write_bson_integer(const string_t & name,const std::int64_t value)13716 void write_bson_integer(const string_t& name,
13717 const std::int64_t value)
13718 {
13719 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
13720 {
13721 write_bson_entry_header(name, 0x10); // int32
13722 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
13723 }
13724 else
13725 {
13726 write_bson_entry_header(name, 0x12); // int64
13727 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
13728 }
13729 }
13730
13731 /*!
13732 @return The size of the BSON-encoded unsigned integer in @a j
13733 */
calc_bson_unsigned_size(const std::uint64_t value)13734 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
13735 {
13736 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
13737 ? sizeof(std::int32_t)
13738 : sizeof(std::int64_t);
13739 }
13740
13741 /*!
13742 @brief Writes a BSON element with key @a name and unsigned @a value
13743 */
write_bson_unsigned(const string_t & name,const std::uint64_t value)13744 void write_bson_unsigned(const string_t& name,
13745 const std::uint64_t value)
13746 {
13747 if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
13748 {
13749 write_bson_entry_header(name, 0x10 /* int32 */);
13750 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
13751 }
13752 else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
13753 {
13754 write_bson_entry_header(name, 0x12 /* int64 */);
13755 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
13756 }
13757 else
13758 {
13759 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64"));
13760 }
13761 }
13762
13763 /*!
13764 @brief Writes a BSON element with key @a name and object @a value
13765 */
write_bson_object_entry(const string_t & name,const typename BasicJsonType::object_t & value)13766 void write_bson_object_entry(const string_t& name,
13767 const typename BasicJsonType::object_t& value)
13768 {
13769 write_bson_entry_header(name, 0x03); // object
13770 write_bson_object(value);
13771 }
13772
13773 /*!
13774 @return The size of the BSON-encoded array @a value
13775 */
calc_bson_array_size(const typename BasicJsonType::array_t & value)13776 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
13777 {
13778 std::size_t array_index = 0ul;
13779
13780 const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), std::size_t(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
13781 {
13782 return result + calc_bson_element_size(std::to_string(array_index++), el);
13783 });
13784
13785 return sizeof(std::int32_t) + embedded_document_size + 1ul;
13786 }
13787
13788 /*!
13789 @return The size of the BSON-encoded binary array @a value
13790 */
calc_bson_binary_size(const typename BasicJsonType::binary_t & value)13791 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
13792 {
13793 return sizeof(std::int32_t) + value.size() + 1ul;
13794 }
13795
13796 /*!
13797 @brief Writes a BSON element with key @a name and array @a value
13798 */
write_bson_array(const string_t & name,const typename BasicJsonType::array_t & value)13799 void write_bson_array(const string_t& name,
13800 const typename BasicJsonType::array_t& value)
13801 {
13802 write_bson_entry_header(name, 0x04); // array
13803 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
13804
13805 std::size_t array_index = 0ul;
13806
13807 for (const auto& el : value)
13808 {
13809 write_bson_element(std::to_string(array_index++), el);
13810 }
13811
13812 oa->write_character(to_char_type(0x00));
13813 }
13814
13815 /*!
13816 @brief Writes a BSON element with key @a name and binary value @a value
13817 */
write_bson_binary(const string_t & name,const binary_t & value)13818 void write_bson_binary(const string_t& name,
13819 const binary_t& value)
13820 {
13821 write_bson_entry_header(name, 0x05);
13822
13823 write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
13824 write_number(value.has_subtype() ? value.subtype() : std::uint8_t(0x00));
13825
13826 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
13827 }
13828
13829 /*!
13830 @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
13831 @return The calculated size for the BSON document entry for @a j with the given @a name.
13832 */
calc_bson_element_size(const string_t & name,const BasicJsonType & j)13833 static std::size_t calc_bson_element_size(const string_t& name,
13834 const BasicJsonType& j)
13835 {
13836 const auto header_size = calc_bson_entry_header_size(name);
13837 switch (j.type())
13838 {
13839 case value_t::object:
13840 return header_size + calc_bson_object_size(*j.m_value.object);
13841
13842 case value_t::array:
13843 return header_size + calc_bson_array_size(*j.m_value.array);
13844
13845 case value_t::binary:
13846 return header_size + calc_bson_binary_size(*j.m_value.binary);
13847
13848 case value_t::boolean:
13849 return header_size + 1ul;
13850
13851 case value_t::number_float:
13852 return header_size + 8ul;
13853
13854 case value_t::number_integer:
13855 return header_size + calc_bson_integer_size(j.m_value.number_integer);
13856
13857 case value_t::number_unsigned:
13858 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
13859
13860 case value_t::string:
13861 return header_size + calc_bson_string_size(*j.m_value.string);
13862
13863 case value_t::null:
13864 return header_size + 0ul;
13865
13866 // LCOV_EXCL_START
13867 default:
13868 JSON_ASSERT(false);
13869 return 0ul;
13870 // LCOV_EXCL_STOP
13871 }
13872 }
13873
13874 /*!
13875 @brief Serializes the JSON value @a j to BSON and associates it with the
13876 key @a name.
13877 @param name The name to associate with the JSON entity @a j within the
13878 current BSON document
13879 @return The size of the BSON entry
13880 */
write_bson_element(const string_t & name,const BasicJsonType & j)13881 void write_bson_element(const string_t& name,
13882 const BasicJsonType& j)
13883 {
13884 switch (j.type())
13885 {
13886 case value_t::object:
13887 return write_bson_object_entry(name, *j.m_value.object);
13888
13889 case value_t::array:
13890 return write_bson_array(name, *j.m_value.array);
13891
13892 case value_t::binary:
13893 return write_bson_binary(name, *j.m_value.binary);
13894
13895 case value_t::boolean:
13896 return write_bson_boolean(name, j.m_value.boolean);
13897
13898 case value_t::number_float:
13899 return write_bson_double(name, j.m_value.number_float);
13900
13901 case value_t::number_integer:
13902 return write_bson_integer(name, j.m_value.number_integer);
13903
13904 case value_t::number_unsigned:
13905 return write_bson_unsigned(name, j.m_value.number_unsigned);
13906
13907 case value_t::string:
13908 return write_bson_string(name, *j.m_value.string);
13909
13910 case value_t::null:
13911 return write_bson_null(name);
13912
13913 // LCOV_EXCL_START
13914 default:
13915 JSON_ASSERT(false);
13916 return;
13917 // LCOV_EXCL_STOP
13918 }
13919 }
13920
13921 /*!
13922 @brief Calculates the size of the BSON serialization of the given
13923 JSON-object @a j.
13924 @param[in] j JSON value to serialize
13925 @pre j.type() == value_t::object
13926 */
calc_bson_object_size(const typename BasicJsonType::object_t & value)13927 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
13928 {
13929 std::size_t document_size = std::accumulate(value.begin(), value.end(), std::size_t(0),
13930 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
13931 {
13932 return result += calc_bson_element_size(el.first, el.second);
13933 });
13934
13935 return sizeof(std::int32_t) + document_size + 1ul;
13936 }
13937
13938 /*!
13939 @param[in] j JSON value to serialize
13940 @pre j.type() == value_t::object
13941 */
write_bson_object(const typename BasicJsonType::object_t & value)13942 void write_bson_object(const typename BasicJsonType::object_t& value)
13943 {
13944 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
13945
13946 for (const auto& el : value)
13947 {
13948 write_bson_element(el.first, el.second);
13949 }
13950
13951 oa->write_character(to_char_type(0x00));
13952 }
13953
13954 //////////
13955 // CBOR //
13956 //////////
13957
get_cbor_float_prefix(float)13958 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
13959 {
13960 return to_char_type(0xFA); // Single-Precision Float
13961 }
13962
get_cbor_float_prefix(double)13963 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
13964 {
13965 return to_char_type(0xFB); // Double-Precision Float
13966 }
13967
13968 /////////////
13969 // MsgPack //
13970 /////////////
13971
get_msgpack_float_prefix(float)13972 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
13973 {
13974 return to_char_type(0xCA); // float 32
13975 }
13976
get_msgpack_float_prefix(double)13977 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
13978 {
13979 return to_char_type(0xCB); // float 64
13980 }
13981
13982 ////////////
13983 // UBJSON //
13984 ////////////
13985
13986 // UBJSON: write number (floating point)
13987 template<typename NumberType, typename std::enable_if<
13988 std::is_floating_point<NumberType>::value, int>::type = 0>
write_number_with_ubjson_prefix(const NumberType n,const bool add_prefix)13989 void write_number_with_ubjson_prefix(const NumberType n,
13990 const bool add_prefix)
13991 {
13992 if (add_prefix)
13993 {
13994 oa->write_character(get_ubjson_float_prefix(n));
13995 }
13996 write_number(n);
13997 }
13998
13999 // UBJSON: write number (unsigned integer)
14000 template<typename NumberType, typename std::enable_if<
14001 std::is_unsigned<NumberType>::value, int>::type = 0>
write_number_with_ubjson_prefix(const NumberType n,const bool add_prefix)14002 void write_number_with_ubjson_prefix(const NumberType n,
14003 const bool add_prefix)
14004 {
14005 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
14006 {
14007 if (add_prefix)
14008 {
14009 oa->write_character(to_char_type('i')); // int8
14010 }
14011 write_number(static_cast<std::uint8_t>(n));
14012 }
14013 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
14014 {
14015 if (add_prefix)
14016 {
14017 oa->write_character(to_char_type('U')); // uint8
14018 }
14019 write_number(static_cast<std::uint8_t>(n));
14020 }
14021 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
14022 {
14023 if (add_prefix)
14024 {
14025 oa->write_character(to_char_type('I')); // int16
14026 }
14027 write_number(static_cast<std::int16_t>(n));
14028 }
14029 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14030 {
14031 if (add_prefix)
14032 {
14033 oa->write_character(to_char_type('l')); // int32
14034 }
14035 write_number(static_cast<std::int32_t>(n));
14036 }
14037 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14038 {
14039 if (add_prefix)
14040 {
14041 oa->write_character(to_char_type('L')); // int64
14042 }
14043 write_number(static_cast<std::int64_t>(n));
14044 }
14045 else
14046 {
14047 if (add_prefix)
14048 {
14049 oa->write_character(to_char_type('H')); // high-precision number
14050 }
14051
14052 const auto number = BasicJsonType(n).dump();
14053 write_number_with_ubjson_prefix(number.size(), true);
14054 for (std::size_t i = 0; i < number.size(); ++i)
14055 {
14056 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
14057 }
14058 }
14059 }
14060
14061 // UBJSON: write number (signed integer)
14062 template < typename NumberType, typename std::enable_if <
14063 std::is_signed<NumberType>::value&&
14064 !std::is_floating_point<NumberType>::value, int >::type = 0 >
write_number_with_ubjson_prefix(const NumberType n,const bool add_prefix)14065 void write_number_with_ubjson_prefix(const NumberType n,
14066 const bool add_prefix)
14067 {
14068 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
14069 {
14070 if (add_prefix)
14071 {
14072 oa->write_character(to_char_type('i')); // int8
14073 }
14074 write_number(static_cast<std::int8_t>(n));
14075 }
14076 else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
14077 {
14078 if (add_prefix)
14079 {
14080 oa->write_character(to_char_type('U')); // uint8
14081 }
14082 write_number(static_cast<std::uint8_t>(n));
14083 }
14084 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
14085 {
14086 if (add_prefix)
14087 {
14088 oa->write_character(to_char_type('I')); // int16
14089 }
14090 write_number(static_cast<std::int16_t>(n));
14091 }
14092 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
14093 {
14094 if (add_prefix)
14095 {
14096 oa->write_character(to_char_type('l')); // int32
14097 }
14098 write_number(static_cast<std::int32_t>(n));
14099 }
14100 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
14101 {
14102 if (add_prefix)
14103 {
14104 oa->write_character(to_char_type('L')); // int64
14105 }
14106 write_number(static_cast<std::int64_t>(n));
14107 }
14108 // LCOV_EXCL_START
14109 else
14110 {
14111 if (add_prefix)
14112 {
14113 oa->write_character(to_char_type('H')); // high-precision number
14114 }
14115
14116 const auto number = BasicJsonType(n).dump();
14117 write_number_with_ubjson_prefix(number.size(), true);
14118 for (std::size_t i = 0; i < number.size(); ++i)
14119 {
14120 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
14121 }
14122 }
14123 // LCOV_EXCL_STOP
14124 }
14125
14126 /*!
14127 @brief determine the type prefix of container values
14128 */
ubjson_prefix(const BasicJsonType & j) const14129 CharType ubjson_prefix(const BasicJsonType& j) const noexcept
14130 {
14131 switch (j.type())
14132 {
14133 case value_t::null:
14134 return 'Z';
14135
14136 case value_t::boolean:
14137 return j.m_value.boolean ? 'T' : 'F';
14138
14139 case value_t::number_integer:
14140 {
14141 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
14142 {
14143 return 'i';
14144 }
14145 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
14146 {
14147 return 'U';
14148 }
14149 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
14150 {
14151 return 'I';
14152 }
14153 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
14154 {
14155 return 'l';
14156 }
14157 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
14158 {
14159 return 'L';
14160 }
14161 // anything else is treated as high-precision number
14162 return 'H'; // LCOV_EXCL_LINE
14163 }
14164
14165 case value_t::number_unsigned:
14166 {
14167 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
14168 {
14169 return 'i';
14170 }
14171 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
14172 {
14173 return 'U';
14174 }
14175 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
14176 {
14177 return 'I';
14178 }
14179 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
14180 {
14181 return 'l';
14182 }
14183 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
14184 {
14185 return 'L';
14186 }
14187 // anything else is treated as high-precision number
14188 return 'H'; // LCOV_EXCL_LINE
14189 }
14190
14191 case value_t::number_float:
14192 return get_ubjson_float_prefix(j.m_value.number_float);
14193
14194 case value_t::string:
14195 return 'S';
14196
14197 case value_t::array: // fallthrough
14198 case value_t::binary:
14199 return '[';
14200
14201 case value_t::object:
14202 return '{';
14203
14204 default: // discarded values
14205 return 'N';
14206 }
14207 }
14208
get_ubjson_float_prefix(float)14209 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
14210 {
14211 return 'd'; // float 32
14212 }
14213
get_ubjson_float_prefix(double)14214 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
14215 {
14216 return 'D'; // float 64
14217 }
14218
14219 ///////////////////////
14220 // Utility functions //
14221 ///////////////////////
14222
14223 /*
14224 @brief write a number to output input
14225 @param[in] n number of type @a NumberType
14226 @tparam NumberType the type of the number
14227 @tparam OutputIsLittleEndian Set to true if output data is
14228 required to be little endian
14229
14230 @note This function needs to respect the system's endianess, because bytes
14231 in CBOR, MessagePack, and UBJSON are stored in network order (big
14232 endian) and therefore need reordering on little endian systems.
14233 */
14234 template<typename NumberType, bool OutputIsLittleEndian = false>
write_number(const NumberType n)14235 void write_number(const NumberType n)
14236 {
14237 // step 1: write number to array of length NumberType
14238 std::array<CharType, sizeof(NumberType)> vec;
14239 std::memcpy(vec.data(), &n, sizeof(NumberType));
14240
14241 // step 2: write array to output (with possible reordering)
14242 if (is_little_endian != OutputIsLittleEndian)
14243 {
14244 // reverse byte order prior to conversion if necessary
14245 std::reverse(vec.begin(), vec.end());
14246 }
14247
14248 oa->write_characters(vec.data(), sizeof(NumberType));
14249 }
14250
write_compact_float(const number_float_t n,detail::input_format_t format)14251 void write_compact_float(const number_float_t n, detail::input_format_t format)
14252 {
14253 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
14254 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
14255 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
14256 {
14257 oa->write_character(format == detail::input_format_t::cbor
14258 ? get_cbor_float_prefix(static_cast<float>(n))
14259 : get_msgpack_float_prefix(static_cast<float>(n)));
14260 write_number(static_cast<float>(n));
14261 }
14262 else
14263 {
14264 oa->write_character(format == detail::input_format_t::cbor
14265 ? get_cbor_float_prefix(n)
14266 : get_msgpack_float_prefix(n));
14267 write_number(n);
14268 }
14269 }
14270
14271 public:
14272 // The following to_char_type functions are implement the conversion
14273 // between uint8_t and CharType. In case CharType is not unsigned,
14274 // such a conversion is required to allow values greater than 128.
14275 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
14276 template < typename C = CharType,
14277 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
to_char_type(std::uint8_t x)14278 static constexpr CharType to_char_type(std::uint8_t x) noexcept
14279 {
14280 return *reinterpret_cast<char*>(&x);
14281 }
14282
14283 template < typename C = CharType,
14284 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
to_char_type(std::uint8_t x)14285 static CharType to_char_type(std::uint8_t x) noexcept
14286 {
14287 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
14288 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
14289 CharType result;
14290 std::memcpy(&result, &x, sizeof(x));
14291 return result;
14292 }
14293
14294 template<typename C = CharType,
14295 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
to_char_type(std::uint8_t x)14296 static constexpr CharType to_char_type(std::uint8_t x) noexcept
14297 {
14298 return x;
14299 }
14300
14301 template < typename InputCharType, typename C = CharType,
14302 enable_if_t <
14303 std::is_signed<C>::value &&
14304 std::is_signed<char>::value &&
14305 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
14306 > * = nullptr >
to_char_type(InputCharType x)14307 static constexpr CharType to_char_type(InputCharType x) noexcept
14308 {
14309 return x;
14310 }
14311
14312 private:
14313 /// whether we can assume little endianess
14314 const bool is_little_endian = little_endianess();
14315
14316 /// the output
14317 output_adapter_t<CharType> oa = nullptr;
14318 };
14319 } // namespace detail
14320 } // namespace nlohmann
14321
14322 // #include <nlohmann/detail/output/output_adapters.hpp>
14323
14324 // #include <nlohmann/detail/output/serializer.hpp>
14325
14326
14327 #include <algorithm> // reverse, remove, fill, find, none_of
14328 #include <array> // array
14329 #include <clocale> // localeconv, lconv
14330 #include <cmath> // labs, isfinite, isnan, signbit
14331 #include <cstddef> // size_t, ptrdiff_t
14332 #include <cstdint> // uint8_t
14333 #include <cstdio> // snprintf
14334 #include <limits> // numeric_limits
14335 #include <string> // string, char_traits
14336 #include <type_traits> // is_same
14337 #include <utility> // move
14338
14339 // #include <nlohmann/detail/conversions/to_chars.hpp>
14340
14341
14342 #include <array> // array
14343 #include <cmath> // signbit, isfinite
14344 #include <cstdint> // intN_t, uintN_t
14345 #include <cstring> // memcpy, memmove
14346 #include <limits> // numeric_limits
14347 #include <type_traits> // conditional
14348
14349 // #include <nlohmann/detail/macro_scope.hpp>
14350
14351
14352 namespace nlohmann
14353 {
14354 namespace detail
14355 {
14356
14357 /*!
14358 @brief implements the Grisu2 algorithm for binary to decimal floating-point
14359 conversion.
14360
14361 This implementation is a slightly modified version of the reference
14362 implementation which may be obtained from
14363 http://florian.loitsch.com/publications (bench.tar.gz).
14364
14365 The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
14366
14367 For a detailed description of the algorithm see:
14368
14369 [1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
14370 Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
14371 Language Design and Implementation, PLDI 2010
14372 [2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
14373 Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
14374 Design and Implementation, PLDI 1996
14375 */
14376 namespace dtoa_impl
14377 {
14378
14379 template<typename Target, typename Source>
reinterpret_bits(const Source source)14380 Target reinterpret_bits(const Source source)
14381 {
14382 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
14383
14384 Target target;
14385 std::memcpy(&target, &source, sizeof(Source));
14386 return target;
14387 }
14388
14389 struct diyfp // f * 2^e
14390 {
14391 static constexpr int kPrecision = 64; // = q
14392
14393 std::uint64_t f = 0;
14394 int e = 0;
14395
diyfpnlohmann::detail::dtoa_impl::diyfp14396 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
14397
14398 /*!
14399 @brief returns x - y
14400 @pre x.e == y.e and x.f >= y.f
14401 */
subnlohmann::detail::dtoa_impl::diyfp14402 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
14403 {
14404 JSON_ASSERT(x.e == y.e);
14405 JSON_ASSERT(x.f >= y.f);
14406
14407 return {x.f - y.f, x.e};
14408 }
14409
14410 /*!
14411 @brief returns x * y
14412 @note The result is rounded. (Only the upper q bits are returned.)
14413 */
mulnlohmann::detail::dtoa_impl::diyfp14414 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
14415 {
14416 static_assert(kPrecision == 64, "internal error");
14417
14418 // Computes:
14419 // f = round((x.f * y.f) / 2^q)
14420 // e = x.e + y.e + q
14421
14422 // Emulate the 64-bit * 64-bit multiplication:
14423 //
14424 // p = u * v
14425 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
14426 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
14427 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
14428 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
14429 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
14430 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
14431 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
14432 //
14433 // (Since Q might be larger than 2^32 - 1)
14434 //
14435 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
14436 //
14437 // (Q_hi + H does not overflow a 64-bit int)
14438 //
14439 // = p_lo + 2^64 p_hi
14440
14441 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
14442 const std::uint64_t u_hi = x.f >> 32u;
14443 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
14444 const std::uint64_t v_hi = y.f >> 32u;
14445
14446 const std::uint64_t p0 = u_lo * v_lo;
14447 const std::uint64_t p1 = u_lo * v_hi;
14448 const std::uint64_t p2 = u_hi * v_lo;
14449 const std::uint64_t p3 = u_hi * v_hi;
14450
14451 const std::uint64_t p0_hi = p0 >> 32u;
14452 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
14453 const std::uint64_t p1_hi = p1 >> 32u;
14454 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
14455 const std::uint64_t p2_hi = p2 >> 32u;
14456
14457 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
14458
14459 // The full product might now be computed as
14460 //
14461 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
14462 // p_lo = p0_lo + (Q << 32)
14463 //
14464 // But in this particular case here, the full p_lo is not required.
14465 // Effectively we only need to add the highest bit in p_lo to p_hi (and
14466 // Q_hi + 1 does not overflow).
14467
14468 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
14469
14470 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
14471
14472 return {h, x.e + y.e + 64};
14473 }
14474
14475 /*!
14476 @brief normalize x such that the significand is >= 2^(q-1)
14477 @pre x.f != 0
14478 */
normalizenlohmann::detail::dtoa_impl::diyfp14479 static diyfp normalize(diyfp x) noexcept
14480 {
14481 JSON_ASSERT(x.f != 0);
14482
14483 while ((x.f >> 63u) == 0)
14484 {
14485 x.f <<= 1u;
14486 x.e--;
14487 }
14488
14489 return x;
14490 }
14491
14492 /*!
14493 @brief normalize x such that the result has the exponent E
14494 @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
14495 */
normalize_tonlohmann::detail::dtoa_impl::diyfp14496 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
14497 {
14498 const int delta = x.e - target_exponent;
14499
14500 JSON_ASSERT(delta >= 0);
14501 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
14502
14503 return {x.f << delta, target_exponent};
14504 }
14505 };
14506
14507 struct boundaries
14508 {
14509 diyfp w;
14510 diyfp minus;
14511 diyfp plus;
14512 };
14513
14514 /*!
14515 Compute the (normalized) diyfp representing the input number 'value' and its
14516 boundaries.
14517
14518 @pre value must be finite and positive
14519 */
14520 template<typename FloatType>
compute_boundaries(FloatType value)14521 boundaries compute_boundaries(FloatType value)
14522 {
14523 JSON_ASSERT(std::isfinite(value));
14524 JSON_ASSERT(value > 0);
14525
14526 // Convert the IEEE representation into a diyfp.
14527 //
14528 // If v is denormal:
14529 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
14530 // If v is normalized:
14531 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
14532
14533 static_assert(std::numeric_limits<FloatType>::is_iec559,
14534 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
14535
14536 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
14537 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
14538 constexpr int kMinExp = 1 - kBias;
14539 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
14540
14541 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
14542
14543 const std::uint64_t bits = reinterpret_bits<bits_type>(value);
14544 const std::uint64_t E = bits >> (kPrecision - 1);
14545 const std::uint64_t F = bits & (kHiddenBit - 1);
14546
14547 const bool is_denormal = E == 0;
14548 const diyfp v = is_denormal
14549 ? diyfp(F, kMinExp)
14550 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
14551
14552 // Compute the boundaries m- and m+ of the floating-point value
14553 // v = f * 2^e.
14554 //
14555 // Determine v- and v+, the floating-point predecessor and successor if v,
14556 // respectively.
14557 //
14558 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
14559 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
14560 //
14561 // v+ = v + 2^e
14562 //
14563 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
14564 // between m- and m+ round to v, regardless of how the input rounding
14565 // algorithm breaks ties.
14566 //
14567 // ---+-------------+-------------+-------------+-------------+--- (A)
14568 // v- m- v m+ v+
14569 //
14570 // -----------------+------+------+-------------+-------------+--- (B)
14571 // v- m- v m+ v+
14572
14573 const bool lower_boundary_is_closer = F == 0 && E > 1;
14574 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
14575 const diyfp m_minus = lower_boundary_is_closer
14576 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
14577 : diyfp(2 * v.f - 1, v.e - 1); // (A)
14578
14579 // Determine the normalized w+ = m+.
14580 const diyfp w_plus = diyfp::normalize(m_plus);
14581
14582 // Determine w- = m- such that e_(w-) = e_(w+).
14583 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
14584
14585 return {diyfp::normalize(v), w_minus, w_plus};
14586 }
14587
14588 // Given normalized diyfp w, Grisu needs to find a (normalized) cached
14589 // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
14590 // within a certain range [alpha, gamma] (Definition 3.2 from [1])
14591 //
14592 // alpha <= e = e_c + e_w + q <= gamma
14593 //
14594 // or
14595 //
14596 // f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
14597 // <= f_c * f_w * 2^gamma
14598 //
14599 // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
14600 //
14601 // 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
14602 //
14603 // or
14604 //
14605 // 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
14606 //
14607 // The choice of (alpha,gamma) determines the size of the table and the form of
14608 // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
14609 // in practice:
14610 //
14611 // The idea is to cut the number c * w = f * 2^e into two parts, which can be
14612 // processed independently: An integral part p1, and a fractional part p2:
14613 //
14614 // f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
14615 // = (f div 2^-e) + (f mod 2^-e) * 2^e
14616 // = p1 + p2 * 2^e
14617 //
14618 // The conversion of p1 into decimal form requires a series of divisions and
14619 // modulos by (a power of) 10. These operations are faster for 32-bit than for
14620 // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
14621 // achieved by choosing
14622 //
14623 // -e >= 32 or e <= -32 := gamma
14624 //
14625 // In order to convert the fractional part
14626 //
14627 // p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
14628 //
14629 // into decimal form, the fraction is repeatedly multiplied by 10 and the digits
14630 // d[-i] are extracted in order:
14631 //
14632 // (10 * p2) div 2^-e = d[-1]
14633 // (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
14634 //
14635 // The multiplication by 10 must not overflow. It is sufficient to choose
14636 //
14637 // 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
14638 //
14639 // Since p2 = f mod 2^-e < 2^-e,
14640 //
14641 // -e <= 60 or e >= -60 := alpha
14642
14643 constexpr int kAlpha = -60;
14644 constexpr int kGamma = -32;
14645
14646 struct cached_power // c = f * 2^e ~= 10^k
14647 {
14648 std::uint64_t f;
14649 int e;
14650 int k;
14651 };
14652
14653 /*!
14654 For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
14655 power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
14656 satisfies (Definition 3.2 from [1])
14657
14658 alpha <= e_c + e + q <= gamma.
14659 */
get_cached_power_for_binary_exponent(int e)14660 inline cached_power get_cached_power_for_binary_exponent(int e)
14661 {
14662 // Now
14663 //
14664 // alpha <= e_c + e + q <= gamma (1)
14665 // ==> f_c * 2^alpha <= c * 2^e * 2^q
14666 //
14667 // and since the c's are normalized, 2^(q-1) <= f_c,
14668 //
14669 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
14670 // ==> 2^(alpha - e - 1) <= c
14671 //
14672 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
14673 //
14674 // k = ceil( log_10( 2^(alpha - e - 1) ) )
14675 // = ceil( (alpha - e - 1) * log_10(2) )
14676 //
14677 // From the paper:
14678 // "In theory the result of the procedure could be wrong since c is rounded,
14679 // and the computation itself is approximated [...]. In practice, however,
14680 // this simple function is sufficient."
14681 //
14682 // For IEEE double precision floating-point numbers converted into
14683 // normalized diyfp's w = f * 2^e, with q = 64,
14684 //
14685 // e >= -1022 (min IEEE exponent)
14686 // -52 (p - 1)
14687 // -52 (p - 1, possibly normalize denormal IEEE numbers)
14688 // -11 (normalize the diyfp)
14689 // = -1137
14690 //
14691 // and
14692 //
14693 // e <= +1023 (max IEEE exponent)
14694 // -52 (p - 1)
14695 // -11 (normalize the diyfp)
14696 // = 960
14697 //
14698 // This binary exponent range [-1137,960] results in a decimal exponent
14699 // range [-307,324]. One does not need to store a cached power for each
14700 // k in this range. For each such k it suffices to find a cached power
14701 // such that the exponent of the product lies in [alpha,gamma].
14702 // This implies that the difference of the decimal exponents of adjacent
14703 // table entries must be less than or equal to
14704 //
14705 // floor( (gamma - alpha) * log_10(2) ) = 8.
14706 //
14707 // (A smaller distance gamma-alpha would require a larger table.)
14708
14709 // NB:
14710 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
14711
14712 constexpr int kCachedPowersMinDecExp = -300;
14713 constexpr int kCachedPowersDecStep = 8;
14714
14715 static constexpr std::array<cached_power, 79> kCachedPowers =
14716 {
14717 {
14718 { 0xAB70FE17C79AC6CA, -1060, -300 },
14719 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
14720 { 0xBE5691EF416BD60C, -1007, -284 },
14721 { 0x8DD01FAD907FFC3C, -980, -276 },
14722 { 0xD3515C2831559A83, -954, -268 },
14723 { 0x9D71AC8FADA6C9B5, -927, -260 },
14724 { 0xEA9C227723EE8BCB, -901, -252 },
14725 { 0xAECC49914078536D, -874, -244 },
14726 { 0x823C12795DB6CE57, -847, -236 },
14727 { 0xC21094364DFB5637, -821, -228 },
14728 { 0x9096EA6F3848984F, -794, -220 },
14729 { 0xD77485CB25823AC7, -768, -212 },
14730 { 0xA086CFCD97BF97F4, -741, -204 },
14731 { 0xEF340A98172AACE5, -715, -196 },
14732 { 0xB23867FB2A35B28E, -688, -188 },
14733 { 0x84C8D4DFD2C63F3B, -661, -180 },
14734 { 0xC5DD44271AD3CDBA, -635, -172 },
14735 { 0x936B9FCEBB25C996, -608, -164 },
14736 { 0xDBAC6C247D62A584, -582, -156 },
14737 { 0xA3AB66580D5FDAF6, -555, -148 },
14738 { 0xF3E2F893DEC3F126, -529, -140 },
14739 { 0xB5B5ADA8AAFF80B8, -502, -132 },
14740 { 0x87625F056C7C4A8B, -475, -124 },
14741 { 0xC9BCFF6034C13053, -449, -116 },
14742 { 0x964E858C91BA2655, -422, -108 },
14743 { 0xDFF9772470297EBD, -396, -100 },
14744 { 0xA6DFBD9FB8E5B88F, -369, -92 },
14745 { 0xF8A95FCF88747D94, -343, -84 },
14746 { 0xB94470938FA89BCF, -316, -76 },
14747 { 0x8A08F0F8BF0F156B, -289, -68 },
14748 { 0xCDB02555653131B6, -263, -60 },
14749 { 0x993FE2C6D07B7FAC, -236, -52 },
14750 { 0xE45C10C42A2B3B06, -210, -44 },
14751 { 0xAA242499697392D3, -183, -36 },
14752 { 0xFD87B5F28300CA0E, -157, -28 },
14753 { 0xBCE5086492111AEB, -130, -20 },
14754 { 0x8CBCCC096F5088CC, -103, -12 },
14755 { 0xD1B71758E219652C, -77, -4 },
14756 { 0x9C40000000000000, -50, 4 },
14757 { 0xE8D4A51000000000, -24, 12 },
14758 { 0xAD78EBC5AC620000, 3, 20 },
14759 { 0x813F3978F8940984, 30, 28 },
14760 { 0xC097CE7BC90715B3, 56, 36 },
14761 { 0x8F7E32CE7BEA5C70, 83, 44 },
14762 { 0xD5D238A4ABE98068, 109, 52 },
14763 { 0x9F4F2726179A2245, 136, 60 },
14764 { 0xED63A231D4C4FB27, 162, 68 },
14765 { 0xB0DE65388CC8ADA8, 189, 76 },
14766 { 0x83C7088E1AAB65DB, 216, 84 },
14767 { 0xC45D1DF942711D9A, 242, 92 },
14768 { 0x924D692CA61BE758, 269, 100 },
14769 { 0xDA01EE641A708DEA, 295, 108 },
14770 { 0xA26DA3999AEF774A, 322, 116 },
14771 { 0xF209787BB47D6B85, 348, 124 },
14772 { 0xB454E4A179DD1877, 375, 132 },
14773 { 0x865B86925B9BC5C2, 402, 140 },
14774 { 0xC83553C5C8965D3D, 428, 148 },
14775 { 0x952AB45CFA97A0B3, 455, 156 },
14776 { 0xDE469FBD99A05FE3, 481, 164 },
14777 { 0xA59BC234DB398C25, 508, 172 },
14778 { 0xF6C69A72A3989F5C, 534, 180 },
14779 { 0xB7DCBF5354E9BECE, 561, 188 },
14780 { 0x88FCF317F22241E2, 588, 196 },
14781 { 0xCC20CE9BD35C78A5, 614, 204 },
14782 { 0x98165AF37B2153DF, 641, 212 },
14783 { 0xE2A0B5DC971F303A, 667, 220 },
14784 { 0xA8D9D1535CE3B396, 694, 228 },
14785 { 0xFB9B7CD9A4A7443C, 720, 236 },
14786 { 0xBB764C4CA7A44410, 747, 244 },
14787 { 0x8BAB8EEFB6409C1A, 774, 252 },
14788 { 0xD01FEF10A657842C, 800, 260 },
14789 { 0x9B10A4E5E9913129, 827, 268 },
14790 { 0xE7109BFBA19C0C9D, 853, 276 },
14791 { 0xAC2820D9623BF429, 880, 284 },
14792 { 0x80444B5E7AA7CF85, 907, 292 },
14793 { 0xBF21E44003ACDD2D, 933, 300 },
14794 { 0x8E679C2F5E44FF8F, 960, 308 },
14795 { 0xD433179D9C8CB841, 986, 316 },
14796 { 0x9E19DB92B4E31BA9, 1013, 324 },
14797 }
14798 };
14799
14800 // This computation gives exactly the same results for k as
14801 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
14802 // for |e| <= 1500, but doesn't require floating-point operations.
14803 // NB: log_10(2) ~= 78913 / 2^18
14804 JSON_ASSERT(e >= -1500);
14805 JSON_ASSERT(e <= 1500);
14806 const int f = kAlpha - e - 1;
14807 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
14808
14809 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
14810 JSON_ASSERT(index >= 0);
14811 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
14812
14813 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
14814 JSON_ASSERT(kAlpha <= cached.e + e + 64);
14815 JSON_ASSERT(kGamma >= cached.e + e + 64);
14816
14817 return cached;
14818 }
14819
14820 /*!
14821 For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
14822 For n == 0, returns 1 and sets pow10 := 1.
14823 */
find_largest_pow10(const std::uint32_t n,std::uint32_t & pow10)14824 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
14825 {
14826 // LCOV_EXCL_START
14827 if (n >= 1000000000)
14828 {
14829 pow10 = 1000000000;
14830 return 10;
14831 }
14832 // LCOV_EXCL_STOP
14833 else if (n >= 100000000)
14834 {
14835 pow10 = 100000000;
14836 return 9;
14837 }
14838 else if (n >= 10000000)
14839 {
14840 pow10 = 10000000;
14841 return 8;
14842 }
14843 else if (n >= 1000000)
14844 {
14845 pow10 = 1000000;
14846 return 7;
14847 }
14848 else if (n >= 100000)
14849 {
14850 pow10 = 100000;
14851 return 6;
14852 }
14853 else if (n >= 10000)
14854 {
14855 pow10 = 10000;
14856 return 5;
14857 }
14858 else if (n >= 1000)
14859 {
14860 pow10 = 1000;
14861 return 4;
14862 }
14863 else if (n >= 100)
14864 {
14865 pow10 = 100;
14866 return 3;
14867 }
14868 else if (n >= 10)
14869 {
14870 pow10 = 10;
14871 return 2;
14872 }
14873 else
14874 {
14875 pow10 = 1;
14876 return 1;
14877 }
14878 }
14879
grisu2_round(char * buf,int len,std::uint64_t dist,std::uint64_t delta,std::uint64_t rest,std::uint64_t ten_k)14880 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
14881 std::uint64_t rest, std::uint64_t ten_k)
14882 {
14883 JSON_ASSERT(len >= 1);
14884 JSON_ASSERT(dist <= delta);
14885 JSON_ASSERT(rest <= delta);
14886 JSON_ASSERT(ten_k > 0);
14887
14888 // <--------------------------- delta ---->
14889 // <---- dist --------->
14890 // --------------[------------------+-------------------]--------------
14891 // M- w M+
14892 //
14893 // ten_k
14894 // <------>
14895 // <---- rest ---->
14896 // --------------[------------------+----+--------------]--------------
14897 // w V
14898 // = buf * 10^k
14899 //
14900 // ten_k represents a unit-in-the-last-place in the decimal representation
14901 // stored in buf.
14902 // Decrement buf by ten_k while this takes buf closer to w.
14903
14904 // The tests are written in this order to avoid overflow in unsigned
14905 // integer arithmetic.
14906
14907 while (rest < dist
14908 && delta - rest >= ten_k
14909 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
14910 {
14911 JSON_ASSERT(buf[len - 1] != '0');
14912 buf[len - 1]--;
14913 rest += ten_k;
14914 }
14915 }
14916
14917 /*!
14918 Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
14919 M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
14920 */
grisu2_digit_gen(char * buffer,int & length,int & decimal_exponent,diyfp M_minus,diyfp w,diyfp M_plus)14921 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
14922 diyfp M_minus, diyfp w, diyfp M_plus)
14923 {
14924 static_assert(kAlpha >= -60, "internal error");
14925 static_assert(kGamma <= -32, "internal error");
14926
14927 // Generates the digits (and the exponent) of a decimal floating-point
14928 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
14929 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
14930 //
14931 // <--------------------------- delta ---->
14932 // <---- dist --------->
14933 // --------------[------------------+-------------------]--------------
14934 // M- w M+
14935 //
14936 // Grisu2 generates the digits of M+ from left to right and stops as soon as
14937 // V is in [M-,M+].
14938
14939 JSON_ASSERT(M_plus.e >= kAlpha);
14940 JSON_ASSERT(M_plus.e <= kGamma);
14941
14942 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
14943 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
14944
14945 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
14946 //
14947 // M+ = f * 2^e
14948 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
14949 // = ((p1 ) * 2^-e + (p2 )) * 2^e
14950 // = p1 + p2 * 2^e
14951
14952 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
14953
14954 auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
14955 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
14956
14957 // 1)
14958 //
14959 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
14960
14961 JSON_ASSERT(p1 > 0);
14962
14963 std::uint32_t pow10;
14964 const int k = find_largest_pow10(p1, pow10);
14965
14966 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
14967 //
14968 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
14969 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
14970 //
14971 // M+ = p1 + p2 * 2^e
14972 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
14973 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
14974 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
14975 //
14976 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
14977 //
14978 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
14979 //
14980 // but stop as soon as
14981 //
14982 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
14983
14984 int n = k;
14985 while (n > 0)
14986 {
14987 // Invariants:
14988 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
14989 // pow10 = 10^(n-1) <= p1 < 10^n
14990 //
14991 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
14992 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
14993 //
14994 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
14995 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
14996 //
14997 JSON_ASSERT(d <= 9);
14998 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
14999 //
15000 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
15001 //
15002 p1 = r;
15003 n--;
15004 //
15005 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
15006 // pow10 = 10^n
15007 //
15008
15009 // Now check if enough digits have been generated.
15010 // Compute
15011 //
15012 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
15013 //
15014 // Note:
15015 // Since rest and delta share the same exponent e, it suffices to
15016 // compare the significands.
15017 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
15018 if (rest <= delta)
15019 {
15020 // V = buffer * 10^n, with M- <= V <= M+.
15021
15022 decimal_exponent += n;
15023
15024 // We may now just stop. But instead look if the buffer could be
15025 // decremented to bring V closer to w.
15026 //
15027 // pow10 = 10^n is now 1 ulp in the decimal representation V.
15028 // The rounding procedure works with diyfp's with an implicit
15029 // exponent of e.
15030 //
15031 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
15032 //
15033 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
15034 grisu2_round(buffer, length, dist, delta, rest, ten_n);
15035
15036 return;
15037 }
15038
15039 pow10 /= 10;
15040 //
15041 // pow10 = 10^(n-1) <= p1 < 10^n
15042 // Invariants restored.
15043 }
15044
15045 // 2)
15046 //
15047 // The digits of the integral part have been generated:
15048 //
15049 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
15050 // = buffer + p2 * 2^e
15051 //
15052 // Now generate the digits of the fractional part p2 * 2^e.
15053 //
15054 // Note:
15055 // No decimal point is generated: the exponent is adjusted instead.
15056 //
15057 // p2 actually represents the fraction
15058 //
15059 // p2 * 2^e
15060 // = p2 / 2^-e
15061 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
15062 //
15063 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
15064 //
15065 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
15066 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
15067 //
15068 // using
15069 //
15070 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
15071 // = ( d) * 2^-e + ( r)
15072 //
15073 // or
15074 // 10^m * p2 * 2^e = d + r * 2^e
15075 //
15076 // i.e.
15077 //
15078 // M+ = buffer + p2 * 2^e
15079 // = buffer + 10^-m * (d + r * 2^e)
15080 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
15081 //
15082 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
15083
15084 JSON_ASSERT(p2 > delta);
15085
15086 int m = 0;
15087 for (;;)
15088 {
15089 // Invariant:
15090 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
15091 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
15092 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
15093 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
15094 //
15095 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
15096 p2 *= 10;
15097 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
15098 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
15099 //
15100 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
15101 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
15102 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
15103 //
15104 JSON_ASSERT(d <= 9);
15105 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
15106 //
15107 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
15108 //
15109 p2 = r;
15110 m++;
15111 //
15112 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
15113 // Invariant restored.
15114
15115 // Check if enough digits have been generated.
15116 //
15117 // 10^-m * p2 * 2^e <= delta * 2^e
15118 // p2 * 2^e <= 10^m * delta * 2^e
15119 // p2 <= 10^m * delta
15120 delta *= 10;
15121 dist *= 10;
15122 if (p2 <= delta)
15123 {
15124 break;
15125 }
15126 }
15127
15128 // V = buffer * 10^-m, with M- <= V <= M+.
15129
15130 decimal_exponent -= m;
15131
15132 // 1 ulp in the decimal representation is now 10^-m.
15133 // Since delta and dist are now scaled by 10^m, we need to do the
15134 // same with ulp in order to keep the units in sync.
15135 //
15136 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
15137 //
15138 const std::uint64_t ten_m = one.f;
15139 grisu2_round(buffer, length, dist, delta, p2, ten_m);
15140
15141 // By construction this algorithm generates the shortest possible decimal
15142 // number (Loitsch, Theorem 6.2) which rounds back to w.
15143 // For an input number of precision p, at least
15144 //
15145 // N = 1 + ceil(p * log_10(2))
15146 //
15147 // decimal digits are sufficient to identify all binary floating-point
15148 // numbers (Matula, "In-and-Out conversions").
15149 // This implies that the algorithm does not produce more than N decimal
15150 // digits.
15151 //
15152 // N = 17 for p = 53 (IEEE double precision)
15153 // N = 9 for p = 24 (IEEE single precision)
15154 }
15155
15156 /*!
15157 v = buf * 10^decimal_exponent
15158 len is the length of the buffer (number of decimal digits)
15159 The buffer must be large enough, i.e. >= max_digits10.
15160 */
15161 JSON_HEDLEY_NON_NULL(1)
grisu2(char * buf,int & len,int & decimal_exponent,diyfp m_minus,diyfp v,diyfp m_plus)15162 inline void grisu2(char* buf, int& len, int& decimal_exponent,
15163 diyfp m_minus, diyfp v, diyfp m_plus)
15164 {
15165 JSON_ASSERT(m_plus.e == m_minus.e);
15166 JSON_ASSERT(m_plus.e == v.e);
15167
15168 // --------(-----------------------+-----------------------)-------- (A)
15169 // m- v m+
15170 //
15171 // --------------------(-----------+-----------------------)-------- (B)
15172 // m- v m+
15173 //
15174 // First scale v (and m- and m+) such that the exponent is in the range
15175 // [alpha, gamma].
15176
15177 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
15178
15179 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
15180
15181 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
15182 const diyfp w = diyfp::mul(v, c_minus_k);
15183 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
15184 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
15185
15186 // ----(---+---)---------------(---+---)---------------(---+---)----
15187 // w- w w+
15188 // = c*m- = c*v = c*m+
15189 //
15190 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
15191 // w+ are now off by a small amount.
15192 // In fact:
15193 //
15194 // w - v * 10^k < 1 ulp
15195 //
15196 // To account for this inaccuracy, add resp. subtract 1 ulp.
15197 //
15198 // --------+---[---------------(---+---)---------------]---+--------
15199 // w- M- w M+ w+
15200 //
15201 // Now any number in [M-, M+] (bounds included) will round to w when input,
15202 // regardless of how the input rounding algorithm breaks ties.
15203 //
15204 // And digit_gen generates the shortest possible such number in [M-, M+].
15205 // Note that this does not mean that Grisu2 always generates the shortest
15206 // possible number in the interval (m-, m+).
15207 const diyfp M_minus(w_minus.f + 1, w_minus.e);
15208 const diyfp M_plus (w_plus.f - 1, w_plus.e );
15209
15210 decimal_exponent = -cached.k; // = -(-k) = k
15211
15212 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
15213 }
15214
15215 /*!
15216 v = buf * 10^decimal_exponent
15217 len is the length of the buffer (number of decimal digits)
15218 The buffer must be large enough, i.e. >= max_digits10.
15219 */
15220 template<typename FloatType>
15221 JSON_HEDLEY_NON_NULL(1)
grisu2(char * buf,int & len,int & decimal_exponent,FloatType value)15222 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
15223 {
15224 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
15225 "internal error: not enough precision");
15226
15227 JSON_ASSERT(std::isfinite(value));
15228 JSON_ASSERT(value > 0);
15229
15230 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
15231 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
15232 // decimal representations are not exactly "short".
15233 //
15234 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
15235 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
15236 // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
15237 // does.
15238 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
15239 // representation using the corresponding std::from_chars function recovers value exactly". That
15240 // indicates that single precision floating-point numbers should be recovered using
15241 // 'std::strtof'.
15242 //
15243 // NB: If the neighbors are computed for single-precision numbers, there is a single float
15244 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
15245 // value is off by 1 ulp.
15246 #if 0
15247 const boundaries w = compute_boundaries(static_cast<double>(value));
15248 #else
15249 const boundaries w = compute_boundaries(value);
15250 #endif
15251
15252 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
15253 }
15254
15255 /*!
15256 @brief appends a decimal representation of e to buf
15257 @return a pointer to the element following the exponent.
15258 @pre -1000 < e < 1000
15259 */
15260 JSON_HEDLEY_NON_NULL(1)
15261 JSON_HEDLEY_RETURNS_NON_NULL
append_exponent(char * buf,int e)15262 inline char* append_exponent(char* buf, int e)
15263 {
15264 JSON_ASSERT(e > -1000);
15265 JSON_ASSERT(e < 1000);
15266
15267 if (e < 0)
15268 {
15269 e = -e;
15270 *buf++ = '-';
15271 }
15272 else
15273 {
15274 *buf++ = '+';
15275 }
15276
15277 auto k = static_cast<std::uint32_t>(e);
15278 if (k < 10)
15279 {
15280 // Always print at least two digits in the exponent.
15281 // This is for compatibility with printf("%g").
15282 *buf++ = '0';
15283 *buf++ = static_cast<char>('0' + k);
15284 }
15285 else if (k < 100)
15286 {
15287 *buf++ = static_cast<char>('0' + k / 10);
15288 k %= 10;
15289 *buf++ = static_cast<char>('0' + k);
15290 }
15291 else
15292 {
15293 *buf++ = static_cast<char>('0' + k / 100);
15294 k %= 100;
15295 *buf++ = static_cast<char>('0' + k / 10);
15296 k %= 10;
15297 *buf++ = static_cast<char>('0' + k);
15298 }
15299
15300 return buf;
15301 }
15302
15303 /*!
15304 @brief prettify v = buf * 10^decimal_exponent
15305
15306 If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
15307 notation. Otherwise it will be printed in exponential notation.
15308
15309 @pre min_exp < 0
15310 @pre max_exp > 0
15311 */
15312 JSON_HEDLEY_NON_NULL(1)
15313 JSON_HEDLEY_RETURNS_NON_NULL
format_buffer(char * buf,int len,int decimal_exponent,int min_exp,int max_exp)15314 inline char* format_buffer(char* buf, int len, int decimal_exponent,
15315 int min_exp, int max_exp)
15316 {
15317 JSON_ASSERT(min_exp < 0);
15318 JSON_ASSERT(max_exp > 0);
15319
15320 const int k = len;
15321 const int n = len + decimal_exponent;
15322
15323 // v = buf * 10^(n-k)
15324 // k is the length of the buffer (number of decimal digits)
15325 // n is the position of the decimal point relative to the start of the buffer.
15326
15327 if (k <= n && n <= max_exp)
15328 {
15329 // digits[000]
15330 // len <= max_exp + 2
15331
15332 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
15333 // Make it look like a floating-point number (#362, #378)
15334 buf[n + 0] = '.';
15335 buf[n + 1] = '0';
15336 return buf + (static_cast<size_t>(n) + 2);
15337 }
15338
15339 if (0 < n && n <= max_exp)
15340 {
15341 // dig.its
15342 // len <= max_digits10 + 1
15343
15344 JSON_ASSERT(k > n);
15345
15346 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
15347 buf[n] = '.';
15348 return buf + (static_cast<size_t>(k) + 1U);
15349 }
15350
15351 if (min_exp < n && n <= 0)
15352 {
15353 // 0.[000]digits
15354 // len <= 2 + (-min_exp - 1) + max_digits10
15355
15356 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
15357 buf[0] = '0';
15358 buf[1] = '.';
15359 std::memset(buf + 2, '0', static_cast<size_t>(-n));
15360 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
15361 }
15362
15363 if (k == 1)
15364 {
15365 // dE+123
15366 // len <= 1 + 5
15367
15368 buf += 1;
15369 }
15370 else
15371 {
15372 // d.igitsE+123
15373 // len <= max_digits10 + 1 + 5
15374
15375 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
15376 buf[1] = '.';
15377 buf += 1 + static_cast<size_t>(k);
15378 }
15379
15380 *buf++ = 'e';
15381 return append_exponent(buf, n - 1);
15382 }
15383
15384 } // namespace dtoa_impl
15385
15386 /*!
15387 @brief generates a decimal representation of the floating-point number value in [first, last).
15388
15389 The format of the resulting decimal representation is similar to printf's %g
15390 format. Returns an iterator pointing past-the-end of the decimal representation.
15391
15392 @note The input number must be finite, i.e. NaN's and Inf's are not supported.
15393 @note The buffer must be large enough.
15394 @note The result is NOT null-terminated.
15395 */
15396 template<typename FloatType>
15397 JSON_HEDLEY_NON_NULL(1, 2)
15398 JSON_HEDLEY_RETURNS_NON_NULL
to_chars(char * first,const char * last,FloatType value)15399 char* to_chars(char* first, const char* last, FloatType value)
15400 {
15401 static_cast<void>(last); // maybe unused - fix warning
15402 JSON_ASSERT(std::isfinite(value));
15403
15404 // Use signbit(value) instead of (value < 0) since signbit works for -0.
15405 if (std::signbit(value))
15406 {
15407 value = -value;
15408 *first++ = '-';
15409 }
15410
15411 if (value == 0) // +-0
15412 {
15413 *first++ = '0';
15414 // Make it look like a floating-point number (#362, #378)
15415 *first++ = '.';
15416 *first++ = '0';
15417 return first;
15418 }
15419
15420 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
15421
15422 // Compute v = buffer * 10^decimal_exponent.
15423 // The decimal digits are stored in the buffer, which needs to be interpreted
15424 // as an unsigned decimal integer.
15425 // len is the length of the buffer, i.e. the number of decimal digits.
15426 int len = 0;
15427 int decimal_exponent = 0;
15428 dtoa_impl::grisu2(first, len, decimal_exponent, value);
15429
15430 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
15431
15432 // Format the buffer like printf("%.*g", prec, value)
15433 constexpr int kMinExp = -4;
15434 // Use digits10 here to increase compatibility with version 2.
15435 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
15436
15437 JSON_ASSERT(last - first >= kMaxExp + 2);
15438 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
15439 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
15440
15441 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
15442 }
15443
15444 } // namespace detail
15445 } // namespace nlohmann
15446
15447 // #include <nlohmann/detail/exceptions.hpp>
15448
15449 // #include <nlohmann/detail/macro_scope.hpp>
15450
15451 // #include <nlohmann/detail/meta/cpp_future.hpp>
15452
15453 // #include <nlohmann/detail/output/binary_writer.hpp>
15454
15455 // #include <nlohmann/detail/output/output_adapters.hpp>
15456
15457 // #include <nlohmann/detail/value_t.hpp>
15458
15459
15460 namespace nlohmann
15461 {
15462 namespace detail
15463 {
15464 ///////////////////
15465 // serialization //
15466 ///////////////////
15467
15468 /// how to treat decoding errors
15469 enum class error_handler_t
15470 {
15471 strict, ///< throw a type_error exception in case of invalid UTF-8
15472 replace, ///< replace invalid UTF-8 sequences with U+FFFD
15473 ignore ///< ignore invalid UTF-8 sequences
15474 };
15475
15476 template<typename BasicJsonType>
15477 class serializer
15478 {
15479 using string_t = typename BasicJsonType::string_t;
15480 using number_float_t = typename BasicJsonType::number_float_t;
15481 using number_integer_t = typename BasicJsonType::number_integer_t;
15482 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
15483 using binary_char_t = typename BasicJsonType::binary_t::value_type;
15484 static constexpr std::uint8_t UTF8_ACCEPT = 0;
15485 static constexpr std::uint8_t UTF8_REJECT = 1;
15486
15487 public:
15488 /*!
15489 @param[in] s output stream to serialize to
15490 @param[in] ichar indentation character to use
15491 @param[in] error_handler_ how to react on decoding errors
15492 */
serializer(output_adapter_t<char> s,const char ichar,error_handler_t error_handler_=error_handler_t::strict)15493 serializer(output_adapter_t<char> s, const char ichar,
15494 error_handler_t error_handler_ = error_handler_t::strict)
15495 : o(std::move(s))
15496 , loc(std::localeconv())
15497 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
15498 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
15499 , indent_char(ichar)
15500 , indent_string(512, indent_char)
15501 , error_handler(error_handler_)
15502 {}
15503
15504 // delete because of pointer members
15505 serializer(const serializer&) = delete;
15506 serializer& operator=(const serializer&) = delete;
15507 serializer(serializer&&) = delete;
15508 serializer& operator=(serializer&&) = delete;
15509 ~serializer() = default;
15510
15511 /*!
15512 @brief internal implementation of the serialization function
15513
15514 This function is called by the public member function dump and organizes
15515 the serialization internally. The indentation level is propagated as
15516 additional parameter. In case of arrays and objects, the function is
15517 called recursively.
15518
15519 - strings and object keys are escaped using `escape_string()`
15520 - integer numbers are converted implicitly via `operator<<`
15521 - floating-point numbers are converted to a string using `"%g"` format
15522 - binary values are serialized as objects containing the subtype and the
15523 byte array
15524
15525 @param[in] val value to serialize
15526 @param[in] pretty_print whether the output shall be pretty-printed
15527 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
15528 in the output are escaped with `\uXXXX` sequences, and the result consists
15529 of ASCII characters only.
15530 @param[in] indent_step the indent level
15531 @param[in] current_indent the current indent level (only used internally)
15532 */
dump(const BasicJsonType & val,const bool pretty_print,const bool ensure_ascii,const unsigned int indent_step,const unsigned int current_indent=0)15533 void dump(const BasicJsonType& val,
15534 const bool pretty_print,
15535 const bool ensure_ascii,
15536 const unsigned int indent_step,
15537 const unsigned int current_indent = 0)
15538 {
15539 switch (val.m_type)
15540 {
15541 case value_t::object:
15542 {
15543 if (val.m_value.object->empty())
15544 {
15545 o->write_characters("{}", 2);
15546 return;
15547 }
15548
15549 if (pretty_print)
15550 {
15551 o->write_characters("{\n", 2);
15552
15553 // variable to hold indentation for recursive calls
15554 const auto new_indent = current_indent + indent_step;
15555 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
15556 {
15557 indent_string.resize(indent_string.size() * 2, ' ');
15558 }
15559
15560 // first n-1 elements
15561 auto i = val.m_value.object->cbegin();
15562 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
15563 {
15564 o->write_characters(indent_string.c_str(), new_indent);
15565 o->write_character('\"');
15566 dump_escaped(i->first, ensure_ascii);
15567 o->write_characters("\": ", 3);
15568 dump(i->second, true, ensure_ascii, indent_step, new_indent);
15569 o->write_characters(",\n", 2);
15570 }
15571
15572 // last element
15573 JSON_ASSERT(i != val.m_value.object->cend());
15574 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
15575 o->write_characters(indent_string.c_str(), new_indent);
15576 o->write_character('\"');
15577 dump_escaped(i->first, ensure_ascii);
15578 o->write_characters("\": ", 3);
15579 dump(i->second, true, ensure_ascii, indent_step, new_indent);
15580
15581 o->write_character('\n');
15582 o->write_characters(indent_string.c_str(), current_indent);
15583 o->write_character('}');
15584 }
15585 else
15586 {
15587 o->write_character('{');
15588
15589 // first n-1 elements
15590 auto i = val.m_value.object->cbegin();
15591 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
15592 {
15593 o->write_character('\"');
15594 dump_escaped(i->first, ensure_ascii);
15595 o->write_characters("\":", 2);
15596 dump(i->second, false, ensure_ascii, indent_step, current_indent);
15597 o->write_character(',');
15598 }
15599
15600 // last element
15601 JSON_ASSERT(i != val.m_value.object->cend());
15602 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
15603 o->write_character('\"');
15604 dump_escaped(i->first, ensure_ascii);
15605 o->write_characters("\":", 2);
15606 dump(i->second, false, ensure_ascii, indent_step, current_indent);
15607
15608 o->write_character('}');
15609 }
15610
15611 return;
15612 }
15613
15614 case value_t::array:
15615 {
15616 if (val.m_value.array->empty())
15617 {
15618 o->write_characters("[]", 2);
15619 return;
15620 }
15621
15622 if (pretty_print)
15623 {
15624 o->write_characters("[\n", 2);
15625
15626 // variable to hold indentation for recursive calls
15627 const auto new_indent = current_indent + indent_step;
15628 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
15629 {
15630 indent_string.resize(indent_string.size() * 2, ' ');
15631 }
15632
15633 // first n-1 elements
15634 for (auto i = val.m_value.array->cbegin();
15635 i != val.m_value.array->cend() - 1; ++i)
15636 {
15637 o->write_characters(indent_string.c_str(), new_indent);
15638 dump(*i, true, ensure_ascii, indent_step, new_indent);
15639 o->write_characters(",\n", 2);
15640 }
15641
15642 // last element
15643 JSON_ASSERT(!val.m_value.array->empty());
15644 o->write_characters(indent_string.c_str(), new_indent);
15645 dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
15646
15647 o->write_character('\n');
15648 o->write_characters(indent_string.c_str(), current_indent);
15649 o->write_character(']');
15650 }
15651 else
15652 {
15653 o->write_character('[');
15654
15655 // first n-1 elements
15656 for (auto i = val.m_value.array->cbegin();
15657 i != val.m_value.array->cend() - 1; ++i)
15658 {
15659 dump(*i, false, ensure_ascii, indent_step, current_indent);
15660 o->write_character(',');
15661 }
15662
15663 // last element
15664 JSON_ASSERT(!val.m_value.array->empty());
15665 dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
15666
15667 o->write_character(']');
15668 }
15669
15670 return;
15671 }
15672
15673 case value_t::string:
15674 {
15675 o->write_character('\"');
15676 dump_escaped(*val.m_value.string, ensure_ascii);
15677 o->write_character('\"');
15678 return;
15679 }
15680
15681 case value_t::binary:
15682 {
15683 if (pretty_print)
15684 {
15685 o->write_characters("{\n", 2);
15686
15687 // variable to hold indentation for recursive calls
15688 const auto new_indent = current_indent + indent_step;
15689 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
15690 {
15691 indent_string.resize(indent_string.size() * 2, ' ');
15692 }
15693
15694 o->write_characters(indent_string.c_str(), new_indent);
15695
15696 o->write_characters("\"bytes\": [", 10);
15697
15698 if (!val.m_value.binary->empty())
15699 {
15700 for (auto i = val.m_value.binary->cbegin();
15701 i != val.m_value.binary->cend() - 1; ++i)
15702 {
15703 dump_integer(*i);
15704 o->write_characters(", ", 2);
15705 }
15706 dump_integer(val.m_value.binary->back());
15707 }
15708
15709 o->write_characters("],\n", 3);
15710 o->write_characters(indent_string.c_str(), new_indent);
15711
15712 o->write_characters("\"subtype\": ", 11);
15713 if (val.m_value.binary->has_subtype())
15714 {
15715 dump_integer(val.m_value.binary->subtype());
15716 }
15717 else
15718 {
15719 o->write_characters("null", 4);
15720 }
15721 o->write_character('\n');
15722 o->write_characters(indent_string.c_str(), current_indent);
15723 o->write_character('}');
15724 }
15725 else
15726 {
15727 o->write_characters("{\"bytes\":[", 10);
15728
15729 if (!val.m_value.binary->empty())
15730 {
15731 for (auto i = val.m_value.binary->cbegin();
15732 i != val.m_value.binary->cend() - 1; ++i)
15733 {
15734 dump_integer(*i);
15735 o->write_character(',');
15736 }
15737 dump_integer(val.m_value.binary->back());
15738 }
15739
15740 o->write_characters("],\"subtype\":", 12);
15741 if (val.m_value.binary->has_subtype())
15742 {
15743 dump_integer(val.m_value.binary->subtype());
15744 o->write_character('}');
15745 }
15746 else
15747 {
15748 o->write_characters("null}", 5);
15749 }
15750 }
15751 return;
15752 }
15753
15754 case value_t::boolean:
15755 {
15756 if (val.m_value.boolean)
15757 {
15758 o->write_characters("true", 4);
15759 }
15760 else
15761 {
15762 o->write_characters("false", 5);
15763 }
15764 return;
15765 }
15766
15767 case value_t::number_integer:
15768 {
15769 dump_integer(val.m_value.number_integer);
15770 return;
15771 }
15772
15773 case value_t::number_unsigned:
15774 {
15775 dump_integer(val.m_value.number_unsigned);
15776 return;
15777 }
15778
15779 case value_t::number_float:
15780 {
15781 dump_float(val.m_value.number_float);
15782 return;
15783 }
15784
15785 case value_t::discarded:
15786 {
15787 o->write_characters("<discarded>", 11);
15788 return;
15789 }
15790
15791 case value_t::null:
15792 {
15793 o->write_characters("null", 4);
15794 return;
15795 }
15796
15797 default: // LCOV_EXCL_LINE
15798 JSON_ASSERT(false); // LCOV_EXCL_LINE
15799 }
15800 }
15801
15802 private:
15803 /*!
15804 @brief dump escaped string
15805
15806 Escape a string by replacing certain special characters by a sequence of an
15807 escape character (backslash) and another character and other control
15808 characters by a sequence of "\u" followed by a four-digit hex
15809 representation. The escaped string is written to output stream @a o.
15810
15811 @param[in] s the string to escape
15812 @param[in] ensure_ascii whether to escape non-ASCII characters with
15813 \uXXXX sequences
15814
15815 @complexity Linear in the length of string @a s.
15816 */
dump_escaped(const string_t & s,const bool ensure_ascii)15817 void dump_escaped(const string_t& s, const bool ensure_ascii)
15818 {
15819 std::uint32_t codepoint;
15820 std::uint8_t state = UTF8_ACCEPT;
15821 std::size_t bytes = 0; // number of bytes written to string_buffer
15822
15823 // number of bytes written at the point of the last valid byte
15824 std::size_t bytes_after_last_accept = 0;
15825 std::size_t undumped_chars = 0;
15826
15827 for (std::size_t i = 0; i < s.size(); ++i)
15828 {
15829 const auto byte = static_cast<uint8_t>(s[i]);
15830
15831 switch (decode(state, codepoint, byte))
15832 {
15833 case UTF8_ACCEPT: // decode found a new code point
15834 {
15835 switch (codepoint)
15836 {
15837 case 0x08: // backspace
15838 {
15839 string_buffer[bytes++] = '\\';
15840 string_buffer[bytes++] = 'b';
15841 break;
15842 }
15843
15844 case 0x09: // horizontal tab
15845 {
15846 string_buffer[bytes++] = '\\';
15847 string_buffer[bytes++] = 't';
15848 break;
15849 }
15850
15851 case 0x0A: // newline
15852 {
15853 string_buffer[bytes++] = '\\';
15854 string_buffer[bytes++] = 'n';
15855 break;
15856 }
15857
15858 case 0x0C: // formfeed
15859 {
15860 string_buffer[bytes++] = '\\';
15861 string_buffer[bytes++] = 'f';
15862 break;
15863 }
15864
15865 case 0x0D: // carriage return
15866 {
15867 string_buffer[bytes++] = '\\';
15868 string_buffer[bytes++] = 'r';
15869 break;
15870 }
15871
15872 case 0x22: // quotation mark
15873 {
15874 string_buffer[bytes++] = '\\';
15875 string_buffer[bytes++] = '\"';
15876 break;
15877 }
15878
15879 case 0x5C: // reverse solidus
15880 {
15881 string_buffer[bytes++] = '\\';
15882 string_buffer[bytes++] = '\\';
15883 break;
15884 }
15885
15886 default:
15887 {
15888 // escape control characters (0x00..0x1F) or, if
15889 // ensure_ascii parameter is used, non-ASCII characters
15890 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
15891 {
15892 if (codepoint <= 0xFFFF)
15893 {
15894 (std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
15895 static_cast<std::uint16_t>(codepoint));
15896 bytes += 6;
15897 }
15898 else
15899 {
15900 (std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
15901 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
15902 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)));
15903 bytes += 12;
15904 }
15905 }
15906 else
15907 {
15908 // copy byte to buffer (all previous bytes
15909 // been copied have in default case above)
15910 string_buffer[bytes++] = s[i];
15911 }
15912 break;
15913 }
15914 }
15915
15916 // write buffer and reset index; there must be 13 bytes
15917 // left, as this is the maximal number of bytes to be
15918 // written ("\uxxxx\uxxxx\0") for one code point
15919 if (string_buffer.size() - bytes < 13)
15920 {
15921 o->write_characters(string_buffer.data(), bytes);
15922 bytes = 0;
15923 }
15924
15925 // remember the byte position of this accept
15926 bytes_after_last_accept = bytes;
15927 undumped_chars = 0;
15928 break;
15929 }
15930
15931 case UTF8_REJECT: // decode found invalid UTF-8 byte
15932 {
15933 switch (error_handler)
15934 {
15935 case error_handler_t::strict:
15936 {
15937 std::string sn(3, '\0');
15938 (std::snprintf)(&sn[0], sn.size(), "%.2X", byte);
15939 JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn));
15940 }
15941
15942 case error_handler_t::ignore:
15943 case error_handler_t::replace:
15944 {
15945 // in case we saw this character the first time, we
15946 // would like to read it again, because the byte
15947 // may be OK for itself, but just not OK for the
15948 // previous sequence
15949 if (undumped_chars > 0)
15950 {
15951 --i;
15952 }
15953
15954 // reset length buffer to the last accepted index;
15955 // thus removing/ignoring the invalid characters
15956 bytes = bytes_after_last_accept;
15957
15958 if (error_handler == error_handler_t::replace)
15959 {
15960 // add a replacement character
15961 if (ensure_ascii)
15962 {
15963 string_buffer[bytes++] = '\\';
15964 string_buffer[bytes++] = 'u';
15965 string_buffer[bytes++] = 'f';
15966 string_buffer[bytes++] = 'f';
15967 string_buffer[bytes++] = 'f';
15968 string_buffer[bytes++] = 'd';
15969 }
15970 else
15971 {
15972 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
15973 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
15974 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
15975 }
15976
15977 // write buffer and reset index; there must be 13 bytes
15978 // left, as this is the maximal number of bytes to be
15979 // written ("\uxxxx\uxxxx\0") for one code point
15980 if (string_buffer.size() - bytes < 13)
15981 {
15982 o->write_characters(string_buffer.data(), bytes);
15983 bytes = 0;
15984 }
15985
15986 bytes_after_last_accept = bytes;
15987 }
15988
15989 undumped_chars = 0;
15990
15991 // continue processing the string
15992 state = UTF8_ACCEPT;
15993 break;
15994 }
15995
15996 default: // LCOV_EXCL_LINE
15997 JSON_ASSERT(false); // LCOV_EXCL_LINE
15998 }
15999 break;
16000 }
16001
16002 default: // decode found yet incomplete multi-byte code point
16003 {
16004 if (!ensure_ascii)
16005 {
16006 // code point will not be escaped - copy byte to buffer
16007 string_buffer[bytes++] = s[i];
16008 }
16009 ++undumped_chars;
16010 break;
16011 }
16012 }
16013 }
16014
16015 // we finished processing the string
16016 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
16017 {
16018 // write buffer
16019 if (bytes > 0)
16020 {
16021 o->write_characters(string_buffer.data(), bytes);
16022 }
16023 }
16024 else
16025 {
16026 // we finish reading, but do not accept: string was incomplete
16027 switch (error_handler)
16028 {
16029 case error_handler_t::strict:
16030 {
16031 std::string sn(3, '\0');
16032 (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast<std::uint8_t>(s.back()));
16033 JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
16034 }
16035
16036 case error_handler_t::ignore:
16037 {
16038 // write all accepted bytes
16039 o->write_characters(string_buffer.data(), bytes_after_last_accept);
16040 break;
16041 }
16042
16043 case error_handler_t::replace:
16044 {
16045 // write all accepted bytes
16046 o->write_characters(string_buffer.data(), bytes_after_last_accept);
16047 // add a replacement character
16048 if (ensure_ascii)
16049 {
16050 o->write_characters("\\ufffd", 6);
16051 }
16052 else
16053 {
16054 o->write_characters("\xEF\xBF\xBD", 3);
16055 }
16056 break;
16057 }
16058
16059 default: // LCOV_EXCL_LINE
16060 JSON_ASSERT(false); // LCOV_EXCL_LINE
16061 }
16062 }
16063 }
16064
16065 /*!
16066 @brief count digits
16067
16068 Count the number of decimal (base 10) digits for an input unsigned integer.
16069
16070 @param[in] x unsigned integer number to count its digits
16071 @return number of decimal digits
16072 */
count_digits(number_unsigned_t x)16073 inline unsigned int count_digits(number_unsigned_t x) noexcept
16074 {
16075 unsigned int n_digits = 1;
16076 for (;;)
16077 {
16078 if (x < 10)
16079 {
16080 return n_digits;
16081 }
16082 if (x < 100)
16083 {
16084 return n_digits + 1;
16085 }
16086 if (x < 1000)
16087 {
16088 return n_digits + 2;
16089 }
16090 if (x < 10000)
16091 {
16092 return n_digits + 3;
16093 }
16094 x = x / 10000u;
16095 n_digits += 4;
16096 }
16097 }
16098
16099 /*!
16100 @brief dump an integer
16101
16102 Dump a given integer to output stream @a o. Works internally with
16103 @a number_buffer.
16104
16105 @param[in] x integer number (signed or unsigned) to dump
16106 @tparam NumberType either @a number_integer_t or @a number_unsigned_t
16107 */
16108 template < typename NumberType, detail::enable_if_t <
16109 std::is_same<NumberType, number_unsigned_t>::value ||
16110 std::is_same<NumberType, number_integer_t>::value ||
16111 std::is_same<NumberType, binary_char_t>::value,
16112 int > = 0 >
dump_integer(NumberType x)16113 void dump_integer(NumberType x)
16114 {
16115 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
16116 {
16117 {
16118 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
16119 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
16120 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
16121 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
16122 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
16123 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
16124 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
16125 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
16126 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
16127 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
16128 }
16129 };
16130
16131 // special case for "0"
16132 if (x == 0)
16133 {
16134 o->write_character('0');
16135 return;
16136 }
16137
16138 // use a pointer to fill the buffer
16139 auto buffer_ptr = number_buffer.begin();
16140
16141 const bool is_negative = std::is_same<NumberType, number_integer_t>::value && !(x >= 0); // see issue #755
16142 number_unsigned_t abs_value;
16143
16144 unsigned int n_chars;
16145
16146 if (is_negative)
16147 {
16148 *buffer_ptr = '-';
16149 abs_value = remove_sign(static_cast<number_integer_t>(x));
16150
16151 // account one more byte for the minus sign
16152 n_chars = 1 + count_digits(abs_value);
16153 }
16154 else
16155 {
16156 abs_value = static_cast<number_unsigned_t>(x);
16157 n_chars = count_digits(abs_value);
16158 }
16159
16160 // spare 1 byte for '\0'
16161 JSON_ASSERT(n_chars < number_buffer.size() - 1);
16162
16163 // jump to the end to generate the string from backward
16164 // so we later avoid reversing the result
16165 buffer_ptr += n_chars;
16166
16167 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
16168 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
16169 while (abs_value >= 100)
16170 {
16171 const auto digits_index = static_cast<unsigned>((abs_value % 100));
16172 abs_value /= 100;
16173 *(--buffer_ptr) = digits_to_99[digits_index][1];
16174 *(--buffer_ptr) = digits_to_99[digits_index][0];
16175 }
16176
16177 if (abs_value >= 10)
16178 {
16179 const auto digits_index = static_cast<unsigned>(abs_value);
16180 *(--buffer_ptr) = digits_to_99[digits_index][1];
16181 *(--buffer_ptr) = digits_to_99[digits_index][0];
16182 }
16183 else
16184 {
16185 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
16186 }
16187
16188 o->write_characters(number_buffer.data(), n_chars);
16189 }
16190
16191 /*!
16192 @brief dump a floating-point number
16193
16194 Dump a given floating-point number to output stream @a o. Works internally
16195 with @a number_buffer.
16196
16197 @param[in] x floating-point number to dump
16198 */
dump_float(number_float_t x)16199 void dump_float(number_float_t x)
16200 {
16201 // NaN / inf
16202 if (!std::isfinite(x))
16203 {
16204 o->write_characters("null", 4);
16205 return;
16206 }
16207
16208 // If number_float_t is an IEEE-754 single or double precision number,
16209 // use the Grisu2 algorithm to produce short numbers which are
16210 // guaranteed to round-trip, using strtof and strtod, resp.
16211 //
16212 // NB: The test below works if <long double> == <double>.
16213 static constexpr bool is_ieee_single_or_double
16214 = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
16215 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
16216
16217 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
16218 }
16219
dump_float(number_float_t x,std::true_type)16220 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
16221 {
16222 char* begin = number_buffer.data();
16223 char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
16224
16225 o->write_characters(begin, static_cast<size_t>(end - begin));
16226 }
16227
dump_float(number_float_t x,std::false_type)16228 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
16229 {
16230 // get number of digits for a float -> text -> float round-trip
16231 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
16232
16233 // the actual conversion
16234 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
16235
16236 // negative value indicates an error
16237 JSON_ASSERT(len > 0);
16238 // check if buffer was large enough
16239 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
16240
16241 // erase thousands separator
16242 if (thousands_sep != '\0')
16243 {
16244 const auto end = std::remove(number_buffer.begin(),
16245 number_buffer.begin() + len, thousands_sep);
16246 std::fill(end, number_buffer.end(), '\0');
16247 JSON_ASSERT((end - number_buffer.begin()) <= len);
16248 len = (end - number_buffer.begin());
16249 }
16250
16251 // convert decimal point to '.'
16252 if (decimal_point != '\0' && decimal_point != '.')
16253 {
16254 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
16255 if (dec_pos != number_buffer.end())
16256 {
16257 *dec_pos = '.';
16258 }
16259 }
16260
16261 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
16262
16263 // determine if need to append ".0"
16264 const bool value_is_int_like =
16265 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
16266 [](char c)
16267 {
16268 return c == '.' || c == 'e';
16269 });
16270
16271 if (value_is_int_like)
16272 {
16273 o->write_characters(".0", 2);
16274 }
16275 }
16276
16277 /*!
16278 @brief check whether a string is UTF-8 encoded
16279
16280 The function checks each byte of a string whether it is UTF-8 encoded. The
16281 result of the check is stored in the @a state parameter. The function must
16282 be called initially with state 0 (accept). State 1 means the string must
16283 be rejected, because the current byte is not allowed. If the string is
16284 completely processed, but the state is non-zero, the string ended
16285 prematurely; that is, the last byte indicated more bytes should have
16286 followed.
16287
16288 @param[in,out] state the state of the decoding
16289 @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
16290 @param[in] byte next byte to decode
16291 @return new state
16292
16293 @note The function has been edited: a std::array is used.
16294
16295 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
16296 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
16297 */
decode(std::uint8_t & state,std::uint32_t & codep,const std::uint8_t byte)16298 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
16299 {
16300 static const std::array<std::uint8_t, 400> utf8d =
16301 {
16302 {
16303 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
16304 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
16305 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
16306 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
16307 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
16308 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
16309 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
16310 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
16311 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
16312 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
16313 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
16314 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
16315 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
16316 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
16317 }
16318 };
16319
16320 const std::uint8_t type = utf8d[byte];
16321
16322 codep = (state != UTF8_ACCEPT)
16323 ? (byte & 0x3fu) | (codep << 6u)
16324 : (0xFFu >> type) & (byte);
16325
16326 std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
16327 JSON_ASSERT(index < 400);
16328 state = utf8d[index];
16329 return state;
16330 }
16331
16332 /*
16333 * Overload to make the compiler happy while it is instantiating
16334 * dump_integer for number_unsigned_t.
16335 * Must never be called.
16336 */
remove_sign(number_unsigned_t x)16337 number_unsigned_t remove_sign(number_unsigned_t x)
16338 {
16339 JSON_ASSERT(false); // LCOV_EXCL_LINE
16340 return x; // LCOV_EXCL_LINE
16341 }
16342
16343 /*
16344 * Helper function for dump_integer
16345 *
16346 * This function takes a negative signed integer and returns its absolute
16347 * value as unsigned integer. The plus/minus shuffling is necessary as we can
16348 * not directly remove the sign of an arbitrary signed integer as the
16349 * absolute values of INT_MIN and INT_MAX are usually not the same. See
16350 * #1708 for details.
16351 */
remove_sign(number_integer_t x)16352 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
16353 {
16354 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)());
16355 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
16356 }
16357
16358 private:
16359 /// the output of the serializer
16360 output_adapter_t<char> o = nullptr;
16361
16362 /// a (hopefully) large enough character buffer
16363 std::array<char, 64> number_buffer{{}};
16364
16365 /// the locale
16366 const std::lconv* loc = nullptr;
16367 /// the locale's thousand separator character
16368 const char thousands_sep = '\0';
16369 /// the locale's decimal point character
16370 const char decimal_point = '\0';
16371
16372 /// string buffer
16373 std::array<char, 512> string_buffer{{}};
16374
16375 /// the indentation character
16376 const char indent_char;
16377 /// the indentation string
16378 string_t indent_string;
16379
16380 /// error_handler how to react on decoding errors
16381 const error_handler_t error_handler;
16382 };
16383 } // namespace detail
16384 } // namespace nlohmann
16385
16386 // #include <nlohmann/detail/value_t.hpp>
16387
16388 // #include <nlohmann/json_fwd.hpp>
16389
16390 // #include <nlohmann/ordered_map.hpp>
16391
16392
16393 #include <functional> // less
16394 #include <memory> // allocator
16395 #include <utility> // pair
16396 #include <vector> // vector
16397
16398 namespace nlohmann
16399 {
16400
16401 /// ordered_map: a minimal map-like container that preserves insertion order
16402 /// for use within nlohmann::basic_json<ordered_map>
16403 template <class Key, class T, class IgnoredLess = std::less<Key>,
16404 class Allocator = std::allocator<std::pair<const Key, T>>>
16405 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
16406 {
16407 using key_type = Key;
16408 using mapped_type = T;
16409 using Container = std::vector<std::pair<const Key, T>, Allocator>;
16410 using typename Container::iterator;
16411 using typename Container::const_iterator;
16412 using typename Container::size_type;
16413 using typename Container::value_type;
16414
16415 // Explicit constructors instead of `using Container::Container`
16416 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
ordered_mapnlohmann::ordered_map16417 ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {}
16418 template <class It>
ordered_mapnlohmann::ordered_map16419 ordered_map(It first, It last, const Allocator& alloc = Allocator())
16420 : Container{first, last, alloc} {}
ordered_mapnlohmann::ordered_map16421 ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator() )
16422 : Container{init, alloc} {}
16423
emplacenlohmann::ordered_map16424 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
16425 {
16426 for (auto it = this->begin(); it != this->end(); ++it)
16427 {
16428 if (it->first == key)
16429 {
16430 return {it, false};
16431 }
16432 }
16433 Container::emplace_back(key, t);
16434 return {--this->end(), true};
16435 }
16436
operator []nlohmann::ordered_map16437 T& operator[](const Key& key)
16438 {
16439 return emplace(key, T{}).first->second;
16440 }
16441
operator []nlohmann::ordered_map16442 const T& operator[](const Key& key) const
16443 {
16444 return at(key);
16445 }
16446
atnlohmann::ordered_map16447 T& at(const Key& key)
16448 {
16449 for (auto it = this->begin(); it != this->end(); ++it)
16450 {
16451 if (it->first == key)
16452 {
16453 return it->second;
16454 }
16455 }
16456
16457 JSON_THROW(std::out_of_range("key not found"));
16458 }
16459
atnlohmann::ordered_map16460 const T& at(const Key& key) const
16461 {
16462 for (auto it = this->begin(); it != this->end(); ++it)
16463 {
16464 if (it->first == key)
16465 {
16466 return it->second;
16467 }
16468 }
16469
16470 JSON_THROW(std::out_of_range("key not found"));
16471 }
16472
erasenlohmann::ordered_map16473 size_type erase(const Key& key)
16474 {
16475 for (auto it = this->begin(); it != this->end(); ++it)
16476 {
16477 if (it->first == key)
16478 {
16479 // Since we cannot move const Keys, re-construct them in place
16480 for (auto next = it; ++next != this->end(); ++it)
16481 {
16482 it->~value_type(); // Destroy but keep allocation
16483 new (&*it) value_type{std::move(*next)};
16484 }
16485 Container::pop_back();
16486 return 1;
16487 }
16488 }
16489 return 0;
16490 }
16491
erasenlohmann::ordered_map16492 iterator erase(iterator pos)
16493 {
16494 auto it = pos;
16495
16496 // Since we cannot move const Keys, re-construct them in place
16497 for (auto next = it; ++next != this->end(); ++it)
16498 {
16499 it->~value_type(); // Destroy but keep allocation
16500 new (&*it) value_type{std::move(*next)};
16501 }
16502 Container::pop_back();
16503 return pos;
16504 }
16505
countnlohmann::ordered_map16506 size_type count(const Key& key) const
16507 {
16508 for (auto it = this->begin(); it != this->end(); ++it)
16509 {
16510 if (it->first == key)
16511 {
16512 return 1;
16513 }
16514 }
16515 return 0;
16516 }
16517
findnlohmann::ordered_map16518 iterator find(const Key& key)
16519 {
16520 for (auto it = this->begin(); it != this->end(); ++it)
16521 {
16522 if (it->first == key)
16523 {
16524 return it;
16525 }
16526 }
16527 return Container::end();
16528 }
16529
findnlohmann::ordered_map16530 const_iterator find(const Key& key) const
16531 {
16532 for (auto it = this->begin(); it != this->end(); ++it)
16533 {
16534 if (it->first == key)
16535 {
16536 return it;
16537 }
16538 }
16539 return Container::end();
16540 }
16541
insertnlohmann::ordered_map16542 std::pair<iterator, bool> insert( value_type&& value )
16543 {
16544 return emplace(value.first, std::move(value.second));
16545 }
16546
insertnlohmann::ordered_map16547 std::pair<iterator, bool> insert( const value_type& value )
16548 {
16549 for (auto it = this->begin(); it != this->end(); ++it)
16550 {
16551 if (it->first == value.first)
16552 {
16553 return {it, false};
16554 }
16555 }
16556 Container::push_back(value);
16557 return {--this->end(), true};
16558 }
16559 };
16560
16561 } // namespace nlohmann
16562
16563
16564 /*!
16565 @brief namespace for Niels Lohmann
16566 @see https://github.com/nlohmann
16567 @since version 1.0.0
16568 */
16569 namespace nlohmann
16570 {
16571
16572 /*!
16573 @brief a class to store JSON values
16574
16575 @tparam ObjectType type for JSON objects (`std::map` by default; will be used
16576 in @ref object_t)
16577 @tparam ArrayType type for JSON arrays (`std::vector` by default; will be used
16578 in @ref array_t)
16579 @tparam StringType type for JSON strings and object keys (`std::string` by
16580 default; will be used in @ref string_t)
16581 @tparam BooleanType type for JSON booleans (`bool` by default; will be used
16582 in @ref boolean_t)
16583 @tparam NumberIntegerType type for JSON integer numbers (`int64_t` by
16584 default; will be used in @ref number_integer_t)
16585 @tparam NumberUnsignedType type for JSON unsigned integer numbers (@c
16586 `uint64_t` by default; will be used in @ref number_unsigned_t)
16587 @tparam NumberFloatType type for JSON floating-point numbers (`double` by
16588 default; will be used in @ref number_float_t)
16589 @tparam BinaryType type for packed binary data for compatibility with binary
16590 serialization formats (`std::vector<std::uint8_t>` by default; will be used in
16591 @ref binary_t)
16592 @tparam AllocatorType type of the allocator to use (`std::allocator` by
16593 default)
16594 @tparam JSONSerializer the serializer to resolve internal calls to `to_json()`
16595 and `from_json()` (@ref adl_serializer by default)
16596
16597 @requirement The class satisfies the following concept requirements:
16598 - Basic
16599 - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible):
16600 JSON values can be default constructed. The result will be a JSON null
16601 value.
16602 - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible):
16603 A JSON value can be constructed from an rvalue argument.
16604 - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible):
16605 A JSON value can be copy-constructed from an lvalue expression.
16606 - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable):
16607 A JSON value van be assigned from an rvalue argument.
16608 - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable):
16609 A JSON value can be copy-assigned from an lvalue expression.
16610 - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible):
16611 JSON values can be destructed.
16612 - Layout
16613 - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType):
16614 JSON values have
16615 [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
16616 All non-static data members are private and standard layout types, the
16617 class has no virtual functions or (virtual) base classes.
16618 - Library-wide
16619 - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable):
16620 JSON values can be compared with `==`, see @ref
16621 operator==(const_reference,const_reference).
16622 - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable):
16623 JSON values can be compared with `<`, see @ref
16624 operator<(const_reference,const_reference).
16625 - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable):
16626 Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
16627 other compatible types, using unqualified function call @ref swap().
16628 - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer):
16629 JSON values can be compared against `std::nullptr_t` objects which are used
16630 to model the `null` value.
16631 - Container
16632 - [Container](https://en.cppreference.com/w/cpp/named_req/Container):
16633 JSON values can be used like STL containers and provide iterator access.
16634 - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer);
16635 JSON values can be used like STL containers and provide reverse iterator
16636 access.
16637
16638 @invariant The member variables @a m_value and @a m_type have the following
16639 relationship:
16640 - If `m_type == value_t::object`, then `m_value.object != nullptr`.
16641 - If `m_type == value_t::array`, then `m_value.array != nullptr`.
16642 - If `m_type == value_t::string`, then `m_value.string != nullptr`.
16643 The invariants are checked by member function assert_invariant().
16644
16645 @internal
16646 @note ObjectType trick from https://stackoverflow.com/a/9860911
16647 @endinternal
16648
16649 @see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange
16650 Format](http://rfc7159.net/rfc7159)
16651
16652 @since version 1.0.0
16653
16654 @nosubgrouping
16655 */
16656 NLOHMANN_BASIC_JSON_TPL_DECLARATION
16657 class basic_json
16658 {
16659 private:
16660 template<detail::value_t> friend struct detail::external_constructor;
16661 friend ::nlohmann::json_pointer<basic_json>;
16662
16663 template<typename BasicJsonType, typename InputType>
16664 friend class ::nlohmann::detail::parser;
16665 friend ::nlohmann::detail::serializer<basic_json>;
16666 template<typename BasicJsonType>
16667 friend class ::nlohmann::detail::iter_impl;
16668 template<typename BasicJsonType, typename CharType>
16669 friend class ::nlohmann::detail::binary_writer;
16670 template<typename BasicJsonType, typename InputType, typename SAX>
16671 friend class ::nlohmann::detail::binary_reader;
16672 template<typename BasicJsonType>
16673 friend class ::nlohmann::detail::json_sax_dom_parser;
16674 template<typename BasicJsonType>
16675 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
16676
16677 /// workaround type for MSVC
16678 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
16679
16680 // convenience aliases for types residing in namespace detail;
16681 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
16682
16683 template<typename InputAdapterType>
parser(InputAdapterType adapter,detail::parser_callback_t<basic_json> cb=nullptr,const bool allow_exceptions=true,const bool ignore_comments=false)16684 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
16685 InputAdapterType adapter,
16686 detail::parser_callback_t<basic_json>cb = nullptr,
16687 const bool allow_exceptions = true,
16688 const bool ignore_comments = false
16689 )
16690 {
16691 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
16692 std::move(cb), allow_exceptions, ignore_comments);
16693 }
16694
16695 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
16696 template<typename BasicJsonType>
16697 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
16698 template<typename BasicJsonType>
16699 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
16700 template<typename Iterator>
16701 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
16702 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
16703
16704 template<typename CharType>
16705 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
16706
16707 template<typename InputType>
16708 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
16709 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
16710
16711 using serializer = ::nlohmann::detail::serializer<basic_json>;
16712
16713 public:
16714 using value_t = detail::value_t;
16715 /// JSON Pointer, see @ref nlohmann::json_pointer
16716 using json_pointer = ::nlohmann::json_pointer<basic_json>;
16717 template<typename T, typename SFINAE>
16718 using json_serializer = JSONSerializer<T, SFINAE>;
16719 /// how to treat decoding errors
16720 using error_handler_t = detail::error_handler_t;
16721 /// how to treat CBOR tags
16722 using cbor_tag_handler_t = detail::cbor_tag_handler_t;
16723 /// helper type for initializer lists of basic_json values
16724 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
16725
16726 using input_format_t = detail::input_format_t;
16727 /// SAX interface type, see @ref nlohmann::json_sax
16728 using json_sax_t = json_sax<basic_json>;
16729
16730 ////////////////
16731 // exceptions //
16732 ////////////////
16733
16734 /// @name exceptions
16735 /// Classes to implement user-defined exceptions.
16736 /// @{
16737
16738 /// @copydoc detail::exception
16739 using exception = detail::exception;
16740 /// @copydoc detail::parse_error
16741 using parse_error = detail::parse_error;
16742 /// @copydoc detail::invalid_iterator
16743 using invalid_iterator = detail::invalid_iterator;
16744 /// @copydoc detail::type_error
16745 using type_error = detail::type_error;
16746 /// @copydoc detail::out_of_range
16747 using out_of_range = detail::out_of_range;
16748 /// @copydoc detail::other_error
16749 using other_error = detail::other_error;
16750
16751 /// @}
16752
16753
16754 /////////////////////
16755 // container types //
16756 /////////////////////
16757
16758 /// @name container types
16759 /// The canonic container types to use @ref basic_json like any other STL
16760 /// container.
16761 /// @{
16762
16763 /// the type of elements in a basic_json container
16764 using value_type = basic_json;
16765
16766 /// the type of an element reference
16767 using reference = value_type&;
16768 /// the type of an element const reference
16769 using const_reference = const value_type&;
16770
16771 /// a type to represent differences between iterators
16772 using difference_type = std::ptrdiff_t;
16773 /// a type to represent container sizes
16774 using size_type = std::size_t;
16775
16776 /// the allocator type
16777 using allocator_type = AllocatorType<basic_json>;
16778
16779 /// the type of an element pointer
16780 using pointer = typename std::allocator_traits<allocator_type>::pointer;
16781 /// the type of an element const pointer
16782 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
16783
16784 /// an iterator for a basic_json container
16785 using iterator = iter_impl<basic_json>;
16786 /// a const iterator for a basic_json container
16787 using const_iterator = iter_impl<const basic_json>;
16788 /// a reverse iterator for a basic_json container
16789 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
16790 /// a const reverse iterator for a basic_json container
16791 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
16792
16793 /// @}
16794
16795
16796 /*!
16797 @brief returns the allocator associated with the container
16798 */
get_allocator()16799 static allocator_type get_allocator()
16800 {
16801 return allocator_type();
16802 }
16803
16804 /*!
16805 @brief returns version information on the library
16806
16807 This function returns a JSON object with information about the library,
16808 including the version number and information on the platform and compiler.
16809
16810 @return JSON object holding version information
16811 key | description
16812 ----------- | ---------------
16813 `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).
16814 `copyright` | The copyright line for the library as string.
16815 `name` | The name of the library as string.
16816 `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`.
16817 `url` | The URL of the project as string.
16818 `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string).
16819
16820 @liveexample{The following code shows an example output of the `meta()`
16821 function.,meta}
16822
16823 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
16824 changes to any JSON value.
16825
16826 @complexity Constant.
16827
16828 @since 2.1.0
16829 */
16830 JSON_HEDLEY_WARN_UNUSED_RESULT
meta()16831 static basic_json meta()
16832 {
16833 basic_json result;
16834
16835 result["copyright"] = "(C) 2013-2020 Niels Lohmann";
16836 result["name"] = "JSON for Modern C++";
16837 result["url"] = "https://github.com/nlohmann/json";
16838 result["version"]["string"] =
16839 std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
16840 std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
16841 std::to_string(NLOHMANN_JSON_VERSION_PATCH);
16842 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
16843 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
16844 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
16845
16846 #ifdef _WIN32
16847 result["platform"] = "win32";
16848 #elif defined __linux__
16849 result["platform"] = "linux";
16850 #elif defined __APPLE__
16851 result["platform"] = "apple";
16852 #elif defined __unix__
16853 result["platform"] = "unix";
16854 #else
16855 result["platform"] = "unknown";
16856 #endif
16857
16858 #if defined(__ICC) || defined(__INTEL_COMPILER)
16859 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
16860 #elif defined(__clang__)
16861 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
16862 #elif defined(__GNUC__) || defined(__GNUG__)
16863 result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
16864 #elif defined(__HP_cc) || defined(__HP_aCC)
16865 result["compiler"] = "hp"
16866 #elif defined(__IBMCPP__)
16867 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
16868 #elif defined(_MSC_VER)
16869 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
16870 #elif defined(__PGI)
16871 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
16872 #elif defined(__SUNPRO_CC)
16873 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
16874 #else
16875 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
16876 #endif
16877
16878 #ifdef __cplusplus
16879 result["compiler"]["c++"] = std::to_string(__cplusplus);
16880 #else
16881 result["compiler"]["c++"] = "unknown";
16882 #endif
16883 return result;
16884 }
16885
16886
16887 ///////////////////////////
16888 // JSON value data types //
16889 ///////////////////////////
16890
16891 /// @name JSON value data types
16892 /// The data types to store a JSON value. These types are derived from
16893 /// the template arguments passed to class @ref basic_json.
16894 /// @{
16895
16896 #if defined(JSON_HAS_CPP_14)
16897 // Use transparent comparator if possible, combined with perfect forwarding
16898 // on find() and count() calls prevents unnecessary string construction.
16899 using object_comparator_t = std::less<>;
16900 #else
16901 using object_comparator_t = std::less<StringType>;
16902 #endif
16903
16904 /*!
16905 @brief a type for an object
16906
16907 [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:
16908 > An object is an unordered collection of zero or more name/value pairs,
16909 > where a name is a string and a value is a string, number, boolean, null,
16910 > object, or array.
16911
16912 To store objects in C++, a type is defined by the template parameters
16913 described below.
16914
16915 @tparam ObjectType the container to store objects (e.g., `std::map` or
16916 `std::unordered_map`)
16917 @tparam StringType the type of the keys or names (e.g., `std::string`).
16918 The comparison function `std::less<StringType>` is used to order elements
16919 inside the container.
16920 @tparam AllocatorType the allocator to use for objects (e.g.,
16921 `std::allocator`)
16922
16923 #### Default type
16924
16925 With the default values for @a ObjectType (`std::map`), @a StringType
16926 (`std::string`), and @a AllocatorType (`std::allocator`), the default
16927 value for @a object_t is:
16928
16929 @code {.cpp}
16930 std::map<
16931 std::string, // key_type
16932 basic_json, // value_type
16933 std::less<std::string>, // key_compare
16934 std::allocator<std::pair<const std::string, basic_json>> // allocator_type
16935 >
16936 @endcode
16937
16938 #### Behavior
16939
16940 The choice of @a object_t influences the behavior of the JSON class. With
16941 the default type, objects have the following behavior:
16942
16943 - When all names are unique, objects will be interoperable in the sense
16944 that all software implementations receiving that object will agree on
16945 the name-value mappings.
16946 - When the names within an object are not unique, it is unspecified which
16947 one of the values for a given key will be chosen. For instance,
16948 `{"key": 2, "key": 1}` could be equal to either `{"key": 1}` or
16949 `{"key": 2}`.
16950 - Internally, name/value pairs are stored in lexicographical order of the
16951 names. Objects will also be serialized (see @ref dump) in this order.
16952 For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored
16953 and serialized as `{"a": 2, "b": 1}`.
16954 - When comparing objects, the order of the name/value pairs is irrelevant.
16955 This makes objects interoperable in the sense that they will not be
16956 affected by these differences. For instance, `{"b": 1, "a": 2}` and
16957 `{"a": 2, "b": 1}` will be treated as equal.
16958
16959 #### Limits
16960
16961 [RFC 7159](http://rfc7159.net/rfc7159) specifies:
16962 > An implementation may set limits on the maximum depth of nesting.
16963
16964 In this class, the object's limit of nesting is not explicitly constrained.
16965 However, a maximum depth of nesting may be introduced by the compiler or
16966 runtime environment. A theoretical limit can be queried by calling the
16967 @ref max_size function of a JSON object.
16968
16969 #### Storage
16970
16971 Objects are stored as pointers in a @ref basic_json type. That is, for any
16972 access to object values, a pointer of type `object_t*` must be
16973 dereferenced.
16974
16975 @sa @ref array_t -- type for an array value
16976
16977 @since version 1.0.0
16978
16979 @note The order name/value pairs are added to the object is *not*
16980 preserved by the library. Therefore, iterating an object may return
16981 name/value pairs in a different order than they were originally stored. In
16982 fact, keys will be traversed in alphabetical order as `std::map` with
16983 `std::less` is used by default. Please note this behavior conforms to [RFC
16984 7159](http://rfc7159.net/rfc7159), because any order implements the
16985 specified "unordered" nature of JSON objects.
16986 */
16987 using object_t = ObjectType<StringType,
16988 basic_json,
16989 object_comparator_t,
16990 AllocatorType<std::pair<const StringType,
16991 basic_json>>>;
16992
16993 /*!
16994 @brief a type for an array
16995
16996 [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:
16997 > An array is an ordered sequence of zero or more values.
16998
16999 To store objects in C++, a type is defined by the template parameters
17000 explained below.
17001
17002 @tparam ArrayType container type to store arrays (e.g., `std::vector` or
17003 `std::list`)
17004 @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)
17005
17006 #### Default type
17007
17008 With the default values for @a ArrayType (`std::vector`) and @a
17009 AllocatorType (`std::allocator`), the default value for @a array_t is:
17010
17011 @code {.cpp}
17012 std::vector<
17013 basic_json, // value_type
17014 std::allocator<basic_json> // allocator_type
17015 >
17016 @endcode
17017
17018 #### Limits
17019
17020 [RFC 7159](http://rfc7159.net/rfc7159) specifies:
17021 > An implementation may set limits on the maximum depth of nesting.
17022
17023 In this class, the array's limit of nesting is not explicitly constrained.
17024 However, a maximum depth of nesting may be introduced by the compiler or
17025 runtime environment. A theoretical limit can be queried by calling the
17026 @ref max_size function of a JSON array.
17027
17028 #### Storage
17029
17030 Arrays are stored as pointers in a @ref basic_json type. That is, for any
17031 access to array values, a pointer of type `array_t*` must be dereferenced.
17032
17033 @sa @ref object_t -- type for an object value
17034
17035 @since version 1.0.0
17036 */
17037 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
17038
17039 /*!
17040 @brief a type for a string
17041
17042 [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:
17043 > A string is a sequence of zero or more Unicode characters.
17044
17045 To store objects in C++, a type is defined by the template parameter
17046 described below. Unicode values are split by the JSON class into
17047 byte-sized characters during deserialization.
17048
17049 @tparam StringType the container to store strings (e.g., `std::string`).
17050 Note this container is used for keys/names in objects, see @ref object_t.
17051
17052 #### Default type
17053
17054 With the default values for @a StringType (`std::string`), the default
17055 value for @a string_t is:
17056
17057 @code {.cpp}
17058 std::string
17059 @endcode
17060
17061 #### Encoding
17062
17063 Strings are stored in UTF-8 encoding. Therefore, functions like
17064 `std::string::size()` or `std::string::length()` return the number of
17065 bytes in the string rather than the number of characters or glyphs.
17066
17067 #### String comparison
17068
17069 [RFC 7159](http://rfc7159.net/rfc7159) states:
17070 > Software implementations are typically required to test names of object
17071 > members for equality. Implementations that transform the textual
17072 > representation into sequences of Unicode code units and then perform the
17073 > comparison numerically, code unit by code unit, are interoperable in the
17074 > sense that implementations will agree in all cases on equality or
17075 > inequality of two strings. For example, implementations that compare
17076 > strings with escaped characters unconverted may incorrectly find that
17077 > `"a\\b"` and `"a\u005Cb"` are not equal.
17078
17079 This implementation is interoperable as it does compare strings code unit
17080 by code unit.
17081
17082 #### Storage
17083
17084 String values are stored as pointers in a @ref basic_json type. That is,
17085 for any access to string values, a pointer of type `string_t*` must be
17086 dereferenced.
17087
17088 @since version 1.0.0
17089 */
17090 using string_t = StringType;
17091
17092 /*!
17093 @brief a type for a boolean
17094
17095 [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a
17096 type which differentiates the two literals `true` and `false`.
17097
17098 To store objects in C++, a type is defined by the template parameter @a
17099 BooleanType which chooses the type to use.
17100
17101 #### Default type
17102
17103 With the default values for @a BooleanType (`bool`), the default value for
17104 @a boolean_t is:
17105
17106 @code {.cpp}
17107 bool
17108 @endcode
17109
17110 #### Storage
17111
17112 Boolean values are stored directly inside a @ref basic_json type.
17113
17114 @since version 1.0.0
17115 */
17116 using boolean_t = BooleanType;
17117
17118 /*!
17119 @brief a type for a number (integer)
17120
17121 [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
17122 > The representation of numbers is similar to that used in most
17123 > programming languages. A number is represented in base 10 using decimal
17124 > digits. It contains an integer component that may be prefixed with an
17125 > optional minus sign, which may be followed by a fraction part and/or an
17126 > exponent part. Leading zeros are not allowed. (...) Numeric values that
17127 > cannot be represented in the grammar below (such as Infinity and NaN)
17128 > are not permitted.
17129
17130 This description includes both integer and floating-point numbers.
17131 However, C++ allows more precise storage if it is known whether the number
17132 is a signed integer, an unsigned integer or a floating-point number.
17133 Therefore, three different types, @ref number_integer_t, @ref
17134 number_unsigned_t and @ref number_float_t are used.
17135
17136 To store integer numbers in C++, a type is defined by the template
17137 parameter @a NumberIntegerType which chooses the type to use.
17138
17139 #### Default type
17140
17141 With the default values for @a NumberIntegerType (`int64_t`), the default
17142 value for @a number_integer_t is:
17143
17144 @code {.cpp}
17145 int64_t
17146 @endcode
17147
17148 #### Default behavior
17149
17150 - The restrictions about leading zeros is not enforced in C++. Instead,
17151 leading zeros in integer literals lead to an interpretation as octal
17152 number. Internally, the value will be stored as decimal number. For
17153 instance, the C++ integer literal `010` will be serialized to `8`.
17154 During deserialization, leading zeros yield an error.
17155 - Not-a-number (NaN) values will be serialized to `null`.
17156
17157 #### Limits
17158
17159 [RFC 7159](http://rfc7159.net/rfc7159) specifies:
17160 > An implementation may set limits on the range and precision of numbers.
17161
17162 When the default type is used, the maximal integer number that can be
17163 stored is `9223372036854775807` (INT64_MAX) and the minimal integer number
17164 that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
17165 that are out of range will yield over/underflow when used in a
17166 constructor. During deserialization, too large or small integer numbers
17167 will be automatically be stored as @ref number_unsigned_t or @ref
17168 number_float_t.
17169
17170 [RFC 7159](http://rfc7159.net/rfc7159) further states:
17171 > Note that when such software is used, numbers that are integers and are
17172 > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
17173 > that implementations will agree exactly on their numeric values.
17174
17175 As this range is a subrange of the exactly supported range [INT64_MIN,
17176 INT64_MAX], this class's integer type is interoperable.
17177
17178 #### Storage
17179
17180 Integer number values are stored directly inside a @ref basic_json type.
17181
17182 @sa @ref number_float_t -- type for number values (floating-point)
17183
17184 @sa @ref number_unsigned_t -- type for number values (unsigned integer)
17185
17186 @since version 1.0.0
17187 */
17188 using number_integer_t = NumberIntegerType;
17189
17190 /*!
17191 @brief a type for a number (unsigned)
17192
17193 [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
17194 > The representation of numbers is similar to that used in most
17195 > programming languages. A number is represented in base 10 using decimal
17196 > digits. It contains an integer component that may be prefixed with an
17197 > optional minus sign, which may be followed by a fraction part and/or an
17198 > exponent part. Leading zeros are not allowed. (...) Numeric values that
17199 > cannot be represented in the grammar below (such as Infinity and NaN)
17200 > are not permitted.
17201
17202 This description includes both integer and floating-point numbers.
17203 However, C++ allows more precise storage if it is known whether the number
17204 is a signed integer, an unsigned integer or a floating-point number.
17205 Therefore, three different types, @ref number_integer_t, @ref
17206 number_unsigned_t and @ref number_float_t are used.
17207
17208 To store unsigned integer numbers in C++, a type is defined by the
17209 template parameter @a NumberUnsignedType which chooses the type to use.
17210
17211 #### Default type
17212
17213 With the default values for @a NumberUnsignedType (`uint64_t`), the
17214 default value for @a number_unsigned_t is:
17215
17216 @code {.cpp}
17217 uint64_t
17218 @endcode
17219
17220 #### Default behavior
17221
17222 - The restrictions about leading zeros is not enforced in C++. Instead,
17223 leading zeros in integer literals lead to an interpretation as octal
17224 number. Internally, the value will be stored as decimal number. For
17225 instance, the C++ integer literal `010` will be serialized to `8`.
17226 During deserialization, leading zeros yield an error.
17227 - Not-a-number (NaN) values will be serialized to `null`.
17228
17229 #### Limits
17230
17231 [RFC 7159](http://rfc7159.net/rfc7159) specifies:
17232 > An implementation may set limits on the range and precision of numbers.
17233
17234 When the default type is used, the maximal integer number that can be
17235 stored is `18446744073709551615` (UINT64_MAX) and the minimal integer
17236 number that can be stored is `0`. Integer numbers that are out of range
17237 will yield over/underflow when used in a constructor. During
17238 deserialization, too large or small integer numbers will be automatically
17239 be stored as @ref number_integer_t or @ref number_float_t.
17240
17241 [RFC 7159](http://rfc7159.net/rfc7159) further states:
17242 > Note that when such software is used, numbers that are integers and are
17243 > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
17244 > that implementations will agree exactly on their numeric values.
17245
17246 As this range is a subrange (when considered in conjunction with the
17247 number_integer_t type) of the exactly supported range [0, UINT64_MAX],
17248 this class's integer type is interoperable.
17249
17250 #### Storage
17251
17252 Integer number values are stored directly inside a @ref basic_json type.
17253
17254 @sa @ref number_float_t -- type for number values (floating-point)
17255 @sa @ref number_integer_t -- type for number values (integer)
17256
17257 @since version 2.0.0
17258 */
17259 using number_unsigned_t = NumberUnsignedType;
17260
17261 /*!
17262 @brief a type for a number (floating-point)
17263
17264 [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
17265 > The representation of numbers is similar to that used in most
17266 > programming languages. A number is represented in base 10 using decimal
17267 > digits. It contains an integer component that may be prefixed with an
17268 > optional minus sign, which may be followed by a fraction part and/or an
17269 > exponent part. Leading zeros are not allowed. (...) Numeric values that
17270 > cannot be represented in the grammar below (such as Infinity and NaN)
17271 > are not permitted.
17272
17273 This description includes both integer and floating-point numbers.
17274 However, C++ allows more precise storage if it is known whether the number
17275 is a signed integer, an unsigned integer or a floating-point number.
17276 Therefore, three different types, @ref number_integer_t, @ref
17277 number_unsigned_t and @ref number_float_t are used.
17278
17279 To store floating-point numbers in C++, a type is defined by the template
17280 parameter @a NumberFloatType which chooses the type to use.
17281
17282 #### Default type
17283
17284 With the default values for @a NumberFloatType (`double`), the default
17285 value for @a number_float_t is:
17286
17287 @code {.cpp}
17288 double
17289 @endcode
17290
17291 #### Default behavior
17292
17293 - The restrictions about leading zeros is not enforced in C++. Instead,
17294 leading zeros in floating-point literals will be ignored. Internally,
17295 the value will be stored as decimal number. For instance, the C++
17296 floating-point literal `01.2` will be serialized to `1.2`. During
17297 deserialization, leading zeros yield an error.
17298 - Not-a-number (NaN) values will be serialized to `null`.
17299
17300 #### Limits
17301
17302 [RFC 7159](http://rfc7159.net/rfc7159) states:
17303 > This specification allows implementations to set limits on the range and
17304 > precision of numbers accepted. Since software that implements IEEE
17305 > 754-2008 binary64 (double precision) numbers is generally available and
17306 > widely used, good interoperability can be achieved by implementations
17307 > that expect no more precision or range than these provide, in the sense
17308 > that implementations will approximate JSON numbers within the expected
17309 > precision.
17310
17311 This implementation does exactly follow this approach, as it uses double
17312 precision floating-point numbers. Note values smaller than
17313 `-1.79769313486232e+308` and values greater than `1.79769313486232e+308`
17314 will be stored as NaN internally and be serialized to `null`.
17315
17316 #### Storage
17317
17318 Floating-point number values are stored directly inside a @ref basic_json
17319 type.
17320
17321 @sa @ref number_integer_t -- type for number values (integer)
17322
17323 @sa @ref number_unsigned_t -- type for number values (unsigned integer)
17324
17325 @since version 1.0.0
17326 */
17327 using number_float_t = NumberFloatType;
17328
17329 /*!
17330 @brief a type for a packed binary type
17331
17332 This type is a type designed to carry binary data that appears in various
17333 serialized formats, such as CBOR's Major Type 2, MessagePack's bin, and
17334 BSON's generic binary subtype. This type is NOT a part of standard JSON and
17335 exists solely for compatibility with these binary types. As such, it is
17336 simply defined as an ordered sequence of zero or more byte values.
17337
17338 Additionally, as an implementation detail, the subtype of the binary data is
17339 carried around as a `std::uint8_t`, which is compatible with both of the
17340 binary data formats that use binary subtyping, (though the specific
17341 numbering is incompatible with each other, and it is up to the user to
17342 translate between them).
17343
17344 [CBOR's RFC 7049](https://tools.ietf.org/html/rfc7049) describes this type
17345 as:
17346 > Major type 2: a byte string. The string's length in bytes is represented
17347 > following the rules for positive integers (major type 0).
17348
17349 [MessagePack's documentation on the bin type
17350 family](https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family)
17351 describes this type as:
17352 > Bin format family stores an byte array in 2, 3, or 5 bytes of extra bytes
17353 > in addition to the size of the byte array.
17354
17355 [BSON's specifications](http://bsonspec.org/spec.html) describe several
17356 binary types; however, this type is intended to represent the generic binary
17357 type which has the description:
17358 > Generic binary subtype - This is the most commonly used binary subtype and
17359 > should be the 'default' for drivers and tools.
17360
17361 None of these impose any limitations on the internal representation other
17362 than the basic unit of storage be some type of array whose parts are
17363 decomposable into bytes.
17364
17365 The default representation of this binary format is a
17366 `std::vector<std::uint8_t>`, which is a very common way to represent a byte
17367 array in modern C++.
17368
17369 #### Default type
17370
17371 The default values for @a BinaryType is `std::vector<std::uint8_t>`
17372
17373 #### Storage
17374
17375 Binary Arrays are stored as pointers in a @ref basic_json type. That is,
17376 for any access to array values, a pointer of the type `binary_t*` must be
17377 dereferenced.
17378
17379 #### Notes on subtypes
17380
17381 - CBOR
17382 - Binary values are represented as byte strings. No subtypes are
17383 supported and will be ignored when CBOR is written.
17384 - MessagePack
17385 - If a subtype is given and the binary array contains exactly 1, 2, 4, 8,
17386 or 16 elements, the fixext family (fixext1, fixext2, fixext4, fixext8)
17387 is used. For other sizes, the ext family (ext8, ext16, ext32) is used.
17388 The subtype is then added as singed 8-bit integer.
17389 - If no subtype is given, the bin family (bin8, bin16, bin32) is used.
17390 - BSON
17391 - If a subtype is given, it is used and added as unsigned 8-bit integer.
17392 - If no subtype is given, the generic binary subtype 0x00 is used.
17393
17394 @sa @ref binary -- create a binary array
17395
17396 @since version 3.8.0
17397 */
17398 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
17399 /// @}
17400
17401 private:
17402
17403 /// helper for exception-safe object creation
17404 template<typename T, typename... Args>
17405 JSON_HEDLEY_RETURNS_NON_NULL
create(Args &&...args)17406 static T* create(Args&& ... args)
17407 {
17408 AllocatorType<T> alloc;
17409 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
17410
17411 auto deleter = [&](T * object)
17412 {
17413 AllocatorTraits::deallocate(alloc, object, 1);
17414 };
17415 std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
17416 AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
17417 JSON_ASSERT(object != nullptr);
17418 return object.release();
17419 }
17420
17421 ////////////////////////
17422 // JSON value storage //
17423 ////////////////////////
17424
17425 /*!
17426 @brief a JSON value
17427
17428 The actual storage for a JSON value of the @ref basic_json class. This
17429 union combines the different storage types for the JSON value types
17430 defined in @ref value_t.
17431
17432 JSON type | value_t type | used type
17433 --------- | --------------- | ------------------------
17434 object | object | pointer to @ref object_t
17435 array | array | pointer to @ref array_t
17436 string | string | pointer to @ref string_t
17437 boolean | boolean | @ref boolean_t
17438 number | number_integer | @ref number_integer_t
17439 number | number_unsigned | @ref number_unsigned_t
17440 number | number_float | @ref number_float_t
17441 binary | binary | pointer to @ref binary_t
17442 null | null | *no value is stored*
17443
17444 @note Variable-length types (objects, arrays, and strings) are stored as
17445 pointers. The size of the union should not exceed 64 bits if the default
17446 value types are used.
17447
17448 @since version 1.0.0
17449 */
17450 union json_value
17451 {
17452 /// object (stored with pointer to save storage)
17453 object_t* object;
17454 /// array (stored with pointer to save storage)
17455 array_t* array;
17456 /// string (stored with pointer to save storage)
17457 string_t* string;
17458 /// binary (stored with pointer to save storage)
17459 binary_t* binary;
17460 /// boolean
17461 boolean_t boolean;
17462 /// number (integer)
17463 number_integer_t number_integer;
17464 /// number (unsigned integer)
17465 number_unsigned_t number_unsigned;
17466 /// number (floating-point)
17467 number_float_t number_float;
17468
17469 /// default constructor (for null values)
17470 json_value() = default;
17471 /// constructor for booleans
json_value(boolean_t v)17472 json_value(boolean_t v) noexcept : boolean(v) {}
17473 /// constructor for numbers (integer)
json_value(number_integer_t v)17474 json_value(number_integer_t v) noexcept : number_integer(v) {}
17475 /// constructor for numbers (unsigned)
json_value(number_unsigned_t v)17476 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
17477 /// constructor for numbers (floating-point)
json_value(number_float_t v)17478 json_value(number_float_t v) noexcept : number_float(v) {}
17479 /// constructor for empty values of a given type
json_value(value_t t)17480 json_value(value_t t)
17481 {
17482 switch (t)
17483 {
17484 case value_t::object:
17485 {
17486 object = create<object_t>();
17487 break;
17488 }
17489
17490 case value_t::array:
17491 {
17492 array = create<array_t>();
17493 break;
17494 }
17495
17496 case value_t::string:
17497 {
17498 string = create<string_t>("");
17499 break;
17500 }
17501
17502 case value_t::binary:
17503 {
17504 binary = create<binary_t>();
17505 break;
17506 }
17507
17508 case value_t::boolean:
17509 {
17510 boolean = boolean_t(false);
17511 break;
17512 }
17513
17514 case value_t::number_integer:
17515 {
17516 number_integer = number_integer_t(0);
17517 break;
17518 }
17519
17520 case value_t::number_unsigned:
17521 {
17522 number_unsigned = number_unsigned_t(0);
17523 break;
17524 }
17525
17526 case value_t::number_float:
17527 {
17528 number_float = number_float_t(0.0);
17529 break;
17530 }
17531
17532 case value_t::null:
17533 {
17534 object = nullptr; // silence warning, see #821
17535 break;
17536 }
17537
17538 default:
17539 {
17540 object = nullptr; // silence warning, see #821
17541 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
17542 {
17543 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.9.1")); // LCOV_EXCL_LINE
17544 }
17545 break;
17546 }
17547 }
17548 }
17549
17550 /// constructor for strings
json_value(const string_t & value)17551 json_value(const string_t& value)
17552 {
17553 string = create<string_t>(value);
17554 }
17555
17556 /// constructor for rvalue strings
json_value(string_t && value)17557 json_value(string_t&& value)
17558 {
17559 string = create<string_t>(std::move(value));
17560 }
17561
17562 /// constructor for objects
json_value(const object_t & value)17563 json_value(const object_t& value)
17564 {
17565 object = create<object_t>(value);
17566 }
17567
17568 /// constructor for rvalue objects
json_value(object_t && value)17569 json_value(object_t&& value)
17570 {
17571 object = create<object_t>(std::move(value));
17572 }
17573
17574 /// constructor for arrays
json_value(const array_t & value)17575 json_value(const array_t& value)
17576 {
17577 array = create<array_t>(value);
17578 }
17579
17580 /// constructor for rvalue arrays
json_value(array_t && value)17581 json_value(array_t&& value)
17582 {
17583 array = create<array_t>(std::move(value));
17584 }
17585
17586 /// constructor for binary arrays
json_value(const typename binary_t::container_type & value)17587 json_value(const typename binary_t::container_type& value)
17588 {
17589 binary = create<binary_t>(value);
17590 }
17591
17592 /// constructor for rvalue binary arrays
json_value(typename binary_t::container_type && value)17593 json_value(typename binary_t::container_type&& value)
17594 {
17595 binary = create<binary_t>(std::move(value));
17596 }
17597
17598 /// constructor for binary arrays (internal type)
json_value(const binary_t & value)17599 json_value(const binary_t& value)
17600 {
17601 binary = create<binary_t>(value);
17602 }
17603
17604 /// constructor for rvalue binary arrays (internal type)
json_value(binary_t && value)17605 json_value(binary_t&& value)
17606 {
17607 binary = create<binary_t>(std::move(value));
17608 }
17609
destroy(value_t t)17610 void destroy(value_t t) noexcept
17611 {
17612 // flatten the current json_value to a heap-allocated stack
17613 std::vector<basic_json> stack;
17614
17615 // move the top-level items to stack
17616 if (t == value_t::array)
17617 {
17618 stack.reserve(array->size());
17619 std::move(array->begin(), array->end(), std::back_inserter(stack));
17620 }
17621 else if (t == value_t::object)
17622 {
17623 stack.reserve(object->size());
17624 for (auto&& it : *object)
17625 {
17626 stack.push_back(std::move(it.second));
17627 }
17628 }
17629
17630 while (!stack.empty())
17631 {
17632 // move the last item to local variable to be processed
17633 basic_json current_item(std::move(stack.back()));
17634 stack.pop_back();
17635
17636 // if current_item is array/object, move
17637 // its children to the stack to be processed later
17638 if (current_item.is_array())
17639 {
17640 std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(),
17641 std::back_inserter(stack));
17642
17643 current_item.m_value.array->clear();
17644 }
17645 else if (current_item.is_object())
17646 {
17647 for (auto&& it : *current_item.m_value.object)
17648 {
17649 stack.push_back(std::move(it.second));
17650 }
17651
17652 current_item.m_value.object->clear();
17653 }
17654
17655 // it's now safe that current_item get destructed
17656 // since it doesn't have any children
17657 }
17658
17659 switch (t)
17660 {
17661 case value_t::object:
17662 {
17663 AllocatorType<object_t> alloc;
17664 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
17665 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
17666 break;
17667 }
17668
17669 case value_t::array:
17670 {
17671 AllocatorType<array_t> alloc;
17672 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
17673 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
17674 break;
17675 }
17676
17677 case value_t::string:
17678 {
17679 AllocatorType<string_t> alloc;
17680 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
17681 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
17682 break;
17683 }
17684
17685 case value_t::binary:
17686 {
17687 AllocatorType<binary_t> alloc;
17688 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
17689 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
17690 break;
17691 }
17692
17693 default:
17694 {
17695 break;
17696 }
17697 }
17698 }
17699 };
17700
17701 /*!
17702 @brief checks the class invariants
17703
17704 This function asserts the class invariants. It needs to be called at the
17705 end of every constructor to make sure that created objects respect the
17706 invariant. Furthermore, it has to be called each time the type of a JSON
17707 value is changed, because the invariant expresses a relationship between
17708 @a m_type and @a m_value.
17709 */
assert_invariant() const17710 void assert_invariant() const noexcept
17711 {
17712 JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
17713 JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
17714 JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
17715 JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
17716 }
17717
17718 public:
17719 //////////////////////////
17720 // JSON parser callback //
17721 //////////////////////////
17722
17723 /*!
17724 @brief parser event types
17725
17726 The parser callback distinguishes the following events:
17727 - `object_start`: the parser read `{` and started to process a JSON object
17728 - `key`: the parser read a key of a value in an object
17729 - `object_end`: the parser read `}` and finished processing a JSON object
17730 - `array_start`: the parser read `[` and started to process a JSON array
17731 - `array_end`: the parser read `]` and finished processing a JSON array
17732 - `value`: the parser finished reading a JSON value
17733
17734 @image html callback_events.png "Example when certain parse events are triggered"
17735
17736 @sa @ref parser_callback_t for more information and examples
17737 */
17738 using parse_event_t = detail::parse_event_t;
17739
17740 /*!
17741 @brief per-element parser callback type
17742
17743 With a parser callback function, the result of parsing a JSON text can be
17744 influenced. When passed to @ref parse, it is called on certain events
17745 (passed as @ref parse_event_t via parameter @a event) with a set recursion
17746 depth @a depth and context JSON value @a parsed. The return value of the
17747 callback function is a boolean indicating whether the element that emitted
17748 the callback shall be kept or not.
17749
17750 We distinguish six scenarios (determined by the event type) in which the
17751 callback function can be called. The following table describes the values
17752 of the parameters @a depth, @a event, and @a parsed.
17753
17754 parameter @a event | description | parameter @a depth | parameter @a parsed
17755 ------------------ | ----------- | ------------------ | -------------------
17756 parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded
17757 parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key
17758 parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object
17759 parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded
17760 parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
17761 parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
17762
17763 @image html callback_events.png "Example when certain parse events are triggered"
17764
17765 Discarding a value (i.e., returning `false`) has different effects
17766 depending on the context in which function was called:
17767
17768 - Discarded values in structured types are skipped. That is, the parser
17769 will behave as if the discarded value was never read.
17770 - In case a value outside a structured type is skipped, it is replaced
17771 with `null`. This case happens if the top-level element is skipped.
17772
17773 @param[in] depth the depth of the recursion during parsing
17774
17775 @param[in] event an event of type parse_event_t indicating the context in
17776 the callback function has been called
17777
17778 @param[in,out] parsed the current intermediate parse result; note that
17779 writing to this value has no effect for parse_event_t::key events
17780
17781 @return Whether the JSON value which called the function during parsing
17782 should be kept (`true`) or not (`false`). In the latter case, it is either
17783 skipped completely or replaced by an empty discarded object.
17784
17785 @sa @ref parse for examples
17786
17787 @since version 1.0.0
17788 */
17789 using parser_callback_t = detail::parser_callback_t<basic_json>;
17790
17791 //////////////////
17792 // constructors //
17793 //////////////////
17794
17795 /// @name constructors and destructors
17796 /// Constructors of class @ref basic_json, copy/move constructor, copy
17797 /// assignment, static functions creating objects, and the destructor.
17798 /// @{
17799
17800 /*!
17801 @brief create an empty value with a given type
17802
17803 Create an empty JSON value with a given type. The value will be default
17804 initialized with an empty value which depends on the type:
17805
17806 Value type | initial value
17807 ----------- | -------------
17808 null | `null`
17809 boolean | `false`
17810 string | `""`
17811 number | `0`
17812 object | `{}`
17813 array | `[]`
17814 binary | empty array
17815
17816 @param[in] v the type of the value to create
17817
17818 @complexity Constant.
17819
17820 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
17821 changes to any JSON value.
17822
17823 @liveexample{The following code shows the constructor for different @ref
17824 value_t values,basic_json__value_t}
17825
17826 @sa @ref clear() -- restores the postcondition of this constructor
17827
17828 @since version 1.0.0
17829 */
basic_json(const value_t v)17830 basic_json(const value_t v)
17831 : m_type(v), m_value(v)
17832 {
17833 assert_invariant();
17834 }
17835
17836 /*!
17837 @brief create a null object
17838
17839 Create a `null` JSON value. It either takes a null pointer as parameter
17840 (explicitly creating `null`) or no parameter (implicitly creating `null`).
17841 The passed null pointer itself is not read -- it is only used to choose
17842 the right constructor.
17843
17844 @complexity Constant.
17845
17846 @exceptionsafety No-throw guarantee: this constructor never throws
17847 exceptions.
17848
17849 @liveexample{The following code shows the constructor with and without a
17850 null pointer parameter.,basic_json__nullptr_t}
17851
17852 @since version 1.0.0
17853 */
basic_json(std::nullptr_t=nullptr)17854 basic_json(std::nullptr_t = nullptr) noexcept
17855 : basic_json(value_t::null)
17856 {
17857 assert_invariant();
17858 }
17859
17860 /*!
17861 @brief create a JSON value
17862
17863 This is a "catch all" constructor for all compatible JSON types; that is,
17864 types for which a `to_json()` method exists. The constructor forwards the
17865 parameter @a val to that method (to `json_serializer<U>::to_json` method
17866 with `U = uncvref_t<CompatibleType>`, to be exact).
17867
17868 Template type @a CompatibleType includes, but is not limited to, the
17869 following types:
17870 - **arrays**: @ref array_t and all kinds of compatible containers such as
17871 `std::vector`, `std::deque`, `std::list`, `std::forward_list`,
17872 `std::array`, `std::valarray`, `std::set`, `std::unordered_set`,
17873 `std::multiset`, and `std::unordered_multiset` with a `value_type` from
17874 which a @ref basic_json value can be constructed.
17875 - **objects**: @ref object_t and all kinds of compatible associative
17876 containers such as `std::map`, `std::unordered_map`, `std::multimap`,
17877 and `std::unordered_multimap` with a `key_type` compatible to
17878 @ref string_t and a `value_type` from which a @ref basic_json value can
17879 be constructed.
17880 - **strings**: @ref string_t, string literals, and all compatible string
17881 containers can be used.
17882 - **numbers**: @ref number_integer_t, @ref number_unsigned_t,
17883 @ref number_float_t, and all convertible number types such as `int`,
17884 `size_t`, `int64_t`, `float` or `double` can be used.
17885 - **boolean**: @ref boolean_t / `bool` can be used.
17886 - **binary**: @ref binary_t / `std::vector<uint8_t>` may be used,
17887 unfortunately because string literals cannot be distinguished from binary
17888 character arrays by the C++ type system, all types compatible with `const
17889 char*` will be directed to the string constructor instead. This is both
17890 for backwards compatibility, and due to the fact that a binary type is not
17891 a standard JSON type.
17892
17893 See the examples below.
17894
17895 @tparam CompatibleType a type such that:
17896 - @a CompatibleType is not derived from `std::istream`,
17897 - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move
17898 constructors),
17899 - @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments)
17900 - @a CompatibleType is not a @ref basic_json nested type (e.g.,
17901 @ref json_pointer, @ref iterator, etc ...)
17902 - @ref @ref json_serializer<U> has a
17903 `to_json(basic_json_t&, CompatibleType&&)` method
17904
17905 @tparam U = `uncvref_t<CompatibleType>`
17906
17907 @param[in] val the value to be forwarded to the respective constructor
17908
17909 @complexity Usually linear in the size of the passed @a val, also
17910 depending on the implementation of the called `to_json()`
17911 method.
17912
17913 @exceptionsafety Depends on the called constructor. For types directly
17914 supported by the library (i.e., all types for which no `to_json()` function
17915 was provided), strong guarantee holds: if an exception is thrown, there are
17916 no changes to any JSON value.
17917
17918 @liveexample{The following code shows the constructor with several
17919 compatible types.,basic_json__CompatibleType}
17920
17921 @since version 2.1.0
17922 */
17923 template < typename CompatibleType,
17924 typename U = detail::uncvref_t<CompatibleType>,
17925 detail::enable_if_t <
17926 !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
basic_json(CompatibleType && val)17927 basic_json(CompatibleType && val) noexcept(noexcept(
17928 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
17929 std::forward<CompatibleType>(val))))
17930 {
17931 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
17932 assert_invariant();
17933 }
17934
17935 /*!
17936 @brief create a JSON value from an existing one
17937
17938 This is a constructor for existing @ref basic_json types.
17939 It does not hijack copy/move constructors, since the parameter has different
17940 template arguments than the current ones.
17941
17942 The constructor tries to convert the internal @ref m_value of the parameter.
17943
17944 @tparam BasicJsonType a type such that:
17945 - @a BasicJsonType is a @ref basic_json type.
17946 - @a BasicJsonType has different template arguments than @ref basic_json_t.
17947
17948 @param[in] val the @ref basic_json value to be converted.
17949
17950 @complexity Usually linear in the size of the passed @a val, also
17951 depending on the implementation of the called `to_json()`
17952 method.
17953
17954 @exceptionsafety Depends on the called constructor. For types directly
17955 supported by the library (i.e., all types for which no `to_json()` function
17956 was provided), strong guarantee holds: if an exception is thrown, there are
17957 no changes to any JSON value.
17958
17959 @since version 3.2.0
17960 */
17961 template < typename BasicJsonType,
17962 detail::enable_if_t <
17963 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
basic_json(const BasicJsonType & val)17964 basic_json(const BasicJsonType& val)
17965 {
17966 using other_boolean_t = typename BasicJsonType::boolean_t;
17967 using other_number_float_t = typename BasicJsonType::number_float_t;
17968 using other_number_integer_t = typename BasicJsonType::number_integer_t;
17969 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
17970 using other_string_t = typename BasicJsonType::string_t;
17971 using other_object_t = typename BasicJsonType::object_t;
17972 using other_array_t = typename BasicJsonType::array_t;
17973 using other_binary_t = typename BasicJsonType::binary_t;
17974
17975 switch (val.type())
17976 {
17977 case value_t::boolean:
17978 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
17979 break;
17980 case value_t::number_float:
17981 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
17982 break;
17983 case value_t::number_integer:
17984 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
17985 break;
17986 case value_t::number_unsigned:
17987 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
17988 break;
17989 case value_t::string:
17990 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
17991 break;
17992 case value_t::object:
17993 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
17994 break;
17995 case value_t::array:
17996 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
17997 break;
17998 case value_t::binary:
17999 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
18000 break;
18001 case value_t::null:
18002 *this = nullptr;
18003 break;
18004 case value_t::discarded:
18005 m_type = value_t::discarded;
18006 break;
18007 default: // LCOV_EXCL_LINE
18008 JSON_ASSERT(false); // LCOV_EXCL_LINE
18009 }
18010 assert_invariant();
18011 }
18012
18013 /*!
18014 @brief create a container (array or object) from an initializer list
18015
18016 Creates a JSON value of type array or object from the passed initializer
18017 list @a init. In case @a type_deduction is `true` (default), the type of
18018 the JSON value to be created is deducted from the initializer list @a init
18019 according to the following rules:
18020
18021 1. If the list is empty, an empty JSON object value `{}` is created.
18022 2. If the list consists of pairs whose first element is a string, a JSON
18023 object value is created where the first elements of the pairs are
18024 treated as keys and the second elements are as values.
18025 3. In all other cases, an array is created.
18026
18027 The rules aim to create the best fit between a C++ initializer list and
18028 JSON values. The rationale is as follows:
18029
18030 1. The empty initializer list is written as `{}` which is exactly an empty
18031 JSON object.
18032 2. C++ has no way of describing mapped types other than to list a list of
18033 pairs. As JSON requires that keys must be of type string, rule 2 is the
18034 weakest constraint one can pose on initializer lists to interpret them
18035 as an object.
18036 3. In all other cases, the initializer list could not be interpreted as
18037 JSON object type, so interpreting it as JSON array type is safe.
18038
18039 With the rules described above, the following JSON values cannot be
18040 expressed by an initializer list:
18041
18042 - the empty array (`[]`): use @ref array(initializer_list_t)
18043 with an empty initializer list in this case
18044 - arrays whose elements satisfy rule 2: use @ref
18045 array(initializer_list_t) with the same initializer list
18046 in this case
18047
18048 @note When used without parentheses around an empty initializer list, @ref
18049 basic_json() is called instead of this function, yielding the JSON null
18050 value.
18051
18052 @param[in] init initializer list with JSON values
18053
18054 @param[in] type_deduction internal parameter; when set to `true`, the type
18055 of the JSON value is deducted from the initializer list @a init; when set
18056 to `false`, the type provided via @a manual_type is forced. This mode is
18057 used by the functions @ref array(initializer_list_t) and
18058 @ref object(initializer_list_t).
18059
18060 @param[in] manual_type internal parameter; when @a type_deduction is set
18061 to `false`, the created JSON value will use the provided type (only @ref
18062 value_t::array and @ref value_t::object are valid); when @a type_deduction
18063 is set to `true`, this parameter has no effect
18064
18065 @throw type_error.301 if @a type_deduction is `false`, @a manual_type is
18066 `value_t::object`, but @a init contains an element which is not a pair
18067 whose first element is a string. In this case, the constructor could not
18068 create an object. If @a type_deduction would have be `true`, an array
18069 would have been created. See @ref object(initializer_list_t)
18070 for an example.
18071
18072 @complexity Linear in the size of the initializer list @a init.
18073
18074 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18075 changes to any JSON value.
18076
18077 @liveexample{The example below shows how JSON values are created from
18078 initializer lists.,basic_json__list_init_t}
18079
18080 @sa @ref array(initializer_list_t) -- create a JSON array
18081 value from an initializer list
18082 @sa @ref object(initializer_list_t) -- create a JSON object
18083 value from an initializer list
18084
18085 @since version 1.0.0
18086 */
basic_json(initializer_list_t init,bool type_deduction=true,value_t manual_type=value_t::array)18087 basic_json(initializer_list_t init,
18088 bool type_deduction = true,
18089 value_t manual_type = value_t::array)
18090 {
18091 // check if each element is an array with two elements whose first
18092 // element is a string
18093 bool is_an_object = std::all_of(init.begin(), init.end(),
18094 [](const detail::json_ref<basic_json>& element_ref)
18095 {
18096 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
18097 });
18098
18099 // adjust type if type deduction is not wanted
18100 if (!type_deduction)
18101 {
18102 // if array is wanted, do not create an object though possible
18103 if (manual_type == value_t::array)
18104 {
18105 is_an_object = false;
18106 }
18107
18108 // if object is wanted but impossible, throw an exception
18109 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
18110 {
18111 JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
18112 }
18113 }
18114
18115 if (is_an_object)
18116 {
18117 // the initializer list is a list of pairs -> create object
18118 m_type = value_t::object;
18119 m_value = value_t::object;
18120
18121 std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
18122 {
18123 auto element = element_ref.moved_or_copied();
18124 m_value.object->emplace(
18125 std::move(*((*element.m_value.array)[0].m_value.string)),
18126 std::move((*element.m_value.array)[1]));
18127 });
18128 }
18129 else
18130 {
18131 // the initializer list describes an array -> create array
18132 m_type = value_t::array;
18133 m_value.array = create<array_t>(init.begin(), init.end());
18134 }
18135
18136 assert_invariant();
18137 }
18138
18139 /*!
18140 @brief explicitly create a binary array (without subtype)
18141
18142 Creates a JSON binary array value from a given binary container. Binary
18143 values are part of various binary formats, such as CBOR, MessagePack, and
18144 BSON. This constructor is used to create a value for serialization to those
18145 formats.
18146
18147 @note Note, this function exists because of the difficulty in correctly
18148 specifying the correct template overload in the standard value ctor, as both
18149 JSON arrays and JSON binary arrays are backed with some form of a
18150 `std::vector`. Because JSON binary arrays are a non-standard extension it
18151 was decided that it would be best to prevent automatic initialization of a
18152 binary array type, for backwards compatibility and so it does not happen on
18153 accident.
18154
18155 @param[in] init container containing bytes to use as binary type
18156
18157 @return JSON binary array value
18158
18159 @complexity Linear in the size of @a init.
18160
18161 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18162 changes to any JSON value.
18163
18164 @since version 3.8.0
18165 */
18166 JSON_HEDLEY_WARN_UNUSED_RESULT
binary(const typename binary_t::container_type & init)18167 static basic_json binary(const typename binary_t::container_type& init)
18168 {
18169 auto res = basic_json();
18170 res.m_type = value_t::binary;
18171 res.m_value = init;
18172 return res;
18173 }
18174
18175 /*!
18176 @brief explicitly create a binary array (with subtype)
18177
18178 Creates a JSON binary array value from a given binary container. Binary
18179 values are part of various binary formats, such as CBOR, MessagePack, and
18180 BSON. This constructor is used to create a value for serialization to those
18181 formats.
18182
18183 @note Note, this function exists because of the difficulty in correctly
18184 specifying the correct template overload in the standard value ctor, as both
18185 JSON arrays and JSON binary arrays are backed with some form of a
18186 `std::vector`. Because JSON binary arrays are a non-standard extension it
18187 was decided that it would be best to prevent automatic initialization of a
18188 binary array type, for backwards compatibility and so it does not happen on
18189 accident.
18190
18191 @param[in] init container containing bytes to use as binary type
18192 @param[in] subtype subtype to use in MessagePack and BSON
18193
18194 @return JSON binary array value
18195
18196 @complexity Linear in the size of @a init.
18197
18198 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18199 changes to any JSON value.
18200
18201 @since version 3.8.0
18202 */
18203 JSON_HEDLEY_WARN_UNUSED_RESULT
binary(const typename binary_t::container_type & init,std::uint8_t subtype)18204 static basic_json binary(const typename binary_t::container_type& init, std::uint8_t subtype)
18205 {
18206 auto res = basic_json();
18207 res.m_type = value_t::binary;
18208 res.m_value = binary_t(init, subtype);
18209 return res;
18210 }
18211
18212 /// @copydoc binary(const typename binary_t::container_type&)
18213 JSON_HEDLEY_WARN_UNUSED_RESULT
binary(typename binary_t::container_type && init)18214 static basic_json binary(typename binary_t::container_type&& init)
18215 {
18216 auto res = basic_json();
18217 res.m_type = value_t::binary;
18218 res.m_value = std::move(init);
18219 return res;
18220 }
18221
18222 /// @copydoc binary(const typename binary_t::container_type&, std::uint8_t)
18223 JSON_HEDLEY_WARN_UNUSED_RESULT
binary(typename binary_t::container_type && init,std::uint8_t subtype)18224 static basic_json binary(typename binary_t::container_type&& init, std::uint8_t subtype)
18225 {
18226 auto res = basic_json();
18227 res.m_type = value_t::binary;
18228 res.m_value = binary_t(std::move(init), subtype);
18229 return res;
18230 }
18231
18232 /*!
18233 @brief explicitly create an array from an initializer list
18234
18235 Creates a JSON array value from a given initializer list. That is, given a
18236 list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the
18237 initializer list is empty, the empty array `[]` is created.
18238
18239 @note This function is only needed to express two edge cases that cannot
18240 be realized with the initializer list constructor (@ref
18241 basic_json(initializer_list_t, bool, value_t)). These cases
18242 are:
18243 1. creating an array whose elements are all pairs whose first element is a
18244 string -- in this case, the initializer list constructor would create an
18245 object, taking the first elements as keys
18246 2. creating an empty array -- passing the empty initializer list to the
18247 initializer list constructor yields an empty object
18248
18249 @param[in] init initializer list with JSON values to create an array from
18250 (optional)
18251
18252 @return JSON array value
18253
18254 @complexity Linear in the size of @a init.
18255
18256 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18257 changes to any JSON value.
18258
18259 @liveexample{The following code shows an example for the `array`
18260 function.,array}
18261
18262 @sa @ref basic_json(initializer_list_t, bool, value_t) --
18263 create a JSON value from an initializer list
18264 @sa @ref object(initializer_list_t) -- create a JSON object
18265 value from an initializer list
18266
18267 @since version 1.0.0
18268 */
18269 JSON_HEDLEY_WARN_UNUSED_RESULT
array(initializer_list_t init={})18270 static basic_json array(initializer_list_t init = {})
18271 {
18272 return basic_json(init, false, value_t::array);
18273 }
18274
18275 /*!
18276 @brief explicitly create an object from an initializer list
18277
18278 Creates a JSON object value from a given initializer list. The initializer
18279 lists elements must be pairs, and their first elements must be strings. If
18280 the initializer list is empty, the empty object `{}` is created.
18281
18282 @note This function is only added for symmetry reasons. In contrast to the
18283 related function @ref array(initializer_list_t), there are
18284 no cases which can only be expressed by this function. That is, any
18285 initializer list @a init can also be passed to the initializer list
18286 constructor @ref basic_json(initializer_list_t, bool, value_t).
18287
18288 @param[in] init initializer list to create an object from (optional)
18289
18290 @return JSON object value
18291
18292 @throw type_error.301 if @a init is not a list of pairs whose first
18293 elements are strings. In this case, no object can be created. When such a
18294 value is passed to @ref basic_json(initializer_list_t, bool, value_t),
18295 an array would have been created from the passed initializer list @a init.
18296 See example below.
18297
18298 @complexity Linear in the size of @a init.
18299
18300 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18301 changes to any JSON value.
18302
18303 @liveexample{The following code shows an example for the `object`
18304 function.,object}
18305
18306 @sa @ref basic_json(initializer_list_t, bool, value_t) --
18307 create a JSON value from an initializer list
18308 @sa @ref array(initializer_list_t) -- create a JSON array
18309 value from an initializer list
18310
18311 @since version 1.0.0
18312 */
18313 JSON_HEDLEY_WARN_UNUSED_RESULT
object(initializer_list_t init={})18314 static basic_json object(initializer_list_t init = {})
18315 {
18316 return basic_json(init, false, value_t::object);
18317 }
18318
18319 /*!
18320 @brief construct an array with count copies of given value
18321
18322 Constructs a JSON array value by creating @a cnt copies of a passed value.
18323 In case @a cnt is `0`, an empty array is created.
18324
18325 @param[in] cnt the number of JSON copies of @a val to create
18326 @param[in] val the JSON value to copy
18327
18328 @post `std::distance(begin(),end()) == cnt` holds.
18329
18330 @complexity Linear in @a cnt.
18331
18332 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18333 changes to any JSON value.
18334
18335 @liveexample{The following code shows examples for the @ref
18336 basic_json(size_type\, const basic_json&)
18337 constructor.,basic_json__size_type_basic_json}
18338
18339 @since version 1.0.0
18340 */
basic_json(size_type cnt,const basic_json & val)18341 basic_json(size_type cnt, const basic_json& val)
18342 : m_type(value_t::array)
18343 {
18344 m_value.array = create<array_t>(cnt, val);
18345 assert_invariant();
18346 }
18347
18348 /*!
18349 @brief construct a JSON container given an iterator range
18350
18351 Constructs the JSON value with the contents of the range `[first, last)`.
18352 The semantics depends on the different types a JSON value can have:
18353 - In case of a null type, invalid_iterator.206 is thrown.
18354 - In case of other primitive types (number, boolean, or string), @a first
18355 must be `begin()` and @a last must be `end()`. In this case, the value is
18356 copied. Otherwise, invalid_iterator.204 is thrown.
18357 - In case of structured types (array, object), the constructor behaves as
18358 similar versions for `std::vector` or `std::map`; that is, a JSON array
18359 or object is constructed from the values in the range.
18360
18361 @tparam InputIT an input iterator type (@ref iterator or @ref
18362 const_iterator)
18363
18364 @param[in] first begin of the range to copy from (included)
18365 @param[in] last end of the range to copy from (excluded)
18366
18367 @pre Iterators @a first and @a last must be initialized. **This
18368 precondition is enforced with an assertion (see warning).** If
18369 assertions are switched off, a violation of this precondition yields
18370 undefined behavior.
18371
18372 @pre Range `[first, last)` is valid. Usually, this precondition cannot be
18373 checked efficiently. Only certain edge cases are detected; see the
18374 description of the exceptions below. A violation of this precondition
18375 yields undefined behavior.
18376
18377 @warning A precondition is enforced with a runtime assertion that will
18378 result in calling `std::abort` if this precondition is not met.
18379 Assertions can be disabled by defining `NDEBUG` at compile time.
18380 See https://en.cppreference.com/w/cpp/error/assert for more
18381 information.
18382
18383 @throw invalid_iterator.201 if iterators @a first and @a last are not
18384 compatible (i.e., do not belong to the same JSON value). In this case,
18385 the range `[first, last)` is undefined.
18386 @throw invalid_iterator.204 if iterators @a first and @a last belong to a
18387 primitive type (number, boolean, or string), but @a first does not point
18388 to the first element any more. In this case, the range `[first, last)` is
18389 undefined. See example code below.
18390 @throw invalid_iterator.206 if iterators @a first and @a last belong to a
18391 null value. In this case, the range `[first, last)` is undefined.
18392
18393 @complexity Linear in distance between @a first and @a last.
18394
18395 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18396 changes to any JSON value.
18397
18398 @liveexample{The example below shows several ways to create JSON values by
18399 specifying a subrange with iterators.,basic_json__InputIt_InputIt}
18400
18401 @since version 1.0.0
18402 */
18403 template < class InputIT, typename std::enable_if <
18404 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
18405 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
basic_json(InputIT first,InputIT last)18406 basic_json(InputIT first, InputIT last)
18407 {
18408 JSON_ASSERT(first.m_object != nullptr);
18409 JSON_ASSERT(last.m_object != nullptr);
18410
18411 // make sure iterator fits the current value
18412 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
18413 {
18414 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
18415 }
18416
18417 // copy type from first iterator
18418 m_type = first.m_object->m_type;
18419
18420 // check if iterator range is complete for primitive values
18421 switch (m_type)
18422 {
18423 case value_t::boolean:
18424 case value_t::number_float:
18425 case value_t::number_integer:
18426 case value_t::number_unsigned:
18427 case value_t::string:
18428 {
18429 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
18430 || !last.m_it.primitive_iterator.is_end()))
18431 {
18432 JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
18433 }
18434 break;
18435 }
18436
18437 default:
18438 break;
18439 }
18440
18441 switch (m_type)
18442 {
18443 case value_t::number_integer:
18444 {
18445 m_value.number_integer = first.m_object->m_value.number_integer;
18446 break;
18447 }
18448
18449 case value_t::number_unsigned:
18450 {
18451 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
18452 break;
18453 }
18454
18455 case value_t::number_float:
18456 {
18457 m_value.number_float = first.m_object->m_value.number_float;
18458 break;
18459 }
18460
18461 case value_t::boolean:
18462 {
18463 m_value.boolean = first.m_object->m_value.boolean;
18464 break;
18465 }
18466
18467 case value_t::string:
18468 {
18469 m_value = *first.m_object->m_value.string;
18470 break;
18471 }
18472
18473 case value_t::object:
18474 {
18475 m_value.object = create<object_t>(first.m_it.object_iterator,
18476 last.m_it.object_iterator);
18477 break;
18478 }
18479
18480 case value_t::array:
18481 {
18482 m_value.array = create<array_t>(first.m_it.array_iterator,
18483 last.m_it.array_iterator);
18484 break;
18485 }
18486
18487 case value_t::binary:
18488 {
18489 m_value = *first.m_object->m_value.binary;
18490 break;
18491 }
18492
18493 default:
18494 JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
18495 std::string(first.m_object->type_name())));
18496 }
18497
18498 assert_invariant();
18499 }
18500
18501
18502 ///////////////////////////////////////
18503 // other constructors and destructor //
18504 ///////////////////////////////////////
18505
18506 template<typename JsonRef,
18507 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
18508 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
basic_json(const JsonRef & ref)18509 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
18510
18511 /*!
18512 @brief copy constructor
18513
18514 Creates a copy of a given JSON value.
18515
18516 @param[in] other the JSON value to copy
18517
18518 @post `*this == other`
18519
18520 @complexity Linear in the size of @a other.
18521
18522 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18523 changes to any JSON value.
18524
18525 @requirement This function helps `basic_json` satisfying the
18526 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
18527 requirements:
18528 - The complexity is linear.
18529 - As postcondition, it holds: `other == basic_json(other)`.
18530
18531 @liveexample{The following code shows an example for the copy
18532 constructor.,basic_json__basic_json}
18533
18534 @since version 1.0.0
18535 */
basic_json(const basic_json & other)18536 basic_json(const basic_json& other)
18537 : m_type(other.m_type)
18538 {
18539 // check of passed value is valid
18540 other.assert_invariant();
18541
18542 switch (m_type)
18543 {
18544 case value_t::object:
18545 {
18546 m_value = *other.m_value.object;
18547 break;
18548 }
18549
18550 case value_t::array:
18551 {
18552 m_value = *other.m_value.array;
18553 break;
18554 }
18555
18556 case value_t::string:
18557 {
18558 m_value = *other.m_value.string;
18559 break;
18560 }
18561
18562 case value_t::boolean:
18563 {
18564 m_value = other.m_value.boolean;
18565 break;
18566 }
18567
18568 case value_t::number_integer:
18569 {
18570 m_value = other.m_value.number_integer;
18571 break;
18572 }
18573
18574 case value_t::number_unsigned:
18575 {
18576 m_value = other.m_value.number_unsigned;
18577 break;
18578 }
18579
18580 case value_t::number_float:
18581 {
18582 m_value = other.m_value.number_float;
18583 break;
18584 }
18585
18586 case value_t::binary:
18587 {
18588 m_value = *other.m_value.binary;
18589 break;
18590 }
18591
18592 default:
18593 break;
18594 }
18595
18596 assert_invariant();
18597 }
18598
18599 /*!
18600 @brief move constructor
18601
18602 Move constructor. Constructs a JSON value with the contents of the given
18603 value @a other using move semantics. It "steals" the resources from @a
18604 other and leaves it as JSON null value.
18605
18606 @param[in,out] other value to move to this object
18607
18608 @post `*this` has the same value as @a other before the call.
18609 @post @a other is a JSON null value.
18610
18611 @complexity Constant.
18612
18613 @exceptionsafety No-throw guarantee: this constructor never throws
18614 exceptions.
18615
18616 @requirement This function helps `basic_json` satisfying the
18617 [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible)
18618 requirements.
18619
18620 @liveexample{The code below shows the move constructor explicitly called
18621 via std::move.,basic_json__moveconstructor}
18622
18623 @since version 1.0.0
18624 */
basic_json(basic_json && other)18625 basic_json(basic_json&& other) noexcept
18626 : m_type(std::move(other.m_type)),
18627 m_value(std::move(other.m_value))
18628 {
18629 // check that passed value is valid
18630 other.assert_invariant();
18631
18632 // invalidate payload
18633 other.m_type = value_t::null;
18634 other.m_value = {};
18635
18636 assert_invariant();
18637 }
18638
18639 /*!
18640 @brief copy assignment
18641
18642 Copy assignment operator. Copies a JSON value via the "copy and swap"
18643 strategy: It is expressed in terms of the copy constructor, destructor,
18644 and the `swap()` member function.
18645
18646 @param[in] other value to copy from
18647
18648 @complexity Linear.
18649
18650 @requirement This function helps `basic_json` satisfying the
18651 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
18652 requirements:
18653 - The complexity is linear.
18654
18655 @liveexample{The code below shows and example for the copy assignment. It
18656 creates a copy of value `a` which is then swapped with `b`. Finally\, the
18657 copy of `a` (which is the null value after the swap) is
18658 destroyed.,basic_json__copyassignment}
18659
18660 @since version 1.0.0
18661 */
operator =(basic_json other)18662 basic_json& operator=(basic_json other) noexcept (
18663 std::is_nothrow_move_constructible<value_t>::value&&
18664 std::is_nothrow_move_assignable<value_t>::value&&
18665 std::is_nothrow_move_constructible<json_value>::value&&
18666 std::is_nothrow_move_assignable<json_value>::value
18667 )
18668 {
18669 // check that passed value is valid
18670 other.assert_invariant();
18671
18672 using std::swap;
18673 swap(m_type, other.m_type);
18674 swap(m_value, other.m_value);
18675
18676 assert_invariant();
18677 return *this;
18678 }
18679
18680 /*!
18681 @brief destructor
18682
18683 Destroys the JSON value and frees all allocated memory.
18684
18685 @complexity Linear.
18686
18687 @requirement This function helps `basic_json` satisfying the
18688 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
18689 requirements:
18690 - The complexity is linear.
18691 - All stored elements are destroyed and all memory is freed.
18692
18693 @since version 1.0.0
18694 */
~basic_json()18695 ~basic_json() noexcept
18696 {
18697 assert_invariant();
18698 m_value.destroy(m_type);
18699 }
18700
18701 /// @}
18702
18703 public:
18704 ///////////////////////
18705 // object inspection //
18706 ///////////////////////
18707
18708 /// @name object inspection
18709 /// Functions to inspect the type of a JSON value.
18710 /// @{
18711
18712 /*!
18713 @brief serialization
18714
18715 Serialization function for JSON values. The function tries to mimic
18716 Python's `json.dumps()` function, and currently supports its @a indent
18717 and @a ensure_ascii parameters.
18718
18719 @param[in] indent If indent is nonnegative, then array elements and object
18720 members will be pretty-printed with that indent level. An indent level of
18721 `0` will only insert newlines. `-1` (the default) selects the most compact
18722 representation.
18723 @param[in] indent_char The character to use for indentation if @a indent is
18724 greater than `0`. The default is ` ` (space).
18725 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
18726 in the output are escaped with `\uXXXX` sequences, and the result consists
18727 of ASCII characters only.
18728 @param[in] error_handler how to react on decoding errors; there are three
18729 possible values: `strict` (throws and exception in case a decoding error
18730 occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD),
18731 and `ignore` (ignore invalid UTF-8 sequences during serialization; all
18732 bytes are copied to the output unchanged).
18733
18734 @return string containing the serialization of the JSON value
18735
18736 @throw type_error.316 if a string stored inside the JSON value is not
18737 UTF-8 encoded and @a error_handler is set to strict
18738
18739 @note Binary values are serialized as object containing two keys:
18740 - "bytes": an array of bytes as integers
18741 - "subtype": the subtype as integer or "null" if the binary has no subtype
18742
18743 @complexity Linear.
18744
18745 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18746 changes in the JSON value.
18747
18748 @liveexample{The following example shows the effect of different @a indent\,
18749 @a indent_char\, and @a ensure_ascii parameters to the result of the
18750 serialization.,dump}
18751
18752 @see https://docs.python.org/2/library/json.html#json.dump
18753
18754 @since version 1.0.0; indentation character @a indent_char, option
18755 @a ensure_ascii and exceptions added in version 3.0.0; error
18756 handlers added in version 3.4.0; serialization of binary values added
18757 in version 3.8.0.
18758 */
dump(const int indent=-1,const char indent_char=' ',const bool ensure_ascii=false,const error_handler_t error_handler=error_handler_t::strict) const18759 string_t dump(const int indent = -1,
18760 const char indent_char = ' ',
18761 const bool ensure_ascii = false,
18762 const error_handler_t error_handler = error_handler_t::strict) const
18763 {
18764 string_t result;
18765 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
18766
18767 if (indent >= 0)
18768 {
18769 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
18770 }
18771 else
18772 {
18773 s.dump(*this, false, ensure_ascii, 0);
18774 }
18775
18776 return result;
18777 }
18778
18779 /*!
18780 @brief return the type of the JSON value (explicit)
18781
18782 Return the type of the JSON value as a value from the @ref value_t
18783 enumeration.
18784
18785 @return the type of the JSON value
18786 Value type | return value
18787 ------------------------- | -------------------------
18788 null | value_t::null
18789 boolean | value_t::boolean
18790 string | value_t::string
18791 number (integer) | value_t::number_integer
18792 number (unsigned integer) | value_t::number_unsigned
18793 number (floating-point) | value_t::number_float
18794 object | value_t::object
18795 array | value_t::array
18796 binary | value_t::binary
18797 discarded | value_t::discarded
18798
18799 @complexity Constant.
18800
18801 @exceptionsafety No-throw guarantee: this member function never throws
18802 exceptions.
18803
18804 @liveexample{The following code exemplifies `type()` for all JSON
18805 types.,type}
18806
18807 @sa @ref operator value_t() -- return the type of the JSON value (implicit)
18808 @sa @ref type_name() -- return the type as string
18809
18810 @since version 1.0.0
18811 */
type() const18812 constexpr value_t type() const noexcept
18813 {
18814 return m_type;
18815 }
18816
18817 /*!
18818 @brief return whether type is primitive
18819
18820 This function returns true if and only if the JSON type is primitive
18821 (string, number, boolean, or null).
18822
18823 @return `true` if type is primitive (string, number, boolean, or null),
18824 `false` otherwise.
18825
18826 @complexity Constant.
18827
18828 @exceptionsafety No-throw guarantee: this member function never throws
18829 exceptions.
18830
18831 @liveexample{The following code exemplifies `is_primitive()` for all JSON
18832 types.,is_primitive}
18833
18834 @sa @ref is_structured() -- returns whether JSON value is structured
18835 @sa @ref is_null() -- returns whether JSON value is `null`
18836 @sa @ref is_string() -- returns whether JSON value is a string
18837 @sa @ref is_boolean() -- returns whether JSON value is a boolean
18838 @sa @ref is_number() -- returns whether JSON value is a number
18839 @sa @ref is_binary() -- returns whether JSON value is a binary array
18840
18841 @since version 1.0.0
18842 */
is_primitive() const18843 constexpr bool is_primitive() const noexcept
18844 {
18845 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
18846 }
18847
18848 /*!
18849 @brief return whether type is structured
18850
18851 This function returns true if and only if the JSON type is structured
18852 (array or object).
18853
18854 @return `true` if type is structured (array or object), `false` otherwise.
18855
18856 @complexity Constant.
18857
18858 @exceptionsafety No-throw guarantee: this member function never throws
18859 exceptions.
18860
18861 @liveexample{The following code exemplifies `is_structured()` for all JSON
18862 types.,is_structured}
18863
18864 @sa @ref is_primitive() -- returns whether value is primitive
18865 @sa @ref is_array() -- returns whether value is an array
18866 @sa @ref is_object() -- returns whether value is an object
18867
18868 @since version 1.0.0
18869 */
is_structured() const18870 constexpr bool is_structured() const noexcept
18871 {
18872 return is_array() || is_object();
18873 }
18874
18875 /*!
18876 @brief return whether value is null
18877
18878 This function returns true if and only if the JSON value is null.
18879
18880 @return `true` if type is null, `false` otherwise.
18881
18882 @complexity Constant.
18883
18884 @exceptionsafety No-throw guarantee: this member function never throws
18885 exceptions.
18886
18887 @liveexample{The following code exemplifies `is_null()` for all JSON
18888 types.,is_null}
18889
18890 @since version 1.0.0
18891 */
is_null() const18892 constexpr bool is_null() const noexcept
18893 {
18894 return m_type == value_t::null;
18895 }
18896
18897 /*!
18898 @brief return whether value is a boolean
18899
18900 This function returns true if and only if the JSON value is a boolean.
18901
18902 @return `true` if type is boolean, `false` otherwise.
18903
18904 @complexity Constant.
18905
18906 @exceptionsafety No-throw guarantee: this member function never throws
18907 exceptions.
18908
18909 @liveexample{The following code exemplifies `is_boolean()` for all JSON
18910 types.,is_boolean}
18911
18912 @since version 1.0.0
18913 */
is_boolean() const18914 constexpr bool is_boolean() const noexcept
18915 {
18916 return m_type == value_t::boolean;
18917 }
18918
18919 /*!
18920 @brief return whether value is a number
18921
18922 This function returns true if and only if the JSON value is a number. This
18923 includes both integer (signed and unsigned) and floating-point values.
18924
18925 @return `true` if type is number (regardless whether integer, unsigned
18926 integer or floating-type), `false` otherwise.
18927
18928 @complexity Constant.
18929
18930 @exceptionsafety No-throw guarantee: this member function never throws
18931 exceptions.
18932
18933 @liveexample{The following code exemplifies `is_number()` for all JSON
18934 types.,is_number}
18935
18936 @sa @ref is_number_integer() -- check if value is an integer or unsigned
18937 integer number
18938 @sa @ref is_number_unsigned() -- check if value is an unsigned integer
18939 number
18940 @sa @ref is_number_float() -- check if value is a floating-point number
18941
18942 @since version 1.0.0
18943 */
is_number() const18944 constexpr bool is_number() const noexcept
18945 {
18946 return is_number_integer() || is_number_float();
18947 }
18948
18949 /*!
18950 @brief return whether value is an integer number
18951
18952 This function returns true if and only if the JSON value is a signed or
18953 unsigned integer number. This excludes floating-point values.
18954
18955 @return `true` if type is an integer or unsigned integer number, `false`
18956 otherwise.
18957
18958 @complexity Constant.
18959
18960 @exceptionsafety No-throw guarantee: this member function never throws
18961 exceptions.
18962
18963 @liveexample{The following code exemplifies `is_number_integer()` for all
18964 JSON types.,is_number_integer}
18965
18966 @sa @ref is_number() -- check if value is a number
18967 @sa @ref is_number_unsigned() -- check if value is an unsigned integer
18968 number
18969 @sa @ref is_number_float() -- check if value is a floating-point number
18970
18971 @since version 1.0.0
18972 */
is_number_integer() const18973 constexpr bool is_number_integer() const noexcept
18974 {
18975 return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
18976 }
18977
18978 /*!
18979 @brief return whether value is an unsigned integer number
18980
18981 This function returns true if and only if the JSON value is an unsigned
18982 integer number. This excludes floating-point and signed integer values.
18983
18984 @return `true` if type is an unsigned integer number, `false` otherwise.
18985
18986 @complexity Constant.
18987
18988 @exceptionsafety No-throw guarantee: this member function never throws
18989 exceptions.
18990
18991 @liveexample{The following code exemplifies `is_number_unsigned()` for all
18992 JSON types.,is_number_unsigned}
18993
18994 @sa @ref is_number() -- check if value is a number
18995 @sa @ref is_number_integer() -- check if value is an integer or unsigned
18996 integer number
18997 @sa @ref is_number_float() -- check if value is a floating-point number
18998
18999 @since version 2.0.0
19000 */
is_number_unsigned() const19001 constexpr bool is_number_unsigned() const noexcept
19002 {
19003 return m_type == value_t::number_unsigned;
19004 }
19005
19006 /*!
19007 @brief return whether value is a floating-point number
19008
19009 This function returns true if and only if the JSON value is a
19010 floating-point number. This excludes signed and unsigned integer values.
19011
19012 @return `true` if type is a floating-point number, `false` otherwise.
19013
19014 @complexity Constant.
19015
19016 @exceptionsafety No-throw guarantee: this member function never throws
19017 exceptions.
19018
19019 @liveexample{The following code exemplifies `is_number_float()` for all
19020 JSON types.,is_number_float}
19021
19022 @sa @ref is_number() -- check if value is number
19023 @sa @ref is_number_integer() -- check if value is an integer number
19024 @sa @ref is_number_unsigned() -- check if value is an unsigned integer
19025 number
19026
19027 @since version 1.0.0
19028 */
is_number_float() const19029 constexpr bool is_number_float() const noexcept
19030 {
19031 return m_type == value_t::number_float;
19032 }
19033
19034 /*!
19035 @brief return whether value is an object
19036
19037 This function returns true if and only if the JSON value is an object.
19038
19039 @return `true` if type is object, `false` otherwise.
19040
19041 @complexity Constant.
19042
19043 @exceptionsafety No-throw guarantee: this member function never throws
19044 exceptions.
19045
19046 @liveexample{The following code exemplifies `is_object()` for all JSON
19047 types.,is_object}
19048
19049 @since version 1.0.0
19050 */
is_object() const19051 constexpr bool is_object() const noexcept
19052 {
19053 return m_type == value_t::object;
19054 }
19055
19056 /*!
19057 @brief return whether value is an array
19058
19059 This function returns true if and only if the JSON value is an array.
19060
19061 @return `true` if type is array, `false` otherwise.
19062
19063 @complexity Constant.
19064
19065 @exceptionsafety No-throw guarantee: this member function never throws
19066 exceptions.
19067
19068 @liveexample{The following code exemplifies `is_array()` for all JSON
19069 types.,is_array}
19070
19071 @since version 1.0.0
19072 */
is_array() const19073 constexpr bool is_array() const noexcept
19074 {
19075 return m_type == value_t::array;
19076 }
19077
19078 /*!
19079 @brief return whether value is a string
19080
19081 This function returns true if and only if the JSON value is a string.
19082
19083 @return `true` if type is string, `false` otherwise.
19084
19085 @complexity Constant.
19086
19087 @exceptionsafety No-throw guarantee: this member function never throws
19088 exceptions.
19089
19090 @liveexample{The following code exemplifies `is_string()` for all JSON
19091 types.,is_string}
19092
19093 @since version 1.0.0
19094 */
is_string() const19095 constexpr bool is_string() const noexcept
19096 {
19097 return m_type == value_t::string;
19098 }
19099
19100 /*!
19101 @brief return whether value is a binary array
19102
19103 This function returns true if and only if the JSON value is a binary array.
19104
19105 @return `true` if type is binary array, `false` otherwise.
19106
19107 @complexity Constant.
19108
19109 @exceptionsafety No-throw guarantee: this member function never throws
19110 exceptions.
19111
19112 @liveexample{The following code exemplifies `is_binary()` for all JSON
19113 types.,is_binary}
19114
19115 @since version 3.8.0
19116 */
is_binary() const19117 constexpr bool is_binary() const noexcept
19118 {
19119 return m_type == value_t::binary;
19120 }
19121
19122 /*!
19123 @brief return whether value is discarded
19124
19125 This function returns true if and only if the JSON value was discarded
19126 during parsing with a callback function (see @ref parser_callback_t).
19127
19128 @note This function will always be `false` for JSON values after parsing.
19129 That is, discarded values can only occur during parsing, but will be
19130 removed when inside a structured value or replaced by null in other cases.
19131
19132 @return `true` if type is discarded, `false` otherwise.
19133
19134 @complexity Constant.
19135
19136 @exceptionsafety No-throw guarantee: this member function never throws
19137 exceptions.
19138
19139 @liveexample{The following code exemplifies `is_discarded()` for all JSON
19140 types.,is_discarded}
19141
19142 @since version 1.0.0
19143 */
is_discarded() const19144 constexpr bool is_discarded() const noexcept
19145 {
19146 return m_type == value_t::discarded;
19147 }
19148
19149 /*!
19150 @brief return the type of the JSON value (implicit)
19151
19152 Implicitly return the type of the JSON value as a value from the @ref
19153 value_t enumeration.
19154
19155 @return the type of the JSON value
19156
19157 @complexity Constant.
19158
19159 @exceptionsafety No-throw guarantee: this member function never throws
19160 exceptions.
19161
19162 @liveexample{The following code exemplifies the @ref value_t operator for
19163 all JSON types.,operator__value_t}
19164
19165 @sa @ref type() -- return the type of the JSON value (explicit)
19166 @sa @ref type_name() -- return the type as string
19167
19168 @since version 1.0.0
19169 */
operator value_t() const19170 constexpr operator value_t() const noexcept
19171 {
19172 return m_type;
19173 }
19174
19175 /// @}
19176
19177 private:
19178 //////////////////
19179 // value access //
19180 //////////////////
19181
19182 /// get a boolean (explicit)
get_impl(boolean_t *) const19183 boolean_t get_impl(boolean_t* /*unused*/) const
19184 {
19185 if (JSON_HEDLEY_LIKELY(is_boolean()))
19186 {
19187 return m_value.boolean;
19188 }
19189
19190 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name())));
19191 }
19192
19193 /// get a pointer to the value (object)
get_impl_ptr(object_t *)19194 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
19195 {
19196 return is_object() ? m_value.object : nullptr;
19197 }
19198
19199 /// get a pointer to the value (object)
get_impl_ptr(const object_t *) const19200 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
19201 {
19202 return is_object() ? m_value.object : nullptr;
19203 }
19204
19205 /// get a pointer to the value (array)
get_impl_ptr(array_t *)19206 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
19207 {
19208 return is_array() ? m_value.array : nullptr;
19209 }
19210
19211 /// get a pointer to the value (array)
get_impl_ptr(const array_t *) const19212 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
19213 {
19214 return is_array() ? m_value.array : nullptr;
19215 }
19216
19217 /// get a pointer to the value (string)
get_impl_ptr(string_t *)19218 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
19219 {
19220 return is_string() ? m_value.string : nullptr;
19221 }
19222
19223 /// get a pointer to the value (string)
get_impl_ptr(const string_t *) const19224 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
19225 {
19226 return is_string() ? m_value.string : nullptr;
19227 }
19228
19229 /// get a pointer to the value (boolean)
get_impl_ptr(boolean_t *)19230 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
19231 {
19232 return is_boolean() ? &m_value.boolean : nullptr;
19233 }
19234
19235 /// get a pointer to the value (boolean)
get_impl_ptr(const boolean_t *) const19236 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
19237 {
19238 return is_boolean() ? &m_value.boolean : nullptr;
19239 }
19240
19241 /// get a pointer to the value (integer number)
get_impl_ptr(number_integer_t *)19242 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
19243 {
19244 return is_number_integer() ? &m_value.number_integer : nullptr;
19245 }
19246
19247 /// get a pointer to the value (integer number)
get_impl_ptr(const number_integer_t *) const19248 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
19249 {
19250 return is_number_integer() ? &m_value.number_integer : nullptr;
19251 }
19252
19253 /// get a pointer to the value (unsigned number)
get_impl_ptr(number_unsigned_t *)19254 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
19255 {
19256 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
19257 }
19258
19259 /// get a pointer to the value (unsigned number)
get_impl_ptr(const number_unsigned_t *) const19260 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
19261 {
19262 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
19263 }
19264
19265 /// get a pointer to the value (floating-point number)
get_impl_ptr(number_float_t *)19266 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
19267 {
19268 return is_number_float() ? &m_value.number_float : nullptr;
19269 }
19270
19271 /// get a pointer to the value (floating-point number)
get_impl_ptr(const number_float_t *) const19272 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
19273 {
19274 return is_number_float() ? &m_value.number_float : nullptr;
19275 }
19276
19277 /// get a pointer to the value (binary)
get_impl_ptr(binary_t *)19278 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
19279 {
19280 return is_binary() ? m_value.binary : nullptr;
19281 }
19282
19283 /// get a pointer to the value (binary)
get_impl_ptr(const binary_t *) const19284 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
19285 {
19286 return is_binary() ? m_value.binary : nullptr;
19287 }
19288
19289 /*!
19290 @brief helper function to implement get_ref()
19291
19292 This function helps to implement get_ref() without code duplication for
19293 const and non-const overloads
19294
19295 @tparam ThisType will be deduced as `basic_json` or `const basic_json`
19296
19297 @throw type_error.303 if ReferenceType does not match underlying value
19298 type of the current JSON
19299 */
19300 template<typename ReferenceType, typename ThisType>
get_ref_impl(ThisType & obj)19301 static ReferenceType get_ref_impl(ThisType& obj)
19302 {
19303 // delegate the call to get_ptr<>()
19304 auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
19305
19306 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
19307 {
19308 return *ptr;
19309 }
19310
19311 JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
19312 }
19313
19314 public:
19315 /// @name value access
19316 /// Direct access to the stored value of a JSON value.
19317 /// @{
19318
19319 /*!
19320 @brief get special-case overload
19321
19322 This overloads avoids a lot of template boilerplate, it can be seen as the
19323 identity method
19324
19325 @tparam BasicJsonType == @ref basic_json
19326
19327 @return a copy of *this
19328
19329 @complexity Constant.
19330
19331 @since version 2.1.0
19332 */
19333 template<typename BasicJsonType, detail::enable_if_t<
19334 std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,
19335 int> = 0>
get() const19336 basic_json get() const
19337 {
19338 return *this;
19339 }
19340
19341 /*!
19342 @brief get special-case overload
19343
19344 This overloads converts the current @ref basic_json in a different
19345 @ref basic_json type
19346
19347 @tparam BasicJsonType == @ref basic_json
19348
19349 @return a copy of *this, converted into @tparam BasicJsonType
19350
19351 @complexity Depending on the implementation of the called `from_json()`
19352 method.
19353
19354 @since version 3.2.0
19355 */
19356 template < typename BasicJsonType, detail::enable_if_t <
19357 !std::is_same<BasicJsonType, basic_json>::value&&
19358 detail::is_basic_json<BasicJsonType>::value, int > = 0 >
get() const19359 BasicJsonType get() const
19360 {
19361 return *this;
19362 }
19363
19364 /*!
19365 @brief get a value (explicit)
19366
19367 Explicit type conversion between the JSON value and a compatible value
19368 which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
19369 and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
19370 The value is converted by calling the @ref json_serializer<ValueType>
19371 `from_json()` method.
19372
19373 The function is equivalent to executing
19374 @code {.cpp}
19375 ValueType ret;
19376 JSONSerializer<ValueType>::from_json(*this, ret);
19377 return ret;
19378 @endcode
19379
19380 This overloads is chosen if:
19381 - @a ValueType is not @ref basic_json,
19382 - @ref json_serializer<ValueType> has a `from_json()` method of the form
19383 `void from_json(const basic_json&, ValueType&)`, and
19384 - @ref json_serializer<ValueType> does not have a `from_json()` method of
19385 the form `ValueType from_json(const basic_json&)`
19386
19387 @tparam ValueTypeCV the provided value type
19388 @tparam ValueType the returned value type
19389
19390 @return copy of the JSON value, converted to @a ValueType
19391
19392 @throw what @ref json_serializer<ValueType> `from_json()` method throws
19393
19394 @liveexample{The example below shows several conversions from JSON values
19395 to other types. There a few things to note: (1) Floating-point numbers can
19396 be converted to integers\, (2) A JSON array can be converted to a standard
19397 `std::vector<short>`\, (3) A JSON object can be converted to C++
19398 associative containers such as `std::unordered_map<std::string\,
19399 json>`.,get__ValueType_const}
19400
19401 @since version 2.1.0
19402 */
19403 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
19404 detail::enable_if_t <
19405 !detail::is_basic_json<ValueType>::value &&
19406 detail::has_from_json<basic_json_t, ValueType>::value &&
19407 !detail::has_non_default_from_json<basic_json_t, ValueType>::value,
19408 int > = 0 >
get() const19409 ValueType get() const noexcept(noexcept(
19410 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
19411 {
19412 // we cannot static_assert on ValueTypeCV being non-const, because
19413 // there is support for get<const basic_json_t>(), which is why we
19414 // still need the uncvref
19415 static_assert(!std::is_reference<ValueTypeCV>::value,
19416 "get() cannot be used with reference types, you might want to use get_ref()");
19417 static_assert(std::is_default_constructible<ValueType>::value,
19418 "types must be DefaultConstructible when used with get()");
19419
19420 ValueType ret;
19421 JSONSerializer<ValueType>::from_json(*this, ret);
19422 return ret;
19423 }
19424
19425 /*!
19426 @brief get a value (explicit); special case
19427
19428 Explicit type conversion between the JSON value and a compatible value
19429 which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
19430 and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
19431 The value is converted by calling the @ref json_serializer<ValueType>
19432 `from_json()` method.
19433
19434 The function is equivalent to executing
19435 @code {.cpp}
19436 return JSONSerializer<ValueTypeCV>::from_json(*this);
19437 @endcode
19438
19439 This overloads is chosen if:
19440 - @a ValueType is not @ref basic_json and
19441 - @ref json_serializer<ValueType> has a `from_json()` method of the form
19442 `ValueType from_json(const basic_json&)`
19443
19444 @note If @ref json_serializer<ValueType> has both overloads of
19445 `from_json()`, this one is chosen.
19446
19447 @tparam ValueTypeCV the provided value type
19448 @tparam ValueType the returned value type
19449
19450 @return copy of the JSON value, converted to @a ValueType
19451
19452 @throw what @ref json_serializer<ValueType> `from_json()` method throws
19453
19454 @since version 2.1.0
19455 */
19456 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
19457 detail::enable_if_t < !std::is_same<basic_json_t, ValueType>::value &&
19458 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
19459 int > = 0 >
get() const19460 ValueType get() const noexcept(noexcept(
19461 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
19462 {
19463 static_assert(!std::is_reference<ValueTypeCV>::value,
19464 "get() cannot be used with reference types, you might want to use get_ref()");
19465 return JSONSerializer<ValueType>::from_json(*this);
19466 }
19467
19468 /*!
19469 @brief get a value (explicit)
19470
19471 Explicit type conversion between the JSON value and a compatible value.
19472 The value is filled into the input parameter by calling the @ref json_serializer<ValueType>
19473 `from_json()` method.
19474
19475 The function is equivalent to executing
19476 @code {.cpp}
19477 ValueType v;
19478 JSONSerializer<ValueType>::from_json(*this, v);
19479 @endcode
19480
19481 This overloads is chosen if:
19482 - @a ValueType is not @ref basic_json,
19483 - @ref json_serializer<ValueType> has a `from_json()` method of the form
19484 `void from_json(const basic_json&, ValueType&)`, and
19485
19486 @tparam ValueType the input parameter type.
19487
19488 @return the input parameter, allowing chaining calls.
19489
19490 @throw what @ref json_serializer<ValueType> `from_json()` method throws
19491
19492 @liveexample{The example below shows several conversions from JSON values
19493 to other types. There a few things to note: (1) Floating-point numbers can
19494 be converted to integers\, (2) A JSON array can be converted to a standard
19495 `std::vector<short>`\, (3) A JSON object can be converted to C++
19496 associative containers such as `std::unordered_map<std::string\,
19497 json>`.,get_to}
19498
19499 @since version 3.3.0
19500 */
19501 template < typename ValueType,
19502 detail::enable_if_t <
19503 !detail::is_basic_json<ValueType>::value&&
19504 detail::has_from_json<basic_json_t, ValueType>::value,
19505 int > = 0 >
get_to(ValueType & v) const19506 ValueType & get_to(ValueType& v) const noexcept(noexcept(
19507 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
19508 {
19509 JSONSerializer<ValueType>::from_json(*this, v);
19510 return v;
19511 }
19512
19513 // specialization to allow to call get_to with a basic_json value
19514 // see https://github.com/nlohmann/json/issues/2175
19515 template<typename ValueType,
19516 detail::enable_if_t <
19517 detail::is_basic_json<ValueType>::value,
19518 int> = 0>
get_to(ValueType & v) const19519 ValueType & get_to(ValueType& v) const
19520 {
19521 v = *this;
19522 return v;
19523 }
19524
19525 template <
19526 typename T, std::size_t N,
19527 typename Array = T (&)[N],
19528 detail::enable_if_t <
19529 detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
get_to(T (& v)[N]) const19530 Array get_to(T (&v)[N]) const
19531 noexcept(noexcept(JSONSerializer<Array>::from_json(
19532 std::declval<const basic_json_t&>(), v)))
19533 {
19534 JSONSerializer<Array>::from_json(*this, v);
19535 return v;
19536 }
19537
19538
19539 /*!
19540 @brief get a pointer value (implicit)
19541
19542 Implicit pointer access to the internally stored JSON value. No copies are
19543 made.
19544
19545 @warning Writing data to the pointee of the result yields an undefined
19546 state.
19547
19548 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
19549 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
19550 @ref number_unsigned_t, or @ref number_float_t. Enforced by a static
19551 assertion.
19552
19553 @return pointer to the internally stored JSON value if the requested
19554 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
19555
19556 @complexity Constant.
19557
19558 @liveexample{The example below shows how pointers to internal values of a
19559 JSON value can be requested. Note that no type conversions are made and a
19560 `nullptr` is returned if the value and the requested pointer type does not
19561 match.,get_ptr}
19562
19563 @since version 1.0.0
19564 */
19565 template<typename PointerType, typename std::enable_if<
19566 std::is_pointer<PointerType>::value, int>::type = 0>
get_ptr()19567 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
19568 {
19569 // delegate the call to get_impl_ptr<>()
19570 return get_impl_ptr(static_cast<PointerType>(nullptr));
19571 }
19572
19573 /*!
19574 @brief get a pointer value (implicit)
19575 @copydoc get_ptr()
19576 */
19577 template < typename PointerType, typename std::enable_if <
19578 std::is_pointer<PointerType>::value&&
19579 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
get_ptr() const19580 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
19581 {
19582 // delegate the call to get_impl_ptr<>() const
19583 return get_impl_ptr(static_cast<PointerType>(nullptr));
19584 }
19585
19586 /*!
19587 @brief get a pointer value (explicit)
19588
19589 Explicit pointer access to the internally stored JSON value. No copies are
19590 made.
19591
19592 @warning The pointer becomes invalid if the underlying JSON object
19593 changes.
19594
19595 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
19596 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
19597 @ref number_unsigned_t, or @ref number_float_t.
19598
19599 @return pointer to the internally stored JSON value if the requested
19600 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
19601
19602 @complexity Constant.
19603
19604 @liveexample{The example below shows how pointers to internal values of a
19605 JSON value can be requested. Note that no type conversions are made and a
19606 `nullptr` is returned if the value and the requested pointer type does not
19607 match.,get__PointerType}
19608
19609 @sa @ref get_ptr() for explicit pointer-member access
19610
19611 @since version 1.0.0
19612 */
19613 template<typename PointerType, typename std::enable_if<
19614 std::is_pointer<PointerType>::value, int>::type = 0>
get()19615 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
19616 {
19617 // delegate the call to get_ptr
19618 return get_ptr<PointerType>();
19619 }
19620
19621 /*!
19622 @brief get a pointer value (explicit)
19623 @copydoc get()
19624 */
19625 template<typename PointerType, typename std::enable_if<
19626 std::is_pointer<PointerType>::value, int>::type = 0>
get() const19627 constexpr auto get() const noexcept -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
19628 {
19629 // delegate the call to get_ptr
19630 return get_ptr<PointerType>();
19631 }
19632
19633 /*!
19634 @brief get a reference value (implicit)
19635
19636 Implicit reference access to the internally stored JSON value. No copies
19637 are made.
19638
19639 @warning Writing data to the referee of the result yields an undefined
19640 state.
19641
19642 @tparam ReferenceType reference type; must be a reference to @ref array_t,
19643 @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or
19644 @ref number_float_t. Enforced by static assertion.
19645
19646 @return reference to the internally stored JSON value if the requested
19647 reference type @a ReferenceType fits to the JSON value; throws
19648 type_error.303 otherwise
19649
19650 @throw type_error.303 in case passed type @a ReferenceType is incompatible
19651 with the stored JSON value; see example below
19652
19653 @complexity Constant.
19654
19655 @liveexample{The example shows several calls to `get_ref()`.,get_ref}
19656
19657 @since version 1.1.0
19658 */
19659 template<typename ReferenceType, typename std::enable_if<
19660 std::is_reference<ReferenceType>::value, int>::type = 0>
get_ref()19661 ReferenceType get_ref()
19662 {
19663 // delegate call to get_ref_impl
19664 return get_ref_impl<ReferenceType>(*this);
19665 }
19666
19667 /*!
19668 @brief get a reference value (implicit)
19669 @copydoc get_ref()
19670 */
19671 template < typename ReferenceType, typename std::enable_if <
19672 std::is_reference<ReferenceType>::value&&
19673 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
get_ref() const19674 ReferenceType get_ref() const
19675 {
19676 // delegate call to get_ref_impl
19677 return get_ref_impl<ReferenceType>(*this);
19678 }
19679
19680 /*!
19681 @brief get a value (implicit)
19682
19683 Implicit type conversion between the JSON value and a compatible value.
19684 The call is realized by calling @ref get() const.
19685
19686 @tparam ValueType non-pointer type compatible to the JSON value, for
19687 instance `int` for JSON integer numbers, `bool` for JSON booleans, or
19688 `std::vector` types for JSON arrays. The character type of @ref string_t
19689 as well as an initializer list of this type is excluded to avoid
19690 ambiguities as these types implicitly convert to `std::string`.
19691
19692 @return copy of the JSON value, converted to type @a ValueType
19693
19694 @throw type_error.302 in case passed type @a ValueType is incompatible
19695 to the JSON value type (e.g., the JSON value is of type boolean, but a
19696 string is requested); see example below
19697
19698 @complexity Linear in the size of the JSON value.
19699
19700 @liveexample{The example below shows several conversions from JSON values
19701 to other types. There a few things to note: (1) Floating-point numbers can
19702 be converted to integers\, (2) A JSON array can be converted to a standard
19703 `std::vector<short>`\, (3) A JSON object can be converted to C++
19704 associative containers such as `std::unordered_map<std::string\,
19705 json>`.,operator__ValueType}
19706
19707 @since version 1.0.0
19708 */
19709 template < typename ValueType, typename std::enable_if <
19710 !std::is_pointer<ValueType>::value&&
19711 !std::is_same<ValueType, detail::json_ref<basic_json>>::value&&
19712 !std::is_same<ValueType, typename string_t::value_type>::value&&
19713 !detail::is_basic_json<ValueType>::value
19714 && !std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
19715 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
19716 && !std::is_same<ValueType, typename std::string_view>::value
19717 #endif
19718 && detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value
19719 , int >::type = 0 >
operator ValueType() const19720 JSON_EXPLICIT operator ValueType() const
19721 {
19722 // delegate the call to get<>() const
19723 return get<ValueType>();
19724 }
19725
19726 /*!
19727 @return reference to the binary value
19728
19729 @throw type_error.302 if the value is not binary
19730
19731 @sa @ref is_binary() to check if the value is binary
19732
19733 @since version 3.8.0
19734 */
get_binary()19735 binary_t& get_binary()
19736 {
19737 if (!is_binary())
19738 {
19739 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name())));
19740 }
19741
19742 return *get_ptr<binary_t*>();
19743 }
19744
19745 /// @copydoc get_binary()
get_binary() const19746 const binary_t& get_binary() const
19747 {
19748 if (!is_binary())
19749 {
19750 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name())));
19751 }
19752
19753 return *get_ptr<const binary_t*>();
19754 }
19755
19756 /// @}
19757
19758
19759 ////////////////////
19760 // element access //
19761 ////////////////////
19762
19763 /// @name element access
19764 /// Access to the JSON value.
19765 /// @{
19766
19767 /*!
19768 @brief access specified array element with bounds checking
19769
19770 Returns a reference to the element at specified location @a idx, with
19771 bounds checking.
19772
19773 @param[in] idx index of the element to access
19774
19775 @return reference to the element at index @a idx
19776
19777 @throw type_error.304 if the JSON value is not an array; in this case,
19778 calling `at` with an index makes no sense. See example below.
19779 @throw out_of_range.401 if the index @a idx is out of range of the array;
19780 that is, `idx >= size()`. See example below.
19781
19782 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
19783 changes in the JSON value.
19784
19785 @complexity Constant.
19786
19787 @since version 1.0.0
19788
19789 @liveexample{The example below shows how array elements can be read and
19790 written using `at()`. It also demonstrates the different exceptions that
19791 can be thrown.,at__size_type}
19792 */
at(size_type idx)19793 reference at(size_type idx)
19794 {
19795 // at only works for arrays
19796 if (JSON_HEDLEY_LIKELY(is_array()))
19797 {
19798 JSON_TRY
19799 {
19800 return m_value.array->at(idx);
19801 }
19802 JSON_CATCH (std::out_of_range&)
19803 {
19804 // create better exception explanation
19805 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
19806 }
19807 }
19808 else
19809 {
19810 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
19811 }
19812 }
19813
19814 /*!
19815 @brief access specified array element with bounds checking
19816
19817 Returns a const reference to the element at specified location @a idx,
19818 with bounds checking.
19819
19820 @param[in] idx index of the element to access
19821
19822 @return const reference to the element at index @a idx
19823
19824 @throw type_error.304 if the JSON value is not an array; in this case,
19825 calling `at` with an index makes no sense. See example below.
19826 @throw out_of_range.401 if the index @a idx is out of range of the array;
19827 that is, `idx >= size()`. See example below.
19828
19829 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
19830 changes in the JSON value.
19831
19832 @complexity Constant.
19833
19834 @since version 1.0.0
19835
19836 @liveexample{The example below shows how array elements can be read using
19837 `at()`. It also demonstrates the different exceptions that can be thrown.,
19838 at__size_type_const}
19839 */
at(size_type idx) const19840 const_reference at(size_type idx) const
19841 {
19842 // at only works for arrays
19843 if (JSON_HEDLEY_LIKELY(is_array()))
19844 {
19845 JSON_TRY
19846 {
19847 return m_value.array->at(idx);
19848 }
19849 JSON_CATCH (std::out_of_range&)
19850 {
19851 // create better exception explanation
19852 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
19853 }
19854 }
19855 else
19856 {
19857 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
19858 }
19859 }
19860
19861 /*!
19862 @brief access specified object element with bounds checking
19863
19864 Returns a reference to the element at with specified key @a key, with
19865 bounds checking.
19866
19867 @param[in] key key of the element to access
19868
19869 @return reference to the element at key @a key
19870
19871 @throw type_error.304 if the JSON value is not an object; in this case,
19872 calling `at` with a key makes no sense. See example below.
19873 @throw out_of_range.403 if the key @a key is is not stored in the object;
19874 that is, `find(key) == end()`. See example below.
19875
19876 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
19877 changes in the JSON value.
19878
19879 @complexity Logarithmic in the size of the container.
19880
19881 @sa @ref operator[](const typename object_t::key_type&) for unchecked
19882 access by reference
19883 @sa @ref value() for access by value with a default value
19884
19885 @since version 1.0.0
19886
19887 @liveexample{The example below shows how object elements can be read and
19888 written using `at()`. It also demonstrates the different exceptions that
19889 can be thrown.,at__object_t_key_type}
19890 */
at(const typename object_t::key_type & key)19891 reference at(const typename object_t::key_type& key)
19892 {
19893 // at only works for objects
19894 if (JSON_HEDLEY_LIKELY(is_object()))
19895 {
19896 JSON_TRY
19897 {
19898 return m_value.object->at(key);
19899 }
19900 JSON_CATCH (std::out_of_range&)
19901 {
19902 // create better exception explanation
19903 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
19904 }
19905 }
19906 else
19907 {
19908 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
19909 }
19910 }
19911
19912 /*!
19913 @brief access specified object element with bounds checking
19914
19915 Returns a const reference to the element at with specified key @a key,
19916 with bounds checking.
19917
19918 @param[in] key key of the element to access
19919
19920 @return const reference to the element at key @a key
19921
19922 @throw type_error.304 if the JSON value is not an object; in this case,
19923 calling `at` with a key makes no sense. See example below.
19924 @throw out_of_range.403 if the key @a key is is not stored in the object;
19925 that is, `find(key) == end()`. See example below.
19926
19927 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
19928 changes in the JSON value.
19929
19930 @complexity Logarithmic in the size of the container.
19931
19932 @sa @ref operator[](const typename object_t::key_type&) for unchecked
19933 access by reference
19934 @sa @ref value() for access by value with a default value
19935
19936 @since version 1.0.0
19937
19938 @liveexample{The example below shows how object elements can be read using
19939 `at()`. It also demonstrates the different exceptions that can be thrown.,
19940 at__object_t_key_type_const}
19941 */
at(const typename object_t::key_type & key) const19942 const_reference at(const typename object_t::key_type& key) const
19943 {
19944 // at only works for objects
19945 if (JSON_HEDLEY_LIKELY(is_object()))
19946 {
19947 JSON_TRY
19948 {
19949 return m_value.object->at(key);
19950 }
19951 JSON_CATCH (std::out_of_range&)
19952 {
19953 // create better exception explanation
19954 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
19955 }
19956 }
19957 else
19958 {
19959 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
19960 }
19961 }
19962
19963 /*!
19964 @brief access specified array element
19965
19966 Returns a reference to the element at specified location @a idx.
19967
19968 @note If @a idx is beyond the range of the array (i.e., `idx >= size()`),
19969 then the array is silently filled up with `null` values to make `idx` a
19970 valid reference to the last stored element.
19971
19972 @param[in] idx index of the element to access
19973
19974 @return reference to the element at index @a idx
19975
19976 @throw type_error.305 if the JSON value is not an array or null; in that
19977 cases, using the [] operator with an index makes no sense.
19978
19979 @complexity Constant if @a idx is in the range of the array. Otherwise
19980 linear in `idx - size()`.
19981
19982 @liveexample{The example below shows how array elements can be read and
19983 written using `[]` operator. Note the addition of `null`
19984 values.,operatorarray__size_type}
19985
19986 @since version 1.0.0
19987 */
operator [](size_type idx)19988 reference operator[](size_type idx)
19989 {
19990 // implicitly convert null value to an empty array
19991 if (is_null())
19992 {
19993 m_type = value_t::array;
19994 m_value.array = create<array_t>();
19995 assert_invariant();
19996 }
19997
19998 // operator[] only works for arrays
19999 if (JSON_HEDLEY_LIKELY(is_array()))
20000 {
20001 // fill up array with null values if given idx is outside range
20002 if (idx >= m_value.array->size())
20003 {
20004 m_value.array->insert(m_value.array->end(),
20005 idx - m_value.array->size() + 1,
20006 basic_json());
20007 }
20008
20009 return m_value.array->operator[](idx);
20010 }
20011
20012 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
20013 }
20014
20015 /*!
20016 @brief access specified array element
20017
20018 Returns a const reference to the element at specified location @a idx.
20019
20020 @param[in] idx index of the element to access
20021
20022 @return const reference to the element at index @a idx
20023
20024 @throw type_error.305 if the JSON value is not an array; in that case,
20025 using the [] operator with an index makes no sense.
20026
20027 @complexity Constant.
20028
20029 @liveexample{The example below shows how array elements can be read using
20030 the `[]` operator.,operatorarray__size_type_const}
20031
20032 @since version 1.0.0
20033 */
operator [](size_type idx) const20034 const_reference operator[](size_type idx) const
20035 {
20036 // const operator[] only works for arrays
20037 if (JSON_HEDLEY_LIKELY(is_array()))
20038 {
20039 return m_value.array->operator[](idx);
20040 }
20041
20042 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
20043 }
20044
20045 /*!
20046 @brief access specified object element
20047
20048 Returns a reference to the element at with specified key @a key.
20049
20050 @note If @a key is not found in the object, then it is silently added to
20051 the object and filled with a `null` value to make `key` a valid reference.
20052 In case the value was `null` before, it is converted to an object.
20053
20054 @param[in] key key of the element to access
20055
20056 @return reference to the element at key @a key
20057
20058 @throw type_error.305 if the JSON value is not an object or null; in that
20059 cases, using the [] operator with a key makes no sense.
20060
20061 @complexity Logarithmic in the size of the container.
20062
20063 @liveexample{The example below shows how object elements can be read and
20064 written using the `[]` operator.,operatorarray__key_type}
20065
20066 @sa @ref at(const typename object_t::key_type&) for access by reference
20067 with range checking
20068 @sa @ref value() for access by value with a default value
20069
20070 @since version 1.0.0
20071 */
operator [](const typename object_t::key_type & key)20072 reference operator[](const typename object_t::key_type& key)
20073 {
20074 // implicitly convert null value to an empty object
20075 if (is_null())
20076 {
20077 m_type = value_t::object;
20078 m_value.object = create<object_t>();
20079 assert_invariant();
20080 }
20081
20082 // operator[] only works for objects
20083 if (JSON_HEDLEY_LIKELY(is_object()))
20084 {
20085 return m_value.object->operator[](key);
20086 }
20087
20088 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
20089 }
20090
20091 /*!
20092 @brief read-only access specified object element
20093
20094 Returns a const reference to the element at with specified key @a key. No
20095 bounds checking is performed.
20096
20097 @warning If the element with key @a key does not exist, the behavior is
20098 undefined.
20099
20100 @param[in] key key of the element to access
20101
20102 @return const reference to the element at key @a key
20103
20104 @pre The element with key @a key must exist. **This precondition is
20105 enforced with an assertion.**
20106
20107 @throw type_error.305 if the JSON value is not an object; in that case,
20108 using the [] operator with a key makes no sense.
20109
20110 @complexity Logarithmic in the size of the container.
20111
20112 @liveexample{The example below shows how object elements can be read using
20113 the `[]` operator.,operatorarray__key_type_const}
20114
20115 @sa @ref at(const typename object_t::key_type&) for access by reference
20116 with range checking
20117 @sa @ref value() for access by value with a default value
20118
20119 @since version 1.0.0
20120 */
operator [](const typename object_t::key_type & key) const20121 const_reference operator[](const typename object_t::key_type& key) const
20122 {
20123 // const operator[] only works for objects
20124 if (JSON_HEDLEY_LIKELY(is_object()))
20125 {
20126 JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
20127 return m_value.object->find(key)->second;
20128 }
20129
20130 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
20131 }
20132
20133 /*!
20134 @brief access specified object element
20135
20136 Returns a reference to the element at with specified key @a key.
20137
20138 @note If @a key is not found in the object, then it is silently added to
20139 the object and filled with a `null` value to make `key` a valid reference.
20140 In case the value was `null` before, it is converted to an object.
20141
20142 @param[in] key key of the element to access
20143
20144 @return reference to the element at key @a key
20145
20146 @throw type_error.305 if the JSON value is not an object or null; in that
20147 cases, using the [] operator with a key makes no sense.
20148
20149 @complexity Logarithmic in the size of the container.
20150
20151 @liveexample{The example below shows how object elements can be read and
20152 written using the `[]` operator.,operatorarray__key_type}
20153
20154 @sa @ref at(const typename object_t::key_type&) for access by reference
20155 with range checking
20156 @sa @ref value() for access by value with a default value
20157
20158 @since version 1.1.0
20159 */
20160 template<typename T>
20161 JSON_HEDLEY_NON_NULL(2)
operator [](T * key)20162 reference operator[](T* key)
20163 {
20164 // implicitly convert null to object
20165 if (is_null())
20166 {
20167 m_type = value_t::object;
20168 m_value = value_t::object;
20169 assert_invariant();
20170 }
20171
20172 // at only works for objects
20173 if (JSON_HEDLEY_LIKELY(is_object()))
20174 {
20175 return m_value.object->operator[](key);
20176 }
20177
20178 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
20179 }
20180
20181 /*!
20182 @brief read-only access specified object element
20183
20184 Returns a const reference to the element at with specified key @a key. No
20185 bounds checking is performed.
20186
20187 @warning If the element with key @a key does not exist, the behavior is
20188 undefined.
20189
20190 @param[in] key key of the element to access
20191
20192 @return const reference to the element at key @a key
20193
20194 @pre The element with key @a key must exist. **This precondition is
20195 enforced with an assertion.**
20196
20197 @throw type_error.305 if the JSON value is not an object; in that case,
20198 using the [] operator with a key makes no sense.
20199
20200 @complexity Logarithmic in the size of the container.
20201
20202 @liveexample{The example below shows how object elements can be read using
20203 the `[]` operator.,operatorarray__key_type_const}
20204
20205 @sa @ref at(const typename object_t::key_type&) for access by reference
20206 with range checking
20207 @sa @ref value() for access by value with a default value
20208
20209 @since version 1.1.0
20210 */
20211 template<typename T>
20212 JSON_HEDLEY_NON_NULL(2)
operator [](T * key) const20213 const_reference operator[](T* key) const
20214 {
20215 // at only works for objects
20216 if (JSON_HEDLEY_LIKELY(is_object()))
20217 {
20218 JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
20219 return m_value.object->find(key)->second;
20220 }
20221
20222 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
20223 }
20224
20225 /*!
20226 @brief access specified object element with default value
20227
20228 Returns either a copy of an object's element at the specified key @a key
20229 or a given default value if no element with key @a key exists.
20230
20231 The function is basically equivalent to executing
20232 @code {.cpp}
20233 try {
20234 return at(key);
20235 } catch(out_of_range) {
20236 return default_value;
20237 }
20238 @endcode
20239
20240 @note Unlike @ref at(const typename object_t::key_type&), this function
20241 does not throw if the given key @a key was not found.
20242
20243 @note Unlike @ref operator[](const typename object_t::key_type& key), this
20244 function does not implicitly add an element to the position defined by @a
20245 key. This function is furthermore also applicable to const objects.
20246
20247 @param[in] key key of the element to access
20248 @param[in] default_value the value to return if @a key is not found
20249
20250 @tparam ValueType type compatible to JSON values, for instance `int` for
20251 JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
20252 JSON arrays. Note the type of the expected value at @a key and the default
20253 value @a default_value must be compatible.
20254
20255 @return copy of the element at key @a key or @a default_value if @a key
20256 is not found
20257
20258 @throw type_error.302 if @a default_value does not match the type of the
20259 value at @a key
20260 @throw type_error.306 if the JSON value is not an object; in that case,
20261 using `value()` with a key makes no sense.
20262
20263 @complexity Logarithmic in the size of the container.
20264
20265 @liveexample{The example below shows how object elements can be queried
20266 with a default value.,basic_json__value}
20267
20268 @sa @ref at(const typename object_t::key_type&) for access by reference
20269 with range checking
20270 @sa @ref operator[](const typename object_t::key_type&) for unchecked
20271 access by reference
20272
20273 @since version 1.0.0
20274 */
20275 // using std::is_convertible in a std::enable_if will fail when using explicit conversions
20276 template < class ValueType, typename std::enable_if <
20277 detail::is_getable<basic_json_t, ValueType>::value
20278 && !std::is_same<value_t, ValueType>::value, int >::type = 0 >
value(const typename object_t::key_type & key,const ValueType & default_value) const20279 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
20280 {
20281 // at only works for objects
20282 if (JSON_HEDLEY_LIKELY(is_object()))
20283 {
20284 // if key is found, return value and given default value otherwise
20285 const auto it = find(key);
20286 if (it != end())
20287 {
20288 return it->template get<ValueType>();
20289 }
20290
20291 return default_value;
20292 }
20293
20294 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
20295 }
20296
20297 /*!
20298 @brief overload for a default value of type const char*
20299 @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const
20300 */
value(const typename object_t::key_type & key,const char * default_value) const20301 string_t value(const typename object_t::key_type& key, const char* default_value) const
20302 {
20303 return value(key, string_t(default_value));
20304 }
20305
20306 /*!
20307 @brief access specified object element via JSON Pointer with default value
20308
20309 Returns either a copy of an object's element at the specified key @a key
20310 or a given default value if no element with key @a key exists.
20311
20312 The function is basically equivalent to executing
20313 @code {.cpp}
20314 try {
20315 return at(ptr);
20316 } catch(out_of_range) {
20317 return default_value;
20318 }
20319 @endcode
20320
20321 @note Unlike @ref at(const json_pointer&), this function does not throw
20322 if the given key @a key was not found.
20323
20324 @param[in] ptr a JSON pointer to the element to access
20325 @param[in] default_value the value to return if @a ptr found no value
20326
20327 @tparam ValueType type compatible to JSON values, for instance `int` for
20328 JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
20329 JSON arrays. Note the type of the expected value at @a key and the default
20330 value @a default_value must be compatible.
20331
20332 @return copy of the element at key @a key or @a default_value if @a key
20333 is not found
20334
20335 @throw type_error.302 if @a default_value does not match the type of the
20336 value at @a ptr
20337 @throw type_error.306 if the JSON value is not an object; in that case,
20338 using `value()` with a key makes no sense.
20339
20340 @complexity Logarithmic in the size of the container.
20341
20342 @liveexample{The example below shows how object elements can be queried
20343 with a default value.,basic_json__value_ptr}
20344
20345 @sa @ref operator[](const json_pointer&) for unchecked access by reference
20346
20347 @since version 2.0.2
20348 */
20349 template<class ValueType, typename std::enable_if<
20350 detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
value(const json_pointer & ptr,const ValueType & default_value) const20351 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
20352 {
20353 // at only works for objects
20354 if (JSON_HEDLEY_LIKELY(is_object()))
20355 {
20356 // if pointer resolves a value, return it or use default value
20357 JSON_TRY
20358 {
20359 return ptr.get_checked(this).template get<ValueType>();
20360 }
20361 JSON_INTERNAL_CATCH (out_of_range&)
20362 {
20363 return default_value;
20364 }
20365 }
20366
20367 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
20368 }
20369
20370 /*!
20371 @brief overload for a default value of type const char*
20372 @copydoc basic_json::value(const json_pointer&, ValueType) const
20373 */
20374 JSON_HEDLEY_NON_NULL(3)
value(const json_pointer & ptr,const char * default_value) const20375 string_t value(const json_pointer& ptr, const char* default_value) const
20376 {
20377 return value(ptr, string_t(default_value));
20378 }
20379
20380 /*!
20381 @brief access the first element
20382
20383 Returns a reference to the first element in the container. For a JSON
20384 container `c`, the expression `c.front()` is equivalent to `*c.begin()`.
20385
20386 @return In case of a structured type (array or object), a reference to the
20387 first element is returned. In case of number, string, boolean, or binary
20388 values, a reference to the value is returned.
20389
20390 @complexity Constant.
20391
20392 @pre The JSON value must not be `null` (would throw `std::out_of_range`)
20393 or an empty array or object (undefined behavior, **guarded by
20394 assertions**).
20395 @post The JSON value remains unchanged.
20396
20397 @throw invalid_iterator.214 when called on `null` value
20398
20399 @liveexample{The following code shows an example for `front()`.,front}
20400
20401 @sa @ref back() -- access the last element
20402
20403 @since version 1.0.0
20404 */
front()20405 reference front()
20406 {
20407 return *begin();
20408 }
20409
20410 /*!
20411 @copydoc basic_json::front()
20412 */
front() const20413 const_reference front() const
20414 {
20415 return *cbegin();
20416 }
20417
20418 /*!
20419 @brief access the last element
20420
20421 Returns a reference to the last element in the container. For a JSON
20422 container `c`, the expression `c.back()` is equivalent to
20423 @code {.cpp}
20424 auto tmp = c.end();
20425 --tmp;
20426 return *tmp;
20427 @endcode
20428
20429 @return In case of a structured type (array or object), a reference to the
20430 last element is returned. In case of number, string, boolean, or binary
20431 values, a reference to the value is returned.
20432
20433 @complexity Constant.
20434
20435 @pre The JSON value must not be `null` (would throw `std::out_of_range`)
20436 or an empty array or object (undefined behavior, **guarded by
20437 assertions**).
20438 @post The JSON value remains unchanged.
20439
20440 @throw invalid_iterator.214 when called on a `null` value. See example
20441 below.
20442
20443 @liveexample{The following code shows an example for `back()`.,back}
20444
20445 @sa @ref front() -- access the first element
20446
20447 @since version 1.0.0
20448 */
back()20449 reference back()
20450 {
20451 auto tmp = end();
20452 --tmp;
20453 return *tmp;
20454 }
20455
20456 /*!
20457 @copydoc basic_json::back()
20458 */
back() const20459 const_reference back() const
20460 {
20461 auto tmp = cend();
20462 --tmp;
20463 return *tmp;
20464 }
20465
20466 /*!
20467 @brief remove element given an iterator
20468
20469 Removes the element specified by iterator @a pos. The iterator @a pos must
20470 be valid and dereferenceable. Thus the `end()` iterator (which is valid,
20471 but is not dereferenceable) cannot be used as a value for @a pos.
20472
20473 If called on a primitive type other than `null`, the resulting JSON value
20474 will be `null`.
20475
20476 @param[in] pos iterator to the element to remove
20477 @return Iterator following the last removed element. If the iterator @a
20478 pos refers to the last element, the `end()` iterator is returned.
20479
20480 @tparam IteratorType an @ref iterator or @ref const_iterator
20481
20482 @post Invalidates iterators and references at or after the point of the
20483 erase, including the `end()` iterator.
20484
20485 @throw type_error.307 if called on a `null` value; example: `"cannot use
20486 erase() with null"`
20487 @throw invalid_iterator.202 if called on an iterator which does not belong
20488 to the current JSON value; example: `"iterator does not fit current
20489 value"`
20490 @throw invalid_iterator.205 if called on a primitive type with invalid
20491 iterator (i.e., any iterator which is not `begin()`); example: `"iterator
20492 out of range"`
20493
20494 @complexity The complexity depends on the type:
20495 - objects: amortized constant
20496 - arrays: linear in distance between @a pos and the end of the container
20497 - strings and binary: linear in the length of the member
20498 - other types: constant
20499
20500 @liveexample{The example shows the result of `erase()` for different JSON
20501 types.,erase__IteratorType}
20502
20503 @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
20504 the given range
20505 @sa @ref erase(const typename object_t::key_type&) -- removes the element
20506 from an object at the given key
20507 @sa @ref erase(const size_type) -- removes the element from an array at
20508 the given index
20509
20510 @since version 1.0.0
20511 */
20512 template < class IteratorType, typename std::enable_if <
20513 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
20514 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
20515 = 0 >
erase(IteratorType pos)20516 IteratorType erase(IteratorType pos)
20517 {
20518 // make sure iterator fits the current value
20519 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
20520 {
20521 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
20522 }
20523
20524 IteratorType result = end();
20525
20526 switch (m_type)
20527 {
20528 case value_t::boolean:
20529 case value_t::number_float:
20530 case value_t::number_integer:
20531 case value_t::number_unsigned:
20532 case value_t::string:
20533 case value_t::binary:
20534 {
20535 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
20536 {
20537 JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
20538 }
20539
20540 if (is_string())
20541 {
20542 AllocatorType<string_t> alloc;
20543 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
20544 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
20545 m_value.string = nullptr;
20546 }
20547 else if (is_binary())
20548 {
20549 AllocatorType<binary_t> alloc;
20550 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
20551 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
20552 m_value.binary = nullptr;
20553 }
20554
20555 m_type = value_t::null;
20556 assert_invariant();
20557 break;
20558 }
20559
20560 case value_t::object:
20561 {
20562 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
20563 break;
20564 }
20565
20566 case value_t::array:
20567 {
20568 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
20569 break;
20570 }
20571
20572 default:
20573 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
20574 }
20575
20576 return result;
20577 }
20578
20579 /*!
20580 @brief remove elements given an iterator range
20581
20582 Removes the element specified by the range `[first; last)`. The iterator
20583 @a first does not need to be dereferenceable if `first == last`: erasing
20584 an empty range is a no-op.
20585
20586 If called on a primitive type other than `null`, the resulting JSON value
20587 will be `null`.
20588
20589 @param[in] first iterator to the beginning of the range to remove
20590 @param[in] last iterator past the end of the range to remove
20591 @return Iterator following the last removed element. If the iterator @a
20592 second refers to the last element, the `end()` iterator is returned.
20593
20594 @tparam IteratorType an @ref iterator or @ref const_iterator
20595
20596 @post Invalidates iterators and references at or after the point of the
20597 erase, including the `end()` iterator.
20598
20599 @throw type_error.307 if called on a `null` value; example: `"cannot use
20600 erase() with null"`
20601 @throw invalid_iterator.203 if called on iterators which does not belong
20602 to the current JSON value; example: `"iterators do not fit current value"`
20603 @throw invalid_iterator.204 if called on a primitive type with invalid
20604 iterators (i.e., if `first != begin()` and `last != end()`); example:
20605 `"iterators out of range"`
20606
20607 @complexity The complexity depends on the type:
20608 - objects: `log(size()) + std::distance(first, last)`
20609 - arrays: linear in the distance between @a first and @a last, plus linear
20610 in the distance between @a last and end of the container
20611 - strings and binary: linear in the length of the member
20612 - other types: constant
20613
20614 @liveexample{The example shows the result of `erase()` for different JSON
20615 types.,erase__IteratorType_IteratorType}
20616
20617 @sa @ref erase(IteratorType) -- removes the element at a given position
20618 @sa @ref erase(const typename object_t::key_type&) -- removes the element
20619 from an object at the given key
20620 @sa @ref erase(const size_type) -- removes the element from an array at
20621 the given index
20622
20623 @since version 1.0.0
20624 */
20625 template < class IteratorType, typename std::enable_if <
20626 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
20627 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
20628 = 0 >
erase(IteratorType first,IteratorType last)20629 IteratorType erase(IteratorType first, IteratorType last)
20630 {
20631 // make sure iterator fits the current value
20632 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
20633 {
20634 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
20635 }
20636
20637 IteratorType result = end();
20638
20639 switch (m_type)
20640 {
20641 case value_t::boolean:
20642 case value_t::number_float:
20643 case value_t::number_integer:
20644 case value_t::number_unsigned:
20645 case value_t::string:
20646 case value_t::binary:
20647 {
20648 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
20649 || !last.m_it.primitive_iterator.is_end()))
20650 {
20651 JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
20652 }
20653
20654 if (is_string())
20655 {
20656 AllocatorType<string_t> alloc;
20657 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
20658 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
20659 m_value.string = nullptr;
20660 }
20661 else if (is_binary())
20662 {
20663 AllocatorType<binary_t> alloc;
20664 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
20665 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
20666 m_value.binary = nullptr;
20667 }
20668
20669 m_type = value_t::null;
20670 assert_invariant();
20671 break;
20672 }
20673
20674 case value_t::object:
20675 {
20676 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
20677 last.m_it.object_iterator);
20678 break;
20679 }
20680
20681 case value_t::array:
20682 {
20683 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
20684 last.m_it.array_iterator);
20685 break;
20686 }
20687
20688 default:
20689 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
20690 }
20691
20692 return result;
20693 }
20694
20695 /*!
20696 @brief remove element from a JSON object given a key
20697
20698 Removes elements from a JSON object with the key value @a key.
20699
20700 @param[in] key value of the elements to remove
20701
20702 @return Number of elements removed. If @a ObjectType is the default
20703 `std::map` type, the return value will always be `0` (@a key was not
20704 found) or `1` (@a key was found).
20705
20706 @post References and iterators to the erased elements are invalidated.
20707 Other references and iterators are not affected.
20708
20709 @throw type_error.307 when called on a type other than JSON object;
20710 example: `"cannot use erase() with null"`
20711
20712 @complexity `log(size()) + count(key)`
20713
20714 @liveexample{The example shows the effect of `erase()`.,erase__key_type}
20715
20716 @sa @ref erase(IteratorType) -- removes the element at a given position
20717 @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
20718 the given range
20719 @sa @ref erase(const size_type) -- removes the element from an array at
20720 the given index
20721
20722 @since version 1.0.0
20723 */
erase(const typename object_t::key_type & key)20724 size_type erase(const typename object_t::key_type& key)
20725 {
20726 // this erase only works for objects
20727 if (JSON_HEDLEY_LIKELY(is_object()))
20728 {
20729 return m_value.object->erase(key);
20730 }
20731
20732 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
20733 }
20734
20735 /*!
20736 @brief remove element from a JSON array given an index
20737
20738 Removes element from a JSON array at the index @a idx.
20739
20740 @param[in] idx index of the element to remove
20741
20742 @throw type_error.307 when called on a type other than JSON object;
20743 example: `"cannot use erase() with null"`
20744 @throw out_of_range.401 when `idx >= size()`; example: `"array index 17
20745 is out of range"`
20746
20747 @complexity Linear in distance between @a idx and the end of the container.
20748
20749 @liveexample{The example shows the effect of `erase()`.,erase__size_type}
20750
20751 @sa @ref erase(IteratorType) -- removes the element at a given position
20752 @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
20753 the given range
20754 @sa @ref erase(const typename object_t::key_type&) -- removes the element
20755 from an object at the given key
20756
20757 @since version 1.0.0
20758 */
erase(const size_type idx)20759 void erase(const size_type idx)
20760 {
20761 // this erase only works for arrays
20762 if (JSON_HEDLEY_LIKELY(is_array()))
20763 {
20764 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
20765 {
20766 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
20767 }
20768
20769 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
20770 }
20771 else
20772 {
20773 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
20774 }
20775 }
20776
20777 /// @}
20778
20779
20780 ////////////
20781 // lookup //
20782 ////////////
20783
20784 /// @name lookup
20785 /// @{
20786
20787 /*!
20788 @brief find an element in a JSON object
20789
20790 Finds an element in a JSON object with key equivalent to @a key. If the
20791 element is not found or the JSON value is not an object, end() is
20792 returned.
20793
20794 @note This method always returns @ref end() when executed on a JSON type
20795 that is not an object.
20796
20797 @param[in] key key value of the element to search for.
20798
20799 @return Iterator to an element with key equivalent to @a key. If no such
20800 element is found or the JSON value is not an object, past-the-end (see
20801 @ref end()) iterator is returned.
20802
20803 @complexity Logarithmic in the size of the JSON object.
20804
20805 @liveexample{The example shows how `find()` is used.,find__key_type}
20806
20807 @sa @ref contains(KeyT&&) const -- checks whether a key exists
20808
20809 @since version 1.0.0
20810 */
20811 template<typename KeyT>
find(KeyT && key)20812 iterator find(KeyT&& key)
20813 {
20814 auto result = end();
20815
20816 if (is_object())
20817 {
20818 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
20819 }
20820
20821 return result;
20822 }
20823
20824 /*!
20825 @brief find an element in a JSON object
20826 @copydoc find(KeyT&&)
20827 */
20828 template<typename KeyT>
find(KeyT && key) const20829 const_iterator find(KeyT&& key) const
20830 {
20831 auto result = cend();
20832
20833 if (is_object())
20834 {
20835 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
20836 }
20837
20838 return result;
20839 }
20840
20841 /*!
20842 @brief returns the number of occurrences of a key in a JSON object
20843
20844 Returns the number of elements with key @a key. If ObjectType is the
20845 default `std::map` type, the return value will always be `0` (@a key was
20846 not found) or `1` (@a key was found).
20847
20848 @note This method always returns `0` when executed on a JSON type that is
20849 not an object.
20850
20851 @param[in] key key value of the element to count
20852
20853 @return Number of elements with key @a key. If the JSON value is not an
20854 object, the return value will be `0`.
20855
20856 @complexity Logarithmic in the size of the JSON object.
20857
20858 @liveexample{The example shows how `count()` is used.,count}
20859
20860 @since version 1.0.0
20861 */
20862 template<typename KeyT>
count(KeyT && key) const20863 size_type count(KeyT&& key) const
20864 {
20865 // return 0 for all nonobject types
20866 return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
20867 }
20868
20869 /*!
20870 @brief check the existence of an element in a JSON object
20871
20872 Check whether an element exists in a JSON object with key equivalent to
20873 @a key. If the element is not found or the JSON value is not an object,
20874 false is returned.
20875
20876 @note This method always returns false when executed on a JSON type
20877 that is not an object.
20878
20879 @param[in] key key value to check its existence.
20880
20881 @return true if an element with specified @a key exists. If no such
20882 element with such key is found or the JSON value is not an object,
20883 false is returned.
20884
20885 @complexity Logarithmic in the size of the JSON object.
20886
20887 @liveexample{The following code shows an example for `contains()`.,contains}
20888
20889 @sa @ref find(KeyT&&) -- returns an iterator to an object element
20890 @sa @ref contains(const json_pointer&) const -- checks the existence for a JSON pointer
20891
20892 @since version 3.6.0
20893 */
20894 template < typename KeyT, typename std::enable_if <
20895 !std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int >::type = 0 >
contains(KeyT && key) const20896 bool contains(KeyT && key) const
20897 {
20898 return is_object() && m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
20899 }
20900
20901 /*!
20902 @brief check the existence of an element in a JSON object given a JSON pointer
20903
20904 Check whether the given JSON pointer @a ptr can be resolved in the current
20905 JSON value.
20906
20907 @note This method can be executed on any JSON value type.
20908
20909 @param[in] ptr JSON pointer to check its existence.
20910
20911 @return true if the JSON pointer can be resolved to a stored value, false
20912 otherwise.
20913
20914 @post If `j.contains(ptr)` returns true, it is safe to call `j[ptr]`.
20915
20916 @throw parse_error.106 if an array index begins with '0'
20917 @throw parse_error.109 if an array index was not a number
20918
20919 @complexity Logarithmic in the size of the JSON object.
20920
20921 @liveexample{The following code shows an example for `contains()`.,contains_json_pointer}
20922
20923 @sa @ref contains(KeyT &&) const -- checks the existence of a key
20924
20925 @since version 3.7.0
20926 */
contains(const json_pointer & ptr) const20927 bool contains(const json_pointer& ptr) const
20928 {
20929 return ptr.contains(this);
20930 }
20931
20932 /// @}
20933
20934
20935 ///////////////
20936 // iterators //
20937 ///////////////
20938
20939 /// @name iterators
20940 /// @{
20941
20942 /*!
20943 @brief returns an iterator to the first element
20944
20945 Returns an iterator to the first element.
20946
20947 @image html range-begin-end.svg "Illustration from cppreference.com"
20948
20949 @return iterator to the first element
20950
20951 @complexity Constant.
20952
20953 @requirement This function helps `basic_json` satisfying the
20954 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
20955 requirements:
20956 - The complexity is constant.
20957
20958 @liveexample{The following code shows an example for `begin()`.,begin}
20959
20960 @sa @ref cbegin() -- returns a const iterator to the beginning
20961 @sa @ref end() -- returns an iterator to the end
20962 @sa @ref cend() -- returns a const iterator to the end
20963
20964 @since version 1.0.0
20965 */
begin()20966 iterator begin() noexcept
20967 {
20968 iterator result(this);
20969 result.set_begin();
20970 return result;
20971 }
20972
20973 /*!
20974 @copydoc basic_json::cbegin()
20975 */
begin() const20976 const_iterator begin() const noexcept
20977 {
20978 return cbegin();
20979 }
20980
20981 /*!
20982 @brief returns a const iterator to the first element
20983
20984 Returns a const iterator to the first element.
20985
20986 @image html range-begin-end.svg "Illustration from cppreference.com"
20987
20988 @return const iterator to the first element
20989
20990 @complexity Constant.
20991
20992 @requirement This function helps `basic_json` satisfying the
20993 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
20994 requirements:
20995 - The complexity is constant.
20996 - Has the semantics of `const_cast<const basic_json&>(*this).begin()`.
20997
20998 @liveexample{The following code shows an example for `cbegin()`.,cbegin}
20999
21000 @sa @ref begin() -- returns an iterator to the beginning
21001 @sa @ref end() -- returns an iterator to the end
21002 @sa @ref cend() -- returns a const iterator to the end
21003
21004 @since version 1.0.0
21005 */
cbegin() const21006 const_iterator cbegin() const noexcept
21007 {
21008 const_iterator result(this);
21009 result.set_begin();
21010 return result;
21011 }
21012
21013 /*!
21014 @brief returns an iterator to one past the last element
21015
21016 Returns an iterator to one past the last element.
21017
21018 @image html range-begin-end.svg "Illustration from cppreference.com"
21019
21020 @return iterator one past the last element
21021
21022 @complexity Constant.
21023
21024 @requirement This function helps `basic_json` satisfying the
21025 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
21026 requirements:
21027 - The complexity is constant.
21028
21029 @liveexample{The following code shows an example for `end()`.,end}
21030
21031 @sa @ref cend() -- returns a const iterator to the end
21032 @sa @ref begin() -- returns an iterator to the beginning
21033 @sa @ref cbegin() -- returns a const iterator to the beginning
21034
21035 @since version 1.0.0
21036 */
end()21037 iterator end() noexcept
21038 {
21039 iterator result(this);
21040 result.set_end();
21041 return result;
21042 }
21043
21044 /*!
21045 @copydoc basic_json::cend()
21046 */
end() const21047 const_iterator end() const noexcept
21048 {
21049 return cend();
21050 }
21051
21052 /*!
21053 @brief returns a const iterator to one past the last element
21054
21055 Returns a const iterator to one past the last element.
21056
21057 @image html range-begin-end.svg "Illustration from cppreference.com"
21058
21059 @return const iterator one past the last element
21060
21061 @complexity Constant.
21062
21063 @requirement This function helps `basic_json` satisfying the
21064 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
21065 requirements:
21066 - The complexity is constant.
21067 - Has the semantics of `const_cast<const basic_json&>(*this).end()`.
21068
21069 @liveexample{The following code shows an example for `cend()`.,cend}
21070
21071 @sa @ref end() -- returns an iterator to the end
21072 @sa @ref begin() -- returns an iterator to the beginning
21073 @sa @ref cbegin() -- returns a const iterator to the beginning
21074
21075 @since version 1.0.0
21076 */
cend() const21077 const_iterator cend() const noexcept
21078 {
21079 const_iterator result(this);
21080 result.set_end();
21081 return result;
21082 }
21083
21084 /*!
21085 @brief returns an iterator to the reverse-beginning
21086
21087 Returns an iterator to the reverse-beginning; that is, the last element.
21088
21089 @image html range-rbegin-rend.svg "Illustration from cppreference.com"
21090
21091 @complexity Constant.
21092
21093 @requirement This function helps `basic_json` satisfying the
21094 [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
21095 requirements:
21096 - The complexity is constant.
21097 - Has the semantics of `reverse_iterator(end())`.
21098
21099 @liveexample{The following code shows an example for `rbegin()`.,rbegin}
21100
21101 @sa @ref crbegin() -- returns a const reverse iterator to the beginning
21102 @sa @ref rend() -- returns a reverse iterator to the end
21103 @sa @ref crend() -- returns a const reverse iterator to the end
21104
21105 @since version 1.0.0
21106 */
rbegin()21107 reverse_iterator rbegin() noexcept
21108 {
21109 return reverse_iterator(end());
21110 }
21111
21112 /*!
21113 @copydoc basic_json::crbegin()
21114 */
rbegin() const21115 const_reverse_iterator rbegin() const noexcept
21116 {
21117 return crbegin();
21118 }
21119
21120 /*!
21121 @brief returns an iterator to the reverse-end
21122
21123 Returns an iterator to the reverse-end; that is, one before the first
21124 element.
21125
21126 @image html range-rbegin-rend.svg "Illustration from cppreference.com"
21127
21128 @complexity Constant.
21129
21130 @requirement This function helps `basic_json` satisfying the
21131 [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
21132 requirements:
21133 - The complexity is constant.
21134 - Has the semantics of `reverse_iterator(begin())`.
21135
21136 @liveexample{The following code shows an example for `rend()`.,rend}
21137
21138 @sa @ref crend() -- returns a const reverse iterator to the end
21139 @sa @ref rbegin() -- returns a reverse iterator to the beginning
21140 @sa @ref crbegin() -- returns a const reverse iterator to the beginning
21141
21142 @since version 1.0.0
21143 */
rend()21144 reverse_iterator rend() noexcept
21145 {
21146 return reverse_iterator(begin());
21147 }
21148
21149 /*!
21150 @copydoc basic_json::crend()
21151 */
rend() const21152 const_reverse_iterator rend() const noexcept
21153 {
21154 return crend();
21155 }
21156
21157 /*!
21158 @brief returns a const reverse iterator to the last element
21159
21160 Returns a const iterator to the reverse-beginning; that is, the last
21161 element.
21162
21163 @image html range-rbegin-rend.svg "Illustration from cppreference.com"
21164
21165 @complexity Constant.
21166
21167 @requirement This function helps `basic_json` satisfying the
21168 [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
21169 requirements:
21170 - The complexity is constant.
21171 - Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.
21172
21173 @liveexample{The following code shows an example for `crbegin()`.,crbegin}
21174
21175 @sa @ref rbegin() -- returns a reverse iterator to the beginning
21176 @sa @ref rend() -- returns a reverse iterator to the end
21177 @sa @ref crend() -- returns a const reverse iterator to the end
21178
21179 @since version 1.0.0
21180 */
crbegin() const21181 const_reverse_iterator crbegin() const noexcept
21182 {
21183 return const_reverse_iterator(cend());
21184 }
21185
21186 /*!
21187 @brief returns a const reverse iterator to one before the first
21188
21189 Returns a const reverse iterator to the reverse-end; that is, one before
21190 the first element.
21191
21192 @image html range-rbegin-rend.svg "Illustration from cppreference.com"
21193
21194 @complexity Constant.
21195
21196 @requirement This function helps `basic_json` satisfying the
21197 [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
21198 requirements:
21199 - The complexity is constant.
21200 - Has the semantics of `const_cast<const basic_json&>(*this).rend()`.
21201
21202 @liveexample{The following code shows an example for `crend()`.,crend}
21203
21204 @sa @ref rend() -- returns a reverse iterator to the end
21205 @sa @ref rbegin() -- returns a reverse iterator to the beginning
21206 @sa @ref crbegin() -- returns a const reverse iterator to the beginning
21207
21208 @since version 1.0.0
21209 */
crend() const21210 const_reverse_iterator crend() const noexcept
21211 {
21212 return const_reverse_iterator(cbegin());
21213 }
21214
21215 public:
21216 /*!
21217 @brief wrapper to access iterator member functions in range-based for
21218
21219 This function allows to access @ref iterator::key() and @ref
21220 iterator::value() during range-based for loops. In these loops, a
21221 reference to the JSON values is returned, so there is no access to the
21222 underlying iterator.
21223
21224 For loop without iterator_wrapper:
21225
21226 @code{cpp}
21227 for (auto it = j_object.begin(); it != j_object.end(); ++it)
21228 {
21229 std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
21230 }
21231 @endcode
21232
21233 Range-based for loop without iterator proxy:
21234
21235 @code{cpp}
21236 for (auto it : j_object)
21237 {
21238 // "it" is of type json::reference and has no key() member
21239 std::cout << "value: " << it << '\n';
21240 }
21241 @endcode
21242
21243 Range-based for loop with iterator proxy:
21244
21245 @code{cpp}
21246 for (auto it : json::iterator_wrapper(j_object))
21247 {
21248 std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
21249 }
21250 @endcode
21251
21252 @note When iterating over an array, `key()` will return the index of the
21253 element as string (see example).
21254
21255 @param[in] ref reference to a JSON value
21256 @return iteration proxy object wrapping @a ref with an interface to use in
21257 range-based for loops
21258
21259 @liveexample{The following code shows how the wrapper is used,iterator_wrapper}
21260
21261 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
21262 changes in the JSON value.
21263
21264 @complexity Constant.
21265
21266 @note The name of this function is not yet final and may change in the
21267 future.
21268
21269 @deprecated This stream operator is deprecated and will be removed in
21270 future 4.0.0 of the library. Please use @ref items() instead;
21271 that is, replace `json::iterator_wrapper(j)` with `j.items()`.
21272 */
items()21273 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
21274 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
21275 {
21276 return ref.items();
21277 }
21278
21279 /*!
21280 @copydoc iterator_wrapper(reference)
21281 */
items()21282 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
21283 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
21284 {
21285 return ref.items();
21286 }
21287
21288 /*!
21289 @brief helper to access iterator member functions in range-based for
21290
21291 This function allows to access @ref iterator::key() and @ref
21292 iterator::value() during range-based for loops. In these loops, a
21293 reference to the JSON values is returned, so there is no access to the
21294 underlying iterator.
21295
21296 For loop without `items()` function:
21297
21298 @code{cpp}
21299 for (auto it = j_object.begin(); it != j_object.end(); ++it)
21300 {
21301 std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
21302 }
21303 @endcode
21304
21305 Range-based for loop without `items()` function:
21306
21307 @code{cpp}
21308 for (auto it : j_object)
21309 {
21310 // "it" is of type json::reference and has no key() member
21311 std::cout << "value: " << it << '\n';
21312 }
21313 @endcode
21314
21315 Range-based for loop with `items()` function:
21316
21317 @code{cpp}
21318 for (auto& el : j_object.items())
21319 {
21320 std::cout << "key: " << el.key() << ", value:" << el.value() << '\n';
21321 }
21322 @endcode
21323
21324 The `items()` function also allows to use
21325 [structured bindings](https://en.cppreference.com/w/cpp/language/structured_binding)
21326 (C++17):
21327
21328 @code{cpp}
21329 for (auto& [key, val] : j_object.items())
21330 {
21331 std::cout << "key: " << key << ", value:" << val << '\n';
21332 }
21333 @endcode
21334
21335 @note When iterating over an array, `key()` will return the index of the
21336 element as string (see example). For primitive types (e.g., numbers),
21337 `key()` returns an empty string.
21338
21339 @warning Using `items()` on temporary objects is dangerous. Make sure the
21340 object's lifetime exeeds the iteration. See
21341 <https://github.com/nlohmann/json/issues/2040> for more
21342 information.
21343
21344 @return iteration proxy object wrapping @a ref with an interface to use in
21345 range-based for loops
21346
21347 @liveexample{The following code shows how the function is used.,items}
21348
21349 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
21350 changes in the JSON value.
21351
21352 @complexity Constant.
21353
21354 @since version 3.1.0, structured bindings support since 3.5.0.
21355 */
items()21356 iteration_proxy<iterator> items() noexcept
21357 {
21358 return iteration_proxy<iterator>(*this);
21359 }
21360
21361 /*!
21362 @copydoc items()
21363 */
items() const21364 iteration_proxy<const_iterator> items() const noexcept
21365 {
21366 return iteration_proxy<const_iterator>(*this);
21367 }
21368
21369 /// @}
21370
21371
21372 //////////////
21373 // capacity //
21374 //////////////
21375
21376 /// @name capacity
21377 /// @{
21378
21379 /*!
21380 @brief checks whether the container is empty.
21381
21382 Checks if a JSON value has no elements (i.e. whether its @ref size is `0`).
21383
21384 @return The return value depends on the different types and is
21385 defined as follows:
21386 Value type | return value
21387 ----------- | -------------
21388 null | `true`
21389 boolean | `false`
21390 string | `false`
21391 number | `false`
21392 binary | `false`
21393 object | result of function `object_t::empty()`
21394 array | result of function `array_t::empty()`
21395
21396 @liveexample{The following code uses `empty()` to check if a JSON
21397 object contains any elements.,empty}
21398
21399 @complexity Constant, as long as @ref array_t and @ref object_t satisfy
21400 the Container concept; that is, their `empty()` functions have constant
21401 complexity.
21402
21403 @iterators No changes.
21404
21405 @exceptionsafety No-throw guarantee: this function never throws exceptions.
21406
21407 @note This function does not return whether a string stored as JSON value
21408 is empty - it returns whether the JSON container itself is empty which is
21409 false in the case of a string.
21410
21411 @requirement This function helps `basic_json` satisfying the
21412 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
21413 requirements:
21414 - The complexity is constant.
21415 - Has the semantics of `begin() == end()`.
21416
21417 @sa @ref size() -- returns the number of elements
21418
21419 @since version 1.0.0
21420 */
empty() const21421 bool empty() const noexcept
21422 {
21423 switch (m_type)
21424 {
21425 case value_t::null:
21426 {
21427 // null values are empty
21428 return true;
21429 }
21430
21431 case value_t::array:
21432 {
21433 // delegate call to array_t::empty()
21434 return m_value.array->empty();
21435 }
21436
21437 case value_t::object:
21438 {
21439 // delegate call to object_t::empty()
21440 return m_value.object->empty();
21441 }
21442
21443 default:
21444 {
21445 // all other types are nonempty
21446 return false;
21447 }
21448 }
21449 }
21450
21451 /*!
21452 @brief returns the number of elements
21453
21454 Returns the number of elements in a JSON value.
21455
21456 @return The return value depends on the different types and is
21457 defined as follows:
21458 Value type | return value
21459 ----------- | -------------
21460 null | `0`
21461 boolean | `1`
21462 string | `1`
21463 number | `1`
21464 binary | `1`
21465 object | result of function object_t::size()
21466 array | result of function array_t::size()
21467
21468 @liveexample{The following code calls `size()` on the different value
21469 types.,size}
21470
21471 @complexity Constant, as long as @ref array_t and @ref object_t satisfy
21472 the Container concept; that is, their size() functions have constant
21473 complexity.
21474
21475 @iterators No changes.
21476
21477 @exceptionsafety No-throw guarantee: this function never throws exceptions.
21478
21479 @note This function does not return the length of a string stored as JSON
21480 value - it returns the number of elements in the JSON value which is 1 in
21481 the case of a string.
21482
21483 @requirement This function helps `basic_json` satisfying the
21484 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
21485 requirements:
21486 - The complexity is constant.
21487 - Has the semantics of `std::distance(begin(), end())`.
21488
21489 @sa @ref empty() -- checks whether the container is empty
21490 @sa @ref max_size() -- returns the maximal number of elements
21491
21492 @since version 1.0.0
21493 */
size() const21494 size_type size() const noexcept
21495 {
21496 switch (m_type)
21497 {
21498 case value_t::null:
21499 {
21500 // null values are empty
21501 return 0;
21502 }
21503
21504 case value_t::array:
21505 {
21506 // delegate call to array_t::size()
21507 return m_value.array->size();
21508 }
21509
21510 case value_t::object:
21511 {
21512 // delegate call to object_t::size()
21513 return m_value.object->size();
21514 }
21515
21516 default:
21517 {
21518 // all other types have size 1
21519 return 1;
21520 }
21521 }
21522 }
21523
21524 /*!
21525 @brief returns the maximum possible number of elements
21526
21527 Returns the maximum number of elements a JSON value is able to hold due to
21528 system or library implementation limitations, i.e. `std::distance(begin(),
21529 end())` for the JSON value.
21530
21531 @return The return value depends on the different types and is
21532 defined as follows:
21533 Value type | return value
21534 ----------- | -------------
21535 null | `0` (same as `size()`)
21536 boolean | `1` (same as `size()`)
21537 string | `1` (same as `size()`)
21538 number | `1` (same as `size()`)
21539 binary | `1` (same as `size()`)
21540 object | result of function `object_t::max_size()`
21541 array | result of function `array_t::max_size()`
21542
21543 @liveexample{The following code calls `max_size()` on the different value
21544 types. Note the output is implementation specific.,max_size}
21545
21546 @complexity Constant, as long as @ref array_t and @ref object_t satisfy
21547 the Container concept; that is, their `max_size()` functions have constant
21548 complexity.
21549
21550 @iterators No changes.
21551
21552 @exceptionsafety No-throw guarantee: this function never throws exceptions.
21553
21554 @requirement This function helps `basic_json` satisfying the
21555 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
21556 requirements:
21557 - The complexity is constant.
21558 - Has the semantics of returning `b.size()` where `b` is the largest
21559 possible JSON value.
21560
21561 @sa @ref size() -- returns the number of elements
21562
21563 @since version 1.0.0
21564 */
max_size() const21565 size_type max_size() const noexcept
21566 {
21567 switch (m_type)
21568 {
21569 case value_t::array:
21570 {
21571 // delegate call to array_t::max_size()
21572 return m_value.array->max_size();
21573 }
21574
21575 case value_t::object:
21576 {
21577 // delegate call to object_t::max_size()
21578 return m_value.object->max_size();
21579 }
21580
21581 default:
21582 {
21583 // all other types have max_size() == size()
21584 return size();
21585 }
21586 }
21587 }
21588
21589 /// @}
21590
21591
21592 ///////////////
21593 // modifiers //
21594 ///////////////
21595
21596 /// @name modifiers
21597 /// @{
21598
21599 /*!
21600 @brief clears the contents
21601
21602 Clears the content of a JSON value and resets it to the default value as
21603 if @ref basic_json(value_t) would have been called with the current value
21604 type from @ref type():
21605
21606 Value type | initial value
21607 ----------- | -------------
21608 null | `null`
21609 boolean | `false`
21610 string | `""`
21611 number | `0`
21612 binary | An empty byte vector
21613 object | `{}`
21614 array | `[]`
21615
21616 @post Has the same effect as calling
21617 @code {.cpp}
21618 *this = basic_json(type());
21619 @endcode
21620
21621 @liveexample{The example below shows the effect of `clear()` to different
21622 JSON types.,clear}
21623
21624 @complexity Linear in the size of the JSON value.
21625
21626 @iterators All iterators, pointers and references related to this container
21627 are invalidated.
21628
21629 @exceptionsafety No-throw guarantee: this function never throws exceptions.
21630
21631 @sa @ref basic_json(value_t) -- constructor that creates an object with the
21632 same value than calling `clear()`
21633
21634 @since version 1.0.0
21635 */
clear()21636 void clear() noexcept
21637 {
21638 switch (m_type)
21639 {
21640 case value_t::number_integer:
21641 {
21642 m_value.number_integer = 0;
21643 break;
21644 }
21645
21646 case value_t::number_unsigned:
21647 {
21648 m_value.number_unsigned = 0;
21649 break;
21650 }
21651
21652 case value_t::number_float:
21653 {
21654 m_value.number_float = 0.0;
21655 break;
21656 }
21657
21658 case value_t::boolean:
21659 {
21660 m_value.boolean = false;
21661 break;
21662 }
21663
21664 case value_t::string:
21665 {
21666 m_value.string->clear();
21667 break;
21668 }
21669
21670 case value_t::binary:
21671 {
21672 m_value.binary->clear();
21673 break;
21674 }
21675
21676 case value_t::array:
21677 {
21678 m_value.array->clear();
21679 break;
21680 }
21681
21682 case value_t::object:
21683 {
21684 m_value.object->clear();
21685 break;
21686 }
21687
21688 default:
21689 break;
21690 }
21691 }
21692
21693 /*!
21694 @brief add an object to an array
21695
21696 Appends the given element @a val to the end of the JSON value. If the
21697 function is called on a JSON null value, an empty array is created before
21698 appending @a val.
21699
21700 @param[in] val the value to add to the JSON array
21701
21702 @throw type_error.308 when called on a type other than JSON array or
21703 null; example: `"cannot use push_back() with number"`
21704
21705 @complexity Amortized constant.
21706
21707 @liveexample{The example shows how `push_back()` and `+=` can be used to
21708 add elements to a JSON array. Note how the `null` value was silently
21709 converted to a JSON array.,push_back}
21710
21711 @since version 1.0.0
21712 */
push_back(basic_json && val)21713 void push_back(basic_json&& val)
21714 {
21715 // push_back only works for null objects or arrays
21716 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
21717 {
21718 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
21719 }
21720
21721 // transform null object into an array
21722 if (is_null())
21723 {
21724 m_type = value_t::array;
21725 m_value = value_t::array;
21726 assert_invariant();
21727 }
21728
21729 // add element to array (move semantics)
21730 m_value.array->push_back(std::move(val));
21731 // if val is moved from, basic_json move constructor marks it null so we do not call the destructor
21732 }
21733
21734 /*!
21735 @brief add an object to an array
21736 @copydoc push_back(basic_json&&)
21737 */
operator +=(basic_json && val)21738 reference operator+=(basic_json&& val)
21739 {
21740 push_back(std::move(val));
21741 return *this;
21742 }
21743
21744 /*!
21745 @brief add an object to an array
21746 @copydoc push_back(basic_json&&)
21747 */
push_back(const basic_json & val)21748 void push_back(const basic_json& val)
21749 {
21750 // push_back only works for null objects or arrays
21751 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
21752 {
21753 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
21754 }
21755
21756 // transform null object into an array
21757 if (is_null())
21758 {
21759 m_type = value_t::array;
21760 m_value = value_t::array;
21761 assert_invariant();
21762 }
21763
21764 // add element to array
21765 m_value.array->push_back(val);
21766 }
21767
21768 /*!
21769 @brief add an object to an array
21770 @copydoc push_back(basic_json&&)
21771 */
operator +=(const basic_json & val)21772 reference operator+=(const basic_json& val)
21773 {
21774 push_back(val);
21775 return *this;
21776 }
21777
21778 /*!
21779 @brief add an object to an object
21780
21781 Inserts the given element @a val to the JSON object. If the function is
21782 called on a JSON null value, an empty object is created before inserting
21783 @a val.
21784
21785 @param[in] val the value to add to the JSON object
21786
21787 @throw type_error.308 when called on a type other than JSON object or
21788 null; example: `"cannot use push_back() with number"`
21789
21790 @complexity Logarithmic in the size of the container, O(log(`size()`)).
21791
21792 @liveexample{The example shows how `push_back()` and `+=` can be used to
21793 add elements to a JSON object. Note how the `null` value was silently
21794 converted to a JSON object.,push_back__object_t__value}
21795
21796 @since version 1.0.0
21797 */
push_back(const typename object_t::value_type & val)21798 void push_back(const typename object_t::value_type& val)
21799 {
21800 // push_back only works for null objects or objects
21801 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
21802 {
21803 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
21804 }
21805
21806 // transform null object into an object
21807 if (is_null())
21808 {
21809 m_type = value_t::object;
21810 m_value = value_t::object;
21811 assert_invariant();
21812 }
21813
21814 // add element to array
21815 m_value.object->insert(val);
21816 }
21817
21818 /*!
21819 @brief add an object to an object
21820 @copydoc push_back(const typename object_t::value_type&)
21821 */
operator +=(const typename object_t::value_type & val)21822 reference operator+=(const typename object_t::value_type& val)
21823 {
21824 push_back(val);
21825 return *this;
21826 }
21827
21828 /*!
21829 @brief add an object to an object
21830
21831 This function allows to use `push_back` with an initializer list. In case
21832
21833 1. the current value is an object,
21834 2. the initializer list @a init contains only two elements, and
21835 3. the first element of @a init is a string,
21836
21837 @a init is converted into an object element and added using
21838 @ref push_back(const typename object_t::value_type&). Otherwise, @a init
21839 is converted to a JSON value and added using @ref push_back(basic_json&&).
21840
21841 @param[in] init an initializer list
21842
21843 @complexity Linear in the size of the initializer list @a init.
21844
21845 @note This function is required to resolve an ambiguous overload error,
21846 because pairs like `{"key", "value"}` can be both interpreted as
21847 `object_t::value_type` or `std::initializer_list<basic_json>`, see
21848 https://github.com/nlohmann/json/issues/235 for more information.
21849
21850 @liveexample{The example shows how initializer lists are treated as
21851 objects when possible.,push_back__initializer_list}
21852 */
push_back(initializer_list_t init)21853 void push_back(initializer_list_t init)
21854 {
21855 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
21856 {
21857 basic_json&& key = init.begin()->moved_or_copied();
21858 push_back(typename object_t::value_type(
21859 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
21860 }
21861 else
21862 {
21863 push_back(basic_json(init));
21864 }
21865 }
21866
21867 /*!
21868 @brief add an object to an object
21869 @copydoc push_back(initializer_list_t)
21870 */
operator +=(initializer_list_t init)21871 reference operator+=(initializer_list_t init)
21872 {
21873 push_back(init);
21874 return *this;
21875 }
21876
21877 /*!
21878 @brief add an object to an array
21879
21880 Creates a JSON value from the passed parameters @a args to the end of the
21881 JSON value. If the function is called on a JSON null value, an empty array
21882 is created before appending the value created from @a args.
21883
21884 @param[in] args arguments to forward to a constructor of @ref basic_json
21885 @tparam Args compatible types to create a @ref basic_json object
21886
21887 @return reference to the inserted element
21888
21889 @throw type_error.311 when called on a type other than JSON array or
21890 null; example: `"cannot use emplace_back() with number"`
21891
21892 @complexity Amortized constant.
21893
21894 @liveexample{The example shows how `push_back()` can be used to add
21895 elements to a JSON array. Note how the `null` value was silently converted
21896 to a JSON array.,emplace_back}
21897
21898 @since version 2.0.8, returns reference since 3.7.0
21899 */
21900 template<class... Args>
emplace_back(Args &&...args)21901 reference emplace_back(Args&& ... args)
21902 {
21903 // emplace_back only works for null objects or arrays
21904 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
21905 {
21906 JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
21907 }
21908
21909 // transform null object into an array
21910 if (is_null())
21911 {
21912 m_type = value_t::array;
21913 m_value = value_t::array;
21914 assert_invariant();
21915 }
21916
21917 // add element to array (perfect forwarding)
21918 #ifdef JSON_HAS_CPP_17
21919 return m_value.array->emplace_back(std::forward<Args>(args)...);
21920 #else
21921 m_value.array->emplace_back(std::forward<Args>(args)...);
21922 return m_value.array->back();
21923 #endif
21924 }
21925
21926 /*!
21927 @brief add an object to an object if key does not exist
21928
21929 Inserts a new element into a JSON object constructed in-place with the
21930 given @a args if there is no element with the key in the container. If the
21931 function is called on a JSON null value, an empty object is created before
21932 appending the value created from @a args.
21933
21934 @param[in] args arguments to forward to a constructor of @ref basic_json
21935 @tparam Args compatible types to create a @ref basic_json object
21936
21937 @return a pair consisting of an iterator to the inserted element, or the
21938 already-existing element if no insertion happened, and a bool
21939 denoting whether the insertion took place.
21940
21941 @throw type_error.311 when called on a type other than JSON object or
21942 null; example: `"cannot use emplace() with number"`
21943
21944 @complexity Logarithmic in the size of the container, O(log(`size()`)).
21945
21946 @liveexample{The example shows how `emplace()` can be used to add elements
21947 to a JSON object. Note how the `null` value was silently converted to a
21948 JSON object. Further note how no value is added if there was already one
21949 value stored with the same key.,emplace}
21950
21951 @since version 2.0.8
21952 */
21953 template<class... Args>
emplace(Args &&...args)21954 std::pair<iterator, bool> emplace(Args&& ... args)
21955 {
21956 // emplace only works for null objects or arrays
21957 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
21958 {
21959 JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
21960 }
21961
21962 // transform null object into an object
21963 if (is_null())
21964 {
21965 m_type = value_t::object;
21966 m_value = value_t::object;
21967 assert_invariant();
21968 }
21969
21970 // add element to array (perfect forwarding)
21971 auto res = m_value.object->emplace(std::forward<Args>(args)...);
21972 // create result iterator and set iterator to the result of emplace
21973 auto it = begin();
21974 it.m_it.object_iterator = res.first;
21975
21976 // return pair of iterator and boolean
21977 return {it, res.second};
21978 }
21979
21980 /// Helper for insertion of an iterator
21981 /// @note: This uses std::distance to support GCC 4.8,
21982 /// see https://github.com/nlohmann/json/pull/1257
21983 template<typename... Args>
insert_iterator(const_iterator pos,Args &&...args)21984 iterator insert_iterator(const_iterator pos, Args&& ... args)
21985 {
21986 iterator result(this);
21987 JSON_ASSERT(m_value.array != nullptr);
21988
21989 auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
21990 m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
21991 result.m_it.array_iterator = m_value.array->begin() + insert_pos;
21992
21993 // This could have been written as:
21994 // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
21995 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
21996
21997 return result;
21998 }
21999
22000 /*!
22001 @brief inserts element
22002
22003 Inserts element @a val before iterator @a pos.
22004
22005 @param[in] pos iterator before which the content will be inserted; may be
22006 the end() iterator
22007 @param[in] val element to insert
22008 @return iterator pointing to the inserted @a val.
22009
22010 @throw type_error.309 if called on JSON values other than arrays;
22011 example: `"cannot use insert() with string"`
22012 @throw invalid_iterator.202 if @a pos is not an iterator of *this;
22013 example: `"iterator does not fit current value"`
22014
22015 @complexity Constant plus linear in the distance between @a pos and end of
22016 the container.
22017
22018 @liveexample{The example shows how `insert()` is used.,insert}
22019
22020 @since version 1.0.0
22021 */
insert(const_iterator pos,const basic_json & val)22022 iterator insert(const_iterator pos, const basic_json& val)
22023 {
22024 // insert only works for arrays
22025 if (JSON_HEDLEY_LIKELY(is_array()))
22026 {
22027 // check if iterator pos fits to this JSON value
22028 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22029 {
22030 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
22031 }
22032
22033 // insert to array and return iterator
22034 return insert_iterator(pos, val);
22035 }
22036
22037 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
22038 }
22039
22040 /*!
22041 @brief inserts element
22042 @copydoc insert(const_iterator, const basic_json&)
22043 */
insert(const_iterator pos,basic_json && val)22044 iterator insert(const_iterator pos, basic_json&& val)
22045 {
22046 return insert(pos, val);
22047 }
22048
22049 /*!
22050 @brief inserts elements
22051
22052 Inserts @a cnt copies of @a val before iterator @a pos.
22053
22054 @param[in] pos iterator before which the content will be inserted; may be
22055 the end() iterator
22056 @param[in] cnt number of copies of @a val to insert
22057 @param[in] val element to insert
22058 @return iterator pointing to the first element inserted, or @a pos if
22059 `cnt==0`
22060
22061 @throw type_error.309 if called on JSON values other than arrays; example:
22062 `"cannot use insert() with string"`
22063 @throw invalid_iterator.202 if @a pos is not an iterator of *this;
22064 example: `"iterator does not fit current value"`
22065
22066 @complexity Linear in @a cnt plus linear in the distance between @a pos
22067 and end of the container.
22068
22069 @liveexample{The example shows how `insert()` is used.,insert__count}
22070
22071 @since version 1.0.0
22072 */
insert(const_iterator pos,size_type cnt,const basic_json & val)22073 iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
22074 {
22075 // insert only works for arrays
22076 if (JSON_HEDLEY_LIKELY(is_array()))
22077 {
22078 // check if iterator pos fits to this JSON value
22079 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22080 {
22081 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
22082 }
22083
22084 // insert to array and return iterator
22085 return insert_iterator(pos, cnt, val);
22086 }
22087
22088 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
22089 }
22090
22091 /*!
22092 @brief inserts elements
22093
22094 Inserts elements from range `[first, last)` before iterator @a pos.
22095
22096 @param[in] pos iterator before which the content will be inserted; may be
22097 the end() iterator
22098 @param[in] first begin of the range of elements to insert
22099 @param[in] last end of the range of elements to insert
22100
22101 @throw type_error.309 if called on JSON values other than arrays; example:
22102 `"cannot use insert() with string"`
22103 @throw invalid_iterator.202 if @a pos is not an iterator of *this;
22104 example: `"iterator does not fit current value"`
22105 @throw invalid_iterator.210 if @a first and @a last do not belong to the
22106 same JSON value; example: `"iterators do not fit"`
22107 @throw invalid_iterator.211 if @a first or @a last are iterators into
22108 container for which insert is called; example: `"passed iterators may not
22109 belong to container"`
22110
22111 @return iterator pointing to the first element inserted, or @a pos if
22112 `first==last`
22113
22114 @complexity Linear in `std::distance(first, last)` plus linear in the
22115 distance between @a pos and end of the container.
22116
22117 @liveexample{The example shows how `insert()` is used.,insert__range}
22118
22119 @since version 1.0.0
22120 */
insert(const_iterator pos,const_iterator first,const_iterator last)22121 iterator insert(const_iterator pos, const_iterator first, const_iterator last)
22122 {
22123 // insert only works for arrays
22124 if (JSON_HEDLEY_UNLIKELY(!is_array()))
22125 {
22126 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
22127 }
22128
22129 // check if iterator pos fits to this JSON value
22130 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22131 {
22132 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
22133 }
22134
22135 // check if range iterators belong to the same JSON object
22136 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22137 {
22138 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
22139 }
22140
22141 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
22142 {
22143 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
22144 }
22145
22146 // insert to array and return iterator
22147 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
22148 }
22149
22150 /*!
22151 @brief inserts elements
22152
22153 Inserts elements from initializer list @a ilist before iterator @a pos.
22154
22155 @param[in] pos iterator before which the content will be inserted; may be
22156 the end() iterator
22157 @param[in] ilist initializer list to insert the values from
22158
22159 @throw type_error.309 if called on JSON values other than arrays; example:
22160 `"cannot use insert() with string"`
22161 @throw invalid_iterator.202 if @a pos is not an iterator of *this;
22162 example: `"iterator does not fit current value"`
22163
22164 @return iterator pointing to the first element inserted, or @a pos if
22165 `ilist` is empty
22166
22167 @complexity Linear in `ilist.size()` plus linear in the distance between
22168 @a pos and end of the container.
22169
22170 @liveexample{The example shows how `insert()` is used.,insert__ilist}
22171
22172 @since version 1.0.0
22173 */
insert(const_iterator pos,initializer_list_t ilist)22174 iterator insert(const_iterator pos, initializer_list_t ilist)
22175 {
22176 // insert only works for arrays
22177 if (JSON_HEDLEY_UNLIKELY(!is_array()))
22178 {
22179 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
22180 }
22181
22182 // check if iterator pos fits to this JSON value
22183 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22184 {
22185 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
22186 }
22187
22188 // insert to array and return iterator
22189 return insert_iterator(pos, ilist.begin(), ilist.end());
22190 }
22191
22192 /*!
22193 @brief inserts elements
22194
22195 Inserts elements from range `[first, last)`.
22196
22197 @param[in] first begin of the range of elements to insert
22198 @param[in] last end of the range of elements to insert
22199
22200 @throw type_error.309 if called on JSON values other than objects; example:
22201 `"cannot use insert() with string"`
22202 @throw invalid_iterator.202 if iterator @a first or @a last does does not
22203 point to an object; example: `"iterators first and last must point to
22204 objects"`
22205 @throw invalid_iterator.210 if @a first and @a last do not belong to the
22206 same JSON value; example: `"iterators do not fit"`
22207
22208 @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number
22209 of elements to insert.
22210
22211 @liveexample{The example shows how `insert()` is used.,insert__range_object}
22212
22213 @since version 3.0.0
22214 */
insert(const_iterator first,const_iterator last)22215 void insert(const_iterator first, const_iterator last)
22216 {
22217 // insert only works for objects
22218 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22219 {
22220 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
22221 }
22222
22223 // check if range iterators belong to the same JSON object
22224 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22225 {
22226 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
22227 }
22228
22229 // passed iterators must belong to objects
22230 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22231 {
22232 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
22233 }
22234
22235 m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
22236 }
22237
22238 /*!
22239 @brief updates a JSON object from another object, overwriting existing keys
22240
22241 Inserts all values from JSON object @a j and overwrites existing keys.
22242
22243 @param[in] j JSON object to read values from
22244
22245 @throw type_error.312 if called on JSON values other than objects; example:
22246 `"cannot use update() with string"`
22247
22248 @complexity O(N*log(size() + N)), where N is the number of elements to
22249 insert.
22250
22251 @liveexample{The example shows how `update()` is used.,update}
22252
22253 @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
22254
22255 @since version 3.0.0
22256 */
update(const_reference j)22257 void update(const_reference j)
22258 {
22259 // implicitly convert null value to an empty object
22260 if (is_null())
22261 {
22262 m_type = value_t::object;
22263 m_value.object = create<object_t>();
22264 assert_invariant();
22265 }
22266
22267 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22268 {
22269 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
22270 }
22271 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
22272 {
22273 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name())));
22274 }
22275
22276 for (auto it = j.cbegin(); it != j.cend(); ++it)
22277 {
22278 m_value.object->operator[](it.key()) = it.value();
22279 }
22280 }
22281
22282 /*!
22283 @brief updates a JSON object from another object, overwriting existing keys
22284
22285 Inserts all values from from range `[first, last)` and overwrites existing
22286 keys.
22287
22288 @param[in] first begin of the range of elements to insert
22289 @param[in] last end of the range of elements to insert
22290
22291 @throw type_error.312 if called on JSON values other than objects; example:
22292 `"cannot use update() with string"`
22293 @throw invalid_iterator.202 if iterator @a first or @a last does does not
22294 point to an object; example: `"iterators first and last must point to
22295 objects"`
22296 @throw invalid_iterator.210 if @a first and @a last do not belong to the
22297 same JSON value; example: `"iterators do not fit"`
22298
22299 @complexity O(N*log(size() + N)), where N is the number of elements to
22300 insert.
22301
22302 @liveexample{The example shows how `update()` is used__range.,update}
22303
22304 @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
22305
22306 @since version 3.0.0
22307 */
update(const_iterator first,const_iterator last)22308 void update(const_iterator first, const_iterator last)
22309 {
22310 // implicitly convert null value to an empty object
22311 if (is_null())
22312 {
22313 m_type = value_t::object;
22314 m_value.object = create<object_t>();
22315 assert_invariant();
22316 }
22317
22318 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22319 {
22320 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
22321 }
22322
22323 // check if range iterators belong to the same JSON object
22324 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22325 {
22326 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
22327 }
22328
22329 // passed iterators must belong to objects
22330 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()
22331 || !last.m_object->is_object()))
22332 {
22333 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
22334 }
22335
22336 for (auto it = first; it != last; ++it)
22337 {
22338 m_value.object->operator[](it.key()) = it.value();
22339 }
22340 }
22341
22342 /*!
22343 @brief exchanges the values
22344
22345 Exchanges the contents of the JSON value with those of @a other. Does not
22346 invoke any move, copy, or swap operations on individual elements. All
22347 iterators and references remain valid. The past-the-end iterator is
22348 invalidated.
22349
22350 @param[in,out] other JSON value to exchange the contents with
22351
22352 @complexity Constant.
22353
22354 @liveexample{The example below shows how JSON values can be swapped with
22355 `swap()`.,swap__reference}
22356
22357 @since version 1.0.0
22358 */
swap(reference other)22359 void swap(reference other) noexcept (
22360 std::is_nothrow_move_constructible<value_t>::value&&
22361 std::is_nothrow_move_assignable<value_t>::value&&
22362 std::is_nothrow_move_constructible<json_value>::value&&
22363 std::is_nothrow_move_assignable<json_value>::value
22364 )
22365 {
22366 std::swap(m_type, other.m_type);
22367 std::swap(m_value, other.m_value);
22368 assert_invariant();
22369 }
22370
22371 /*!
22372 @brief exchanges the values
22373
22374 Exchanges the contents of the JSON value from @a left with those of @a right. Does not
22375 invoke any move, copy, or swap operations on individual elements. All
22376 iterators and references remain valid. The past-the-end iterator is
22377 invalidated. implemented as a friend function callable via ADL.
22378
22379 @param[in,out] left JSON value to exchange the contents with
22380 @param[in,out] right JSON value to exchange the contents with
22381
22382 @complexity Constant.
22383
22384 @liveexample{The example below shows how JSON values can be swapped with
22385 `swap()`.,swap__reference}
22386
22387 @since version 1.0.0
22388 */
swap(reference left,reference right)22389 friend void swap(reference left, reference right) noexcept (
22390 std::is_nothrow_move_constructible<value_t>::value&&
22391 std::is_nothrow_move_assignable<value_t>::value&&
22392 std::is_nothrow_move_constructible<json_value>::value&&
22393 std::is_nothrow_move_assignable<json_value>::value
22394 )
22395 {
22396 left.swap(right);
22397 }
22398
22399 /*!
22400 @brief exchanges the values
22401
22402 Exchanges the contents of a JSON array with those of @a other. Does not
22403 invoke any move, copy, or swap operations on individual elements. All
22404 iterators and references remain valid. The past-the-end iterator is
22405 invalidated.
22406
22407 @param[in,out] other array to exchange the contents with
22408
22409 @throw type_error.310 when JSON value is not an array; example: `"cannot
22410 use swap() with string"`
22411
22412 @complexity Constant.
22413
22414 @liveexample{The example below shows how arrays can be swapped with
22415 `swap()`.,swap__array_t}
22416
22417 @since version 1.0.0
22418 */
swap(array_t & other)22419 void swap(array_t& other)
22420 {
22421 // swap only works for arrays
22422 if (JSON_HEDLEY_LIKELY(is_array()))
22423 {
22424 std::swap(*(m_value.array), other);
22425 }
22426 else
22427 {
22428 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
22429 }
22430 }
22431
22432 /*!
22433 @brief exchanges the values
22434
22435 Exchanges the contents of a JSON object with those of @a other. Does not
22436 invoke any move, copy, or swap operations on individual elements. All
22437 iterators and references remain valid. The past-the-end iterator is
22438 invalidated.
22439
22440 @param[in,out] other object to exchange the contents with
22441
22442 @throw type_error.310 when JSON value is not an object; example:
22443 `"cannot use swap() with string"`
22444
22445 @complexity Constant.
22446
22447 @liveexample{The example below shows how objects can be swapped with
22448 `swap()`.,swap__object_t}
22449
22450 @since version 1.0.0
22451 */
swap(object_t & other)22452 void swap(object_t& other)
22453 {
22454 // swap only works for objects
22455 if (JSON_HEDLEY_LIKELY(is_object()))
22456 {
22457 std::swap(*(m_value.object), other);
22458 }
22459 else
22460 {
22461 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
22462 }
22463 }
22464
22465 /*!
22466 @brief exchanges the values
22467
22468 Exchanges the contents of a JSON string with those of @a other. Does not
22469 invoke any move, copy, or swap operations on individual elements. All
22470 iterators and references remain valid. The past-the-end iterator is
22471 invalidated.
22472
22473 @param[in,out] other string to exchange the contents with
22474
22475 @throw type_error.310 when JSON value is not a string; example: `"cannot
22476 use swap() with boolean"`
22477
22478 @complexity Constant.
22479
22480 @liveexample{The example below shows how strings can be swapped with
22481 `swap()`.,swap__string_t}
22482
22483 @since version 1.0.0
22484 */
swap(string_t & other)22485 void swap(string_t& other)
22486 {
22487 // swap only works for strings
22488 if (JSON_HEDLEY_LIKELY(is_string()))
22489 {
22490 std::swap(*(m_value.string), other);
22491 }
22492 else
22493 {
22494 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
22495 }
22496 }
22497
22498 /*!
22499 @brief exchanges the values
22500
22501 Exchanges the contents of a JSON string with those of @a other. Does not
22502 invoke any move, copy, or swap operations on individual elements. All
22503 iterators and references remain valid. The past-the-end iterator is
22504 invalidated.
22505
22506 @param[in,out] other binary to exchange the contents with
22507
22508 @throw type_error.310 when JSON value is not a string; example: `"cannot
22509 use swap() with boolean"`
22510
22511 @complexity Constant.
22512
22513 @liveexample{The example below shows how strings can be swapped with
22514 `swap()`.,swap__binary_t}
22515
22516 @since version 3.8.0
22517 */
swap(binary_t & other)22518 void swap(binary_t& other)
22519 {
22520 // swap only works for strings
22521 if (JSON_HEDLEY_LIKELY(is_binary()))
22522 {
22523 std::swap(*(m_value.binary), other);
22524 }
22525 else
22526 {
22527 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
22528 }
22529 }
22530
22531 /// @copydoc swap(binary_t)
swap(typename binary_t::container_type & other)22532 void swap(typename binary_t::container_type& other)
22533 {
22534 // swap only works for strings
22535 if (JSON_HEDLEY_LIKELY(is_binary()))
22536 {
22537 std::swap(*(m_value.binary), other);
22538 }
22539 else
22540 {
22541 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
22542 }
22543 }
22544
22545 /// @}
22546
22547 public:
22548 //////////////////////////////////////////
22549 // lexicographical comparison operators //
22550 //////////////////////////////////////////
22551
22552 /// @name lexicographical comparison operators
22553 /// @{
22554
22555 /*!
22556 @brief comparison: equal
22557
22558 Compares two JSON values for equality according to the following rules:
22559 - Two JSON values are equal if (1) they are from the same type and (2)
22560 their stored values are the same according to their respective
22561 `operator==`.
22562 - Integer and floating-point numbers are automatically converted before
22563 comparison. Note that two NaN values are always treated as unequal.
22564 - Two JSON null values are equal.
22565
22566 @note Floating-point inside JSON values numbers are compared with
22567 `json::number_float_t::operator==` which is `double::operator==` by
22568 default. To compare floating-point while respecting an epsilon, an alternative
22569 [comparison function](https://github.com/mariokonrad/marnav/blob/master/include/marnav/math/floatingpoint.hpp#L34-#L39)
22570 could be used, for instance
22571 @code {.cpp}
22572 template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>
22573 inline bool is_same(T a, T b, T epsilon = std::numeric_limits<T>::epsilon()) noexcept
22574 {
22575 return std::abs(a - b) <= epsilon;
22576 }
22577 @endcode
22578 Or you can self-defined operator equal function like this:
22579 @code {.cpp}
22580 bool my_equal(const_reference lhs, const_reference rhs) {
22581 const auto lhs_type lhs.type();
22582 const auto rhs_type rhs.type();
22583 if (lhs_type == rhs_type) {
22584 switch(lhs_type)
22585 // self_defined case
22586 case value_t::number_float:
22587 return std::abs(lhs - rhs) <= std::numeric_limits<float>::epsilon();
22588 // other cases remain the same with the original
22589 ...
22590 }
22591 ...
22592 }
22593 @endcode
22594
22595 @note NaN values never compare equal to themselves or to other NaN values.
22596
22597 @param[in] lhs first JSON value to consider
22598 @param[in] rhs second JSON value to consider
22599 @return whether the values @a lhs and @a rhs are equal
22600
22601 @exceptionsafety No-throw guarantee: this function never throws exceptions.
22602
22603 @complexity Linear.
22604
22605 @liveexample{The example demonstrates comparing several JSON
22606 types.,operator__equal}
22607
22608 @since version 1.0.0
22609 */
operator ==(const_reference lhs,const_reference rhs)22610 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
22611 {
22612 const auto lhs_type = lhs.type();
22613 const auto rhs_type = rhs.type();
22614
22615 if (lhs_type == rhs_type)
22616 {
22617 switch (lhs_type)
22618 {
22619 case value_t::array:
22620 return *lhs.m_value.array == *rhs.m_value.array;
22621
22622 case value_t::object:
22623 return *lhs.m_value.object == *rhs.m_value.object;
22624
22625 case value_t::null:
22626 return true;
22627
22628 case value_t::string:
22629 return *lhs.m_value.string == *rhs.m_value.string;
22630
22631 case value_t::boolean:
22632 return lhs.m_value.boolean == rhs.m_value.boolean;
22633
22634 case value_t::number_integer:
22635 return lhs.m_value.number_integer == rhs.m_value.number_integer;
22636
22637 case value_t::number_unsigned:
22638 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
22639
22640 case value_t::number_float:
22641 return lhs.m_value.number_float == rhs.m_value.number_float;
22642
22643 case value_t::binary:
22644 return *lhs.m_value.binary == *rhs.m_value.binary;
22645
22646 default:
22647 return false;
22648 }
22649 }
22650 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
22651 {
22652 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
22653 }
22654 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
22655 {
22656 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
22657 }
22658 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
22659 {
22660 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
22661 }
22662 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
22663 {
22664 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
22665 }
22666 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
22667 {
22668 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
22669 }
22670 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
22671 {
22672 return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
22673 }
22674
22675 return false;
22676 }
22677
22678 /*!
22679 @brief comparison: equal
22680 @copydoc operator==(const_reference, const_reference)
22681 */
22682 template<typename ScalarType, typename std::enable_if<
22683 std::is_scalar<ScalarType>::value, int>::type = 0>
operator ==(const_reference lhs,const ScalarType rhs)22684 friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
22685 {
22686 return lhs == basic_json(rhs);
22687 }
22688
22689 /*!
22690 @brief comparison: equal
22691 @copydoc operator==(const_reference, const_reference)
22692 */
22693 template<typename ScalarType, typename std::enable_if<
22694 std::is_scalar<ScalarType>::value, int>::type = 0>
operator ==(const ScalarType lhs,const_reference rhs)22695 friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
22696 {
22697 return basic_json(lhs) == rhs;
22698 }
22699
22700 /*!
22701 @brief comparison: not equal
22702
22703 Compares two JSON values for inequality by calculating `not (lhs == rhs)`.
22704
22705 @param[in] lhs first JSON value to consider
22706 @param[in] rhs second JSON value to consider
22707 @return whether the values @a lhs and @a rhs are not equal
22708
22709 @complexity Linear.
22710
22711 @exceptionsafety No-throw guarantee: this function never throws exceptions.
22712
22713 @liveexample{The example demonstrates comparing several JSON
22714 types.,operator__notequal}
22715
22716 @since version 1.0.0
22717 */
operator !=(const_reference lhs,const_reference rhs)22718 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
22719 {
22720 return !(lhs == rhs);
22721 }
22722
22723 /*!
22724 @brief comparison: not equal
22725 @copydoc operator!=(const_reference, const_reference)
22726 */
22727 template<typename ScalarType, typename std::enable_if<
22728 std::is_scalar<ScalarType>::value, int>::type = 0>
operator !=(const_reference lhs,const ScalarType rhs)22729 friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
22730 {
22731 return lhs != basic_json(rhs);
22732 }
22733
22734 /*!
22735 @brief comparison: not equal
22736 @copydoc operator!=(const_reference, const_reference)
22737 */
22738 template<typename ScalarType, typename std::enable_if<
22739 std::is_scalar<ScalarType>::value, int>::type = 0>
operator !=(const ScalarType lhs,const_reference rhs)22740 friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
22741 {
22742 return basic_json(lhs) != rhs;
22743 }
22744
22745 /*!
22746 @brief comparison: less than
22747
22748 Compares whether one JSON value @a lhs is less than another JSON value @a
22749 rhs according to the following rules:
22750 - If @a lhs and @a rhs have the same type, the values are compared using
22751 the default `<` operator.
22752 - Integer and floating-point numbers are automatically converted before
22753 comparison
22754 - In case @a lhs and @a rhs have different types, the values are ignored
22755 and the order of the types is considered, see
22756 @ref operator<(const value_t, const value_t).
22757
22758 @param[in] lhs first JSON value to consider
22759 @param[in] rhs second JSON value to consider
22760 @return whether @a lhs is less than @a rhs
22761
22762 @complexity Linear.
22763
22764 @exceptionsafety No-throw guarantee: this function never throws exceptions.
22765
22766 @liveexample{The example demonstrates comparing several JSON
22767 types.,operator__less}
22768
22769 @since version 1.0.0
22770 */
operator <(const_reference lhs,const_reference rhs)22771 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
22772 {
22773 const auto lhs_type = lhs.type();
22774 const auto rhs_type = rhs.type();
22775
22776 if (lhs_type == rhs_type)
22777 {
22778 switch (lhs_type)
22779 {
22780 case value_t::array:
22781 // note parentheses are necessary, see
22782 // https://github.com/nlohmann/json/issues/1530
22783 return (*lhs.m_value.array) < (*rhs.m_value.array);
22784
22785 case value_t::object:
22786 return (*lhs.m_value.object) < (*rhs.m_value.object);
22787
22788 case value_t::null:
22789 return false;
22790
22791 case value_t::string:
22792 return (*lhs.m_value.string) < (*rhs.m_value.string);
22793
22794 case value_t::boolean:
22795 return (lhs.m_value.boolean) < (rhs.m_value.boolean);
22796
22797 case value_t::number_integer:
22798 return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
22799
22800 case value_t::number_unsigned:
22801 return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned);
22802
22803 case value_t::number_float:
22804 return (lhs.m_value.number_float) < (rhs.m_value.number_float);
22805
22806 case value_t::binary:
22807 return (*lhs.m_value.binary) < (*rhs.m_value.binary);
22808
22809 default:
22810 return false;
22811 }
22812 }
22813 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
22814 {
22815 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
22816 }
22817 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
22818 {
22819 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
22820 }
22821 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
22822 {
22823 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
22824 }
22825 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
22826 {
22827 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
22828 }
22829 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
22830 {
22831 return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
22832 }
22833 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
22834 {
22835 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
22836 }
22837
22838 // We only reach this line if we cannot compare values. In that case,
22839 // we compare types. Note we have to call the operator explicitly,
22840 // because MSVC has problems otherwise.
22841 return operator<(lhs_type, rhs_type);
22842 }
22843
22844 /*!
22845 @brief comparison: less than
22846 @copydoc operator<(const_reference, const_reference)
22847 */
22848 template<typename ScalarType, typename std::enable_if<
22849 std::is_scalar<ScalarType>::value, int>::type = 0>
operator <(const_reference lhs,const ScalarType rhs)22850 friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
22851 {
22852 return lhs < basic_json(rhs);
22853 }
22854
22855 /*!
22856 @brief comparison: less than
22857 @copydoc operator<(const_reference, const_reference)
22858 */
22859 template<typename ScalarType, typename std::enable_if<
22860 std::is_scalar<ScalarType>::value, int>::type = 0>
operator <(const ScalarType lhs,const_reference rhs)22861 friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
22862 {
22863 return basic_json(lhs) < rhs;
22864 }
22865
22866 /*!
22867 @brief comparison: less than or equal
22868
22869 Compares whether one JSON value @a lhs is less than or equal to another
22870 JSON value by calculating `not (rhs < lhs)`.
22871
22872 @param[in] lhs first JSON value to consider
22873 @param[in] rhs second JSON value to consider
22874 @return whether @a lhs is less than or equal to @a rhs
22875
22876 @complexity Linear.
22877
22878 @exceptionsafety No-throw guarantee: this function never throws exceptions.
22879
22880 @liveexample{The example demonstrates comparing several JSON
22881 types.,operator__greater}
22882
22883 @since version 1.0.0
22884 */
operator <=(const_reference lhs,const_reference rhs)22885 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
22886 {
22887 return !(rhs < lhs);
22888 }
22889
22890 /*!
22891 @brief comparison: less than or equal
22892 @copydoc operator<=(const_reference, const_reference)
22893 */
22894 template<typename ScalarType, typename std::enable_if<
22895 std::is_scalar<ScalarType>::value, int>::type = 0>
operator <=(const_reference lhs,const ScalarType rhs)22896 friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
22897 {
22898 return lhs <= basic_json(rhs);
22899 }
22900
22901 /*!
22902 @brief comparison: less than or equal
22903 @copydoc operator<=(const_reference, const_reference)
22904 */
22905 template<typename ScalarType, typename std::enable_if<
22906 std::is_scalar<ScalarType>::value, int>::type = 0>
operator <=(const ScalarType lhs,const_reference rhs)22907 friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
22908 {
22909 return basic_json(lhs) <= rhs;
22910 }
22911
22912 /*!
22913 @brief comparison: greater than
22914
22915 Compares whether one JSON value @a lhs is greater than another
22916 JSON value by calculating `not (lhs <= rhs)`.
22917
22918 @param[in] lhs first JSON value to consider
22919 @param[in] rhs second JSON value to consider
22920 @return whether @a lhs is greater than to @a rhs
22921
22922 @complexity Linear.
22923
22924 @exceptionsafety No-throw guarantee: this function never throws exceptions.
22925
22926 @liveexample{The example demonstrates comparing several JSON
22927 types.,operator__lessequal}
22928
22929 @since version 1.0.0
22930 */
operator >(const_reference lhs,const_reference rhs)22931 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
22932 {
22933 return !(lhs <= rhs);
22934 }
22935
22936 /*!
22937 @brief comparison: greater than
22938 @copydoc operator>(const_reference, const_reference)
22939 */
22940 template<typename ScalarType, typename std::enable_if<
22941 std::is_scalar<ScalarType>::value, int>::type = 0>
operator >(const_reference lhs,const ScalarType rhs)22942 friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
22943 {
22944 return lhs > basic_json(rhs);
22945 }
22946
22947 /*!
22948 @brief comparison: greater than
22949 @copydoc operator>(const_reference, const_reference)
22950 */
22951 template<typename ScalarType, typename std::enable_if<
22952 std::is_scalar<ScalarType>::value, int>::type = 0>
operator >(const ScalarType lhs,const_reference rhs)22953 friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
22954 {
22955 return basic_json(lhs) > rhs;
22956 }
22957
22958 /*!
22959 @brief comparison: greater than or equal
22960
22961 Compares whether one JSON value @a lhs is greater than or equal to another
22962 JSON value by calculating `not (lhs < rhs)`.
22963
22964 @param[in] lhs first JSON value to consider
22965 @param[in] rhs second JSON value to consider
22966 @return whether @a lhs is greater than or equal to @a rhs
22967
22968 @complexity Linear.
22969
22970 @exceptionsafety No-throw guarantee: this function never throws exceptions.
22971
22972 @liveexample{The example demonstrates comparing several JSON
22973 types.,operator__greaterequal}
22974
22975 @since version 1.0.0
22976 */
operator >=(const_reference lhs,const_reference rhs)22977 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
22978 {
22979 return !(lhs < rhs);
22980 }
22981
22982 /*!
22983 @brief comparison: greater than or equal
22984 @copydoc operator>=(const_reference, const_reference)
22985 */
22986 template<typename ScalarType, typename std::enable_if<
22987 std::is_scalar<ScalarType>::value, int>::type = 0>
operator >=(const_reference lhs,const ScalarType rhs)22988 friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
22989 {
22990 return lhs >= basic_json(rhs);
22991 }
22992
22993 /*!
22994 @brief comparison: greater than or equal
22995 @copydoc operator>=(const_reference, const_reference)
22996 */
22997 template<typename ScalarType, typename std::enable_if<
22998 std::is_scalar<ScalarType>::value, int>::type = 0>
operator >=(const ScalarType lhs,const_reference rhs)22999 friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
23000 {
23001 return basic_json(lhs) >= rhs;
23002 }
23003
23004 /// @}
23005
23006 ///////////////////
23007 // serialization //
23008 ///////////////////
23009
23010 /// @name serialization
23011 /// @{
23012
23013 /*!
23014 @brief serialize to stream
23015
23016 Serialize the given JSON value @a j to the output stream @a o. The JSON
23017 value will be serialized using the @ref dump member function.
23018
23019 - The indentation of the output can be controlled with the member variable
23020 `width` of the output stream @a o. For instance, using the manipulator
23021 `std::setw(4)` on @a o sets the indentation level to `4` and the
23022 serialization result is the same as calling `dump(4)`.
23023
23024 - The indentation character can be controlled with the member variable
23025 `fill` of the output stream @a o. For instance, the manipulator
23026 `std::setfill('\\t')` sets indentation to use a tab character rather than
23027 the default space character.
23028
23029 @param[in,out] o stream to serialize to
23030 @param[in] j JSON value to serialize
23031
23032 @return the stream @a o
23033
23034 @throw type_error.316 if a string stored inside the JSON value is not
23035 UTF-8 encoded
23036
23037 @complexity Linear.
23038
23039 @liveexample{The example below shows the serialization with different
23040 parameters to `width` to adjust the indentation level.,operator_serialize}
23041
23042 @since version 1.0.0; indentation character added in version 3.0.0
23043 */
operator <<(std::ostream & o,const basic_json & j)23044 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
23045 {
23046 // read width member and use it as indentation parameter if nonzero
23047 const bool pretty_print = o.width() > 0;
23048 const auto indentation = pretty_print ? o.width() : 0;
23049
23050 // reset width to 0 for subsequent calls to this stream
23051 o.width(0);
23052
23053 // do the actual serialization
23054 serializer s(detail::output_adapter<char>(o), o.fill());
23055 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
23056 return o;
23057 }
23058
23059 /*!
23060 @brief serialize to stream
23061 @deprecated This stream operator is deprecated and will be removed in
23062 future 4.0.0 of the library. Please use
23063 @ref operator<<(std::ostream&, const basic_json&)
23064 instead; that is, replace calls like `j >> o;` with `o << j;`.
23065 @since version 1.0.0; deprecated since version 3.0.0
23066 */
23067 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
operator >>(const basic_json & j,std::ostream & o)23068 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
23069 {
23070 return o << j;
23071 }
23072
23073 /// @}
23074
23075
23076 /////////////////////
23077 // deserialization //
23078 /////////////////////
23079
23080 /// @name deserialization
23081 /// @{
23082
23083 /*!
23084 @brief deserialize from a compatible input
23085
23086 @tparam InputType A compatible input, for instance
23087 - an std::istream object
23088 - a FILE pointer
23089 - a C-style array of characters
23090 - a pointer to a null-terminated string of single byte characters
23091 - an object obj for which begin(obj) and end(obj) produces a valid pair of
23092 iterators.
23093
23094 @param[in] i input to read from
23095 @param[in] cb a parser callback function of type @ref parser_callback_t
23096 which is used to control the deserialization by filtering unwanted values
23097 (optional)
23098 @param[in] allow_exceptions whether to throw exceptions in case of a
23099 parse error (optional, true by default)
23100 @param[in] ignore_comments whether comments should be ignored and treated
23101 like whitespace (true) or yield a parse error (true); (optional, false by
23102 default)
23103
23104 @return deserialized JSON value; in case of a parse error and
23105 @a allow_exceptions set to `false`, the return value will be
23106 value_t::discarded.
23107
23108 @throw parse_error.101 if a parse error occurs; example: `""unexpected end
23109 of input; expected string literal""`
23110 @throw parse_error.102 if to_unicode fails or surrogate error
23111 @throw parse_error.103 if to_unicode fails
23112
23113 @complexity Linear in the length of the input. The parser is a predictive
23114 LL(1) parser. The complexity can be higher if the parser callback function
23115 @a cb or reading from the input @a i has a super-linear complexity.
23116
23117 @note A UTF-8 byte order mark is silently ignored.
23118
23119 @liveexample{The example below demonstrates the `parse()` function reading
23120 from an array.,parse__array__parser_callback_t}
23121
23122 @liveexample{The example below demonstrates the `parse()` function with
23123 and without callback function.,parse__string__parser_callback_t}
23124
23125 @liveexample{The example below demonstrates the `parse()` function with
23126 and without callback function.,parse__istream__parser_callback_t}
23127
23128 @liveexample{The example below demonstrates the `parse()` function reading
23129 from a contiguous container.,parse__contiguouscontainer__parser_callback_t}
23130
23131 @since version 2.0.3 (contiguous containers); version 3.9.0 allowed to
23132 ignore comments.
23133 */
23134 template<typename InputType>
23135 JSON_HEDLEY_WARN_UNUSED_RESULT
parse(InputType && i,const parser_callback_t cb=nullptr,const bool allow_exceptions=true,const bool ignore_comments=false)23136 static basic_json parse(InputType&& i,
23137 const parser_callback_t cb = nullptr,
23138 const bool allow_exceptions = true,
23139 const bool ignore_comments = false)
23140 {
23141 basic_json result;
23142 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
23143 return result;
23144 }
23145
23146 /*!
23147 @brief deserialize from a pair of character iterators
23148
23149 The value_type of the iterator must be a integral type with size of 1, 2 or
23150 4 bytes, which will be interpreted respectively as UTF-8, UTF-16 and UTF-32.
23151
23152 @param[in] first iterator to start of character range
23153 @param[in] last iterator to end of character range
23154 @param[in] cb a parser callback function of type @ref parser_callback_t
23155 which is used to control the deserialization by filtering unwanted values
23156 (optional)
23157 @param[in] allow_exceptions whether to throw exceptions in case of a
23158 parse error (optional, true by default)
23159 @param[in] ignore_comments whether comments should be ignored and treated
23160 like whitespace (true) or yield a parse error (true); (optional, false by
23161 default)
23162
23163 @return deserialized JSON value; in case of a parse error and
23164 @a allow_exceptions set to `false`, the return value will be
23165 value_t::discarded.
23166
23167 @throw parse_error.101 if a parse error occurs; example: `""unexpected end
23168 of input; expected string literal""`
23169 @throw parse_error.102 if to_unicode fails or surrogate error
23170 @throw parse_error.103 if to_unicode fails
23171 */
23172 template<typename IteratorType>
23173 JSON_HEDLEY_WARN_UNUSED_RESULT
parse(IteratorType first,IteratorType last,const parser_callback_t cb=nullptr,const bool allow_exceptions=true,const bool ignore_comments=false)23174 static basic_json parse(IteratorType first,
23175 IteratorType last,
23176 const parser_callback_t cb = nullptr,
23177 const bool allow_exceptions = true,
23178 const bool ignore_comments = false)
23179 {
23180 basic_json result;
23181 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
23182 return result;
23183 }
23184
23185 JSON_HEDLEY_WARN_UNUSED_RESULT
23186 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
parse(detail::span_input_adapter && i,const parser_callback_t cb=nullptr,const bool allow_exceptions=true,const bool ignore_comments=false)23187 static basic_json parse(detail::span_input_adapter&& i,
23188 const parser_callback_t cb = nullptr,
23189 const bool allow_exceptions = true,
23190 const bool ignore_comments = false)
23191 {
23192 basic_json result;
23193 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
23194 return result;
23195 }
23196
23197 /*!
23198 @brief check if the input is valid JSON
23199
23200 Unlike the @ref parse(InputType&&, const parser_callback_t,const bool)
23201 function, this function neither throws an exception in case of invalid JSON
23202 input (i.e., a parse error) nor creates diagnostic information.
23203
23204 @tparam InputType A compatible input, for instance
23205 - an std::istream object
23206 - a FILE pointer
23207 - a C-style array of characters
23208 - a pointer to a null-terminated string of single byte characters
23209 - an object obj for which begin(obj) and end(obj) produces a valid pair of
23210 iterators.
23211
23212 @param[in] i input to read from
23213 @param[in] ignore_comments whether comments should be ignored and treated
23214 like whitespace (true) or yield a parse error (true); (optional, false by
23215 default)
23216
23217 @return Whether the input read from @a i is valid JSON.
23218
23219 @complexity Linear in the length of the input. The parser is a predictive
23220 LL(1) parser.
23221
23222 @note A UTF-8 byte order mark is silently ignored.
23223
23224 @liveexample{The example below demonstrates the `accept()` function reading
23225 from a string.,accept__string}
23226 */
23227 template<typename InputType>
accept(InputType && i,const bool ignore_comments=false)23228 static bool accept(InputType&& i,
23229 const bool ignore_comments = false)
23230 {
23231 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
23232 }
23233
23234 template<typename IteratorType>
accept(IteratorType first,IteratorType last,const bool ignore_comments=false)23235 static bool accept(IteratorType first, IteratorType last,
23236 const bool ignore_comments = false)
23237 {
23238 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
23239 }
23240
23241 JSON_HEDLEY_WARN_UNUSED_RESULT
23242 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
accept(detail::span_input_adapter && i,const bool ignore_comments=false)23243 static bool accept(detail::span_input_adapter&& i,
23244 const bool ignore_comments = false)
23245 {
23246 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
23247 }
23248
23249 /*!
23250 @brief generate SAX events
23251
23252 The SAX event lister must follow the interface of @ref json_sax.
23253
23254 This function reads from a compatible input. Examples are:
23255 - an std::istream object
23256 - a FILE pointer
23257 - a C-style array of characters
23258 - a pointer to a null-terminated string of single byte characters
23259 - an object obj for which begin(obj) and end(obj) produces a valid pair of
23260 iterators.
23261
23262 @param[in] i input to read from
23263 @param[in,out] sax SAX event listener
23264 @param[in] format the format to parse (JSON, CBOR, MessagePack, or UBJSON)
23265 @param[in] strict whether the input has to be consumed completely
23266 @param[in] ignore_comments whether comments should be ignored and treated
23267 like whitespace (true) or yield a parse error (true); (optional, false by
23268 default); only applies to the JSON file format.
23269
23270 @return return value of the last processed SAX event
23271
23272 @throw parse_error.101 if a parse error occurs; example: `""unexpected end
23273 of input; expected string literal""`
23274 @throw parse_error.102 if to_unicode fails or surrogate error
23275 @throw parse_error.103 if to_unicode fails
23276
23277 @complexity Linear in the length of the input. The parser is a predictive
23278 LL(1) parser. The complexity can be higher if the SAX consumer @a sax has
23279 a super-linear complexity.
23280
23281 @note A UTF-8 byte order mark is silently ignored.
23282
23283 @liveexample{The example below demonstrates the `sax_parse()` function
23284 reading from string and processing the events with a user-defined SAX
23285 event consumer.,sax_parse}
23286
23287 @since version 3.2.0
23288 */
23289 template <typename InputType, typename SAX>
23290 JSON_HEDLEY_NON_NULL(2)
sax_parse(InputType && i,SAX * sax,input_format_t format=input_format_t::json,const bool strict=true,const bool ignore_comments=false)23291 static bool sax_parse(InputType&& i, SAX* sax,
23292 input_format_t format = input_format_t::json,
23293 const bool strict = true,
23294 const bool ignore_comments = false)
23295 {
23296 auto ia = detail::input_adapter(std::forward<InputType>(i));
23297 return format == input_format_t::json
23298 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23299 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
23300 }
23301
23302 template<class IteratorType, class SAX>
23303 JSON_HEDLEY_NON_NULL(3)
sax_parse(IteratorType first,IteratorType last,SAX * sax,input_format_t format=input_format_t::json,const bool strict=true,const bool ignore_comments=false)23304 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
23305 input_format_t format = input_format_t::json,
23306 const bool strict = true,
23307 const bool ignore_comments = false)
23308 {
23309 auto ia = detail::input_adapter(std::move(first), std::move(last));
23310 return format == input_format_t::json
23311 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23312 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
23313 }
23314
23315 template <typename SAX>
23316 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
23317 JSON_HEDLEY_NON_NULL(2)
sax_parse(detail::span_input_adapter && i,SAX * sax,input_format_t format=input_format_t::json,const bool strict=true,const bool ignore_comments=false)23318 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
23319 input_format_t format = input_format_t::json,
23320 const bool strict = true,
23321 const bool ignore_comments = false)
23322 {
23323 auto ia = i.get();
23324 return format == input_format_t::json
23325 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23326 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
23327 }
23328
23329 /*!
23330 @brief deserialize from stream
23331 @deprecated This stream operator is deprecated and will be removed in
23332 version 4.0.0 of the library. Please use
23333 @ref operator>>(std::istream&, basic_json&)
23334 instead; that is, replace calls like `j << i;` with `i >> j;`.
23335 @since version 1.0.0; deprecated since version 3.0.0
23336 */
23337 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
operator <<(basic_json & j,std::istream & i)23338 friend std::istream& operator<<(basic_json& j, std::istream& i)
23339 {
23340 return operator>>(i, j);
23341 }
23342
23343 /*!
23344 @brief deserialize from stream
23345
23346 Deserializes an input stream to a JSON value.
23347
23348 @param[in,out] i input stream to read a serialized JSON value from
23349 @param[in,out] j JSON value to write the deserialized input to
23350
23351 @throw parse_error.101 in case of an unexpected token
23352 @throw parse_error.102 if to_unicode fails or surrogate error
23353 @throw parse_error.103 if to_unicode fails
23354
23355 @complexity Linear in the length of the input. The parser is a predictive
23356 LL(1) parser.
23357
23358 @note A UTF-8 byte order mark is silently ignored.
23359
23360 @liveexample{The example below shows how a JSON value is constructed by
23361 reading a serialization from a stream.,operator_deserialize}
23362
23363 @sa parse(std::istream&, const parser_callback_t) for a variant with a
23364 parser callback function to filter values while parsing
23365
23366 @since version 1.0.0
23367 */
operator >>(std::istream & i,basic_json & j)23368 friend std::istream& operator>>(std::istream& i, basic_json& j)
23369 {
23370 parser(detail::input_adapter(i)).parse(false, j);
23371 return i;
23372 }
23373
23374 /// @}
23375
23376 ///////////////////////////
23377 // convenience functions //
23378 ///////////////////////////
23379
23380 /*!
23381 @brief return the type as string
23382
23383 Returns the type name as string to be used in error messages - usually to
23384 indicate that a function was called on a wrong JSON type.
23385
23386 @return a string representation of a the @a m_type member:
23387 Value type | return value
23388 ----------- | -------------
23389 null | `"null"`
23390 boolean | `"boolean"`
23391 string | `"string"`
23392 number | `"number"` (for all number types)
23393 object | `"object"`
23394 array | `"array"`
23395 binary | `"binary"`
23396 discarded | `"discarded"`
23397
23398 @exceptionsafety No-throw guarantee: this function never throws exceptions.
23399
23400 @complexity Constant.
23401
23402 @liveexample{The following code exemplifies `type_name()` for all JSON
23403 types.,type_name}
23404
23405 @sa @ref type() -- return the type of the JSON value
23406 @sa @ref operator value_t() -- return the type of the JSON value (implicit)
23407
23408 @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept`
23409 since 3.0.0
23410 */
23411 JSON_HEDLEY_RETURNS_NON_NULL
type_name() const23412 const char* type_name() const noexcept
23413 {
23414 {
23415 switch (m_type)
23416 {
23417 case value_t::null:
23418 return "null";
23419 case value_t::object:
23420 return "object";
23421 case value_t::array:
23422 return "array";
23423 case value_t::string:
23424 return "string";
23425 case value_t::boolean:
23426 return "boolean";
23427 case value_t::binary:
23428 return "binary";
23429 case value_t::discarded:
23430 return "discarded";
23431 default:
23432 return "number";
23433 }
23434 }
23435 }
23436
23437
23438 private:
23439 //////////////////////
23440 // member variables //
23441 //////////////////////
23442
23443 /// the type of the current element
23444 value_t m_type = value_t::null;
23445
23446 /// the value of the current element
23447 json_value m_value = {};
23448
23449 //////////////////////////////////////////
23450 // binary serialization/deserialization //
23451 //////////////////////////////////////////
23452
23453 /// @name binary serialization/deserialization support
23454 /// @{
23455
23456 public:
23457 /*!
23458 @brief create a CBOR serialization of a given JSON value
23459
23460 Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
23461 Binary Object Representation) serialization format. CBOR is a binary
23462 serialization format which aims to be more compact than JSON itself, yet
23463 more efficient to parse.
23464
23465 The library uses the following mapping from JSON values types to
23466 CBOR types according to the CBOR specification (RFC 7049):
23467
23468 JSON value type | value/range | CBOR type | first byte
23469 --------------- | ------------------------------------------ | ---------------------------------- | ---------------
23470 null | `null` | Null | 0xF6
23471 boolean | `true` | True | 0xF5
23472 boolean | `false` | False | 0xF4
23473 number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3B
23474 number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3A
23475 number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39
23476 number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38
23477 number_integer | -24..-1 | Negative integer | 0x20..0x37
23478 number_integer | 0..23 | Integer | 0x00..0x17
23479 number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18
23480 number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19
23481 number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A
23482 number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B
23483 number_unsigned | 0..23 | Integer | 0x00..0x17
23484 number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18
23485 number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19
23486 number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A
23487 number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B
23488 number_float | *any value representable by a float* | Single-Precision Float | 0xFA
23489 number_float | *any value NOT representable by a float* | Double-Precision Float | 0xFB
23490 string | *length*: 0..23 | UTF-8 string | 0x60..0x77
23491 string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78
23492 string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79
23493 string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A
23494 string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B
23495 array | *size*: 0..23 | array | 0x80..0x97
23496 array | *size*: 23..255 | array (1 byte follow) | 0x98
23497 array | *size*: 256..65535 | array (2 bytes follow) | 0x99
23498 array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A
23499 array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B
23500 object | *size*: 0..23 | map | 0xA0..0xB7
23501 object | *size*: 23..255 | map (1 byte follow) | 0xB8
23502 object | *size*: 256..65535 | map (2 bytes follow) | 0xB9
23503 object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA
23504 object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB
23505 binary | *size*: 0..23 | byte string | 0x40..0x57
23506 binary | *size*: 23..255 | byte string (1 byte follow) | 0x58
23507 binary | *size*: 256..65535 | byte string (2 bytes follow) | 0x59
23508 binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A
23509 binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B
23510
23511 @note The mapping is **complete** in the sense that any JSON value type
23512 can be converted to a CBOR value.
23513
23514 @note If NaN or Infinity are stored inside a JSON number, they are
23515 serialized properly. This behavior differs from the @ref dump()
23516 function which serializes NaN or Infinity to `null`.
23517
23518 @note The following CBOR types are not used in the conversion:
23519 - UTF-8 strings terminated by "break" (0x7F)
23520 - arrays terminated by "break" (0x9F)
23521 - maps terminated by "break" (0xBF)
23522 - byte strings terminated by "break" (0x5F)
23523 - date/time (0xC0..0xC1)
23524 - bignum (0xC2..0xC3)
23525 - decimal fraction (0xC4)
23526 - bigfloat (0xC5)
23527 - expected conversions (0xD5..0xD7)
23528 - simple values (0xE0..0xF3, 0xF8)
23529 - undefined (0xF7)
23530 - half-precision floats (0xF9)
23531 - break (0xFF)
23532
23533 @param[in] j JSON value to serialize
23534 @return CBOR serialization as byte vector
23535
23536 @complexity Linear in the size of the JSON value @a j.
23537
23538 @liveexample{The example shows the serialization of a JSON value to a byte
23539 vector in CBOR format.,to_cbor}
23540
23541 @sa http://cbor.io
23542 @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
23543 analogous deserialization
23544 @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
23545 @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
23546 related UBJSON format
23547
23548 @since version 2.0.9; compact representation of floating-point numbers
23549 since version 3.8.0
23550 */
to_cbor(const basic_json & j)23551 static std::vector<uint8_t> to_cbor(const basic_json& j)
23552 {
23553 std::vector<uint8_t> result;
23554 to_cbor(j, result);
23555 return result;
23556 }
23557
to_cbor(const basic_json & j,detail::output_adapter<uint8_t> o)23558 static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
23559 {
23560 binary_writer<uint8_t>(o).write_cbor(j);
23561 }
23562
to_cbor(const basic_json & j,detail::output_adapter<char> o)23563 static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
23564 {
23565 binary_writer<char>(o).write_cbor(j);
23566 }
23567
23568 /*!
23569 @brief create a MessagePack serialization of a given JSON value
23570
23571 Serializes a given JSON value @a j to a byte vector using the MessagePack
23572 serialization format. MessagePack is a binary serialization format which
23573 aims to be more compact than JSON itself, yet more efficient to parse.
23574
23575 The library uses the following mapping from JSON values types to
23576 MessagePack types according to the MessagePack specification:
23577
23578 JSON value type | value/range | MessagePack type | first byte
23579 --------------- | --------------------------------- | ---------------- | ----------
23580 null | `null` | nil | 0xC0
23581 boolean | `true` | true | 0xC3
23582 boolean | `false` | false | 0xC2
23583 number_integer | -9223372036854775808..-2147483649 | int64 | 0xD3
23584 number_integer | -2147483648..-32769 | int32 | 0xD2
23585 number_integer | -32768..-129 | int16 | 0xD1
23586 number_integer | -128..-33 | int8 | 0xD0
23587 number_integer | -32..-1 | negative fixint | 0xE0..0xFF
23588 number_integer | 0..127 | positive fixint | 0x00..0x7F
23589 number_integer | 128..255 | uint 8 | 0xCC
23590 number_integer | 256..65535 | uint 16 | 0xCD
23591 number_integer | 65536..4294967295 | uint 32 | 0xCE
23592 number_integer | 4294967296..18446744073709551615 | uint 64 | 0xCF
23593 number_unsigned | 0..127 | positive fixint | 0x00..0x7F
23594 number_unsigned | 128..255 | uint 8 | 0xCC
23595 number_unsigned | 256..65535 | uint 16 | 0xCD
23596 number_unsigned | 65536..4294967295 | uint 32 | 0xCE
23597 number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF
23598 number_float | *any value representable by a float* | float 32 | 0xCA
23599 number_float | *any value NOT representable by a float* | float 64 | 0xCB
23600 string | *length*: 0..31 | fixstr | 0xA0..0xBF
23601 string | *length*: 32..255 | str 8 | 0xD9
23602 string | *length*: 256..65535 | str 16 | 0xDA
23603 string | *length*: 65536..4294967295 | str 32 | 0xDB
23604 array | *size*: 0..15 | fixarray | 0x90..0x9F
23605 array | *size*: 16..65535 | array 16 | 0xDC
23606 array | *size*: 65536..4294967295 | array 32 | 0xDD
23607 object | *size*: 0..15 | fix map | 0x80..0x8F
23608 object | *size*: 16..65535 | map 16 | 0xDE
23609 object | *size*: 65536..4294967295 | map 32 | 0xDF
23610 binary | *size*: 0..255 | bin 8 | 0xC4
23611 binary | *size*: 256..65535 | bin 16 | 0xC5
23612 binary | *size*: 65536..4294967295 | bin 32 | 0xC6
23613
23614 @note The mapping is **complete** in the sense that any JSON value type
23615 can be converted to a MessagePack value.
23616
23617 @note The following values can **not** be converted to a MessagePack value:
23618 - strings with more than 4294967295 bytes
23619 - byte strings with more than 4294967295 bytes
23620 - arrays with more than 4294967295 elements
23621 - objects with more than 4294967295 elements
23622
23623 @note Any MessagePack output created @ref to_msgpack can be successfully
23624 parsed by @ref from_msgpack.
23625
23626 @note If NaN or Infinity are stored inside a JSON number, they are
23627 serialized properly. This behavior differs from the @ref dump()
23628 function which serializes NaN or Infinity to `null`.
23629
23630 @param[in] j JSON value to serialize
23631 @return MessagePack serialization as byte vector
23632
23633 @complexity Linear in the size of the JSON value @a j.
23634
23635 @liveexample{The example shows the serialization of a JSON value to a byte
23636 vector in MessagePack format.,to_msgpack}
23637
23638 @sa http://msgpack.org
23639 @sa @ref from_msgpack for the analogous deserialization
23640 @sa @ref to_cbor(const basic_json& for the related CBOR format
23641 @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
23642 related UBJSON format
23643
23644 @since version 2.0.9
23645 */
to_msgpack(const basic_json & j)23646 static std::vector<uint8_t> to_msgpack(const basic_json& j)
23647 {
23648 std::vector<uint8_t> result;
23649 to_msgpack(j, result);
23650 return result;
23651 }
23652
to_msgpack(const basic_json & j,detail::output_adapter<uint8_t> o)23653 static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
23654 {
23655 binary_writer<uint8_t>(o).write_msgpack(j);
23656 }
23657
to_msgpack(const basic_json & j,detail::output_adapter<char> o)23658 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
23659 {
23660 binary_writer<char>(o).write_msgpack(j);
23661 }
23662
23663 /*!
23664 @brief create a UBJSON serialization of a given JSON value
23665
23666 Serializes a given JSON value @a j to a byte vector using the UBJSON
23667 (Universal Binary JSON) serialization format. UBJSON aims to be more compact
23668 than JSON itself, yet more efficient to parse.
23669
23670 The library uses the following mapping from JSON values types to
23671 UBJSON types according to the UBJSON specification:
23672
23673 JSON value type | value/range | UBJSON type | marker
23674 --------------- | --------------------------------- | ----------- | ------
23675 null | `null` | null | `Z`
23676 boolean | `true` | true | `T`
23677 boolean | `false` | false | `F`
23678 number_integer | -9223372036854775808..-2147483649 | int64 | `L`
23679 number_integer | -2147483648..-32769 | int32 | `l`
23680 number_integer | -32768..-129 | int16 | `I`
23681 number_integer | -128..127 | int8 | `i`
23682 number_integer | 128..255 | uint8 | `U`
23683 number_integer | 256..32767 | int16 | `I`
23684 number_integer | 32768..2147483647 | int32 | `l`
23685 number_integer | 2147483648..9223372036854775807 | int64 | `L`
23686 number_unsigned | 0..127 | int8 | `i`
23687 number_unsigned | 128..255 | uint8 | `U`
23688 number_unsigned | 256..32767 | int16 | `I`
23689 number_unsigned | 32768..2147483647 | int32 | `l`
23690 number_unsigned | 2147483648..9223372036854775807 | int64 | `L`
23691 number_unsigned | 2147483649..18446744073709551615 | high-precision | `H`
23692 number_float | *any value* | float64 | `D`
23693 string | *with shortest length indicator* | string | `S`
23694 array | *see notes on optimized format* | array | `[`
23695 object | *see notes on optimized format* | map | `{`
23696
23697 @note The mapping is **complete** in the sense that any JSON value type
23698 can be converted to a UBJSON value.
23699
23700 @note The following values can **not** be converted to a UBJSON value:
23701 - strings with more than 9223372036854775807 bytes (theoretical)
23702
23703 @note The following markers are not used in the conversion:
23704 - `Z`: no-op values are not created.
23705 - `C`: single-byte strings are serialized with `S` markers.
23706
23707 @note Any UBJSON output created @ref to_ubjson can be successfully parsed
23708 by @ref from_ubjson.
23709
23710 @note If NaN or Infinity are stored inside a JSON number, they are
23711 serialized properly. This behavior differs from the @ref dump()
23712 function which serializes NaN or Infinity to `null`.
23713
23714 @note The optimized formats for containers are supported: Parameter
23715 @a use_size adds size information to the beginning of a container and
23716 removes the closing marker. Parameter @a use_type further checks
23717 whether all elements of a container have the same type and adds the
23718 type marker to the beginning of the container. The @a use_type
23719 parameter must only be used together with @a use_size = true. Note
23720 that @a use_size = true alone may result in larger representations -
23721 the benefit of this parameter is that the receiving side is
23722 immediately informed on the number of elements of the container.
23723
23724 @note If the JSON data contains the binary type, the value stored is a list
23725 of integers, as suggested by the UBJSON documentation. In particular,
23726 this means that serialization and the deserialization of a JSON
23727 containing binary values into UBJSON and back will result in a
23728 different JSON object.
23729
23730 @param[in] j JSON value to serialize
23731 @param[in] use_size whether to add size annotations to container types
23732 @param[in] use_type whether to add type annotations to container types
23733 (must be combined with @a use_size = true)
23734 @return UBJSON serialization as byte vector
23735
23736 @complexity Linear in the size of the JSON value @a j.
23737
23738 @liveexample{The example shows the serialization of a JSON value to a byte
23739 vector in UBJSON format.,to_ubjson}
23740
23741 @sa http://ubjson.org
23742 @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
23743 analogous deserialization
23744 @sa @ref to_cbor(const basic_json& for the related CBOR format
23745 @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
23746
23747 @since version 3.1.0
23748 */
to_ubjson(const basic_json & j,const bool use_size=false,const bool use_type=false)23749 static std::vector<uint8_t> to_ubjson(const basic_json& j,
23750 const bool use_size = false,
23751 const bool use_type = false)
23752 {
23753 std::vector<uint8_t> result;
23754 to_ubjson(j, result, use_size, use_type);
23755 return result;
23756 }
23757
to_ubjson(const basic_json & j,detail::output_adapter<uint8_t> o,const bool use_size=false,const bool use_type=false)23758 static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,
23759 const bool use_size = false, const bool use_type = false)
23760 {
23761 binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
23762 }
23763
to_ubjson(const basic_json & j,detail::output_adapter<char> o,const bool use_size=false,const bool use_type=false)23764 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
23765 const bool use_size = false, const bool use_type = false)
23766 {
23767 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
23768 }
23769
23770
23771 /*!
23772 @brief Serializes the given JSON object `j` to BSON and returns a vector
23773 containing the corresponding BSON-representation.
23774
23775 BSON (Binary JSON) is a binary format in which zero or more ordered key/value pairs are
23776 stored as a single entity (a so-called document).
23777
23778 The library uses the following mapping from JSON values types to BSON types:
23779
23780 JSON value type | value/range | BSON type | marker
23781 --------------- | --------------------------------- | ----------- | ------
23782 null | `null` | null | 0x0A
23783 boolean | `true`, `false` | boolean | 0x08
23784 number_integer | -9223372036854775808..-2147483649 | int64 | 0x12
23785 number_integer | -2147483648..2147483647 | int32 | 0x10
23786 number_integer | 2147483648..9223372036854775807 | int64 | 0x12
23787 number_unsigned | 0..2147483647 | int32 | 0x10
23788 number_unsigned | 2147483648..9223372036854775807 | int64 | 0x12
23789 number_unsigned | 9223372036854775808..18446744073709551615| -- | --
23790 number_float | *any value* | double | 0x01
23791 string | *any value* | string | 0x02
23792 array | *any value* | document | 0x04
23793 object | *any value* | document | 0x03
23794 binary | *any value* | binary | 0x05
23795
23796 @warning The mapping is **incomplete**, since only JSON-objects (and things
23797 contained therein) can be serialized to BSON.
23798 Also, integers larger than 9223372036854775807 cannot be serialized to BSON,
23799 and the keys may not contain U+0000, since they are serialized a
23800 zero-terminated c-strings.
23801
23802 @throw out_of_range.407 if `j.is_number_unsigned() && j.get<std::uint64_t>() > 9223372036854775807`
23803 @throw out_of_range.409 if a key in `j` contains a NULL (U+0000)
23804 @throw type_error.317 if `!j.is_object()`
23805
23806 @pre The input `j` is required to be an object: `j.is_object() == true`.
23807
23808 @note Any BSON output created via @ref to_bson can be successfully parsed
23809 by @ref from_bson.
23810
23811 @param[in] j JSON value to serialize
23812 @return BSON serialization as byte vector
23813
23814 @complexity Linear in the size of the JSON value @a j.
23815
23816 @liveexample{The example shows the serialization of a JSON value to a byte
23817 vector in BSON format.,to_bson}
23818
23819 @sa http://bsonspec.org/spec.html
23820 @sa @ref from_bson(detail::input_adapter&&, const bool strict) for the
23821 analogous deserialization
23822 @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
23823 related UBJSON format
23824 @sa @ref to_cbor(const basic_json&) for the related CBOR format
23825 @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
23826 */
to_bson(const basic_json & j)23827 static std::vector<uint8_t> to_bson(const basic_json& j)
23828 {
23829 std::vector<uint8_t> result;
23830 to_bson(j, result);
23831 return result;
23832 }
23833
23834 /*!
23835 @brief Serializes the given JSON object `j` to BSON and forwards the
23836 corresponding BSON-representation to the given output_adapter `o`.
23837 @param j The JSON object to convert to BSON.
23838 @param o The output adapter that receives the binary BSON representation.
23839 @pre The input `j` shall be an object: `j.is_object() == true`
23840 @sa @ref to_bson(const basic_json&)
23841 */
to_bson(const basic_json & j,detail::output_adapter<uint8_t> o)23842 static void to_bson(const basic_json& j, detail::output_adapter<uint8_t> o)
23843 {
23844 binary_writer<uint8_t>(o).write_bson(j);
23845 }
23846
23847 /*!
23848 @copydoc to_bson(const basic_json&, detail::output_adapter<uint8_t>)
23849 */
to_bson(const basic_json & j,detail::output_adapter<char> o)23850 static void to_bson(const basic_json& j, detail::output_adapter<char> o)
23851 {
23852 binary_writer<char>(o).write_bson(j);
23853 }
23854
23855
23856 /*!
23857 @brief create a JSON value from an input in CBOR format
23858
23859 Deserializes a given input @a i to a JSON value using the CBOR (Concise
23860 Binary Object Representation) serialization format.
23861
23862 The library maps CBOR types to JSON value types as follows:
23863
23864 CBOR type | JSON value type | first byte
23865 ---------------------- | --------------- | ----------
23866 Integer | number_unsigned | 0x00..0x17
23867 Unsigned integer | number_unsigned | 0x18
23868 Unsigned integer | number_unsigned | 0x19
23869 Unsigned integer | number_unsigned | 0x1A
23870 Unsigned integer | number_unsigned | 0x1B
23871 Negative integer | number_integer | 0x20..0x37
23872 Negative integer | number_integer | 0x38
23873 Negative integer | number_integer | 0x39
23874 Negative integer | number_integer | 0x3A
23875 Negative integer | number_integer | 0x3B
23876 Byte string | binary | 0x40..0x57
23877 Byte string | binary | 0x58
23878 Byte string | binary | 0x59
23879 Byte string | binary | 0x5A
23880 Byte string | binary | 0x5B
23881 UTF-8 string | string | 0x60..0x77
23882 UTF-8 string | string | 0x78
23883 UTF-8 string | string | 0x79
23884 UTF-8 string | string | 0x7A
23885 UTF-8 string | string | 0x7B
23886 UTF-8 string | string | 0x7F
23887 array | array | 0x80..0x97
23888 array | array | 0x98
23889 array | array | 0x99
23890 array | array | 0x9A
23891 array | array | 0x9B
23892 array | array | 0x9F
23893 map | object | 0xA0..0xB7
23894 map | object | 0xB8
23895 map | object | 0xB9
23896 map | object | 0xBA
23897 map | object | 0xBB
23898 map | object | 0xBF
23899 False | `false` | 0xF4
23900 True | `true` | 0xF5
23901 Null | `null` | 0xF6
23902 Half-Precision Float | number_float | 0xF9
23903 Single-Precision Float | number_float | 0xFA
23904 Double-Precision Float | number_float | 0xFB
23905
23906 @warning The mapping is **incomplete** in the sense that not all CBOR
23907 types can be converted to a JSON value. The following CBOR types
23908 are not supported and will yield parse errors (parse_error.112):
23909 - date/time (0xC0..0xC1)
23910 - bignum (0xC2..0xC3)
23911 - decimal fraction (0xC4)
23912 - bigfloat (0xC5)
23913 - expected conversions (0xD5..0xD7)
23914 - simple values (0xE0..0xF3, 0xF8)
23915 - undefined (0xF7)
23916
23917 @warning CBOR allows map keys of any type, whereas JSON only allows
23918 strings as keys in object values. Therefore, CBOR maps with keys
23919 other than UTF-8 strings are rejected (parse_error.113).
23920
23921 @note Any CBOR output created @ref to_cbor can be successfully parsed by
23922 @ref from_cbor.
23923
23924 @param[in] i an input in CBOR format convertible to an input adapter
23925 @param[in] strict whether to expect the input to be consumed until EOF
23926 (true by default)
23927 @param[in] allow_exceptions whether to throw exceptions in case of a
23928 parse error (optional, true by default)
23929 @param[in] tag_handler how to treat CBOR tags (optional, error by default)
23930
23931 @return deserialized JSON value; in case of a parse error and
23932 @a allow_exceptions set to `false`, the return value will be
23933 value_t::discarded.
23934
23935 @throw parse_error.110 if the given input ends prematurely or the end of
23936 file was not reached when @a strict was set to true
23937 @throw parse_error.112 if unsupported features from CBOR were
23938 used in the given input @a v or if the input is not valid CBOR
23939 @throw parse_error.113 if a string was expected as map key, but not found
23940
23941 @complexity Linear in the size of the input @a i.
23942
23943 @liveexample{The example shows the deserialization of a byte vector in CBOR
23944 format to a JSON value.,from_cbor}
23945
23946 @sa http://cbor.io
23947 @sa @ref to_cbor(const basic_json&) for the analogous serialization
23948 @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for the
23949 related MessagePack format
23950 @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
23951 related UBJSON format
23952
23953 @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
23954 consume input adapters, removed start_index parameter, and added
23955 @a strict parameter since 3.0.0; added @a allow_exceptions parameter
23956 since 3.2.0; added @a tag_handler parameter since 3.9.0.
23957 */
23958 template<typename InputType>
23959 JSON_HEDLEY_WARN_UNUSED_RESULT
from_cbor(InputType && i,const bool strict=true,const bool allow_exceptions=true,const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)23960 static basic_json from_cbor(InputType&& i,
23961 const bool strict = true,
23962 const bool allow_exceptions = true,
23963 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23964 {
23965 basic_json result;
23966 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23967 auto ia = detail::input_adapter(std::forward<InputType>(i));
23968 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23969 return res ? result : basic_json(value_t::discarded);
23970 }
23971
23972 /*!
23973 @copydoc from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t)
23974 */
23975 template<typename IteratorType>
23976 JSON_HEDLEY_WARN_UNUSED_RESULT
from_cbor(IteratorType first,IteratorType last,const bool strict=true,const bool allow_exceptions=true,const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)23977 static basic_json from_cbor(IteratorType first, IteratorType last,
23978 const bool strict = true,
23979 const bool allow_exceptions = true,
23980 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23981 {
23982 basic_json result;
23983 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23984 auto ia = detail::input_adapter(std::move(first), std::move(last));
23985 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23986 return res ? result : basic_json(value_t::discarded);
23987 }
23988
23989 template<typename T>
23990 JSON_HEDLEY_WARN_UNUSED_RESULT
23991 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
from_cbor(const T * ptr,std::size_t len,const bool strict=true,const bool allow_exceptions=true,const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)23992 static basic_json from_cbor(const T* ptr, std::size_t len,
23993 const bool strict = true,
23994 const bool allow_exceptions = true,
23995 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23996 {
23997 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
23998 }
23999
24000
24001 JSON_HEDLEY_WARN_UNUSED_RESULT
24002 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
from_cbor(detail::span_input_adapter && i,const bool strict=true,const bool allow_exceptions=true,const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)24003 static basic_json from_cbor(detail::span_input_adapter&& i,
24004 const bool strict = true,
24005 const bool allow_exceptions = true,
24006 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24007 {
24008 basic_json result;
24009 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24010 auto ia = i.get();
24011 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
24012 return res ? result : basic_json(value_t::discarded);
24013 }
24014
24015 /*!
24016 @brief create a JSON value from an input in MessagePack format
24017
24018 Deserializes a given input @a i to a JSON value using the MessagePack
24019 serialization format.
24020
24021 The library maps MessagePack types to JSON value types as follows:
24022
24023 MessagePack type | JSON value type | first byte
24024 ---------------- | --------------- | ----------
24025 positive fixint | number_unsigned | 0x00..0x7F
24026 fixmap | object | 0x80..0x8F
24027 fixarray | array | 0x90..0x9F
24028 fixstr | string | 0xA0..0xBF
24029 nil | `null` | 0xC0
24030 false | `false` | 0xC2
24031 true | `true` | 0xC3
24032 float 32 | number_float | 0xCA
24033 float 64 | number_float | 0xCB
24034 uint 8 | number_unsigned | 0xCC
24035 uint 16 | number_unsigned | 0xCD
24036 uint 32 | number_unsigned | 0xCE
24037 uint 64 | number_unsigned | 0xCF
24038 int 8 | number_integer | 0xD0
24039 int 16 | number_integer | 0xD1
24040 int 32 | number_integer | 0xD2
24041 int 64 | number_integer | 0xD3
24042 str 8 | string | 0xD9
24043 str 16 | string | 0xDA
24044 str 32 | string | 0xDB
24045 array 16 | array | 0xDC
24046 array 32 | array | 0xDD
24047 map 16 | object | 0xDE
24048 map 32 | object | 0xDF
24049 bin 8 | binary | 0xC4
24050 bin 16 | binary | 0xC5
24051 bin 32 | binary | 0xC6
24052 ext 8 | binary | 0xC7
24053 ext 16 | binary | 0xC8
24054 ext 32 | binary | 0xC9
24055 fixext 1 | binary | 0xD4
24056 fixext 2 | binary | 0xD5
24057 fixext 4 | binary | 0xD6
24058 fixext 8 | binary | 0xD7
24059 fixext 16 | binary | 0xD8
24060 negative fixint | number_integer | 0xE0-0xFF
24061
24062 @note Any MessagePack output created @ref to_msgpack can be successfully
24063 parsed by @ref from_msgpack.
24064
24065 @param[in] i an input in MessagePack format convertible to an input
24066 adapter
24067 @param[in] strict whether to expect the input to be consumed until EOF
24068 (true by default)
24069 @param[in] allow_exceptions whether to throw exceptions in case of a
24070 parse error (optional, true by default)
24071
24072 @return deserialized JSON value; in case of a parse error and
24073 @a allow_exceptions set to `false`, the return value will be
24074 value_t::discarded.
24075
24076 @throw parse_error.110 if the given input ends prematurely or the end of
24077 file was not reached when @a strict was set to true
24078 @throw parse_error.112 if unsupported features from MessagePack were
24079 used in the given input @a i or if the input is not valid MessagePack
24080 @throw parse_error.113 if a string was expected as map key, but not found
24081
24082 @complexity Linear in the size of the input @a i.
24083
24084 @liveexample{The example shows the deserialization of a byte vector in
24085 MessagePack format to a JSON value.,from_msgpack}
24086
24087 @sa http://msgpack.org
24088 @sa @ref to_msgpack(const basic_json&) for the analogous serialization
24089 @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
24090 related CBOR format
24091 @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for
24092 the related UBJSON format
24093 @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for
24094 the related BSON format
24095
24096 @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
24097 consume input adapters, removed start_index parameter, and added
24098 @a strict parameter since 3.0.0; added @a allow_exceptions parameter
24099 since 3.2.0
24100 */
24101 template<typename InputType>
24102 JSON_HEDLEY_WARN_UNUSED_RESULT
from_msgpack(InputType && i,const bool strict=true,const bool allow_exceptions=true)24103 static basic_json from_msgpack(InputType&& i,
24104 const bool strict = true,
24105 const bool allow_exceptions = true)
24106 {
24107 basic_json result;
24108 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24109 auto ia = detail::input_adapter(std::forward<InputType>(i));
24110 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
24111 return res ? result : basic_json(value_t::discarded);
24112 }
24113
24114 /*!
24115 @copydoc from_msgpack(detail::input_adapter&&, const bool, const bool)
24116 */
24117 template<typename IteratorType>
24118 JSON_HEDLEY_WARN_UNUSED_RESULT
from_msgpack(IteratorType first,IteratorType last,const bool strict=true,const bool allow_exceptions=true)24119 static basic_json from_msgpack(IteratorType first, IteratorType last,
24120 const bool strict = true,
24121 const bool allow_exceptions = true)
24122 {
24123 basic_json result;
24124 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24125 auto ia = detail::input_adapter(std::move(first), std::move(last));
24126 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
24127 return res ? result : basic_json(value_t::discarded);
24128 }
24129
24130
24131 template<typename T>
24132 JSON_HEDLEY_WARN_UNUSED_RESULT
24133 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
from_msgpack(const T * ptr,std::size_t len,const bool strict=true,const bool allow_exceptions=true)24134 static basic_json from_msgpack(const T* ptr, std::size_t len,
24135 const bool strict = true,
24136 const bool allow_exceptions = true)
24137 {
24138 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
24139 }
24140
24141 JSON_HEDLEY_WARN_UNUSED_RESULT
24142 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
from_msgpack(detail::span_input_adapter && i,const bool strict=true,const bool allow_exceptions=true)24143 static basic_json from_msgpack(detail::span_input_adapter&& i,
24144 const bool strict = true,
24145 const bool allow_exceptions = true)
24146 {
24147 basic_json result;
24148 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24149 auto ia = i.get();
24150 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
24151 return res ? result : basic_json(value_t::discarded);
24152 }
24153
24154
24155 /*!
24156 @brief create a JSON value from an input in UBJSON format
24157
24158 Deserializes a given input @a i to a JSON value using the UBJSON (Universal
24159 Binary JSON) serialization format.
24160
24161 The library maps UBJSON types to JSON value types as follows:
24162
24163 UBJSON type | JSON value type | marker
24164 ----------- | --------------------------------------- | ------
24165 no-op | *no value, next value is read* | `N`
24166 null | `null` | `Z`
24167 false | `false` | `F`
24168 true | `true` | `T`
24169 float32 | number_float | `d`
24170 float64 | number_float | `D`
24171 uint8 | number_unsigned | `U`
24172 int8 | number_integer | `i`
24173 int16 | number_integer | `I`
24174 int32 | number_integer | `l`
24175 int64 | number_integer | `L`
24176 high-precision number | number_integer, number_unsigned, or number_float - depends on number string | 'H'
24177 string | string | `S`
24178 char | string | `C`
24179 array | array (optimized values are supported) | `[`
24180 object | object (optimized values are supported) | `{`
24181
24182 @note The mapping is **complete** in the sense that any UBJSON value can
24183 be converted to a JSON value.
24184
24185 @param[in] i an input in UBJSON format convertible to an input adapter
24186 @param[in] strict whether to expect the input to be consumed until EOF
24187 (true by default)
24188 @param[in] allow_exceptions whether to throw exceptions in case of a
24189 parse error (optional, true by default)
24190
24191 @return deserialized JSON value; in case of a parse error and
24192 @a allow_exceptions set to `false`, the return value will be
24193 value_t::discarded.
24194
24195 @throw parse_error.110 if the given input ends prematurely or the end of
24196 file was not reached when @a strict was set to true
24197 @throw parse_error.112 if a parse error occurs
24198 @throw parse_error.113 if a string could not be parsed successfully
24199
24200 @complexity Linear in the size of the input @a i.
24201
24202 @liveexample{The example shows the deserialization of a byte vector in
24203 UBJSON format to a JSON value.,from_ubjson}
24204
24205 @sa http://ubjson.org
24206 @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
24207 analogous serialization
24208 @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
24209 related CBOR format
24210 @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
24211 the related MessagePack format
24212 @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for
24213 the related BSON format
24214
24215 @since version 3.1.0; added @a allow_exceptions parameter since 3.2.0
24216 */
24217 template<typename InputType>
24218 JSON_HEDLEY_WARN_UNUSED_RESULT
from_ubjson(InputType && i,const bool strict=true,const bool allow_exceptions=true)24219 static basic_json from_ubjson(InputType&& i,
24220 const bool strict = true,
24221 const bool allow_exceptions = true)
24222 {
24223 basic_json result;
24224 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24225 auto ia = detail::input_adapter(std::forward<InputType>(i));
24226 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
24227 return res ? result : basic_json(value_t::discarded);
24228 }
24229
24230 /*!
24231 @copydoc from_ubjson(detail::input_adapter&&, const bool, const bool)
24232 */
24233 template<typename IteratorType>
24234 JSON_HEDLEY_WARN_UNUSED_RESULT
from_ubjson(IteratorType first,IteratorType last,const bool strict=true,const bool allow_exceptions=true)24235 static basic_json from_ubjson(IteratorType first, IteratorType last,
24236 const bool strict = true,
24237 const bool allow_exceptions = true)
24238 {
24239 basic_json result;
24240 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24241 auto ia = detail::input_adapter(std::move(first), std::move(last));
24242 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
24243 return res ? result : basic_json(value_t::discarded);
24244 }
24245
24246 template<typename T>
24247 JSON_HEDLEY_WARN_UNUSED_RESULT
24248 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
from_ubjson(const T * ptr,std::size_t len,const bool strict=true,const bool allow_exceptions=true)24249 static basic_json from_ubjson(const T* ptr, std::size_t len,
24250 const bool strict = true,
24251 const bool allow_exceptions = true)
24252 {
24253 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
24254 }
24255
24256 JSON_HEDLEY_WARN_UNUSED_RESULT
24257 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
from_ubjson(detail::span_input_adapter && i,const bool strict=true,const bool allow_exceptions=true)24258 static basic_json from_ubjson(detail::span_input_adapter&& i,
24259 const bool strict = true,
24260 const bool allow_exceptions = true)
24261 {
24262 basic_json result;
24263 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24264 auto ia = i.get();
24265 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
24266 return res ? result : basic_json(value_t::discarded);
24267 }
24268
24269
24270 /*!
24271 @brief Create a JSON value from an input in BSON format
24272
24273 Deserializes a given input @a i to a JSON value using the BSON (Binary JSON)
24274 serialization format.
24275
24276 The library maps BSON record types to JSON value types as follows:
24277
24278 BSON type | BSON marker byte | JSON value type
24279 --------------- | ---------------- | ---------------------------
24280 double | 0x01 | number_float
24281 string | 0x02 | string
24282 document | 0x03 | object
24283 array | 0x04 | array
24284 binary | 0x05 | still unsupported
24285 undefined | 0x06 | still unsupported
24286 ObjectId | 0x07 | still unsupported
24287 boolean | 0x08 | boolean
24288 UTC Date-Time | 0x09 | still unsupported
24289 null | 0x0A | null
24290 Regular Expr. | 0x0B | still unsupported
24291 DB Pointer | 0x0C | still unsupported
24292 JavaScript Code | 0x0D | still unsupported
24293 Symbol | 0x0E | still unsupported
24294 JavaScript Code | 0x0F | still unsupported
24295 int32 | 0x10 | number_integer
24296 Timestamp | 0x11 | still unsupported
24297 128-bit decimal float | 0x13 | still unsupported
24298 Max Key | 0x7F | still unsupported
24299 Min Key | 0xFF | still unsupported
24300
24301 @warning The mapping is **incomplete**. The unsupported mappings
24302 are indicated in the table above.
24303
24304 @param[in] i an input in BSON format convertible to an input adapter
24305 @param[in] strict whether to expect the input to be consumed until EOF
24306 (true by default)
24307 @param[in] allow_exceptions whether to throw exceptions in case of a
24308 parse error (optional, true by default)
24309
24310 @return deserialized JSON value; in case of a parse error and
24311 @a allow_exceptions set to `false`, the return value will be
24312 value_t::discarded.
24313
24314 @throw parse_error.114 if an unsupported BSON record type is encountered
24315
24316 @complexity Linear in the size of the input @a i.
24317
24318 @liveexample{The example shows the deserialization of a byte vector in
24319 BSON format to a JSON value.,from_bson}
24320
24321 @sa http://bsonspec.org/spec.html
24322 @sa @ref to_bson(const basic_json&) for the analogous serialization
24323 @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
24324 related CBOR format
24325 @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
24326 the related MessagePack format
24327 @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
24328 related UBJSON format
24329 */
24330 template<typename InputType>
24331 JSON_HEDLEY_WARN_UNUSED_RESULT
from_bson(InputType && i,const bool strict=true,const bool allow_exceptions=true)24332 static basic_json from_bson(InputType&& i,
24333 const bool strict = true,
24334 const bool allow_exceptions = true)
24335 {
24336 basic_json result;
24337 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24338 auto ia = detail::input_adapter(std::forward<InputType>(i));
24339 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
24340 return res ? result : basic_json(value_t::discarded);
24341 }
24342
24343 /*!
24344 @copydoc from_bson(detail::input_adapter&&, const bool, const bool)
24345 */
24346 template<typename IteratorType>
24347 JSON_HEDLEY_WARN_UNUSED_RESULT
from_bson(IteratorType first,IteratorType last,const bool strict=true,const bool allow_exceptions=true)24348 static basic_json from_bson(IteratorType first, IteratorType last,
24349 const bool strict = true,
24350 const bool allow_exceptions = true)
24351 {
24352 basic_json result;
24353 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24354 auto ia = detail::input_adapter(std::move(first), std::move(last));
24355 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
24356 return res ? result : basic_json(value_t::discarded);
24357 }
24358
24359 template<typename T>
24360 JSON_HEDLEY_WARN_UNUSED_RESULT
24361 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
from_bson(const T * ptr,std::size_t len,const bool strict=true,const bool allow_exceptions=true)24362 static basic_json from_bson(const T* ptr, std::size_t len,
24363 const bool strict = true,
24364 const bool allow_exceptions = true)
24365 {
24366 return from_bson(ptr, ptr + len, strict, allow_exceptions);
24367 }
24368
24369 JSON_HEDLEY_WARN_UNUSED_RESULT
24370 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
from_bson(detail::span_input_adapter && i,const bool strict=true,const bool allow_exceptions=true)24371 static basic_json from_bson(detail::span_input_adapter&& i,
24372 const bool strict = true,
24373 const bool allow_exceptions = true)
24374 {
24375 basic_json result;
24376 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24377 auto ia = i.get();
24378 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
24379 return res ? result : basic_json(value_t::discarded);
24380 }
24381 /// @}
24382
24383 //////////////////////////
24384 // JSON Pointer support //
24385 //////////////////////////
24386
24387 /// @name JSON Pointer functions
24388 /// @{
24389
24390 /*!
24391 @brief access specified element via JSON Pointer
24392
24393 Uses a JSON pointer to retrieve a reference to the respective JSON value.
24394 No bound checking is performed. Similar to @ref operator[](const typename
24395 object_t::key_type&), `null` values are created in arrays and objects if
24396 necessary.
24397
24398 In particular:
24399 - If the JSON pointer points to an object key that does not exist, it
24400 is created an filled with a `null` value before a reference to it
24401 is returned.
24402 - If the JSON pointer points to an array index that does not exist, it
24403 is created an filled with a `null` value before a reference to it
24404 is returned. All indices between the current maximum and the given
24405 index are also filled with `null`.
24406 - The special value `-` is treated as a synonym for the index past the
24407 end.
24408
24409 @param[in] ptr a JSON pointer
24410
24411 @return reference to the element pointed to by @a ptr
24412
24413 @complexity Constant.
24414
24415 @throw parse_error.106 if an array index begins with '0'
24416 @throw parse_error.109 if an array index was not a number
24417 @throw out_of_range.404 if the JSON pointer can not be resolved
24418
24419 @liveexample{The behavior is shown in the example.,operatorjson_pointer}
24420
24421 @since version 2.0.0
24422 */
operator [](const json_pointer & ptr)24423 reference operator[](const json_pointer& ptr)
24424 {
24425 return ptr.get_unchecked(this);
24426 }
24427
24428 /*!
24429 @brief access specified element via JSON Pointer
24430
24431 Uses a JSON pointer to retrieve a reference to the respective JSON value.
24432 No bound checking is performed. The function does not change the JSON
24433 value; no `null` values are created. In particular, the special value
24434 `-` yields an exception.
24435
24436 @param[in] ptr JSON pointer to the desired element
24437
24438 @return const reference to the element pointed to by @a ptr
24439
24440 @complexity Constant.
24441
24442 @throw parse_error.106 if an array index begins with '0'
24443 @throw parse_error.109 if an array index was not a number
24444 @throw out_of_range.402 if the array index '-' is used
24445 @throw out_of_range.404 if the JSON pointer can not be resolved
24446
24447 @liveexample{The behavior is shown in the example.,operatorjson_pointer_const}
24448
24449 @since version 2.0.0
24450 */
operator [](const json_pointer & ptr) const24451 const_reference operator[](const json_pointer& ptr) const
24452 {
24453 return ptr.get_unchecked(this);
24454 }
24455
24456 /*!
24457 @brief access specified element via JSON Pointer
24458
24459 Returns a reference to the element at with specified JSON pointer @a ptr,
24460 with bounds checking.
24461
24462 @param[in] ptr JSON pointer to the desired element
24463
24464 @return reference to the element pointed to by @a ptr
24465
24466 @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
24467 begins with '0'. See example below.
24468
24469 @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
24470 is not a number. See example below.
24471
24472 @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
24473 is out of range. See example below.
24474
24475 @throw out_of_range.402 if the array index '-' is used in the passed JSON
24476 pointer @a ptr. As `at` provides checked access (and no elements are
24477 implicitly inserted), the index '-' is always invalid. See example below.
24478
24479 @throw out_of_range.403 if the JSON pointer describes a key of an object
24480 which cannot be found. See example below.
24481
24482 @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
24483 See example below.
24484
24485 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
24486 changes in the JSON value.
24487
24488 @complexity Constant.
24489
24490 @since version 2.0.0
24491
24492 @liveexample{The behavior is shown in the example.,at_json_pointer}
24493 */
at(const json_pointer & ptr)24494 reference at(const json_pointer& ptr)
24495 {
24496 return ptr.get_checked(this);
24497 }
24498
24499 /*!
24500 @brief access specified element via JSON Pointer
24501
24502 Returns a const reference to the element at with specified JSON pointer @a
24503 ptr, with bounds checking.
24504
24505 @param[in] ptr JSON pointer to the desired element
24506
24507 @return reference to the element pointed to by @a ptr
24508
24509 @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
24510 begins with '0'. See example below.
24511
24512 @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
24513 is not a number. See example below.
24514
24515 @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
24516 is out of range. See example below.
24517
24518 @throw out_of_range.402 if the array index '-' is used in the passed JSON
24519 pointer @a ptr. As `at` provides checked access (and no elements are
24520 implicitly inserted), the index '-' is always invalid. See example below.
24521
24522 @throw out_of_range.403 if the JSON pointer describes a key of an object
24523 which cannot be found. See example below.
24524
24525 @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
24526 See example below.
24527
24528 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
24529 changes in the JSON value.
24530
24531 @complexity Constant.
24532
24533 @since version 2.0.0
24534
24535 @liveexample{The behavior is shown in the example.,at_json_pointer_const}
24536 */
at(const json_pointer & ptr) const24537 const_reference at(const json_pointer& ptr) const
24538 {
24539 return ptr.get_checked(this);
24540 }
24541
24542 /*!
24543 @brief return flattened JSON value
24544
24545 The function creates a JSON object whose keys are JSON pointers (see [RFC
24546 6901](https://tools.ietf.org/html/rfc6901)) and whose values are all
24547 primitive. The original JSON value can be restored using the @ref
24548 unflatten() function.
24549
24550 @return an object that maps JSON pointers to primitive values
24551
24552 @note Empty objects and arrays are flattened to `null` and will not be
24553 reconstructed correctly by the @ref unflatten() function.
24554
24555 @complexity Linear in the size the JSON value.
24556
24557 @liveexample{The following code shows how a JSON object is flattened to an
24558 object whose keys consist of JSON pointers.,flatten}
24559
24560 @sa @ref unflatten() for the reverse function
24561
24562 @since version 2.0.0
24563 */
flatten() const24564 basic_json flatten() const
24565 {
24566 basic_json result(value_t::object);
24567 json_pointer::flatten("", *this, result);
24568 return result;
24569 }
24570
24571 /*!
24572 @brief unflatten a previously flattened JSON value
24573
24574 The function restores the arbitrary nesting of a JSON value that has been
24575 flattened before using the @ref flatten() function. The JSON value must
24576 meet certain constraints:
24577 1. The value must be an object.
24578 2. The keys must be JSON pointers (see
24579 [RFC 6901](https://tools.ietf.org/html/rfc6901))
24580 3. The mapped values must be primitive JSON types.
24581
24582 @return the original JSON from a flattened version
24583
24584 @note Empty objects and arrays are flattened by @ref flatten() to `null`
24585 values and can not unflattened to their original type. Apart from
24586 this example, for a JSON value `j`, the following is always true:
24587 `j == j.flatten().unflatten()`.
24588
24589 @complexity Linear in the size the JSON value.
24590
24591 @throw type_error.314 if value is not an object
24592 @throw type_error.315 if object values are not primitive
24593
24594 @liveexample{The following code shows how a flattened JSON object is
24595 unflattened into the original nested JSON object.,unflatten}
24596
24597 @sa @ref flatten() for the reverse function
24598
24599 @since version 2.0.0
24600 */
unflatten() const24601 basic_json unflatten() const
24602 {
24603 return json_pointer::unflatten(*this);
24604 }
24605
24606 /// @}
24607
24608 //////////////////////////
24609 // JSON Patch functions //
24610 //////////////////////////
24611
24612 /// @name JSON Patch functions
24613 /// @{
24614
24615 /*!
24616 @brief applies a JSON patch
24617
24618 [JSON Patch](http://jsonpatch.com) defines a JSON document structure for
24619 expressing a sequence of operations to apply to a JSON) document. With
24620 this function, a JSON Patch is applied to the current JSON value by
24621 executing all operations from the patch.
24622
24623 @param[in] json_patch JSON patch document
24624 @return patched document
24625
24626 @note The application of a patch is atomic: Either all operations succeed
24627 and the patched document is returned or an exception is thrown. In
24628 any case, the original value is not changed: the patch is applied
24629 to a copy of the value.
24630
24631 @throw parse_error.104 if the JSON patch does not consist of an array of
24632 objects
24633
24634 @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory
24635 attributes are missing); example: `"operation add must have member path"`
24636
24637 @throw out_of_range.401 if an array index is out of range.
24638
24639 @throw out_of_range.403 if a JSON pointer inside the patch could not be
24640 resolved successfully in the current JSON value; example: `"key baz not
24641 found"`
24642
24643 @throw out_of_range.405 if JSON pointer has no parent ("add", "remove",
24644 "move")
24645
24646 @throw other_error.501 if "test" operation was unsuccessful
24647
24648 @complexity Linear in the size of the JSON value and the length of the
24649 JSON patch. As usually only a fraction of the JSON value is affected by
24650 the patch, the complexity can usually be neglected.
24651
24652 @liveexample{The following code shows how a JSON patch is applied to a
24653 value.,patch}
24654
24655 @sa @ref diff -- create a JSON patch by comparing two JSON values
24656
24657 @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
24658 @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901)
24659
24660 @since version 2.0.0
24661 */
patch(const basic_json & json_patch) const24662 basic_json patch(const basic_json& json_patch) const
24663 {
24664 // make a working copy to apply the patch to
24665 basic_json result = *this;
24666
24667 // the valid JSON Patch operations
24668 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24669
24670 const auto get_op = [](const std::string & op)
24671 {
24672 if (op == "add")
24673 {
24674 return patch_operations::add;
24675 }
24676 if (op == "remove")
24677 {
24678 return patch_operations::remove;
24679 }
24680 if (op == "replace")
24681 {
24682 return patch_operations::replace;
24683 }
24684 if (op == "move")
24685 {
24686 return patch_operations::move;
24687 }
24688 if (op == "copy")
24689 {
24690 return patch_operations::copy;
24691 }
24692 if (op == "test")
24693 {
24694 return patch_operations::test;
24695 }
24696
24697 return patch_operations::invalid;
24698 };
24699
24700 // wrapper for "add" operation; add value at ptr
24701 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
24702 {
24703 // adding to the root of the target document means replacing it
24704 if (ptr.empty())
24705 {
24706 result = val;
24707 return;
24708 }
24709
24710 // make sure the top element of the pointer exists
24711 json_pointer top_pointer = ptr.top();
24712 if (top_pointer != ptr)
24713 {
24714 result.at(top_pointer);
24715 }
24716
24717 // get reference to parent of JSON pointer ptr
24718 const auto last_path = ptr.back();
24719 ptr.pop_back();
24720 basic_json& parent = result[ptr];
24721
24722 switch (parent.m_type)
24723 {
24724 case value_t::null:
24725 case value_t::object:
24726 {
24727 // use operator[] to add value
24728 parent[last_path] = val;
24729 break;
24730 }
24731
24732 case value_t::array:
24733 {
24734 if (last_path == "-")
24735 {
24736 // special case: append to back
24737 parent.push_back(val);
24738 }
24739 else
24740 {
24741 const auto idx = json_pointer::array_index(last_path);
24742 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24743 {
24744 // avoid undefined behavior
24745 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
24746 }
24747
24748 // default case: insert add offset
24749 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24750 }
24751 break;
24752 }
24753
24754 // if there exists a parent it cannot be primitive
24755 default: // LCOV_EXCL_LINE
24756 JSON_ASSERT(false); // LCOV_EXCL_LINE
24757 }
24758 };
24759
24760 // wrapper for "remove" operation; remove value at ptr
24761 const auto operation_remove = [&result](json_pointer & ptr)
24762 {
24763 // get reference to parent of JSON pointer ptr
24764 const auto last_path = ptr.back();
24765 ptr.pop_back();
24766 basic_json& parent = result.at(ptr);
24767
24768 // remove child
24769 if (parent.is_object())
24770 {
24771 // perform range check
24772 auto it = parent.find(last_path);
24773 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24774 {
24775 parent.erase(it);
24776 }
24777 else
24778 {
24779 JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found"));
24780 }
24781 }
24782 else if (parent.is_array())
24783 {
24784 // note erase performs range check
24785 parent.erase(json_pointer::array_index(last_path));
24786 }
24787 };
24788
24789 // type check: top level value must be an array
24790 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24791 {
24792 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
24793 }
24794
24795 // iterate and apply the operations
24796 for (const auto& val : json_patch)
24797 {
24798 // wrapper to get a value for an operation
24799 const auto get_value = [&val](const std::string & op,
24800 const std::string & member,
24801 bool string_type) -> basic_json &
24802 {
24803 // find value
24804 auto it = val.m_value.object->find(member);
24805
24806 // context-sensitive error message
24807 const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
24808
24809 // check if desired value is present
24810 if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
24811 {
24812 JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
24813 }
24814
24815 // check if result is of type string
24816 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24817 {
24818 JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
24819 }
24820
24821 // no error: return value
24822 return it->second;
24823 };
24824
24825 // type check: every element of the array must be an object
24826 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24827 {
24828 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
24829 }
24830
24831 // collect mandatory members
24832 const auto op = get_value("op", "op", true).template get<std::string>();
24833 const auto path = get_value(op, "path", true).template get<std::string>();
24834 json_pointer ptr(path);
24835
24836 switch (get_op(op))
24837 {
24838 case patch_operations::add:
24839 {
24840 operation_add(ptr, get_value("add", "value", false));
24841 break;
24842 }
24843
24844 case patch_operations::remove:
24845 {
24846 operation_remove(ptr);
24847 break;
24848 }
24849
24850 case patch_operations::replace:
24851 {
24852 // the "path" location must exist - use at()
24853 result.at(ptr) = get_value("replace", "value", false);
24854 break;
24855 }
24856
24857 case patch_operations::move:
24858 {
24859 const auto from_path = get_value("move", "from", true).template get<std::string>();
24860 json_pointer from_ptr(from_path);
24861
24862 // the "from" location must exist - use at()
24863 basic_json v = result.at(from_ptr);
24864
24865 // The move operation is functionally identical to a
24866 // "remove" operation on the "from" location, followed
24867 // immediately by an "add" operation at the target
24868 // location with the value that was just removed.
24869 operation_remove(from_ptr);
24870 operation_add(ptr, v);
24871 break;
24872 }
24873
24874 case patch_operations::copy:
24875 {
24876 const auto from_path = get_value("copy", "from", true).template get<std::string>();
24877 const json_pointer from_ptr(from_path);
24878
24879 // the "from" location must exist - use at()
24880 basic_json v = result.at(from_ptr);
24881
24882 // The copy is functionally identical to an "add"
24883 // operation at the target location using the value
24884 // specified in the "from" member.
24885 operation_add(ptr, v);
24886 break;
24887 }
24888
24889 case patch_operations::test:
24890 {
24891 bool success = false;
24892 JSON_TRY
24893 {
24894 // check if "value" matches the one at "path"
24895 // the "path" location must exist - use at()
24896 success = (result.at(ptr) == get_value("test", "value", false));
24897 }
24898 JSON_INTERNAL_CATCH (out_of_range&)
24899 {
24900 // ignore out of range errors: success remains false
24901 }
24902
24903 // throw an exception if test fails
24904 if (JSON_HEDLEY_UNLIKELY(!success))
24905 {
24906 JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
24907 }
24908
24909 break;
24910 }
24911
24912 default:
24913 {
24914 // op must be "add", "remove", "replace", "move", "copy", or
24915 // "test"
24916 JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid"));
24917 }
24918 }
24919 }
24920
24921 return result;
24922 }
24923
24924 /*!
24925 @brief creates a diff as a JSON patch
24926
24927 Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can
24928 be changed into the value @a target by calling @ref patch function.
24929
24930 @invariant For two JSON values @a source and @a target, the following code
24931 yields always `true`:
24932 @code {.cpp}
24933 source.patch(diff(source, target)) == target;
24934 @endcode
24935
24936 @note Currently, only `remove`, `add`, and `replace` operations are
24937 generated.
24938
24939 @param[in] source JSON value to compare from
24940 @param[in] target JSON value to compare against
24941 @param[in] path helper value to create JSON pointers
24942
24943 @return a JSON patch to convert the @a source to @a target
24944
24945 @complexity Linear in the lengths of @a source and @a target.
24946
24947 @liveexample{The following code shows how a JSON patch is created as a
24948 diff for two JSON values.,diff}
24949
24950 @sa @ref patch -- apply a JSON patch
24951 @sa @ref merge_patch -- apply a JSON Merge Patch
24952
24953 @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
24954
24955 @since version 2.0.0
24956 */
24957 JSON_HEDLEY_WARN_UNUSED_RESULT
diff(const basic_json & source,const basic_json & target,const std::string & path="")24958 static basic_json diff(const basic_json& source, const basic_json& target,
24959 const std::string& path = "")
24960 {
24961 // the patch
24962 basic_json result(value_t::array);
24963
24964 // if the values are the same, return empty patch
24965 if (source == target)
24966 {
24967 return result;
24968 }
24969
24970 if (source.type() != target.type())
24971 {
24972 // different types: replace value
24973 result.push_back(
24974 {
24975 {"op", "replace"}, {"path", path}, {"value", target}
24976 });
24977 return result;
24978 }
24979
24980 switch (source.type())
24981 {
24982 case value_t::array:
24983 {
24984 // first pass: traverse common elements
24985 std::size_t i = 0;
24986 while (i < source.size() && i < target.size())
24987 {
24988 // recursive call to compare array values at index i
24989 auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
24990 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24991 ++i;
24992 }
24993
24994 // i now reached the end of at least one array
24995 // in a second pass, traverse the remaining elements
24996
24997 // remove my remaining elements
24998 const auto end_index = static_cast<difference_type>(result.size());
24999 while (i < source.size())
25000 {
25001 // add operations in reverse order to avoid invalid
25002 // indices
25003 result.insert(result.begin() + end_index, object(
25004 {
25005 {"op", "remove"},
25006 {"path", path + "/" + std::to_string(i)}
25007 }));
25008 ++i;
25009 }
25010
25011 // add other remaining elements
25012 while (i < target.size())
25013 {
25014 result.push_back(
25015 {
25016 {"op", "add"},
25017 {"path", path + "/-"},
25018 {"value", target[i]}
25019 });
25020 ++i;
25021 }
25022
25023 break;
25024 }
25025
25026 case value_t::object:
25027 {
25028 // first pass: traverse this object's elements
25029 for (auto it = source.cbegin(); it != source.cend(); ++it)
25030 {
25031 // escape the key name to be used in a JSON patch
25032 const auto key = json_pointer::escape(it.key());
25033
25034 if (target.find(it.key()) != target.end())
25035 {
25036 // recursive call to compare object values at key it
25037 auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
25038 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25039 }
25040 else
25041 {
25042 // found a key that is not in o -> remove it
25043 result.push_back(object(
25044 {
25045 {"op", "remove"}, {"path", path + "/" + key}
25046 }));
25047 }
25048 }
25049
25050 // second pass: traverse other object's elements
25051 for (auto it = target.cbegin(); it != target.cend(); ++it)
25052 {
25053 if (source.find(it.key()) == source.end())
25054 {
25055 // found a key that is not in this -> add it
25056 const auto key = json_pointer::escape(it.key());
25057 result.push_back(
25058 {
25059 {"op", "add"}, {"path", path + "/" + key},
25060 {"value", it.value()}
25061 });
25062 }
25063 }
25064
25065 break;
25066 }
25067
25068 default:
25069 {
25070 // both primitive type: replace value
25071 result.push_back(
25072 {
25073 {"op", "replace"}, {"path", path}, {"value", target}
25074 });
25075 break;
25076 }
25077 }
25078
25079 return result;
25080 }
25081
25082 /// @}
25083
25084 ////////////////////////////////
25085 // JSON Merge Patch functions //
25086 ////////////////////////////////
25087
25088 /// @name JSON Merge Patch functions
25089 /// @{
25090
25091 /*!
25092 @brief applies a JSON Merge Patch
25093
25094 The merge patch format is primarily intended for use with the HTTP PATCH
25095 method as a means of describing a set of modifications to a target
25096 resource's content. This function applies a merge patch to the current
25097 JSON value.
25098
25099 The function implements the following algorithm from Section 2 of
25100 [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396):
25101
25102 ```
25103 define MergePatch(Target, Patch):
25104 if Patch is an Object:
25105 if Target is not an Object:
25106 Target = {} // Ignore the contents and set it to an empty Object
25107 for each Name/Value pair in Patch:
25108 if Value is null:
25109 if Name exists in Target:
25110 remove the Name/Value pair from Target
25111 else:
25112 Target[Name] = MergePatch(Target[Name], Value)
25113 return Target
25114 else:
25115 return Patch
25116 ```
25117
25118 Thereby, `Target` is the current object; that is, the patch is applied to
25119 the current value.
25120
25121 @param[in] apply_patch the patch to apply
25122
25123 @complexity Linear in the lengths of @a patch.
25124
25125 @liveexample{The following code shows how a JSON Merge Patch is applied to
25126 a JSON document.,merge_patch}
25127
25128 @sa @ref patch -- apply a JSON patch
25129 @sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396)
25130
25131 @since version 3.0.0
25132 */
merge_patch(const basic_json & apply_patch)25133 void merge_patch(const basic_json& apply_patch)
25134 {
25135 if (apply_patch.is_object())
25136 {
25137 if (!is_object())
25138 {
25139 *this = object();
25140 }
25141 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
25142 {
25143 if (it.value().is_null())
25144 {
25145 erase(it.key());
25146 }
25147 else
25148 {
25149 operator[](it.key()).merge_patch(it.value());
25150 }
25151 }
25152 }
25153 else
25154 {
25155 *this = apply_patch;
25156 }
25157 }
25158
25159 /// @}
25160 };
25161
25162 /*!
25163 @brief user-defined to_string function for JSON values
25164
25165 This function implements a user-defined to_string for JSON objects.
25166
25167 @param[in] j a JSON object
25168 @return a std::string object
25169 */
25170
25171 NLOHMANN_BASIC_JSON_TPL_DECLARATION
to_string(const NLOHMANN_BASIC_JSON_TPL & j)25172 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
25173 {
25174 return j.dump();
25175 }
25176 } // namespace nlohmann
25177
25178 ///////////////////////
25179 // nonmember support //
25180 ///////////////////////
25181
25182 // specialization of std::swap, and std::hash
25183 namespace std
25184 {
25185
25186 /// hash value for JSON objects
25187 template<>
25188 struct hash<nlohmann::json>
25189 {
25190 /*!
25191 @brief return a hash value for a JSON object
25192
25193 @since version 1.0.0
25194 */
operator ()std::hash25195 std::size_t operator()(const nlohmann::json& j) const
25196 {
25197 return nlohmann::detail::hash(j);
25198 }
25199 };
25200
25201 /// specialization for std::less<value_t>
25202 /// @note: do not remove the space after '<',
25203 /// see https://github.com/nlohmann/json/pull/679
25204 template<>
25205 struct less<::nlohmann::detail::value_t>
25206 {
25207 /*!
25208 @brief compare two value_t enum values
25209 @since version 3.0.0
25210 */
operator ()std::less25211 bool operator()(nlohmann::detail::value_t lhs,
25212 nlohmann::detail::value_t rhs) const noexcept
25213 {
25214 return nlohmann::detail::operator<(lhs, rhs);
25215 }
25216 };
25217
25218 // C++20 prohibit function specialization in the std namespace.
25219 #ifndef JSON_HAS_CPP_20
25220
25221 /*!
25222 @brief exchanges the values of two JSON objects
25223
25224 @since version 1.0.0
25225 */
25226 template<>
swap(nlohmann::json & j1,nlohmann::json & j2)25227 inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
25228 is_nothrow_move_constructible<nlohmann::json>::value&&
25229 is_nothrow_move_assignable<nlohmann::json>::value
25230 )
25231 {
25232 j1.swap(j2);
25233 }
25234
25235 #endif
25236
25237 } // namespace std
25238
25239 /*!
25240 @brief user-defined string literal for JSON values
25241
25242 This operator implements a user-defined string literal for JSON objects. It
25243 can be used by adding `"_json"` to a string literal and returns a JSON object
25244 if no parse error occurred.
25245
25246 @param[in] s a string representation of a JSON object
25247 @param[in] n the length of string @a s
25248 @return a JSON object
25249
25250 @since version 1.0.0
25251 */
25252 JSON_HEDLEY_NON_NULL(1)
operator ""_json(const char * s,std::size_t n)25253 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
25254 {
25255 return nlohmann::json::parse(s, s + n);
25256 }
25257
25258 /*!
25259 @brief user-defined string literal for JSON pointer
25260
25261 This operator implements a user-defined string literal for JSON Pointers. It
25262 can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer
25263 object if no parse error occurred.
25264
25265 @param[in] s a string representation of a JSON Pointer
25266 @param[in] n the length of string @a s
25267 @return a JSON pointer object
25268
25269 @since version 2.0.0
25270 */
25271 JSON_HEDLEY_NON_NULL(1)
operator ""_json_pointer(const char * s,std::size_t n)25272 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
25273 {
25274 return nlohmann::json::json_pointer(std::string(s, n));
25275 }
25276
25277 // #include <nlohmann/detail/macro_unscope.hpp>
25278
25279
25280 // restore GCC/clang diagnostic settings
25281 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
25282 #pragma GCC diagnostic pop
25283 #endif
25284 #if defined(__clang__)
25285 #pragma GCC diagnostic pop
25286 #endif
25287
25288 // clean up
25289 #undef JSON_ASSERT
25290 #undef JSON_INTERNAL_CATCH
25291 #undef JSON_CATCH
25292 #undef JSON_THROW
25293 #undef JSON_TRY
25294 #undef JSON_HAS_CPP_14
25295 #undef JSON_HAS_CPP_17
25296 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
25297 #undef NLOHMANN_BASIC_JSON_TPL
25298 #undef JSON_EXPLICIT
25299
25300 // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
25301 #undef JSON_HEDLEY_ALWAYS_INLINE
25302 #undef JSON_HEDLEY_ARM_VERSION
25303 #undef JSON_HEDLEY_ARM_VERSION_CHECK
25304 #undef JSON_HEDLEY_ARRAY_PARAM
25305 #undef JSON_HEDLEY_ASSUME
25306 #undef JSON_HEDLEY_BEGIN_C_DECLS
25307 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
25308 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
25309 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
25310 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
25311 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
25312 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
25313 #undef JSON_HEDLEY_CLANG_HAS_WARNING
25314 #undef JSON_HEDLEY_COMPCERT_VERSION
25315 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
25316 #undef JSON_HEDLEY_CONCAT
25317 #undef JSON_HEDLEY_CONCAT3
25318 #undef JSON_HEDLEY_CONCAT3_EX
25319 #undef JSON_HEDLEY_CONCAT_EX
25320 #undef JSON_HEDLEY_CONST
25321 #undef JSON_HEDLEY_CONSTEXPR
25322 #undef JSON_HEDLEY_CONST_CAST
25323 #undef JSON_HEDLEY_CPP_CAST
25324 #undef JSON_HEDLEY_CRAY_VERSION
25325 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
25326 #undef JSON_HEDLEY_C_DECL
25327 #undef JSON_HEDLEY_DEPRECATED
25328 #undef JSON_HEDLEY_DEPRECATED_FOR
25329 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
25330 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
25331 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
25332 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
25333 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
25334 #undef JSON_HEDLEY_DIAGNOSTIC_POP
25335 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
25336 #undef JSON_HEDLEY_DMC_VERSION
25337 #undef JSON_HEDLEY_DMC_VERSION_CHECK
25338 #undef JSON_HEDLEY_EMPTY_BASES
25339 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
25340 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
25341 #undef JSON_HEDLEY_END_C_DECLS
25342 #undef JSON_HEDLEY_FLAGS
25343 #undef JSON_HEDLEY_FLAGS_CAST
25344 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
25345 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
25346 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
25347 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
25348 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
25349 #undef JSON_HEDLEY_GCC_HAS_FEATURE
25350 #undef JSON_HEDLEY_GCC_HAS_WARNING
25351 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
25352 #undef JSON_HEDLEY_GCC_VERSION
25353 #undef JSON_HEDLEY_GCC_VERSION_CHECK
25354 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
25355 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
25356 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
25357 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
25358 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
25359 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
25360 #undef JSON_HEDLEY_GNUC_HAS_WARNING
25361 #undef JSON_HEDLEY_GNUC_VERSION
25362 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
25363 #undef JSON_HEDLEY_HAS_ATTRIBUTE
25364 #undef JSON_HEDLEY_HAS_BUILTIN
25365 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
25366 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
25367 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
25368 #undef JSON_HEDLEY_HAS_EXTENSION
25369 #undef JSON_HEDLEY_HAS_FEATURE
25370 #undef JSON_HEDLEY_HAS_WARNING
25371 #undef JSON_HEDLEY_IAR_VERSION
25372 #undef JSON_HEDLEY_IAR_VERSION_CHECK
25373 #undef JSON_HEDLEY_IBM_VERSION
25374 #undef JSON_HEDLEY_IBM_VERSION_CHECK
25375 #undef JSON_HEDLEY_IMPORT
25376 #undef JSON_HEDLEY_INLINE
25377 #undef JSON_HEDLEY_INTEL_VERSION
25378 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
25379 #undef JSON_HEDLEY_IS_CONSTANT
25380 #undef JSON_HEDLEY_IS_CONSTEXPR_
25381 #undef JSON_HEDLEY_LIKELY
25382 #undef JSON_HEDLEY_MALLOC
25383 #undef JSON_HEDLEY_MESSAGE
25384 #undef JSON_HEDLEY_MSVC_VERSION
25385 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
25386 #undef JSON_HEDLEY_NEVER_INLINE
25387 #undef JSON_HEDLEY_NON_NULL
25388 #undef JSON_HEDLEY_NO_ESCAPE
25389 #undef JSON_HEDLEY_NO_RETURN
25390 #undef JSON_HEDLEY_NO_THROW
25391 #undef JSON_HEDLEY_NULL
25392 #undef JSON_HEDLEY_PELLES_VERSION
25393 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
25394 #undef JSON_HEDLEY_PGI_VERSION
25395 #undef JSON_HEDLEY_PGI_VERSION_CHECK
25396 #undef JSON_HEDLEY_PREDICT
25397 #undef JSON_HEDLEY_PRINTF_FORMAT
25398 #undef JSON_HEDLEY_PRIVATE
25399 #undef JSON_HEDLEY_PUBLIC
25400 #undef JSON_HEDLEY_PURE
25401 #undef JSON_HEDLEY_REINTERPRET_CAST
25402 #undef JSON_HEDLEY_REQUIRE
25403 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
25404 #undef JSON_HEDLEY_REQUIRE_MSG
25405 #undef JSON_HEDLEY_RESTRICT
25406 #undef JSON_HEDLEY_RETURNS_NON_NULL
25407 #undef JSON_HEDLEY_SENTINEL
25408 #undef JSON_HEDLEY_STATIC_ASSERT
25409 #undef JSON_HEDLEY_STATIC_CAST
25410 #undef JSON_HEDLEY_STRINGIFY
25411 #undef JSON_HEDLEY_STRINGIFY_EX
25412 #undef JSON_HEDLEY_SUNPRO_VERSION
25413 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
25414 #undef JSON_HEDLEY_TINYC_VERSION
25415 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
25416 #undef JSON_HEDLEY_TI_ARMCL_VERSION
25417 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
25418 #undef JSON_HEDLEY_TI_CL2000_VERSION
25419 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
25420 #undef JSON_HEDLEY_TI_CL430_VERSION
25421 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
25422 #undef JSON_HEDLEY_TI_CL6X_VERSION
25423 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
25424 #undef JSON_HEDLEY_TI_CL7X_VERSION
25425 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
25426 #undef JSON_HEDLEY_TI_CLPRU_VERSION
25427 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
25428 #undef JSON_HEDLEY_TI_VERSION
25429 #undef JSON_HEDLEY_TI_VERSION_CHECK
25430 #undef JSON_HEDLEY_UNAVAILABLE
25431 #undef JSON_HEDLEY_UNLIKELY
25432 #undef JSON_HEDLEY_UNPREDICTABLE
25433 #undef JSON_HEDLEY_UNREACHABLE
25434 #undef JSON_HEDLEY_UNREACHABLE_RETURN
25435 #undef JSON_HEDLEY_VERSION
25436 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
25437 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
25438 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
25439 #undef JSON_HEDLEY_VERSION_ENCODE
25440 #undef JSON_HEDLEY_WARNING
25441 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
25442 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
25443 #undef JSON_HEDLEY_FALL_THROUGH
25444
25445
25446
25447 #endif // INCLUDE_NLOHMANN_JSON_HPP_
25448