Coverage Report

Created: 2023-11-19 07:17

/src/jsonnet/third_party/json/json.hpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
    __ _____ _____ _____
3
 __|  |   __|     |   | |  JSON for Modern C++
4
|  |  |__   |  |  | | | |  version 3.6.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 6
35
#define NLOHMANN_JSON_VERSION_PATCH 1
36
37
#include <algorithm> // all_of, find, for_each
38
#include <cassert> // assert
39
#include <ciso646> // and, not, or
40
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
41
#include <functional> // hash, less
42
#include <initializer_list> // initializer_list
43
#include <iosfwd> // istream, ostream
44
#include <iterator> // random_access_iterator_tag
45
#include <memory> // unique_ptr
46
#include <numeric> // accumulate
47
#include <string> // string, stoi, to_string
48
#include <utility> // declval, forward, move, pair, swap
49
#include <vector> // vector
50
51
// #include <nlohmann/adl_serializer.hpp>
52
53
54
#include <utility>
55
56
// #include <nlohmann/detail/conversions/from_json.hpp>
57
58
59
#include <algorithm> // transform
60
#include <array> // array
61
#include <ciso646> // and, not
62
#include <forward_list> // forward_list
63
#include <iterator> // inserter, front_inserter, end
64
#include <map> // map
65
#include <string> // string
66
#include <tuple> // tuple, make_tuple
67
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
68
#include <unordered_map> // unordered_map
69
#include <utility> // pair, declval
70
#include <valarray> // valarray
71
72
// #include <nlohmann/detail/exceptions.hpp>
73
74
75
#include <exception> // exception
76
#include <stdexcept> // runtime_error
77
#include <string> // to_string
78
79
// #include <nlohmann/detail/input/position_t.hpp>
80
81
82
#include <cstddef> // size_t
83
84
namespace nlohmann
85
{
86
namespace detail
87
{
88
/// struct to capture the start position of the current token
89
struct position_t
90
{
91
    /// the total number of characters read
92
    std::size_t chars_read_total = 0;
93
    /// the number of characters read in the current line
94
    std::size_t chars_read_current_line = 0;
95
    /// the number of lines read
96
    std::size_t lines_read = 0;
97
98
    /// conversion to size_t to preserve SAX interface
99
    constexpr operator size_t() const
100
0
    {
101
0
        return chars_read_total;
102
0
    }
103
};
104
105
} // namespace detail
106
} // namespace nlohmann
107
108
109
namespace nlohmann
110
{
111
namespace detail
112
{
113
////////////////
114
// exceptions //
115
////////////////
116
117
/*!
118
@brief general exception of the @ref basic_json class
119
120
This class is an extension of `std::exception` objects with a member @a id for
121
exception ids. It is used as the base class for all exceptions thrown by the
122
@ref basic_json class. This class can hence be used as "wildcard" to catch
123
exceptions.
124
125
Subclasses:
126
- @ref parse_error for exceptions indicating a parse error
127
- @ref invalid_iterator for exceptions indicating errors with iterators
128
- @ref type_error for exceptions indicating executing a member function with
129
                  a wrong type
130
- @ref out_of_range for exceptions indicating access out of the defined range
131
- @ref other_error for exceptions indicating other library errors
132
133
@internal
134
@note To have nothrow-copy-constructible exceptions, we internally use
135
      `std::runtime_error` which can cope with arbitrary-length error messages.
136
      Intermediate strings are built with static functions and then passed to
137
      the actual constructor.
138
@endinternal
139
140
@liveexample{The following code shows how arbitrary library exceptions can be
141
caught.,exception}
142
143
@since version 3.0.0
144
*/
145
class exception : public std::exception
146
{
147
  public:
148
    /// returns the explanatory string
149
    const char* what() const noexcept override
150
0
    {
151
0
        return m.what();
152
0
    }
153
154
    /// the id of the exception
155
    const int id;
156
157
  protected:
158
0
    exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
159
160
    static std::string name(const std::string& ename, int id_)
161
0
    {
162
0
        return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
163
0
    }
164
165
  private:
166
    /// an exception object as storage for error messages
167
    std::runtime_error m;
168
};
169
170
/*!
171
@brief exception indicating a parse error
172
173
This exception is thrown by the library when a parse error occurs. Parse errors
174
can occur during the deserialization of JSON text, CBOR, MessagePack, as well
175
as when using JSON Patch.
176
177
Member @a byte holds the byte index of the last read character in the input
178
file.
179
180
Exceptions have ids 1xx.
181
182
name / id                      | example message | description
183
------------------------------ | --------------- | -------------------------
184
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.
185
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.
186
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.
187
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.
188
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.
189
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`.
190
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.
191
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.
192
json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.
193
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.
194
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.
195
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.
196
json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet).
197
198
@note For an input with n bytes, 1 is the index of the first character and n+1
199
      is the index of the terminating null byte or the end of file. This also
200
      holds true when reading a byte vector (CBOR or MessagePack).
201
202
@liveexample{The following code shows how a `parse_error` exception can be
203
caught.,parse_error}
204
205
@sa - @ref exception for the base class of the library exceptions
206
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
207
@sa - @ref type_error for exceptions indicating executing a member function with
208
                    a wrong type
209
@sa - @ref out_of_range for exceptions indicating access out of the defined range
210
@sa - @ref other_error for exceptions indicating other library errors
211
212
@since version 3.0.0
213
*/
214
class parse_error : public exception
215
{
216
  public:
217
    /*!
218
    @brief create a parse error exception
219
    @param[in] id_       the id of the exception
220
    @param[in] pos       the position where the error occurred (or with
221
                         chars_read_total=0 if the position cannot be
222
                         determined)
223
    @param[in] what_arg  the explanatory string
224
    @return parse_error object
225
    */
226
    static parse_error create(int id_, const position_t& pos, const std::string& what_arg)
227
0
    {
228
0
        std::string w = exception::name("parse_error", id_) + "parse error" +
229
0
                        position_string(pos) + ": " + what_arg;
230
0
        return parse_error(id_, pos.chars_read_total, w.c_str());
231
0
    }
232
233
    static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)
234
0
    {
235
0
        std::string w = exception::name("parse_error", id_) + "parse error" +
236
0
                        (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
237
0
                        ": " + what_arg;
238
0
        return parse_error(id_, byte_, w.c_str());
239
0
    }
240
241
    /*!
242
    @brief byte index of the parse error
243
244
    The byte index of the last read character in the input file.
245
246
    @note For an input with n bytes, 1 is the index of the first character and
247
          n+1 is the index of the terminating null byte or the end of file.
248
          This also holds true when reading a byte vector (CBOR or MessagePack).
249
    */
250
    const std::size_t byte;
251
252
  private:
253
    parse_error(int id_, std::size_t byte_, const char* what_arg)
254
0
        : exception(id_, what_arg), byte(byte_) {}
255
256
    static std::string position_string(const position_t& pos)
257
0
    {
258
0
        return " at line " + std::to_string(pos.lines_read + 1) +
259
0
               ", column " + std::to_string(pos.chars_read_current_line);
260
0
    }
261
};
262
263
/*!
264
@brief exception indicating errors with iterators
265
266
This exception is thrown if iterators passed to a library function do not match
267
the expected semantics.
268
269
Exceptions have ids 2xx.
270
271
name / id                           | example message | description
272
----------------------------------- | --------------- | -------------------------
273
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.
274
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.
275
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.
276
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.
277
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.
278
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.
279
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.
280
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.
281
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.
282
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.
283
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.
284
json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container.
285
json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered.
286
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().
287
288
@liveexample{The following code shows how an `invalid_iterator` exception can be
289
caught.,invalid_iterator}
290
291
@sa - @ref exception for the base class of the library exceptions
292
@sa - @ref parse_error for exceptions indicating a parse error
293
@sa - @ref type_error for exceptions indicating executing a member function with
294
                    a wrong type
295
@sa - @ref out_of_range for exceptions indicating access out of the defined range
296
@sa - @ref other_error for exceptions indicating other library errors
297
298
@since version 3.0.0
299
*/
300
class invalid_iterator : public exception
301
{
302
  public:
303
    static invalid_iterator create(int id_, const std::string& what_arg)
304
0
    {
305
0
        std::string w = exception::name("invalid_iterator", id_) + what_arg;
306
0
        return invalid_iterator(id_, w.c_str());
307
0
    }
308
309
  private:
310
    invalid_iterator(int id_, const char* what_arg)
311
0
        : exception(id_, what_arg) {}
312
};
313
314
/*!
315
@brief exception indicating executing a member function with a wrong type
316
317
This exception is thrown in case of a type error; that is, a library function is
318
executed on a JSON value whose type does not match the expected semantics.
319
320
Exceptions have ids 3xx.
321
322
name / id                     | example message | description
323
----------------------------- | --------------- | -------------------------
324
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.
325
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.
326
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 &.
327
json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
328
json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
329
json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
330
json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.
331
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.
332
json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.
333
json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.
334
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.
335
json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.
336
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.
337
json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.
338
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.
339
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. |
340
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) |
341
342
@liveexample{The following code shows how a `type_error` exception can be
343
caught.,type_error}
344
345
@sa - @ref exception for the base class of the library exceptions
346
@sa - @ref parse_error for exceptions indicating a parse error
347
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
348
@sa - @ref out_of_range for exceptions indicating access out of the defined range
349
@sa - @ref other_error for exceptions indicating other library errors
350
351
@since version 3.0.0
352
*/
353
class type_error : public exception
354
{
355
  public:
356
    static type_error create(int id_, const std::string& what_arg)
357
0
    {
358
0
        std::string w = exception::name("type_error", id_) + what_arg;
359
0
        return type_error(id_, w.c_str());
360
0
    }
361
362
  private:
363
0
    type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
364
};
365
366
/*!
367
@brief exception indicating access out of the defined range
368
369
This exception is thrown in case a library function is called on an input
370
parameter that exceeds the expected range, for instance in case of array
371
indices or nonexisting object keys.
372
373
Exceptions have ids 4xx.
374
375
name / id                       | example message | description
376
------------------------------- | --------------- | -------------------------
377
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.
378
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.
379
json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.
380
json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
381
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.
382
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.
383
json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. |
384
json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
385
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 |
386
387
@liveexample{The following code shows how an `out_of_range` exception can be
388
caught.,out_of_range}
389
390
@sa - @ref exception for the base class of the library exceptions
391
@sa - @ref parse_error for exceptions indicating a parse error
392
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
393
@sa - @ref type_error for exceptions indicating executing a member function with
394
                    a wrong type
395
@sa - @ref other_error for exceptions indicating other library errors
396
397
@since version 3.0.0
398
*/
399
class out_of_range : public exception
400
{
401
  public:
402
    static out_of_range create(int id_, const std::string& what_arg)
403
0
    {
404
0
        std::string w = exception::name("out_of_range", id_) + what_arg;
405
0
        return out_of_range(id_, w.c_str());
406
0
    }
407
408
  private:
409
0
    out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
410
};
411
412
/*!
413
@brief exception indicating other library errors
414
415
This exception is thrown in case of errors that cannot be classified with the
416
other exception types.
417
418
Exceptions have ids 5xx.
419
420
name / id                      | example message | description
421
------------------------------ | --------------- | -------------------------
422
json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
423
424
@sa - @ref exception for the base class of the library exceptions
425
@sa - @ref parse_error for exceptions indicating a parse error
426
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
427
@sa - @ref type_error for exceptions indicating executing a member function with
428
                    a wrong type
429
@sa - @ref out_of_range for exceptions indicating access out of the defined range
430
431
@liveexample{The following code shows how an `other_error` exception can be
432
caught.,other_error}
433
434
@since version 3.0.0
435
*/
436
class other_error : public exception
437
{
438
  public:
439
    static other_error create(int id_, const std::string& what_arg)
440
0
    {
441
0
        std::string w = exception::name("other_error", id_) + what_arg;
442
0
        return other_error(id_, w.c_str());
443
0
    }
444
445
  private:
446
0
    other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
447
};
448
}  // namespace detail
449
}  // namespace nlohmann
450
451
// #include <nlohmann/detail/macro_scope.hpp>
452
453
454
#include <utility> // pair
455
456
// This file contains all internal macro definitions
457
// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
458
459
// exclude unsupported compilers
460
#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
461
    #if defined(__clang__)
462
        #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
463
            #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
464
        #endif
465
    #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
466
        #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
467
            #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
468
        #endif
469
    #endif
470
#endif
471
472
// disable float-equal warnings on GCC/clang
473
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
474
    #pragma GCC diagnostic push
475
    #pragma GCC diagnostic ignored "-Wfloat-equal"
476
#endif
477
478
// disable documentation warnings on clang
479
#if defined(__clang__)
480
    #pragma GCC diagnostic push
481
    #pragma GCC diagnostic ignored "-Wdocumentation"
482
#endif
483
484
// allow for portable deprecation warnings
485
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
486
    #define JSON_DEPRECATED __attribute__((deprecated))
487
#elif defined(_MSC_VER)
488
    #define JSON_DEPRECATED __declspec(deprecated)
489
#else
490
    #define JSON_DEPRECATED
491
#endif
492
493
// allow for portable nodiscard warnings
494
#if defined(__has_cpp_attribute)
495
    #if __has_cpp_attribute(nodiscard)
496
        #define JSON_NODISCARD [[nodiscard]]
497
    #elif __has_cpp_attribute(gnu::warn_unused_result)
498
        #define JSON_NODISCARD [[gnu::warn_unused_result]]
499
    #else
500
        #define JSON_NODISCARD
501
    #endif
502
#else
503
    #define JSON_NODISCARD
504
#endif
505
506
// allow to disable exceptions
507
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
508
0
    #define JSON_THROW(exception) throw exception
509
    #define JSON_TRY try
510
    #define JSON_CATCH(exception) catch(exception)
511
    #define JSON_INTERNAL_CATCH(exception) catch(exception)
512
#else
513
    #include <cstdlib>
514
    #define JSON_THROW(exception) std::abort()
515
    #define JSON_TRY if(true)
516
    #define JSON_CATCH(exception) if(false)
517
    #define JSON_INTERNAL_CATCH(exception) if(false)
518
#endif
519
520
// override exception macros
521
#if defined(JSON_THROW_USER)
522
    #undef JSON_THROW
523
    #define JSON_THROW JSON_THROW_USER
524
#endif
525
#if defined(JSON_TRY_USER)
526
    #undef JSON_TRY
527
    #define JSON_TRY JSON_TRY_USER
528
#endif
529
#if defined(JSON_CATCH_USER)
530
    #undef JSON_CATCH
531
    #define JSON_CATCH JSON_CATCH_USER
532
    #undef JSON_INTERNAL_CATCH
533
    #define JSON_INTERNAL_CATCH JSON_CATCH_USER
534
#endif
535
#if defined(JSON_INTERNAL_CATCH_USER)
536
    #undef JSON_INTERNAL_CATCH
537
    #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
538
#endif
539
540
// manual branch prediction
541
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
542
0
    #define JSON_LIKELY(x)      __builtin_expect(x, 1)
543
0
    #define JSON_UNLIKELY(x)    __builtin_expect(x, 0)
544
#else
545
    #define JSON_LIKELY(x)      x
546
    #define JSON_UNLIKELY(x)    x
547
#endif
548
549
// C++ language standard detection
550
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
551
    #define JSON_HAS_CPP_17
552
    #define JSON_HAS_CPP_14
553
#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
554
    #define JSON_HAS_CPP_14
555
#endif
556
557
/*!
558
@brief macro to briefly define a mapping between an enum and JSON
559
@def NLOHMANN_JSON_SERIALIZE_ENUM
560
@since version 3.4.0
561
*/
562
#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...)                                           \
563
    template<typename BasicJsonType>                                                           \
564
    inline void to_json(BasicJsonType& j, const ENUM_TYPE& e)                                  \
565
    {                                                                                          \
566
        static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");         \
567
        static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                    \
568
        auto it = std::find_if(std::begin(m), std::end(m),                                     \
569
                               [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
570
        {                                                                                      \
571
            return ej_pair.first == e;                                                         \
572
        });                                                                                    \
573
        j = ((it != std::end(m)) ? it : std::begin(m))->second;                                \
574
    }                                                                                          \
575
    template<typename BasicJsonType>                                                           \
576
    inline void from_json(const BasicJsonType& j, ENUM_TYPE& e)                                \
577
    {                                                                                          \
578
        static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");         \
579
        static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                    \
580
        auto it = std::find_if(std::begin(m), std::end(m),                                     \
581
                               [j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
582
        {                                                                                      \
583
            return ej_pair.second == j;                                                        \
584
        });                                                                                    \
585
        e = ((it != std::end(m)) ? it : std::begin(m))->first;                                 \
586
    }
587
588
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
589
// may be removed in the future once the class is split.
590
591
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION                                \
592
    template<template<typename, typename, typename...> class ObjectType,   \
593
             template<typename, typename...> class ArrayType,              \
594
             class StringType, class BooleanType, class NumberIntegerType, \
595
             class NumberUnsignedType, class NumberFloatType,              \
596
             template<typename> class AllocatorType,                       \
597
             template<typename, typename = void> class JSONSerializer>
598
599
#define NLOHMANN_BASIC_JSON_TPL                                            \
600
    basic_json<ObjectType, ArrayType, StringType, BooleanType,             \
601
    NumberIntegerType, NumberUnsignedType, NumberFloatType,                \
602
    AllocatorType, JSONSerializer>
603
604
// #include <nlohmann/detail/meta/cpp_future.hpp>
605
606
607
#include <ciso646> // not
608
#include <cstddef> // size_t
609
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
610
611
namespace nlohmann
612
{
613
namespace detail
614
{
615
// alias templates to reduce boilerplate
616
template<bool B, typename T = void>
617
using enable_if_t = typename std::enable_if<B, T>::type;
618
619
template<typename T>
620
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
621
622
// implementation of C++14 index_sequence and affiliates
623
// source: https://stackoverflow.com/a/32223343
624
template<std::size_t... Ints>
625
struct index_sequence
626
{
627
    using type = index_sequence;
628
    using value_type = std::size_t;
629
    static constexpr std::size_t size() noexcept
630
    {
631
        return sizeof...(Ints);
632
    }
633
};
634
635
template<class Sequence1, class Sequence2>
636
struct merge_and_renumber;
637
638
template<std::size_t... I1, std::size_t... I2>
639
struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
640
        : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
641
642
template<std::size_t N>
643
struct make_index_sequence
644
    : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
645
      typename make_index_sequence < N - N / 2 >::type > {};
646
647
template<> struct make_index_sequence<0> : index_sequence<> {};
648
template<> struct make_index_sequence<1> : index_sequence<0> {};
649
650
template<typename... Ts>
651
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
652
653
// dispatch utility (taken from ranges-v3)
654
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
655
template<> struct priority_tag<0> {};
656
657
// taken from ranges-v3
658
template<typename T>
659
struct static_const
660
{
661
    static constexpr T value{};
662
};
663
664
template<typename T>
665
constexpr T static_const<T>::value;
666
}  // namespace detail
667
}  // namespace nlohmann
668
669
// #include <nlohmann/detail/meta/type_traits.hpp>
670
671
672
#include <ciso646> // not
673
#include <limits> // numeric_limits
674
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
675
#include <utility> // declval
676
677
// #include <nlohmann/detail/iterators/iterator_traits.hpp>
678
679
680
#include <iterator> // random_access_iterator_tag
681
682
// #include <nlohmann/detail/meta/void_t.hpp>
683
684
685
namespace nlohmann
686
{
687
namespace detail
688
{
689
template <typename ...Ts> struct make_void
690
{
691
    using type = void;
692
};
693
template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
694
} // namespace detail
695
}  // namespace nlohmann
696
697
// #include <nlohmann/detail/meta/cpp_future.hpp>
698
699
700
namespace nlohmann
701
{
702
namespace detail
703
{
704
template <typename It, typename = void>
705
struct iterator_types {};
706
707
template <typename It>
708
struct iterator_types <
709
    It,
710
    void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
711
    typename It::reference, typename It::iterator_category >>
712
{
713
    using difference_type = typename It::difference_type;
714
    using value_type = typename It::value_type;
715
    using pointer = typename It::pointer;
716
    using reference = typename It::reference;
717
    using iterator_category = typename It::iterator_category;
718
};
719
720
// This is required as some compilers implement std::iterator_traits in a way that
721
// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
722
template <typename T, typename = void>
723
struct iterator_traits
724
{
725
};
726
727
template <typename T>
728
struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
729
            : iterator_types<T>
730
{
731
};
732
733
template <typename T>
734
struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
735
{
736
    using iterator_category = std::random_access_iterator_tag;
737
    using value_type = T;
738
    using difference_type = ptrdiff_t;
739
    using pointer = T*;
740
    using reference = T&;
741
};
742
} // namespace detail
743
} // namespace nlohmann
744
745
// #include <nlohmann/detail/macro_scope.hpp>
746
747
// #include <nlohmann/detail/meta/cpp_future.hpp>
748
749
// #include <nlohmann/detail/meta/detected.hpp>
750
751
752
#include <type_traits>
753
754
// #include <nlohmann/detail/meta/void_t.hpp>
755
756
757
// http://en.cppreference.com/w/cpp/experimental/is_detected
758
namespace nlohmann
759
{
760
namespace detail
761
{
762
struct nonesuch
763
{
764
    nonesuch() = delete;
765
    ~nonesuch() = delete;
766
    nonesuch(nonesuch const&) = delete;
767
    nonesuch(nonesuch const&&) = delete;
768
    void operator=(nonesuch const&) = delete;
769
    void operator=(nonesuch&&) = delete;
770
};
771
772
template <class Default,
773
          class AlwaysVoid,
774
          template <class...> class Op,
775
          class... Args>
776
struct detector
777
{
778
    using value_t = std::false_type;
779
    using type = Default;
780
};
781
782
template <class Default, template <class...> class Op, class... Args>
783
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
784
{
785
    using value_t = std::true_type;
786
    using type = Op<Args...>;
787
};
788
789
template <template <class...> class Op, class... Args>
790
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
791
792
template <template <class...> class Op, class... Args>
793
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
794
795
template <class Default, template <class...> class Op, class... Args>
796
using detected_or = detector<Default, void, Op, Args...>;
797
798
template <class Default, template <class...> class Op, class... Args>
799
using detected_or_t = typename detected_or<Default, Op, Args...>::type;
800
801
template <class Expected, template <class...> class Op, class... Args>
802
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
803
804
template <class To, template <class...> class Op, class... Args>
805
using is_detected_convertible =
806
    std::is_convertible<detected_t<Op, Args...>, To>;
807
}  // namespace detail
808
}  // namespace nlohmann
809
810
// #include <nlohmann/json_fwd.hpp>
811
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
812
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
813
814
#include <cstdint> // int64_t, uint64_t
815
#include <map> // map
816
#include <memory> // allocator
817
#include <string> // string
818
#include <vector> // vector
819
820
/*!
821
@brief namespace for Niels Lohmann
822
@see https://github.com/nlohmann
823
@since version 1.0.0
824
*/
825
namespace nlohmann
826
{
827
/*!
828
@brief default JSONSerializer template argument
829
830
This serializer ignores the template arguments and uses ADL
831
([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
832
for serialization.
833
*/
834
template<typename T = void, typename SFINAE = void>
835
struct adl_serializer;
836
837
template<template<typename U, typename V, typename... Args> class ObjectType =
838
         std::map,
839
         template<typename U, typename... Args> class ArrayType = std::vector,
840
         class StringType = std::string, class BooleanType = bool,
841
         class NumberIntegerType = std::int64_t,
842
         class NumberUnsignedType = std::uint64_t,
843
         class NumberFloatType = double,
844
         template<typename U> class AllocatorType = std::allocator,
845
         template<typename T, typename SFINAE = void> class JSONSerializer =
846
         adl_serializer>
847
class basic_json;
848
849
/*!
850
@brief JSON Pointer
851
852
A JSON pointer defines a string syntax for identifying a specific value
853
within a JSON document. It can be used with functions `at` and
854
`operator[]`. Furthermore, JSON pointers are the base for JSON patches.
855
856
@sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
857
858
@since version 2.0.0
859
*/
860
template<typename BasicJsonType>
861
class json_pointer;
862
863
/*!
864
@brief default JSON class
865
866
This type is the default specialization of the @ref basic_json class which
867
uses the standard template types.
868
869
@since version 1.0.0
870
*/
871
using json = basic_json<>;
872
}  // namespace nlohmann
873
874
#endif  // INCLUDE_NLOHMANN_JSON_FWD_HPP_
875
876
877
namespace nlohmann
878
{
879
/*!
880
@brief detail namespace with internal helper functions
881
882
This namespace collects functions that should not be exposed,
883
implementations of some @ref basic_json methods, and meta-programming helpers.
884
885
@since version 2.1.0
886
*/
887
namespace detail
888
{
889
/////////////
890
// helpers //
891
/////////////
892
893
// Note to maintainers:
894
//
895
// Every trait in this file expects a non CV-qualified type.
896
// The only exceptions are in the 'aliases for detected' section
897
// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
898
//
899
// In this case, T has to be properly CV-qualified to constraint the function arguments
900
// (e.g. to_json(BasicJsonType&, const T&))
901
902
template<typename> struct is_basic_json : std::false_type {};
903
904
NLOHMANN_BASIC_JSON_TPL_DECLARATION
905
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
906
907
//////////////////////////
908
// aliases for detected //
909
//////////////////////////
910
911
template <typename T>
912
using mapped_type_t = typename T::mapped_type;
913
914
template <typename T>
915
using key_type_t = typename T::key_type;
916
917
template <typename T>
918
using value_type_t = typename T::value_type;
919
920
template <typename T>
921
using difference_type_t = typename T::difference_type;
922
923
template <typename T>
924
using pointer_t = typename T::pointer;
925
926
template <typename T>
927
using reference_t = typename T::reference;
928
929
template <typename T>
930
using iterator_category_t = typename T::iterator_category;
931
932
template <typename T>
933
using iterator_t = typename T::iterator;
934
935
template <typename T, typename... Args>
936
using to_json_function = decltype(T::to_json(std::declval<Args>()...));
937
938
template <typename T, typename... Args>
939
using from_json_function = decltype(T::from_json(std::declval<Args>()...));
940
941
template <typename T, typename U>
942
using get_template_function = decltype(std::declval<T>().template get<U>());
943
944
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
945
template <typename BasicJsonType, typename T, typename = void>
946
struct has_from_json : std::false_type {};
947
948
template <typename BasicJsonType, typename T>
949
struct has_from_json<BasicJsonType, T,
950
           enable_if_t<not is_basic_json<T>::value>>
951
{
952
    using serializer = typename BasicJsonType::template json_serializer<T, void>;
953
954
    static constexpr bool value =
955
        is_detected_exact<void, from_json_function, serializer,
956
        const BasicJsonType&, T&>::value;
957
};
958
959
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
960
// this overload is used for non-default-constructible user-defined-types
961
template <typename BasicJsonType, typename T, typename = void>
962
struct has_non_default_from_json : std::false_type {};
963
964
template<typename BasicJsonType, typename T>
965
struct has_non_default_from_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
966
{
967
    using serializer = typename BasicJsonType::template json_serializer<T, void>;
968
969
    static constexpr bool value =
970
        is_detected_exact<T, from_json_function, serializer,
971
        const BasicJsonType&>::value;
972
};
973
974
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
975
// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
976
template <typename BasicJsonType, typename T, typename = void>
977
struct has_to_json : std::false_type {};
978
979
template <typename BasicJsonType, typename T>
980
struct has_to_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
981
{
982
    using serializer = typename BasicJsonType::template json_serializer<T, void>;
983
984
    static constexpr bool value =
985
        is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
986
        T>::value;
987
};
988
989
990
///////////////////
991
// is_ functions //
992
///////////////////
993
994
template <typename T, typename = void>
995
struct is_iterator_traits : std::false_type {};
996
997
template <typename T>
998
struct is_iterator_traits<iterator_traits<T>>
999
{
1000
  private:
1001
    using traits = iterator_traits<T>;
1002
1003
  public:
1004
    static constexpr auto value =
1005
        is_detected<value_type_t, traits>::value &&
1006
        is_detected<difference_type_t, traits>::value &&
1007
        is_detected<pointer_t, traits>::value &&
1008
        is_detected<iterator_category_t, traits>::value &&
1009
        is_detected<reference_t, traits>::value;
1010
};
1011
1012
// source: https://stackoverflow.com/a/37193089/4116453
1013
1014
template <typename T, typename = void>
1015
struct is_complete_type : std::false_type {};
1016
1017
template <typename T>
1018
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
1019
1020
template <typename BasicJsonType, typename CompatibleObjectType,
1021
          typename = void>
1022
struct is_compatible_object_type_impl : std::false_type {};
1023
1024
template <typename BasicJsonType, typename CompatibleObjectType>
1025
struct is_compatible_object_type_impl <
1026
    BasicJsonType, CompatibleObjectType,
1027
    enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value and
1028
    is_detected<key_type_t, CompatibleObjectType>::value >>
1029
{
1030
1031
    using object_t = typename BasicJsonType::object_t;
1032
1033
    // macOS's is_constructible does not play well with nonesuch...
1034
    static constexpr bool value =
1035
        std::is_constructible<typename object_t::key_type,
1036
        typename CompatibleObjectType::key_type>::value and
1037
        std::is_constructible<typename object_t::mapped_type,
1038
        typename CompatibleObjectType::mapped_type>::value;
1039
};
1040
1041
template <typename BasicJsonType, typename CompatibleObjectType>
1042
struct is_compatible_object_type
1043
    : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
1044
1045
template <typename BasicJsonType, typename ConstructibleObjectType,
1046
          typename = void>
1047
struct is_constructible_object_type_impl : std::false_type {};
1048
1049
template <typename BasicJsonType, typename ConstructibleObjectType>
1050
struct is_constructible_object_type_impl <
1051
    BasicJsonType, ConstructibleObjectType,
1052
    enable_if_t<is_detected<mapped_type_t, ConstructibleObjectType>::value and
1053
    is_detected<key_type_t, ConstructibleObjectType>::value >>
1054
{
1055
    using object_t = typename BasicJsonType::object_t;
1056
1057
    static constexpr bool value =
1058
        (std::is_constructible<typename ConstructibleObjectType::key_type, typename object_t::key_type>::value and
1059
         std::is_same<typename object_t::mapped_type, typename ConstructibleObjectType::mapped_type>::value) or
1060
        (has_from_json<BasicJsonType, typename ConstructibleObjectType::mapped_type>::value or
1061
         has_non_default_from_json<BasicJsonType, typename ConstructibleObjectType::mapped_type >::value);
1062
};
1063
1064
template <typename BasicJsonType, typename ConstructibleObjectType>
1065
struct is_constructible_object_type
1066
    : is_constructible_object_type_impl<BasicJsonType,
1067
      ConstructibleObjectType> {};
1068
1069
template <typename BasicJsonType, typename CompatibleStringType,
1070
          typename = void>
1071
struct is_compatible_string_type_impl : std::false_type {};
1072
1073
template <typename BasicJsonType, typename CompatibleStringType>
1074
struct is_compatible_string_type_impl <
1075
    BasicJsonType, CompatibleStringType,
1076
    enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
1077
    value_type_t, CompatibleStringType>::value >>
1078
{
1079
    static constexpr auto value =
1080
        std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
1081
};
1082
1083
template <typename BasicJsonType, typename ConstructibleStringType>
1084
struct is_compatible_string_type
1085
    : is_compatible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
1086
1087
template <typename BasicJsonType, typename ConstructibleStringType,
1088
          typename = void>
1089
struct is_constructible_string_type_impl : std::false_type {};
1090
1091
template <typename BasicJsonType, typename ConstructibleStringType>
1092
struct is_constructible_string_type_impl <
1093
    BasicJsonType, ConstructibleStringType,
1094
    enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
1095
    value_type_t, ConstructibleStringType>::value >>
1096
{
1097
    static constexpr auto value =
1098
        std::is_constructible<ConstructibleStringType,
1099
        typename BasicJsonType::string_t>::value;
1100
};
1101
1102
template <typename BasicJsonType, typename ConstructibleStringType>
1103
struct is_constructible_string_type
1104
    : is_constructible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
1105
1106
template <typename BasicJsonType, typename CompatibleArrayType, typename = void>
1107
struct is_compatible_array_type_impl : std::false_type {};
1108
1109
template <typename BasicJsonType, typename CompatibleArrayType>
1110
struct is_compatible_array_type_impl <
1111
    BasicJsonType, CompatibleArrayType,
1112
    enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and
1113
    is_detected<iterator_t, CompatibleArrayType>::value and
1114
// This is needed because json_reverse_iterator has a ::iterator type...
1115
// Therefore it is detected as a CompatibleArrayType.
1116
// The real fix would be to have an Iterable concept.
1117
    not is_iterator_traits<
1118
    iterator_traits<CompatibleArrayType>>::value >>
1119
{
1120
    static constexpr bool value =
1121
        std::is_constructible<BasicJsonType,
1122
        typename CompatibleArrayType::value_type>::value;
1123
};
1124
1125
template <typename BasicJsonType, typename CompatibleArrayType>
1126
struct is_compatible_array_type
1127
    : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
1128
1129
template <typename BasicJsonType, typename ConstructibleArrayType, typename = void>
1130
struct is_constructible_array_type_impl : std::false_type {};
1131
1132
template <typename BasicJsonType, typename ConstructibleArrayType>
1133
struct is_constructible_array_type_impl <
1134
    BasicJsonType, ConstructibleArrayType,
1135
    enable_if_t<std::is_same<ConstructibleArrayType,
1136
    typename BasicJsonType::value_type>::value >>
1137
            : std::true_type {};
1138
1139
template <typename BasicJsonType, typename ConstructibleArrayType>
1140
struct is_constructible_array_type_impl <
1141
    BasicJsonType, ConstructibleArrayType,
1142
    enable_if_t<not std::is_same<ConstructibleArrayType,
1143
    typename BasicJsonType::value_type>::value and
1144
    is_detected<value_type_t, ConstructibleArrayType>::value and
1145
    is_detected<iterator_t, ConstructibleArrayType>::value and
1146
    is_complete_type<
1147
    detected_t<value_type_t, ConstructibleArrayType>>::value >>
1148
{
1149
    static constexpr bool value =
1150
        // This is needed because json_reverse_iterator has a ::iterator type,
1151
        // furthermore, std::back_insert_iterator (and other iterators) have a base class `iterator`...
1152
        // Therefore it is detected as a ConstructibleArrayType.
1153
        // The real fix would be to have an Iterable concept.
1154
        not is_iterator_traits <
1155
        iterator_traits<ConstructibleArrayType >>::value and
1156
1157
        (std::is_same<typename ConstructibleArrayType::value_type, typename BasicJsonType::array_t::value_type>::value or
1158
         has_from_json<BasicJsonType,
1159
         typename ConstructibleArrayType::value_type>::value or
1160
         has_non_default_from_json <
1161
         BasicJsonType, typename ConstructibleArrayType::value_type >::value);
1162
};
1163
1164
template <typename BasicJsonType, typename ConstructibleArrayType>
1165
struct is_constructible_array_type
1166
    : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
1167
1168
template <typename RealIntegerType, typename CompatibleNumberIntegerType,
1169
          typename = void>
1170
struct is_compatible_integer_type_impl : std::false_type {};
1171
1172
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
1173
struct is_compatible_integer_type_impl <
1174
    RealIntegerType, CompatibleNumberIntegerType,
1175
    enable_if_t<std::is_integral<RealIntegerType>::value and
1176
    std::is_integral<CompatibleNumberIntegerType>::value and
1177
    not std::is_same<bool, CompatibleNumberIntegerType>::value >>
1178
{
1179
    // is there an assert somewhere on overflows?
1180
    using RealLimits = std::numeric_limits<RealIntegerType>;
1181
    using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
1182
1183
    static constexpr auto value =
1184
        std::is_constructible<RealIntegerType,
1185
        CompatibleNumberIntegerType>::value and
1186
        CompatibleLimits::is_integer and
1187
        RealLimits::is_signed == CompatibleLimits::is_signed;
1188
};
1189
1190
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
1191
struct is_compatible_integer_type
1192
    : is_compatible_integer_type_impl<RealIntegerType,
1193
      CompatibleNumberIntegerType> {};
1194
1195
template <typename BasicJsonType, typename CompatibleType, typename = void>
1196
struct is_compatible_type_impl: std::false_type {};
1197
1198
template <typename BasicJsonType, typename CompatibleType>
1199
struct is_compatible_type_impl <
1200
    BasicJsonType, CompatibleType,
1201
    enable_if_t<is_complete_type<CompatibleType>::value >>
1202
{
1203
    static constexpr bool value =
1204
        has_to_json<BasicJsonType, CompatibleType>::value;
1205
};
1206
1207
template <typename BasicJsonType, typename CompatibleType>
1208
struct is_compatible_type
1209
    : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
1210
}  // namespace detail
1211
}  // namespace nlohmann
1212
1213
// #include <nlohmann/detail/value_t.hpp>
1214
1215
1216
#include <array> // array
1217
#include <ciso646> // and
1218
#include <cstddef> // size_t
1219
#include <cstdint> // uint8_t
1220
#include <string> // string
1221
1222
namespace nlohmann
1223
{
1224
namespace detail
1225
{
1226
///////////////////////////
1227
// JSON type enumeration //
1228
///////////////////////////
1229
1230
/*!
1231
@brief the JSON type enumeration
1232
1233
This enumeration collects the different JSON types. It is internally used to
1234
distinguish the stored values, and the functions @ref basic_json::is_null(),
1235
@ref basic_json::is_object(), @ref basic_json::is_array(),
1236
@ref basic_json::is_string(), @ref basic_json::is_boolean(),
1237
@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
1238
@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
1239
@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
1240
@ref basic_json::is_structured() rely on it.
1241
1242
@note There are three enumeration entries (number_integer, number_unsigned, and
1243
number_float), because the library distinguishes these three types for numbers:
1244
@ref basic_json::number_unsigned_t is used for unsigned integers,
1245
@ref basic_json::number_integer_t is used for signed integers, and
1246
@ref basic_json::number_float_t is used for floating-point numbers or to
1247
approximate integers which do not fit in the limits of their respective type.
1248
1249
@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON
1250
value with the default value for a given type
1251
1252
@since version 1.0.0
1253
*/
1254
enum class value_t : std::uint8_t
1255
{
1256
    null,             ///< null value
1257
    object,           ///< object (unordered set of name/value pairs)
1258
    array,            ///< array (ordered collection of values)
1259
    string,           ///< string value
1260
    boolean,          ///< boolean value
1261
    number_integer,   ///< number value (signed integer)
1262
    number_unsigned,  ///< number value (unsigned integer)
1263
    number_float,     ///< number value (floating-point)
1264
    discarded         ///< discarded by the the parser callback function
1265
};
1266
1267
/*!
1268
@brief comparison operator for JSON types
1269
1270
Returns an ordering that is similar to Python:
1271
- order: null < boolean < number < object < array < string
1272
- furthermore, each type is not smaller than itself
1273
- discarded values are not comparable
1274
1275
@since version 1.0.0
1276
*/
1277
inline bool operator<(const value_t lhs, const value_t rhs) noexcept
1278
0
{
1279
0
    static constexpr std::array<std::uint8_t, 8> order = {{
1280
0
            0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
1281
0
            1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */
1282
0
        }
1283
0
    };
1284
0
1285
0
    const auto l_index = static_cast<std::size_t>(lhs);
1286
0
    const auto r_index = static_cast<std::size_t>(rhs);
1287
0
    return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];
1288
0
}
1289
}  // namespace detail
1290
}  // namespace nlohmann
1291
1292
1293
namespace nlohmann
1294
{
1295
namespace detail
1296
{
1297
template<typename BasicJsonType>
1298
void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
1299
{
1300
    if (JSON_UNLIKELY(not j.is_null()))
1301
    {
1302
        JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
1303
    }
1304
    n = nullptr;
1305
}
1306
1307
// overloads for basic_json template parameters
1308
template<typename BasicJsonType, typename ArithmeticType,
1309
         enable_if_t<std::is_arithmetic<ArithmeticType>::value and
1310
                     not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1311
                     int> = 0>
1312
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
1313
0
{
1314
0
    switch (static_cast<value_t>(j))
1315
0
    {
1316
0
        case value_t::number_unsigned:
1317
0
        {
1318
0
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
1319
0
            break;
1320
0
        }
1321
0
        case value_t::number_integer:
1322
0
        {
1323
0
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
1324
0
            break;
1325
0
        }
1326
0
        case value_t::number_float:
1327
0
        {
1328
0
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
1329
0
            break;
1330
0
        }
1331
1332
0
        default:
1333
0
            JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
1334
0
    }
1335
0
}
1336
1337
template<typename BasicJsonType>
1338
void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
1339
0
{
1340
0
    if (JSON_UNLIKELY(not j.is_boolean()))
1341
0
    {
1342
0
        JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
1343
0
    }
1344
0
    b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
1345
0
}
1346
1347
template<typename BasicJsonType>
1348
void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
1349
0
{
1350
0
    if (JSON_UNLIKELY(not j.is_string()))
1351
0
    {
1352
0
        JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
1353
0
    }
1354
0
    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
1355
0
}
1356
1357
template <
1358
    typename BasicJsonType, typename ConstructibleStringType,
1359
    enable_if_t <
1360
        is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value and
1361
        not std::is_same<typename BasicJsonType::string_t,
1362
                         ConstructibleStringType>::value,
1363
        int > = 0 >
1364
void from_json(const BasicJsonType& j, ConstructibleStringType& s)
1365
{
1366
    if (JSON_UNLIKELY(not j.is_string()))
1367
    {
1368
        JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
1369
    }
1370
1371
    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
1372
}
1373
1374
template<typename BasicJsonType>
1375
void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
1376
0
{
1377
0
    get_arithmetic_value(j, val);
1378
0
}
1379
1380
template<typename BasicJsonType>
1381
void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
1382
{
1383
    get_arithmetic_value(j, val);
1384
}
1385
1386
template<typename BasicJsonType>
1387
void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
1388
{
1389
    get_arithmetic_value(j, val);
1390
}
1391
1392
template<typename BasicJsonType, typename EnumType,
1393
         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
1394
void from_json(const BasicJsonType& j, EnumType& e)
1395
{
1396
    typename std::underlying_type<EnumType>::type val;
1397
    get_arithmetic_value(j, val);
1398
    e = static_cast<EnumType>(val);
1399
}
1400
1401
// forward_list doesn't have an insert method
1402
template<typename BasicJsonType, typename T, typename Allocator,
1403
         enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1404
void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
1405
{
1406
    if (JSON_UNLIKELY(not j.is_array()))
1407
    {
1408
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1409
    }
1410
    std::transform(j.rbegin(), j.rend(),
1411
                   std::front_inserter(l), [](const BasicJsonType & i)
1412
    {
1413
        return i.template get<T>();
1414
    });
1415
}
1416
1417
// valarray doesn't have an insert method
1418
template<typename BasicJsonType, typename T,
1419
         enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1420
void from_json(const BasicJsonType& j, std::valarray<T>& l)
1421
{
1422
    if (JSON_UNLIKELY(not j.is_array()))
1423
    {
1424
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1425
    }
1426
    l.resize(j.size());
1427
    std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
1428
}
1429
1430
template<typename BasicJsonType>
1431
void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
1432
{
1433
    arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
1434
}
1435
1436
template <typename BasicJsonType, typename T, std::size_t N>
1437
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
1438
                          priority_tag<2> /*unused*/)
1439
-> decltype(j.template get<T>(), void())
1440
{
1441
    for (std::size_t i = 0; i < N; ++i)
1442
    {
1443
        arr[i] = j.at(i).template get<T>();
1444
    }
1445
}
1446
1447
template<typename BasicJsonType, typename ConstructibleArrayType>
1448
auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
1449
-> decltype(
1450
    arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
1451
    j.template get<typename ConstructibleArrayType::value_type>(),
1452
    void())
1453
{
1454
    using std::end;
1455
1456
    arr.reserve(j.size());
1457
    std::transform(j.begin(), j.end(),
1458
                   std::inserter(arr, end(arr)), [](const BasicJsonType & i)
1459
    {
1460
        // get<BasicJsonType>() returns *this, this won't call a from_json
1461
        // method when value_type is BasicJsonType
1462
        return i.template get<typename ConstructibleArrayType::value_type>();
1463
    });
1464
}
1465
1466
template <typename BasicJsonType, typename ConstructibleArrayType>
1467
void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
1468
                          priority_tag<0> /*unused*/)
1469
{
1470
    using std::end;
1471
1472
    std::transform(
1473
        j.begin(), j.end(), std::inserter(arr, end(arr)),
1474
        [](const BasicJsonType & i)
1475
    {
1476
        // get<BasicJsonType>() returns *this, this won't call a from_json
1477
        // method when value_type is BasicJsonType
1478
        return i.template get<typename ConstructibleArrayType::value_type>();
1479
    });
1480
}
1481
1482
template <typename BasicJsonType, typename ConstructibleArrayType,
1483
          enable_if_t <
1484
              is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value and
1485
              not is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value and
1486
              not is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value and
1487
              not is_basic_json<ConstructibleArrayType>::value,
1488
              int > = 0 >
1489
1490
auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
1491
-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
1492
j.template get<typename ConstructibleArrayType::value_type>(),
1493
void())
1494
{
1495
    if (JSON_UNLIKELY(not j.is_array()))
1496
    {
1497
        JSON_THROW(type_error::create(302, "type must be array, but is " +
1498
                                      std::string(j.type_name())));
1499
    }
1500
1501
    from_json_array_impl(j, arr, priority_tag<3> {});
1502
}
1503
1504
template<typename BasicJsonType, typename ConstructibleObjectType,
1505
         enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
1506
void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
1507
{
1508
    if (JSON_UNLIKELY(not j.is_object()))
1509
    {
1510
        JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
1511
    }
1512
1513
    auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
1514
    using value_type = typename ConstructibleObjectType::value_type;
1515
    std::transform(
1516
        inner_object->begin(), inner_object->end(),
1517
        std::inserter(obj, obj.begin()),
1518
        [](typename BasicJsonType::object_t::value_type const & p)
1519
    {
1520
        return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
1521
    });
1522
}
1523
1524
// overload for arithmetic types, not chosen for basic_json template arguments
1525
// (BooleanType, etc..); note: Is it really necessary to provide explicit
1526
// overloads for boolean_t etc. in case of a custom BooleanType which is not
1527
// an arithmetic type?
1528
template<typename BasicJsonType, typename ArithmeticType,
1529
         enable_if_t <
1530
             std::is_arithmetic<ArithmeticType>::value and
1531
             not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
1532
             not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
1533
             not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
1534
             not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1535
             int> = 0>
1536
void from_json(const BasicJsonType& j, ArithmeticType& val)
1537
{
1538
    switch (static_cast<value_t>(j))
1539
    {
1540
        case value_t::number_unsigned:
1541
        {
1542
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
1543
            break;
1544
        }
1545
        case value_t::number_integer:
1546
        {
1547
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
1548
            break;
1549
        }
1550
        case value_t::number_float:
1551
        {
1552
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
1553
            break;
1554
        }
1555
        case value_t::boolean:
1556
        {
1557
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
1558
            break;
1559
        }
1560
1561
        default:
1562
            JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
1563
    }
1564
}
1565
1566
template<typename BasicJsonType, typename A1, typename A2>
1567
void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
1568
{
1569
    p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
1570
}
1571
1572
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
1573
void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...> /*unused*/)
1574
{
1575
    t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
1576
}
1577
1578
template<typename BasicJsonType, typename... Args>
1579
void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
1580
{
1581
    from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
1582
}
1583
1584
template <typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
1585
          typename = enable_if_t<not std::is_constructible<
1586
                                     typename BasicJsonType::string_t, Key>::value>>
1587
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
1588
{
1589
    if (JSON_UNLIKELY(not j.is_array()))
1590
    {
1591
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1592
    }
1593
    for (const auto& p : j)
1594
    {
1595
        if (JSON_UNLIKELY(not p.is_array()))
1596
        {
1597
            JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1598
        }
1599
        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1600
    }
1601
}
1602
1603
template <typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
1604
          typename = enable_if_t<not std::is_constructible<
1605
                                     typename BasicJsonType::string_t, Key>::value>>
1606
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
1607
{
1608
    if (JSON_UNLIKELY(not j.is_array()))
1609
    {
1610
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1611
    }
1612
    for (const auto& p : j)
1613
    {
1614
        if (JSON_UNLIKELY(not p.is_array()))
1615
        {
1616
            JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1617
        }
1618
        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1619
    }
1620
}
1621
1622
struct from_json_fn
1623
{
1624
    template<typename BasicJsonType, typename T>
1625
    auto operator()(const BasicJsonType& j, T& val) const
1626
    noexcept(noexcept(from_json(j, val)))
1627
    -> decltype(from_json(j, val), void())
1628
0
    {
1629
0
        return from_json(j, val);
1630
0
    }
Unexecuted instantiation: decltype ((from_json({parm#1}, {parm#2})),((void)())) nlohmann::detail::from_json_fn::operator()<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) const
Unexecuted instantiation: decltype ((from_json({parm#1}, {parm#2})),((void)())) nlohmann::detail::from_json_fn::operator()<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>, bool>(nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> const&, bool&) const
Unexecuted instantiation: decltype ((from_json({parm#1}, {parm#2})),((void)())) nlohmann::detail::from_json_fn::operator()<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>, double>(nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> const&, double&) const
1631
};
1632
}  // namespace detail
1633
1634
/// namespace to hold default `from_json` function
1635
/// to see why this is required:
1636
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
1637
namespace
1638
{
1639
constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
1640
} // namespace
1641
}  // namespace nlohmann
1642
1643
// #include <nlohmann/detail/conversions/to_json.hpp>
1644
1645
1646
#include <algorithm> // copy
1647
#include <ciso646> // or, and, not
1648
#include <iterator> // begin, end
1649
#include <string> // string
1650
#include <tuple> // tuple, get
1651
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
1652
#include <utility> // move, forward, declval, pair
1653
#include <valarray> // valarray
1654
#include <vector> // vector
1655
1656
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
1657
1658
1659
#include <cstddef> // size_t
1660
#include <iterator> // input_iterator_tag
1661
#include <string> // string, to_string
1662
#include <tuple> // tuple_size, get, tuple_element
1663
1664
// #include <nlohmann/detail/meta/type_traits.hpp>
1665
1666
// #include <nlohmann/detail/value_t.hpp>
1667
1668
1669
namespace nlohmann
1670
{
1671
namespace detail
1672
{
1673
template <typename IteratorType> class iteration_proxy_value
1674
{
1675
  public:
1676
    using difference_type = std::ptrdiff_t;
1677
    using value_type = iteration_proxy_value;
1678
    using pointer = value_type * ;
1679
    using reference = value_type & ;
1680
    using iterator_category = std::input_iterator_tag;
1681
1682
  private:
1683
    /// the iterator
1684
    IteratorType anchor;
1685
    /// an index for arrays (used to create key names)
1686
    std::size_t array_index = 0;
1687
    /// last stringified array index
1688
    mutable std::size_t array_index_last = 0;
1689
    /// a string representation of the array index
1690
    mutable std::string array_index_str = "0";
1691
    /// an empty string (to return a reference for primitive values)
1692
    const std::string empty_str = "";
1693
1694
  public:
1695
    explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {}
1696
1697
    /// dereference operator (needed for range-based for)
1698
    iteration_proxy_value& operator*()
1699
    {
1700
        return *this;
1701
    }
1702
1703
    /// increment operator (needed for range-based for)
1704
    iteration_proxy_value& operator++()
1705
    {
1706
        ++anchor;
1707
        ++array_index;
1708
1709
        return *this;
1710
    }
1711
1712
    /// equality operator (needed for InputIterator)
1713
    bool operator==(const iteration_proxy_value& o) const
1714
    {
1715
        return anchor == o.anchor;
1716
    }
1717
1718
    /// inequality operator (needed for range-based for)
1719
    bool operator!=(const iteration_proxy_value& o) const
1720
    {
1721
        return anchor != o.anchor;
1722
    }
1723
1724
    /// return key of the iterator
1725
    const std::string& key() const
1726
    {
1727
        assert(anchor.m_object != nullptr);
1728
1729
        switch (anchor.m_object->type())
1730
        {
1731
            // use integer array index as key
1732
            case value_t::array:
1733
            {
1734
                if (array_index != array_index_last)
1735
                {
1736
                    array_index_str = std::to_string(array_index);
1737
                    array_index_last = array_index;
1738
                }
1739
                return array_index_str;
1740
            }
1741
1742
            // use key from the object
1743
            case value_t::object:
1744
                return anchor.key();
1745
1746
            // use an empty key for all primitive types
1747
            default:
1748
                return empty_str;
1749
        }
1750
    }
1751
1752
    /// return value of the iterator
1753
    typename IteratorType::reference value() const
1754
    {
1755
        return anchor.value();
1756
    }
1757
};
1758
1759
/// proxy class for the items() function
1760
template<typename IteratorType> class iteration_proxy
1761
{
1762
  private:
1763
    /// the container to iterate
1764
    typename IteratorType::reference container;
1765
1766
  public:
1767
    /// construct iteration proxy from a container
1768
    explicit iteration_proxy(typename IteratorType::reference cont) noexcept
1769
        : container(cont) {}
1770
1771
    /// return iterator begin (needed for range-based for)
1772
    iteration_proxy_value<IteratorType> begin() noexcept
1773
    {
1774
        return iteration_proxy_value<IteratorType>(container.begin());
1775
    }
1776
1777
    /// return iterator end (needed for range-based for)
1778
    iteration_proxy_value<IteratorType> end() noexcept
1779
    {
1780
        return iteration_proxy_value<IteratorType>(container.end());
1781
    }
1782
};
1783
// Structured Bindings Support
1784
// For further reference see https://blog.tartanllama.xyz/structured-bindings/
1785
// And see https://github.com/nlohmann/json/pull/1391
1786
template <std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
1787
auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
1788
{
1789
    return i.key();
1790
}
1791
// Structured Bindings Support
1792
// For further reference see https://blog.tartanllama.xyz/structured-bindings/
1793
// And see https://github.com/nlohmann/json/pull/1391
1794
template <std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
1795
auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
1796
{
1797
    return i.value();
1798
}
1799
}  // namespace detail
1800
}  // namespace nlohmann
1801
1802
// The Addition to the STD Namespace is required to add
1803
// Structured Bindings Support to the iteration_proxy_value class
1804
// For further reference see https://blog.tartanllama.xyz/structured-bindings/
1805
// And see https://github.com/nlohmann/json/pull/1391
1806
namespace std
1807
{
1808
#if defined(__clang__)
1809
    // Fix: https://github.com/nlohmann/json/issues/1401
1810
    #pragma clang diagnostic push
1811
    #pragma clang diagnostic ignored "-Wmismatched-tags"
1812
#endif
1813
template <typename IteratorType>
1814
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
1815
            : public std::integral_constant<std::size_t, 2> {};
1816
1817
template <std::size_t N, typename IteratorType>
1818
class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
1819
{
1820
  public:
1821
    using type = decltype(
1822
                     get<N>(std::declval <
1823
                            ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
1824
};
1825
#if defined(__clang__)
1826
    #pragma clang diagnostic pop
1827
#endif
1828
} // namespace std
1829
1830
// #include <nlohmann/detail/meta/cpp_future.hpp>
1831
1832
// #include <nlohmann/detail/meta/type_traits.hpp>
1833
1834
// #include <nlohmann/detail/value_t.hpp>
1835
1836
1837
namespace nlohmann
1838
{
1839
namespace detail
1840
{
1841
//////////////////
1842
// constructors //
1843
//////////////////
1844
1845
template<value_t> struct external_constructor;
1846
1847
template<>
1848
struct external_constructor<value_t::boolean>
1849
{
1850
    template<typename BasicJsonType>
1851
    static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
1852
0
    {
1853
0
        j.m_type = value_t::boolean;
1854
0
        j.m_value = b;
1855
0
        j.assert_invariant();
1856
0
    }
1857
};
1858
1859
template<>
1860
struct external_constructor<value_t::string>
1861
{
1862
    template<typename BasicJsonType>
1863
    static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
1864
0
    {
1865
0
        j.m_type = value_t::string;
1866
0
        j.m_value = s;
1867
0
        j.assert_invariant();
1868
0
    }
1869
1870
    template<typename BasicJsonType>
1871
    static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
1872
    {
1873
        j.m_type = value_t::string;
1874
        j.m_value = std::move(s);
1875
        j.assert_invariant();
1876
    }
1877
1878
    template<typename BasicJsonType, typename CompatibleStringType,
1879
             enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
1880
                         int> = 0>
1881
    static void construct(BasicJsonType& j, const CompatibleStringType& str)
1882
    {
1883
        j.m_type = value_t::string;
1884
        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
1885
        j.assert_invariant();
1886
    }
1887
};
1888
1889
template<>
1890
struct external_constructor<value_t::number_float>
1891
{
1892
    template<typename BasicJsonType>
1893
    static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
1894
0
    {
1895
0
        j.m_type = value_t::number_float;
1896
0
        j.m_value = val;
1897
0
        j.assert_invariant();
1898
0
    }
1899
};
1900
1901
template<>
1902
struct external_constructor<value_t::number_unsigned>
1903
{
1904
    template<typename BasicJsonType>
1905
    static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
1906
0
    {
1907
0
        j.m_type = value_t::number_unsigned;
1908
0
        j.m_value = val;
1909
0
        j.assert_invariant();
1910
0
    }
1911
};
1912
1913
template<>
1914
struct external_constructor<value_t::number_integer>
1915
{
1916
    template<typename BasicJsonType>
1917
    static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
1918
0
    {
1919
0
        j.m_type = value_t::number_integer;
1920
0
        j.m_value = val;
1921
0
        j.assert_invariant();
1922
0
    }
1923
};
1924
1925
template<>
1926
struct external_constructor<value_t::array>
1927
{
1928
    template<typename BasicJsonType>
1929
    static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
1930
    {
1931
        j.m_type = value_t::array;
1932
        j.m_value = arr;
1933
        j.assert_invariant();
1934
    }
1935
1936
    template<typename BasicJsonType>
1937
    static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
1938
    {
1939
        j.m_type = value_t::array;
1940
        j.m_value = std::move(arr);
1941
        j.assert_invariant();
1942
    }
1943
1944
    template<typename BasicJsonType, typename CompatibleArrayType,
1945
             enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
1946
                         int> = 0>
1947
    static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
1948
    {
1949
        using std::begin;
1950
        using std::end;
1951
        j.m_type = value_t::array;
1952
        j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
1953
        j.assert_invariant();
1954
    }
1955
1956
    template<typename BasicJsonType>
1957
    static void construct(BasicJsonType& j, const std::vector<bool>& arr)
1958
    {
1959
        j.m_type = value_t::array;
1960
        j.m_value = value_t::array;
1961
        j.m_value.array->reserve(arr.size());
1962
        for (const bool x : arr)
1963
        {
1964
            j.m_value.array->push_back(x);
1965
        }
1966
        j.assert_invariant();
1967
    }
1968
1969
    template<typename BasicJsonType, typename T,
1970
             enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
1971
    static void construct(BasicJsonType& j, const std::valarray<T>& arr)
1972
    {
1973
        j.m_type = value_t::array;
1974
        j.m_value = value_t::array;
1975
        j.m_value.array->resize(arr.size());
1976
        std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
1977
        j.assert_invariant();
1978
    }
1979
};
1980
1981
template<>
1982
struct external_constructor<value_t::object>
1983
{
1984
    template<typename BasicJsonType>
1985
    static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
1986
    {
1987
        j.m_type = value_t::object;
1988
        j.m_value = obj;
1989
        j.assert_invariant();
1990
    }
1991
1992
    template<typename BasicJsonType>
1993
    static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
1994
    {
1995
        j.m_type = value_t::object;
1996
        j.m_value = std::move(obj);
1997
        j.assert_invariant();
1998
    }
1999
2000
    template<typename BasicJsonType, typename CompatibleObjectType,
2001
             enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
2002
    static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
2003
    {
2004
        using std::begin;
2005
        using std::end;
2006
2007
        j.m_type = value_t::object;
2008
        j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
2009
        j.assert_invariant();
2010
    }
2011
};
2012
2013
/////////////
2014
// to_json //
2015
/////////////
2016
2017
template<typename BasicJsonType, typename T,
2018
         enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
2019
void to_json(BasicJsonType& j, T b) noexcept
2020
0
{
2021
0
    external_constructor<value_t::boolean>::construct(j, b);
2022
0
}
2023
2024
template<typename BasicJsonType, typename CompatibleString,
2025
         enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
2026
void to_json(BasicJsonType& j, const CompatibleString& s)
2027
0
{
2028
0
    external_constructor<value_t::string>::construct(j, s);
2029
0
}
2030
2031
template<typename BasicJsonType>
2032
void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
2033
{
2034
    external_constructor<value_t::string>::construct(j, std::move(s));
2035
}
2036
2037
template<typename BasicJsonType, typename FloatType,
2038
         enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
2039
void to_json(BasicJsonType& j, FloatType val) noexcept
2040
0
{
2041
0
    external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
2042
0
}
2043
2044
template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
2045
         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
2046
void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
2047
0
{
2048
0
    external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
2049
0
}
2050
2051
template<typename BasicJsonType, typename CompatibleNumberIntegerType,
2052
         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
2053
void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
2054
0
{
2055
0
    external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
2056
0
}
2057
2058
template<typename BasicJsonType, typename EnumType,
2059
         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
2060
void to_json(BasicJsonType& j, EnumType e) noexcept
2061
{
2062
    using underlying_type = typename std::underlying_type<EnumType>::type;
2063
    external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
2064
}
2065
2066
template<typename BasicJsonType>
2067
void to_json(BasicJsonType& j, const std::vector<bool>& e)
2068
{
2069
    external_constructor<value_t::array>::construct(j, e);
2070
}
2071
2072
template <typename BasicJsonType, typename CompatibleArrayType,
2073
          enable_if_t<is_compatible_array_type<BasicJsonType,
2074
                      CompatibleArrayType>::value and
2075
                      not is_compatible_object_type<
2076
                          BasicJsonType, CompatibleArrayType>::value and
2077
                      not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
2078
                      not is_basic_json<CompatibleArrayType>::value,
2079
                      int> = 0>
2080
void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
2081
{
2082
    external_constructor<value_t::array>::construct(j, arr);
2083
}
2084
2085
template<typename BasicJsonType, typename T,
2086
         enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
2087
void to_json(BasicJsonType& j, const std::valarray<T>& arr)
2088
{
2089
    external_constructor<value_t::array>::construct(j, std::move(arr));
2090
}
2091
2092
template<typename BasicJsonType>
2093
void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
2094
{
2095
    external_constructor<value_t::array>::construct(j, std::move(arr));
2096
}
2097
2098
template<typename BasicJsonType, typename CompatibleObjectType,
2099
         enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0>
2100
void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
2101
{
2102
    external_constructor<value_t::object>::construct(j, obj);
2103
}
2104
2105
template<typename BasicJsonType>
2106
void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
2107
{
2108
    external_constructor<value_t::object>::construct(j, std::move(obj));
2109
}
2110
2111
template <
2112
    typename BasicJsonType, typename T, std::size_t N,
2113
    enable_if_t<not std::is_constructible<typename BasicJsonType::string_t,
2114
                const T(&)[N]>::value,
2115
                int> = 0 >
2116
void to_json(BasicJsonType& j, const T(&arr)[N])
2117
{
2118
    external_constructor<value_t::array>::construct(j, arr);
2119
}
2120
2121
template<typename BasicJsonType, typename... Args>
2122
void to_json(BasicJsonType& j, const std::pair<Args...>& p)
2123
{
2124
    j = { p.first, p.second };
2125
}
2126
2127
// for https://github.com/nlohmann/json/pull/1134
2128
template < typename BasicJsonType, typename T,
2129
           enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
2130
void to_json(BasicJsonType& j, const T& b)
2131
{
2132
    j = { {b.key(), b.value()} };
2133
}
2134
2135
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
2136
void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
2137
{
2138
    j = { std::get<Idx>(t)... };
2139
}
2140
2141
template<typename BasicJsonType, typename... Args>
2142
void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
2143
{
2144
    to_json_tuple_impl(j, t, index_sequence_for<Args...> {});
2145
}
2146
2147
struct to_json_fn
2148
{
2149
    template<typename BasicJsonType, typename T>
2150
    auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
2151
    -> decltype(to_json(j, std::forward<T>(val)), void())
2152
0
    {
2153
0
        return to_json(j, std::forward<T>(val));
2154
0
    }
Unexecuted instantiation: _ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonINSt3__13mapENS4_6vectorENS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEblmdSA_NS_14adl_serializerEEERSC_EEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSG_
Unexecuted instantiation: _ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonINSt3__13mapENS4_6vectorENS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEblmdSA_NS_14adl_serializerEEERdEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSG_
Unexecuted instantiation: _ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonINSt3__13mapENS4_6vectorENS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEblmdSA_NS_14adl_serializerEEERbEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSG_
Unexecuted instantiation: _ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonINSt3__13mapENS4_6vectorENS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEblmdSA_NS_14adl_serializerEEERlEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSG_
Unexecuted instantiation: _ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonINSt3__13mapENS4_6vectorENS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEblmdSA_NS_14adl_serializerEEERmEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSG_
2155
};
2156
}  // namespace detail
2157
2158
/// namespace to hold default `to_json` function
2159
namespace
2160
{
2161
constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
2162
} // namespace
2163
}  // namespace nlohmann
2164
2165
2166
namespace nlohmann
2167
{
2168
2169
template<typename, typename>
2170
struct adl_serializer
2171
{
2172
    /*!
2173
    @brief convert a JSON value to any value type
2174
2175
    This function is usually called by the `get()` function of the
2176
    @ref basic_json class (either explicit or via conversion operators).
2177
2178
    @param[in] j        JSON value to read from
2179
    @param[in,out] val  value to write to
2180
    */
2181
    template<typename BasicJsonType, typename ValueType>
2182
    static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(
2183
        noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
2184
    -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
2185
0
    {
2186
0
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
2187
0
    }
Unexecuted instantiation: _ZN8nlohmann14adl_serializerINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEvE9from_jsonIRKNS_10basic_jsonINS1_3mapENS1_6vectorES7_blmdS5_S0_EES7_EEDTcmclL_ZNS_12_GLOBAL__N_19from_jsonEEclsr3stdE7forwardIT_Efp_Efp0_Ecvv_EEOSH_RT0_
Unexecuted instantiation: _ZN8nlohmann14adl_serializerIbvE9from_jsonIRKNS_10basic_jsonINSt3__13mapENS4_6vectorENS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEblmdSA_S0_EEbEEDTcmclL_ZNS_12_GLOBAL__N_19from_jsonEEclsr3stdE7forwardIT_Efp_Efp0_Ecvv_EEOSH_RT0_
Unexecuted instantiation: _ZN8nlohmann14adl_serializerIdvE9from_jsonIRKNS_10basic_jsonINSt3__13mapENS4_6vectorENS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEblmdSA_S0_EEdEEDTcmclL_ZNS_12_GLOBAL__N_19from_jsonEEclsr3stdE7forwardIT_Efp_Efp0_Ecvv_EEOSH_RT0_
2188
2189
    /*!
2190
    @brief convert any value type to a JSON value
2191
2192
    This function is usually called by the constructors of the @ref basic_json
2193
    class.
2194
2195
    @param[in,out] j  JSON value to write to
2196
    @param[in] val    value to read from
2197
    */
2198
    template <typename BasicJsonType, typename ValueType>
2199
    static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
2200
        noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
2201
    -> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)), void())
2202
0
    {
2203
0
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
2204
0
    }
Unexecuted instantiation: _ZN8nlohmann14adl_serializerINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEvE7to_jsonINS_10basic_jsonINS1_3mapENS1_6vectorES7_blmdS5_S0_EERS7_EEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSG_
Unexecuted instantiation: _ZN8nlohmann14adl_serializerIdvE7to_jsonINS_10basic_jsonINSt3__13mapENS4_6vectorENS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEblmdSA_S0_EERdEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSG_
Unexecuted instantiation: _ZN8nlohmann14adl_serializerIbvE7to_jsonINS_10basic_jsonINSt3__13mapENS4_6vectorENS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEblmdSA_S0_EERbEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSG_
Unexecuted instantiation: _ZN8nlohmann14adl_serializerIlvE7to_jsonINS_10basic_jsonINSt3__13mapENS4_6vectorENS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEblmdSA_S0_EERlEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSG_
Unexecuted instantiation: _ZN8nlohmann14adl_serializerImvE7to_jsonINS_10basic_jsonINSt3__13mapENS4_6vectorENS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEblmdSA_S0_EERmEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSG_
2205
};
2206
2207
}  // namespace nlohmann
2208
2209
// #include <nlohmann/detail/conversions/from_json.hpp>
2210
2211
// #include <nlohmann/detail/conversions/to_json.hpp>
2212
2213
// #include <nlohmann/detail/exceptions.hpp>
2214
2215
// #include <nlohmann/detail/input/binary_reader.hpp>
2216
2217
2218
#include <algorithm> // generate_n
2219
#include <array> // array
2220
#include <cassert> // assert
2221
#include <cmath> // ldexp
2222
#include <cstddef> // size_t
2223
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
2224
#include <cstdio> // snprintf
2225
#include <cstring> // memcpy
2226
#include <iterator> // back_inserter
2227
#include <limits> // numeric_limits
2228
#include <string> // char_traits, string
2229
#include <utility> // make_pair, move
2230
2231
// #include <nlohmann/detail/exceptions.hpp>
2232
2233
// #include <nlohmann/detail/input/input_adapters.hpp>
2234
2235
2236
#include <array> // array
2237
#include <cassert> // assert
2238
#include <cstddef> // size_t
2239
#include <cstdio> //FILE *
2240
#include <cstring> // strlen
2241
#include <istream> // istream
2242
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
2243
#include <memory> // shared_ptr, make_shared, addressof
2244
#include <numeric> // accumulate
2245
#include <string> // string, char_traits
2246
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
2247
#include <utility> // pair, declval
2248
2249
// #include <nlohmann/detail/iterators/iterator_traits.hpp>
2250
2251
// #include <nlohmann/detail/macro_scope.hpp>
2252
2253
2254
namespace nlohmann
2255
{
2256
namespace detail
2257
{
2258
/// the supported input formats
2259
enum class input_format_t { json, cbor, msgpack, ubjson, bson };
2260
2261
////////////////////
2262
// input adapters //
2263
////////////////////
2264
2265
/*!
2266
@brief abstract input adapter interface
2267
2268
Produces a stream of std::char_traits<char>::int_type characters from a
2269
std::istream, a buffer, or some other input type. Accepts the return of
2270
exactly one non-EOF character for future input. The int_type characters
2271
returned consist of all valid char values as positive values (typically
2272
unsigned char), plus an EOF value outside that range, specified by the value
2273
of the function std::char_traits<char>::eof(). This value is typically -1, but
2274
could be any arbitrary value which is not a valid char value.
2275
*/
2276
struct input_adapter_protocol
2277
{
2278
    /// get a character [0,255] or std::char_traits<char>::eof().
2279
    virtual std::char_traits<char>::int_type get_character() = 0;
2280
0
    virtual ~input_adapter_protocol() = default;
2281
};
2282
2283
/// a type to simplify interfaces
2284
using input_adapter_t = std::shared_ptr<input_adapter_protocol>;
2285
2286
/*!
2287
Input adapter for stdio file access. This adapter read only 1 byte and do not use any
2288
 buffer. This adapter is a very low level adapter.
2289
*/
2290
class file_input_adapter : public input_adapter_protocol
2291
{
2292
  public:
2293
    explicit file_input_adapter(std::FILE* f)  noexcept
2294
        : m_file(f)
2295
0
    {}
2296
2297
    // make class move-only
2298
    file_input_adapter(const file_input_adapter&) = delete;
2299
    file_input_adapter(file_input_adapter&&) = default;
2300
    file_input_adapter& operator=(const file_input_adapter&) = delete;
2301
    file_input_adapter& operator=(file_input_adapter&&) = default;
2302
    ~file_input_adapter() override = default;
2303
2304
    std::char_traits<char>::int_type get_character() noexcept override
2305
0
    {
2306
0
        return std::fgetc(m_file);
2307
0
    }
2308
2309
  private:
2310
    /// the file pointer to read from
2311
    std::FILE* m_file;
2312
};
2313
2314
2315
/*!
2316
Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
2317
beginning of input. Does not support changing the underlying std::streambuf
2318
in mid-input. Maintains underlying std::istream and std::streambuf to support
2319
subsequent use of standard std::istream operations to process any input
2320
characters following those used in parsing the JSON input.  Clears the
2321
std::istream flags; any input errors (e.g., EOF) will be detected by the first
2322
subsequent call for input from the std::istream.
2323
*/
2324
class input_stream_adapter : public input_adapter_protocol
2325
{
2326
  public:
2327
    ~input_stream_adapter() override
2328
0
    {
2329
0
        // clear stream flags; we use underlying streambuf I/O, do not
2330
0
        // maintain ifstream flags, except eof
2331
0
        is.clear(is.rdstate() & std::ios::eofbit);
2332
0
    }
2333
2334
    explicit input_stream_adapter(std::istream& i)
2335
        : is(i), sb(*i.rdbuf())
2336
0
    {}
2337
2338
    // delete because of pointer members
2339
    input_stream_adapter(const input_stream_adapter&) = delete;
2340
    input_stream_adapter& operator=(input_stream_adapter&) = delete;
2341
    input_stream_adapter(input_stream_adapter&&) = delete;
2342
    input_stream_adapter& operator=(input_stream_adapter&&) = delete;
2343
2344
    // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
2345
    // ensure that std::char_traits<char>::eof() and the character 0xFF do not
2346
    // end up as the same value, eg. 0xFFFFFFFF.
2347
    std::char_traits<char>::int_type get_character() override
2348
0
    {
2349
0
        auto res = sb.sbumpc();
2350
0
        // set eof manually, as we don't use the istream interface.
2351
0
        if (res == EOF)
2352
0
        {
2353
0
            is.clear(is.rdstate() | std::ios::eofbit);
2354
0
        }
2355
0
        return res;
2356
0
    }
2357
2358
  private:
2359
    /// the associated input stream
2360
    std::istream& is;
2361
    std::streambuf& sb;
2362
};
2363
2364
/// input adapter for buffer input
2365
class input_buffer_adapter : public input_adapter_protocol
2366
{
2367
  public:
2368
    input_buffer_adapter(const char* b, const std::size_t l) noexcept
2369
        : cursor(b), limit(b + l)
2370
0
    {}
2371
2372
    // delete because of pointer members
2373
    input_buffer_adapter(const input_buffer_adapter&) = delete;
2374
    input_buffer_adapter& operator=(input_buffer_adapter&) = delete;
2375
    input_buffer_adapter(input_buffer_adapter&&) = delete;
2376
    input_buffer_adapter& operator=(input_buffer_adapter&&) = delete;
2377
    ~input_buffer_adapter() override = default;
2378
2379
    std::char_traits<char>::int_type get_character() noexcept override
2380
0
    {
2381
0
        if (JSON_LIKELY(cursor < limit))
2382
0
        {
2383
0
            return std::char_traits<char>::to_int_type(*(cursor++));
2384
0
        }
2385
2386
0
        return std::char_traits<char>::eof();
2387
0
    }
2388
2389
  private:
2390
    /// pointer to the current character
2391
    const char* cursor;
2392
    /// pointer past the last character
2393
    const char* const limit;
2394
};
2395
2396
template<typename WideStringType, size_t T>
2397
struct wide_string_input_helper
2398
{
2399
    // UTF-32
2400
    static void fill_buffer(const WideStringType& str,
2401
                            size_t& current_wchar,
2402
                            std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
2403
                            size_t& utf8_bytes_index,
2404
                            size_t& utf8_bytes_filled)
2405
0
    {
2406
0
        utf8_bytes_index = 0;
2407
0
2408
0
        if (current_wchar == str.size())
2409
0
        {
2410
0
            utf8_bytes[0] = std::char_traits<char>::eof();
2411
0
            utf8_bytes_filled = 1;
2412
0
        }
2413
0
        else
2414
0
        {
2415
0
            // get the current character
2416
0
            const auto wc = static_cast<unsigned int>(str[current_wchar++]);
2417
0
2418
0
            // UTF-32 to UTF-8 encoding
2419
0
            if (wc < 0x80)
2420
0
            {
2421
0
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
2422
0
                utf8_bytes_filled = 1;
2423
0
            }
2424
0
            else if (wc <= 0x7FF)
2425
0
            {
2426
0
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u) & 0x1Fu));
2427
0
                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
2428
0
                utf8_bytes_filled = 2;
2429
0
            }
2430
0
            else if (wc <= 0xFFFF)
2431
0
            {
2432
0
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u) & 0x0Fu));
2433
0
                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
2434
0
                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
2435
0
                utf8_bytes_filled = 3;
2436
0
            }
2437
0
            else if (wc <= 0x10FFFF)
2438
0
            {
2439
0
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((wc >> 18u) & 0x07u));
2440
0
                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 12u) & 0x3Fu));
2441
0
                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
2442
0
                utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
2443
0
                utf8_bytes_filled = 4;
2444
0
            }
2445
0
            else
2446
0
            {
2447
0
                // unknown character
2448
0
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
2449
0
                utf8_bytes_filled = 1;
2450
0
            }
2451
0
        }
2452
0
    }
Unexecuted instantiation: nlohmann::detail::wide_string_input_helper<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, 4ul>::fill_buffer(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&, unsigned long&, std::__1::array<int, 4ul>&, unsigned long&, unsigned long&)
Unexecuted instantiation: nlohmann::detail::wide_string_input_helper<std::__1::basic_string<char32_t, std::__1::char_traits<char32_t>, std::__1::allocator<char32_t> >, 4ul>::fill_buffer(std::__1::basic_string<char32_t, std::__1::char_traits<char32_t>, std::__1::allocator<char32_t> > const&, unsigned long&, std::__1::array<int, 4ul>&, unsigned long&, unsigned long&)
2453
};
2454
2455
template<typename WideStringType>
2456
struct wide_string_input_helper<WideStringType, 2>
2457
{
2458
    // UTF-16
2459
    static void fill_buffer(const WideStringType& str,
2460
                            size_t& current_wchar,
2461
                            std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
2462
                            size_t& utf8_bytes_index,
2463
                            size_t& utf8_bytes_filled)
2464
0
    {
2465
0
        utf8_bytes_index = 0;
2466
0
2467
0
        if (current_wchar == str.size())
2468
0
        {
2469
0
            utf8_bytes[0] = std::char_traits<char>::eof();
2470
0
            utf8_bytes_filled = 1;
2471
0
        }
2472
0
        else
2473
0
        {
2474
0
            // get the current character
2475
0
            const auto wc = static_cast<unsigned int>(str[current_wchar++]);
2476
0
2477
0
            // UTF-16 to UTF-8 encoding
2478
0
            if (wc < 0x80)
2479
0
            {
2480
0
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
2481
0
                utf8_bytes_filled = 1;
2482
0
            }
2483
0
            else if (wc <= 0x7FF)
2484
0
            {
2485
0
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u)));
2486
0
                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
2487
0
                utf8_bytes_filled = 2;
2488
0
            }
2489
0
            else if (0xD800 > wc or wc >= 0xE000)
2490
0
            {
2491
0
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u)));
2492
0
                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
2493
0
                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
2494
0
                utf8_bytes_filled = 3;
2495
0
            }
2496
0
            else
2497
0
            {
2498
0
                if (current_wchar < str.size())
2499
0
                {
2500
0
                    const auto wc2 = static_cast<unsigned int>(str[current_wchar++]);
2501
0
                    const auto charcode = 0x10000u + (((wc & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
2502
0
                    utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
2503
0
                    utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
2504
0
                    utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
2505
0
                    utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
2506
0
                    utf8_bytes_filled = 4;
2507
0
                }
2508
0
                else
2509
0
                {
2510
0
                    // unknown character
2511
0
                    ++current_wchar;
2512
0
                    utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
2513
0
                    utf8_bytes_filled = 1;
2514
0
                }
2515
0
            }
2516
0
        }
2517
0
    }
2518
};
2519
2520
template<typename WideStringType>
2521
class wide_string_input_adapter : public input_adapter_protocol
2522
{
2523
  public:
2524
    explicit wide_string_input_adapter(const WideStringType& w) noexcept
2525
        : str(w)
2526
    {}
2527
2528
    std::char_traits<char>::int_type get_character() noexcept override
2529
0
    {
2530
0
        // check if buffer needs to be filled
2531
0
        if (utf8_bytes_index == utf8_bytes_filled)
2532
0
        {
2533
0
            fill_buffer<sizeof(typename WideStringType::value_type)>();
2534
0
2535
0
            assert(utf8_bytes_filled > 0);
2536
0
            assert(utf8_bytes_index == 0);
2537
0
        }
2538
0
2539
0
        // use buffer
2540
0
        assert(utf8_bytes_filled > 0);
2541
0
        assert(utf8_bytes_index < utf8_bytes_filled);
2542
0
        return utf8_bytes[utf8_bytes_index++];
2543
0
    }
Unexecuted instantiation: nlohmann::detail::wide_string_input_adapter<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > >::get_character()
Unexecuted instantiation: nlohmann::detail::wide_string_input_adapter<std::__1::basic_string<char16_t, std::__1::char_traits<char16_t>, std::__1::allocator<char16_t> > >::get_character()
Unexecuted instantiation: nlohmann::detail::wide_string_input_adapter<std::__1::basic_string<char32_t, std::__1::char_traits<char32_t>, std::__1::allocator<char32_t> > >::get_character()
2544
2545
  private:
2546
    template<size_t T>
2547
    void fill_buffer()
2548
0
    {
2549
0
        wide_string_input_helper<WideStringType, T>::fill_buffer(str, current_wchar, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
2550
0
    }
Unexecuted instantiation: void nlohmann::detail::wide_string_input_adapter<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > >::fill_buffer<4ul>()
Unexecuted instantiation: void nlohmann::detail::wide_string_input_adapter<std::__1::basic_string<char16_t, std::__1::char_traits<char16_t>, std::__1::allocator<char16_t> > >::fill_buffer<2ul>()
Unexecuted instantiation: void nlohmann::detail::wide_string_input_adapter<std::__1::basic_string<char32_t, std::__1::char_traits<char32_t>, std::__1::allocator<char32_t> > >::fill_buffer<4ul>()
2551
2552
    /// the wstring to process
2553
    const WideStringType& str;
2554
2555
    /// index of the current wchar in str
2556
    std::size_t current_wchar = 0;
2557
2558
    /// a buffer for UTF-8 bytes
2559
    std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
2560
2561
    /// index to the utf8_codes array for the next valid byte
2562
    std::size_t utf8_bytes_index = 0;
2563
    /// number of valid bytes in the utf8_codes array
2564
    std::size_t utf8_bytes_filled = 0;
2565
};
2566
2567
class input_adapter
2568
{
2569
  public:
2570
    // native support
2571
    input_adapter(std::FILE* file)
2572
0
        : ia(std::make_shared<file_input_adapter>(file)) {}
2573
    /// input adapter for input stream
2574
    input_adapter(std::istream& i)
2575
0
        : ia(std::make_shared<input_stream_adapter>(i)) {}
2576
2577
    /// input adapter for input stream
2578
    input_adapter(std::istream&& i)
2579
0
        : ia(std::make_shared<input_stream_adapter>(i)) {}
2580
2581
    input_adapter(const std::wstring& ws)
2582
0
        : ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {}
2583
2584
    input_adapter(const std::u16string& ws)
2585
0
        : ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {}
2586
2587
    input_adapter(const std::u32string& ws)
2588
0
        : ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {}
2589
2590
    /// input adapter for buffer
2591
    template<typename CharT,
2592
             typename std::enable_if<
2593
                 std::is_pointer<CharT>::value and
2594
                 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
2595
                 sizeof(typename std::remove_pointer<CharT>::type) == 1,
2596
                 int>::type = 0>
2597
    input_adapter(CharT b, std::size_t l)
2598
        : ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l)) {}
2599
2600
    // derived support
2601
2602
    /// input adapter for string literal
2603
    template<typename CharT,
2604
             typename std::enable_if<
2605
                 std::is_pointer<CharT>::value and
2606
                 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
2607
                 sizeof(typename std::remove_pointer<CharT>::type) == 1,
2608
                 int>::type = 0>
2609
    input_adapter(CharT b)
2610
        : input_adapter(reinterpret_cast<const char*>(b),
2611
                        std::strlen(reinterpret_cast<const char*>(b))) {}
2612
2613
    /// input adapter for iterator range with contiguous storage
2614
    template<class IteratorType,
2615
             typename std::enable_if<
2616
                 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
2617
                 int>::type = 0>
2618
    input_adapter(IteratorType first, IteratorType last)
2619
0
    {
2620
0
#ifndef NDEBUG
2621
        // assertion to check that the iterator range is indeed contiguous,
2622
        // see http://stackoverflow.com/a/35008842/266378 for more discussion
2623
0
        const auto is_contiguous = std::accumulate(
2624
0
                                       first, last, std::pair<bool, int>(true, 0),
2625
0
                                       [&first](std::pair<bool, int> res, decltype(*first) val)
2626
0
        {
2627
0
            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
2628
0
            return res;
2629
0
        }).first;
2630
0
        assert(is_contiguous);
2631
0
#endif
2632
2633
        // assertion to check that each element is 1 byte long
2634
0
        static_assert(
2635
0
            sizeof(typename iterator_traits<IteratorType>::value_type) == 1,
2636
0
            "each element in the iterator range must have the size of 1 byte");
2637
2638
0
        const auto len = static_cast<size_t>(std::distance(first, last));
2639
0
        if (JSON_LIKELY(len > 0))
2640
0
        {
2641
            // there is at least one element: use the address of first
2642
0
            ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
2643
0
        }
2644
0
        else
2645
0
        {
2646
            // the address of first cannot be used: use nullptr
2647
0
            ia = std::make_shared<input_buffer_adapter>(nullptr, len);
2648
0
        }
2649
0
    }
2650
2651
    /// input adapter for array
2652
    template<class T, std::size_t N>
2653
    input_adapter(T (&array)[N])
2654
        : input_adapter(std::begin(array), std::end(array)) {}
2655
2656
    /// input adapter for contiguous container
2657
    template<class ContiguousContainer, typename
2658
             std::enable_if<not std::is_pointer<ContiguousContainer>::value and
2659
                            std::is_base_of<std::random_access_iterator_tag, typename iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
2660
                            int>::type = 0>
2661
    input_adapter(const ContiguousContainer& c)
2662
0
        : input_adapter(std::begin(c), std::end(c)) {}
2663
2664
    operator input_adapter_t()
2665
0
    {
2666
0
        return ia;
2667
0
    }
2668
2669
  private:
2670
    /// the actual adapter
2671
    input_adapter_t ia = nullptr;
2672
};
2673
}  // namespace detail
2674
}  // namespace nlohmann
2675
2676
// #include <nlohmann/detail/input/json_sax.hpp>
2677
2678
2679
#include <cassert> // assert
2680
#include <cstddef>
2681
#include <string> // string
2682
#include <utility> // move
2683
#include <vector> // vector
2684
2685
// #include <nlohmann/detail/exceptions.hpp>
2686
2687
// #include <nlohmann/detail/macro_scope.hpp>
2688
2689
2690
namespace nlohmann
2691
{
2692
2693
/*!
2694
@brief SAX interface
2695
2696
This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
2697
Each function is called in different situations while the input is parsed. The
2698
boolean return value informs the parser whether to continue processing the
2699
input.
2700
*/
2701
template<typename BasicJsonType>
2702
struct json_sax
2703
{
2704
    /// type for (signed) integers
2705
    using number_integer_t = typename BasicJsonType::number_integer_t;
2706
    /// type for unsigned integers
2707
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
2708
    /// type for floating-point numbers
2709
    using number_float_t = typename BasicJsonType::number_float_t;
2710
    /// type for strings
2711
    using string_t = typename BasicJsonType::string_t;
2712
2713
    /*!
2714
    @brief a null value was read
2715
    @return whether parsing should proceed
2716
    */
2717
    virtual bool null() = 0;
2718
2719
    /*!
2720
    @brief a boolean value was read
2721
    @param[in] val  boolean value
2722
    @return whether parsing should proceed
2723
    */
2724
    virtual bool boolean(bool val) = 0;
2725
2726
    /*!
2727
    @brief an integer number was read
2728
    @param[in] val  integer value
2729
    @return whether parsing should proceed
2730
    */
2731
    virtual bool number_integer(number_integer_t val) = 0;
2732
2733
    /*!
2734
    @brief an unsigned integer number was read
2735
    @param[in] val  unsigned integer value
2736
    @return whether parsing should proceed
2737
    */
2738
    virtual bool number_unsigned(number_unsigned_t val) = 0;
2739
2740
    /*!
2741
    @brief an floating-point number was read
2742
    @param[in] val  floating-point value
2743
    @param[in] s    raw token value
2744
    @return whether parsing should proceed
2745
    */
2746
    virtual bool number_float(number_float_t val, const string_t& s) = 0;
2747
2748
    /*!
2749
    @brief a string was read
2750
    @param[in] val  string value
2751
    @return whether parsing should proceed
2752
    @note It is safe to move the passed string.
2753
    */
2754
    virtual bool string(string_t& val) = 0;
2755
2756
    /*!
2757
    @brief the beginning of an object was read
2758
    @param[in] elements  number of object elements or -1 if unknown
2759
    @return whether parsing should proceed
2760
    @note binary formats may report the number of elements
2761
    */
2762
    virtual bool start_object(std::size_t elements) = 0;
2763
2764
    /*!
2765
    @brief an object key was read
2766
    @param[in] val  object key
2767
    @return whether parsing should proceed
2768
    @note It is safe to move the passed string.
2769
    */
2770
    virtual bool key(string_t& val) = 0;
2771
2772
    /*!
2773
    @brief the end of an object was read
2774
    @return whether parsing should proceed
2775
    */
2776
    virtual bool end_object() = 0;
2777
2778
    /*!
2779
    @brief the beginning of an array was read
2780
    @param[in] elements  number of array elements or -1 if unknown
2781
    @return whether parsing should proceed
2782
    @note binary formats may report the number of elements
2783
    */
2784
    virtual bool start_array(std::size_t elements) = 0;
2785
2786
    /*!
2787
    @brief the end of an array was read
2788
    @return whether parsing should proceed
2789
    */
2790
    virtual bool end_array() = 0;
2791
2792
    /*!
2793
    @brief a parse error occurred
2794
    @param[in] position    the position in the input where the error occurs
2795
    @param[in] last_token  the last read token
2796
    @param[in] ex          an exception object describing the error
2797
    @return whether parsing should proceed (must return false)
2798
    */
2799
    virtual bool parse_error(std::size_t position,
2800
                             const std::string& last_token,
2801
                             const detail::exception& ex) = 0;
2802
2803
    virtual ~json_sax() = default;
2804
};
2805
2806
2807
namespace detail
2808
{
2809
/*!
2810
@brief SAX implementation to create a JSON value from SAX events
2811
2812
This class implements the @ref json_sax interface and processes the SAX events
2813
to create a JSON value which makes it basically a DOM parser. The structure or
2814
hierarchy of the JSON value is managed by the stack `ref_stack` which contains
2815
a pointer to the respective array or object for each recursion depth.
2816
2817
After successful parsing, the value that is passed by reference to the
2818
constructor contains the parsed value.
2819
2820
@tparam BasicJsonType  the JSON type
2821
*/
2822
template<typename BasicJsonType>
2823
class json_sax_dom_parser
2824
{
2825
  public:
2826
    using number_integer_t = typename BasicJsonType::number_integer_t;
2827
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
2828
    using number_float_t = typename BasicJsonType::number_float_t;
2829
    using string_t = typename BasicJsonType::string_t;
2830
2831
    /*!
2832
    @param[in, out] r  reference to a JSON value that is manipulated while
2833
                       parsing
2834
    @param[in] allow_exceptions_  whether parse errors yield exceptions
2835
    */
2836
    explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
2837
        : root(r), allow_exceptions(allow_exceptions_)
2838
0
    {}
2839
2840
    // make class move-only
2841
    json_sax_dom_parser(const json_sax_dom_parser&) = delete;
2842
    json_sax_dom_parser(json_sax_dom_parser&&) = default;
2843
    json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
2844
    json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default;
2845
0
    ~json_sax_dom_parser() = default;
2846
2847
    bool null()
2848
0
    {
2849
0
        handle_value(nullptr);
2850
0
        return true;
2851
0
    }
2852
2853
    bool boolean(bool val)
2854
0
    {
2855
0
        handle_value(val);
2856
0
        return true;
2857
0
    }
2858
2859
    bool number_integer(number_integer_t val)
2860
0
    {
2861
0
        handle_value(val);
2862
0
        return true;
2863
0
    }
2864
2865
    bool number_unsigned(number_unsigned_t val)
2866
0
    {
2867
0
        handle_value(val);
2868
0
        return true;
2869
0
    }
2870
2871
    bool number_float(number_float_t val, const string_t& /*unused*/)
2872
0
    {
2873
0
        handle_value(val);
2874
0
        return true;
2875
0
    }
2876
2877
    bool string(string_t& val)
2878
0
    {
2879
0
        handle_value(val);
2880
0
        return true;
2881
0
    }
2882
2883
    bool start_object(std::size_t len)
2884
0
    {
2885
0
        ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
2886
2887
0
        if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
2888
0
        {
2889
0
            JSON_THROW(out_of_range::create(408,
2890
0
                                            "excessive object size: " + std::to_string(len)));
2891
0
        }
2892
2893
0
        return true;
2894
0
    }
2895
2896
    bool key(string_t& val)
2897
0
    {
2898
        // add null at given key and store the reference for later
2899
0
        object_element = &(ref_stack.back()->m_value.object->operator[](val));
2900
0
        return true;
2901
0
    }
2902
2903
    bool end_object()
2904
0
    {
2905
0
        ref_stack.pop_back();
2906
0
        return true;
2907
0
    }
2908
2909
    bool start_array(std::size_t len)
2910
0
    {
2911
0
        ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
2912
2913
0
        if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
2914
0
        {
2915
0
            JSON_THROW(out_of_range::create(408,
2916
0
                                            "excessive array size: " + std::to_string(len)));
2917
0
        }
2918
2919
0
        return true;
2920
0
    }
2921
2922
    bool end_array()
2923
0
    {
2924
0
        ref_stack.pop_back();
2925
0
        return true;
2926
0
    }
2927
2928
    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
2929
                     const detail::exception& ex)
2930
0
    {
2931
0
        errored = true;
2932
0
        if (allow_exceptions)
2933
0
        {
2934
            // determine the proper exception type from the id
2935
0
            switch ((ex.id / 100) % 100)
2936
0
            {
2937
0
                case 1:
2938
0
                    JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
2939
0
                case 4:
2940
0
                    JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
2941
                // LCOV_EXCL_START
2942
0
                case 2:
2943
0
                    JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
2944
0
                case 3:
2945
0
                    JSON_THROW(*static_cast<const detail::type_error*>(&ex));
2946
0
                case 5:
2947
0
                    JSON_THROW(*static_cast<const detail::other_error*>(&ex));
2948
0
                default:
2949
0
                    assert(false);
2950
                    // LCOV_EXCL_STOP
2951
0
            }
2952
0
        }
2953
0
        return false;
2954
0
    }
2955
2956
    constexpr bool is_errored() const
2957
0
    {
2958
0
        return errored;
2959
0
    }
2960
2961
  private:
2962
    /*!
2963
    @invariant If the ref stack is empty, then the passed value will be the new
2964
               root.
2965
    @invariant If the ref stack contains a value, then it is an array or an
2966
               object to which we can add elements
2967
    */
2968
    template<typename Value>
2969
    BasicJsonType* handle_value(Value&& v)
2970
0
    {
2971
0
        if (ref_stack.empty())
2972
0
        {
2973
0
            root = BasicJsonType(std::forward<Value>(v));
2974
0
            return &root;
2975
0
        }
2976
2977
0
        assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
2978
2979
0
        if (ref_stack.back()->is_array())
2980
0
        {
2981
0
            ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
2982
0
            return &(ref_stack.back()->m_value.array->back());
2983
0
        }
2984
2985
0
        assert(ref_stack.back()->is_object());
2986
0
        assert(object_element);
2987
0
        *object_element = BasicJsonType(std::forward<Value>(v));
2988
0
        return object_element;
2989
0
    }
Unexecuted instantiation: nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>* nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::handle_value<nlohmann::detail::value_t>(nlohmann::detail::value_t&&)
Unexecuted instantiation: nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>* nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::handle_value<double&>(double&)
Unexecuted instantiation: nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>* nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::handle_value<bool&>(bool&)
Unexecuted instantiation: nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>* nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::handle_value<decltype(nullptr)>(decltype(nullptr)&&)
Unexecuted instantiation: nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>* nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::handle_value<long&>(long&)
Unexecuted instantiation: nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>* nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::handle_value<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Unexecuted instantiation: nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>* nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::handle_value<unsigned long&>(unsigned long&)
2990
2991
    /// the parsed JSON value
2992
    BasicJsonType& root;
2993
    /// stack to model hierarchy of values
2994
    std::vector<BasicJsonType*> ref_stack {};
2995
    /// helper to hold the reference for the next object element
2996
    BasicJsonType* object_element = nullptr;
2997
    /// whether a syntax error occurred
2998
    bool errored = false;
2999
    /// whether to throw exceptions in case of errors
3000
    const bool allow_exceptions = true;
3001
};
3002
3003
template<typename BasicJsonType>
3004
class json_sax_dom_callback_parser
3005
{
3006
  public:
3007
    using number_integer_t = typename BasicJsonType::number_integer_t;
3008
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3009
    using number_float_t = typename BasicJsonType::number_float_t;
3010
    using string_t = typename BasicJsonType::string_t;
3011
    using parser_callback_t = typename BasicJsonType::parser_callback_t;
3012
    using parse_event_t = typename BasicJsonType::parse_event_t;
3013
3014
    json_sax_dom_callback_parser(BasicJsonType& r,
3015
                                 const parser_callback_t cb,
3016
                                 const bool allow_exceptions_ = true)
3017
        : root(r), callback(cb), allow_exceptions(allow_exceptions_)
3018
0
    {
3019
0
        keep_stack.push_back(true);
3020
0
    }
3021
3022
    // make class move-only
3023
    json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
3024
    json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default;
3025
    json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
3026
    json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default;
3027
0
    ~json_sax_dom_callback_parser() = default;
3028
3029
    bool null()
3030
0
    {
3031
0
        handle_value(nullptr);
3032
0
        return true;
3033
0
    }
3034
3035
    bool boolean(bool val)
3036
0
    {
3037
0
        handle_value(val);
3038
0
        return true;
3039
0
    }
3040
3041
    bool number_integer(number_integer_t val)
3042
0
    {
3043
0
        handle_value(val);
3044
0
        return true;
3045
0
    }
3046
3047
    bool number_unsigned(number_unsigned_t val)
3048
0
    {
3049
0
        handle_value(val);
3050
0
        return true;
3051
0
    }
3052
3053
    bool number_float(number_float_t val, const string_t& /*unused*/)
3054
0
    {
3055
0
        handle_value(val);
3056
0
        return true;
3057
0
    }
3058
3059
    bool string(string_t& val)
3060
0
    {
3061
0
        handle_value(val);
3062
0
        return true;
3063
0
    }
3064
3065
    bool start_object(std::size_t len)
3066
0
    {
3067
        // check callback for object start
3068
0
        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
3069
0
        keep_stack.push_back(keep);
3070
3071
0
        auto val = handle_value(BasicJsonType::value_t::object, true);
3072
0
        ref_stack.push_back(val.second);
3073
3074
        // check object limit
3075
0
        if (ref_stack.back() and JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
3076
0
        {
3077
0
            JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len)));
3078
0
        }
3079
3080
0
        return true;
3081
0
    }
3082
3083
    bool key(string_t& val)
3084
0
    {
3085
0
        BasicJsonType k = BasicJsonType(val);
3086
3087
        // check callback for key
3088
0
        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
3089
0
        key_keep_stack.push_back(keep);
3090
3091
        // add discarded value at given key and store the reference for later
3092
0
        if (keep and ref_stack.back())
3093
0
        {
3094
0
            object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
3095
0
        }
3096
3097
0
        return true;
3098
0
    }
3099
3100
    bool end_object()
3101
0
    {
3102
0
        if (ref_stack.back() and not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
3103
0
        {
3104
            // discard object
3105
0
            *ref_stack.back() = discarded;
3106
0
        }
3107
3108
0
        assert(not ref_stack.empty());
3109
0
        assert(not keep_stack.empty());
3110
0
        ref_stack.pop_back();
3111
0
        keep_stack.pop_back();
3112
3113
0
        if (not ref_stack.empty() and ref_stack.back() and ref_stack.back()->is_object())
3114
0
        {
3115
            // remove discarded value
3116
0
            for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
3117
0
            {
3118
0
                if (it->is_discarded())
3119
0
                {
3120
0
                    ref_stack.back()->erase(it);
3121
0
                    break;
3122
0
                }
3123
0
            }
3124
0
        }
3125
3126
0
        return true;
3127
0
    }
3128
3129
    bool start_array(std::size_t len)
3130
0
    {
3131
0
        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
3132
0
        keep_stack.push_back(keep);
3133
3134
0
        auto val = handle_value(BasicJsonType::value_t::array, true);
3135
0
        ref_stack.push_back(val.second);
3136
3137
        // check array limit
3138
0
        if (ref_stack.back() and JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
3139
0
        {
3140
0
            JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len)));
3141
0
        }
3142
3143
0
        return true;
3144
0
    }
3145
3146
    bool end_array()
3147
0
    {
3148
0
        bool keep = true;
3149
3150
0
        if (ref_stack.back())
3151
0
        {
3152
0
            keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
3153
0
            if (not keep)
3154
0
            {
3155
                // discard array
3156
0
                *ref_stack.back() = discarded;
3157
0
            }
3158
0
        }
3159
3160
0
        assert(not ref_stack.empty());
3161
0
        assert(not keep_stack.empty());
3162
0
        ref_stack.pop_back();
3163
0
        keep_stack.pop_back();
3164
3165
        // remove discarded value
3166
0
        if (not keep and not ref_stack.empty() and ref_stack.back()->is_array())
3167
0
        {
3168
0
            ref_stack.back()->m_value.array->pop_back();
3169
0
        }
3170
3171
0
        return true;
3172
0
    }
3173
3174
    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
3175
                     const detail::exception& ex)
3176
0
    {
3177
0
        errored = true;
3178
0
        if (allow_exceptions)
3179
0
        {
3180
            // determine the proper exception type from the id
3181
0
            switch ((ex.id / 100) % 100)
3182
0
            {
3183
0
                case 1:
3184
0
                    JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
3185
0
                case 4:
3186
0
                    JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
3187
                // LCOV_EXCL_START
3188
0
                case 2:
3189
0
                    JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
3190
0
                case 3:
3191
0
                    JSON_THROW(*static_cast<const detail::type_error*>(&ex));
3192
0
                case 5:
3193
0
                    JSON_THROW(*static_cast<const detail::other_error*>(&ex));
3194
0
                default:
3195
0
                    assert(false);
3196
                    // LCOV_EXCL_STOP
3197
0
            }
3198
0
        }
3199
0
        return false;
3200
0
    }
3201
3202
    constexpr bool is_errored() const
3203
0
    {
3204
0
        return errored;
3205
0
    }
3206
3207
  private:
3208
    /*!
3209
    @param[in] v  value to add to the JSON value we build during parsing
3210
    @param[in] skip_callback  whether we should skip calling the callback
3211
               function; this is required after start_array() and
3212
               start_object() SAX events, because otherwise we would call the
3213
               callback function with an empty array or object, respectively.
3214
3215
    @invariant If the ref stack is empty, then the passed value will be the new
3216
               root.
3217
    @invariant If the ref stack contains a value, then it is an array or an
3218
               object to which we can add elements
3219
3220
    @return pair of boolean (whether value should be kept) and pointer (to the
3221
            passed value in the ref_stack hierarchy; nullptr if not kept)
3222
    */
3223
    template<typename Value>
3224
    std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
3225
0
    {
3226
0
        assert(not keep_stack.empty());
3227
3228
        // do not handle this value if we know it would be added to a discarded
3229
        // container
3230
0
        if (not keep_stack.back())
3231
0
        {
3232
0
            return {false, nullptr};
3233
0
        }
3234
3235
        // create value
3236
0
        auto value = BasicJsonType(std::forward<Value>(v));
3237
3238
        // check callback
3239
0
        const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
3240
3241
        // do not handle this value if we just learnt it shall be discarded
3242
0
        if (not keep)
3243
0
        {
3244
0
            return {false, nullptr};
3245
0
        }
3246
3247
0
        if (ref_stack.empty())
3248
0
        {
3249
0
            root = std::move(value);
3250
0
            return {true, &root};
3251
0
        }
3252
3253
        // skip this value if we already decided to skip the parent
3254
        // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
3255
0
        if (not ref_stack.back())
3256
0
        {
3257
0
            return {false, nullptr};
3258
0
        }
3259
3260
        // we now only expect arrays and objects
3261
0
        assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
3262
3263
        // array
3264
0
        if (ref_stack.back()->is_array())
3265
0
        {
3266
0
            ref_stack.back()->m_value.array->push_back(std::move(value));
3267
0
            return {true, &(ref_stack.back()->m_value.array->back())};
3268
0
        }
3269
3270
        // object
3271
0
        assert(ref_stack.back()->is_object());
3272
        // check if we should store an element for the current key
3273
0
        assert(not key_keep_stack.empty());
3274
0
        const bool store_element = key_keep_stack.back();
3275
0
        key_keep_stack.pop_back();
3276
3277
0
        if (not store_element)
3278
0
        {
3279
0
            return {false, nullptr};
3280
0
        }
3281
3282
0
        assert(object_element);
3283
0
        *object_element = std::move(value);
3284
0
        return {true, object_element};
3285
0
    }
Unexecuted instantiation: std::__1::pair<bool, nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>*> nlohmann::detail::json_sax_dom_callback_parser<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::handle_value<nlohmann::detail::value_t>(nlohmann::detail::value_t&&, bool)
Unexecuted instantiation: std::__1::pair<bool, nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>*> nlohmann::detail::json_sax_dom_callback_parser<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::handle_value<double&>(double&, bool)
Unexecuted instantiation: std::__1::pair<bool, nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>*> nlohmann::detail::json_sax_dom_callback_parser<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::handle_value<bool&>(bool&, bool)
Unexecuted instantiation: std::__1::pair<bool, nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>*> nlohmann::detail::json_sax_dom_callback_parser<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::handle_value<decltype(nullptr)>(decltype(nullptr)&&, bool)
Unexecuted instantiation: std::__1::pair<bool, nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>*> nlohmann::detail::json_sax_dom_callback_parser<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::handle_value<long&>(long&, bool)
Unexecuted instantiation: std::__1::pair<bool, nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>*> nlohmann::detail::json_sax_dom_callback_parser<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::handle_value<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, bool)
Unexecuted instantiation: std::__1::pair<bool, nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer>*> nlohmann::detail::json_sax_dom_callback_parser<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::adl_serializer> >::handle_value<unsigned long&>(unsigned long&, bool)
3286
3287
    /// the parsed JSON value
3288
    BasicJsonType& root;
3289
    /// stack to model hierarchy of values
3290
    std::vector<BasicJsonType*> ref_stack {};
3291
    /// stack to manage which values to keep
3292
    std::vector<bool> keep_stack {};
3293
    /// stack to manage which object keys to keep
3294
    std::vector<bool> key_keep_stack {};
3295
    /// helper to hold the reference for the next object element
3296
    BasicJsonType* object_element = nullptr;
3297
    /// whether a syntax error occurred
3298
    bool errored = false;
3299
    /// callback function
3300
    const parser_callback_t callback = nullptr;
3301
    /// whether to throw exceptions in case of errors
3302
    const bool allow_exceptions = true;
3303
    /// a discarded value for the callback
3304
    BasicJsonType discarded = BasicJsonType::value_t::discarded;
3305
};
3306
3307
template<typename BasicJsonType>
3308
class json_sax_acceptor
3309
{
3310
  public:
3311
    using number_integer_t = typename BasicJsonType::number_integer_t;
3312
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3313
    using number_float_t = typename BasicJsonType::number_float_t;
3314
    using string_t = typename BasicJsonType::string_t;
3315
3316
    bool null()
3317
    {
3318
        return true;
3319
    }
3320
3321
    bool boolean(bool /*unused*/)
3322
    {
3323
        return true;
3324
    }
3325
3326
    bool number_integer(number_integer_t /*unused*/)
3327
    {
3328
        return true;
3329
    }
3330
3331
    bool number_unsigned(number_unsigned_t /*unused*/)
3332
    {
3333
        return true;
3334
    }
3335
3336
    bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
3337
    {
3338
        return true;
3339
    }
3340
3341
    bool string(string_t& /*unused*/)
3342
    {
3343
        return true;
3344
    }
3345
3346
    bool start_object(std::size_t  /*unused*/ = std::size_t(-1))
3347
    {
3348
        return true;
3349
    }
3350
3351
    bool key(string_t& /*unused*/)
3352
    {
3353
        return true;
3354
    }
3355
3356
    bool end_object()
3357
    {
3358
        return true;
3359
    }
3360
3361
    bool start_array(std::size_t  /*unused*/ = std::size_t(-1))
3362
    {
3363
        return true;
3364
    }
3365
3366
    bool end_array()
3367
    {
3368
        return true;
3369
    }
3370
3371
    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
3372
    {
3373
        return false;
3374
    }
3375
};
3376
}  // namespace detail
3377
3378
}  // namespace nlohmann
3379
3380
// #include <nlohmann/detail/macro_scope.hpp>
3381
3382
// #include <nlohmann/detail/meta/is_sax.hpp>
3383
3384
3385
#include <cstdint> // size_t
3386
#include <utility> // declval
3387
#include <string> // string
3388
3389
// #include <nlohmann/detail/meta/detected.hpp>
3390
3391
// #include <nlohmann/detail/meta/type_traits.hpp>
3392
3393
3394
namespace nlohmann
3395
{
3396
namespace detail
3397
{
3398
template <typename T>
3399
using null_function_t = decltype(std::declval<T&>().null());
3400
3401
template <typename T>
3402
using boolean_function_t =
3403
    decltype(std::declval<T&>().boolean(std::declval<bool>()));
3404
3405
template <typename T, typename Integer>
3406
using number_integer_function_t =
3407
    decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
3408
3409
template <typename T, typename Unsigned>
3410
using number_unsigned_function_t =
3411
    decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
3412
3413
template <typename T, typename Float, typename String>
3414
using number_float_function_t = decltype(std::declval<T&>().number_float(
3415
                                    std::declval<Float>(), std::declval<const String&>()));
3416
3417
template <typename T, typename String>
3418
using string_function_t =
3419
    decltype(std::declval<T&>().string(std::declval<String&>()));
3420
3421
template <typename T>
3422
using start_object_function_t =
3423
    decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
3424
3425
template <typename T, typename String>
3426
using key_function_t =
3427
    decltype(std::declval<T&>().key(std::declval<String&>()));
3428
3429
template <typename T>
3430
using end_object_function_t = decltype(std::declval<T&>().end_object());
3431
3432
template <typename T>
3433
using start_array_function_t =
3434
    decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
3435
3436
template <typename T>
3437
using end_array_function_t = decltype(std::declval<T&>().end_array());
3438
3439
template <typename T, typename Exception>
3440
using parse_error_function_t = decltype(std::declval<T&>().parse_error(
3441
        std::declval<std::size_t>(), std::declval<const std::string&>(),
3442
        std::declval<const Exception&>()));
3443
3444
template <typename SAX, typename BasicJsonType>
3445
struct is_sax
3446
{
3447
  private:
3448
    static_assert(is_basic_json<BasicJsonType>::value,
3449
                  "BasicJsonType must be of type basic_json<...>");
3450
3451
    using number_integer_t = typename BasicJsonType::number_integer_t;
3452
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3453
    using number_float_t = typename BasicJsonType::number_float_t;
3454
    using string_t = typename BasicJsonType::string_t;
3455
    using exception_t = typename BasicJsonType::exception;
3456
3457
  public:
3458
    static constexpr bool value =
3459
        is_detected_exact<bool, null_function_t, SAX>::value &&
3460
        is_detected_exact<bool, boolean_function_t, SAX>::value &&
3461
        is_detected_exact<bool, number_integer_function_t, SAX,
3462
        number_integer_t>::value &&
3463
        is_detected_exact<bool, number_unsigned_function_t, SAX,
3464
        number_unsigned_t>::value &&
3465
        is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
3466
        string_t>::value &&
3467
        is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
3468
        is_detected_exact<bool, start_object_function_t, SAX>::value &&
3469
        is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
3470
        is_detected_exact<bool, end_object_function_t, SAX>::value &&
3471
        is_detected_exact<bool, start_array_function_t, SAX>::value &&
3472
        is_detected_exact<bool, end_array_function_t, SAX>::value &&
3473
        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
3474
};
3475
3476
template <typename SAX, typename BasicJsonType>
3477
struct is_sax_static_asserts
3478
{
3479
  private:
3480
    static_assert(is_basic_json<BasicJsonType>::value,
3481
                  "BasicJsonType must be of type basic_json<...>");
3482
3483
    using number_integer_t = typename BasicJsonType::number_integer_t;
3484
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3485
    using number_float_t = typename BasicJsonType::number_float_t;
3486
    using string_t = typename BasicJsonType::string_t;
3487
    using exception_t = typename BasicJsonType::exception;
3488
3489
  public:
3490
    static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
3491
                  "Missing/invalid function: bool null()");
3492
    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
3493
                  "Missing/invalid function: bool boolean(bool)");
3494
    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
3495
                  "Missing/invalid function: bool boolean(bool)");
3496
    static_assert(
3497
        is_detected_exact<bool, number_integer_function_t, SAX,
3498
        number_integer_t>::value,
3499
        "Missing/invalid function: bool number_integer(number_integer_t)");
3500
    static_assert(
3501
        is_detected_exact<bool, number_unsigned_function_t, SAX,
3502
        number_unsigned_t>::value,
3503
        "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
3504
    static_assert(is_detected_exact<bool, number_float_function_t, SAX,
3505
                  number_float_t, string_t>::value,
3506
                  "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
3507
    static_assert(
3508
        is_detected_exact<bool, string_function_t, SAX, string_t>::value,
3509
        "Missing/invalid function: bool string(string_t&)");
3510
    static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
3511
                  "Missing/invalid function: bool start_object(std::size_t)");
3512
    static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
3513
                  "Missing/invalid function: bool key(string_t&)");
3514
    static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
3515
                  "Missing/invalid function: bool end_object()");
3516
    static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
3517
                  "Missing/invalid function: bool start_array(std::size_t)");
3518
    static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
3519
                  "Missing/invalid function: bool end_array()");
3520
    static_assert(
3521
        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
3522
        "Missing/invalid function: bool parse_error(std::size_t, const "
3523
        "std::string&, const exception&)");
3524
};
3525
}  // namespace detail
3526
}  // namespace nlohmann
3527
3528
// #include <nlohmann/detail/value_t.hpp>
3529
3530
3531
namespace nlohmann
3532
{
3533
namespace detail
3534
{
3535
///////////////////
3536
// binary reader //
3537
///////////////////
3538
3539
/*!
3540
@brief deserialization of CBOR, MessagePack, and UBJSON values
3541
*/
3542
template<typename BasicJsonType, typename SAX = json_sax_dom_parser<BasicJsonType>>
3543
class binary_reader
3544
{
3545
    using number_integer_t = typename BasicJsonType::number_integer_t;
3546
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3547
    using number_float_t = typename BasicJsonType::number_float_t;
3548
    using string_t = typename BasicJsonType::string_t;
3549
    using json_sax_t = SAX;
3550
3551
  public:
3552
    /*!
3553
    @brief create a binary reader
3554
3555
    @param[in] adapter  input adapter to read from
3556
    */
3557
    explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
3558
    {
3559
        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
3560
        assert(ia);
3561
    }
3562
3563
    // make class move-only
3564
    binary_reader(const binary_reader&) = delete;
3565
    binary_reader(binary_reader&&) = default;
3566
    binary_reader& operator=(const binary_reader&) = delete;
3567
    binary_reader& operator=(binary_reader&&) = default;
3568
    ~binary_reader() = default;
3569
3570
    /*!
3571
    @param[in] format  the binary format to parse
3572
    @param[in] sax_    a SAX event processor
3573
    @param[in] strict  whether to expect the input to be consumed completed
3574
3575
    @return
3576
    */
3577
    bool sax_parse(const input_format_t format,
3578
                   json_sax_t* sax_,
3579
                   const bool strict = true)
3580
    {
3581
        sax = sax_;
3582
        bool result = false;
3583
3584
        switch (format)
3585
        {
3586
            case input_format_t::bson:
3587
                result = parse_bson_internal();
3588
                break;
3589
3590
            case input_format_t::cbor:
3591
                result = parse_cbor_internal();
3592
                break;
3593
3594
            case input_format_t::msgpack:
3595
                result = parse_msgpack_internal();
3596
                break;
3597
3598
            case input_format_t::ubjson:
3599
                result = parse_ubjson_internal();
3600
                break;
3601
3602
            default:            // LCOV_EXCL_LINE
3603
                assert(false);  // LCOV_EXCL_LINE
3604
        }
3605
3606
        // strict mode: next byte must be EOF
3607
        if (result and strict)
3608
        {
3609
            if (format == input_format_t::ubjson)
3610
            {
3611
                get_ignore_noop();
3612
            }
3613
            else
3614
            {
3615
                get();
3616
            }
3617
3618
            if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
3619
            {
3620
                return sax->parse_error(chars_read, get_token_string(),
3621
                                        parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value")));
3622
            }
3623
        }
3624
3625
        return result;
3626
    }
3627
3628
    /*!
3629
    @brief determine system byte order
3630
3631
    @return true if and only if system's byte order is little endian
3632
3633
    @note from http://stackoverflow.com/a/1001328/266378
3634
    */
3635
    static constexpr bool little_endianess(int num = 1) noexcept
3636
    {
3637
        return *reinterpret_cast<char*>(&num) == 1;
3638
    }
3639
3640
  private:
3641
    //////////
3642
    // BSON //
3643
    //////////
3644
3645
    /*!
3646
    @brief Reads in a BSON-object and passes it to the SAX-parser.
3647
    @return whether a valid BSON-value was passed to the SAX parser
3648
    */
3649
    bool parse_bson_internal()
3650
    {
3651
        std::int32_t document_size;
3652
        get_number<std::int32_t, true>(input_format_t::bson, document_size);
3653
3654
        if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
3655
        {
3656
            return false;
3657
        }
3658
3659
        if (JSON_UNLIKELY(not parse_bson_element_list(/*is_array*/false)))
3660
        {
3661
            return false;
3662
        }
3663
3664
        return sax->end_object();
3665
    }
3666
3667
    /*!
3668
    @brief Parses a C-style string from the BSON input.
3669
    @param[in, out] result  A reference to the string variable where the read
3670
                            string is to be stored.
3671
    @return `true` if the \x00-byte indicating the end of the string was
3672
             encountered before the EOF; false` indicates an unexpected EOF.
3673
    */
3674
    bool get_bson_cstr(string_t& result)
3675
    {
3676
        auto out = std::back_inserter(result);
3677
        while (true)
3678
        {
3679
            get();
3680
            if (JSON_UNLIKELY(not unexpect_eof(input_format_t::bson, "cstring")))
3681
            {
3682
                return false;
3683
            }
3684
            if (current == 0x00)
3685
            {
3686
                return true;
3687
            }
3688
            *out++ = static_cast<char>(current);
3689
        }
3690
3691
        return true;
3692
    }
3693
3694
    /*!
3695
    @brief Parses a zero-terminated string of length @a len from the BSON
3696
           input.
3697
    @param[in] len  The length (including the zero-byte at the end) of the
3698
                    string to be read.
3699
    @param[in, out] result  A reference to the string variable where the read
3700
                            string is to be stored.
3701
    @tparam NumberType The type of the length @a len
3702
    @pre len >= 1
3703
    @return `true` if the string was successfully parsed
3704
    */
3705
    template<typename NumberType>
3706
    bool get_bson_string(const NumberType len, string_t& result)
3707
    {
3708
        if (JSON_UNLIKELY(len < 1))
3709
        {
3710
            auto last_token = get_token_string();
3711
            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")));
3712
        }
3713
3714
        return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) and get() != std::char_traits<char>::eof();
3715
    }
3716
3717
    /*!
3718
    @brief Read a BSON document element of the given @a element_type.
3719
    @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
3720
    @param[in] element_type_parse_position The position in the input stream,
3721
               where the `element_type` was read.
3722
    @warning Not all BSON element types are supported yet. An unsupported
3723
             @a element_type will give rise to a parse_error.114:
3724
             Unsupported BSON record type 0x...
3725
    @return whether a valid BSON-object/array was passed to the SAX parser
3726
    */
3727
    bool parse_bson_element_internal(const int element_type,
3728
                                     const std::size_t element_type_parse_position)
3729
    {
3730
        switch (element_type)
3731
        {
3732
            case 0x01: // double
3733
            {
3734
                double number;
3735
                return get_number<double, true>(input_format_t::bson, number) and sax->number_float(static_cast<number_float_t>(number), "");
3736
            }
3737
3738
            case 0x02: // string
3739
            {
3740
                std::int32_t len;
3741
                string_t value;
3742
                return get_number<std::int32_t, true>(input_format_t::bson, len) and get_bson_string(len, value) and sax->string(value);
3743
            }
3744
3745
            case 0x03: // object
3746
            {
3747
                return parse_bson_internal();
3748
            }
3749
3750
            case 0x04: // array
3751
            {
3752
                return parse_bson_array();
3753
            }
3754
3755
            case 0x08: // boolean
3756
            {
3757
                return sax->boolean(get() != 0);
3758
            }
3759
3760
            case 0x0A: // null
3761
            {
3762
                return sax->null();
3763
            }
3764
3765
            case 0x10: // int32
3766
            {
3767
                std::int32_t value;
3768
                return get_number<std::int32_t, true>(input_format_t::bson, value) and sax->number_integer(value);
3769
            }
3770
3771
            case 0x12: // int64
3772
            {
3773
                std::int64_t value;
3774
                return get_number<std::int64_t, true>(input_format_t::bson, value) and sax->number_integer(value);
3775
            }
3776
3777
            default: // anything else not supported (yet)
3778
            {
3779
                std::array<char, 3> cr{{}};
3780
                (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type));
3781
                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())));
3782
            }
3783
        }
3784
    }
3785
3786
    /*!
3787
    @brief Read a BSON element list (as specified in the BSON-spec)
3788
3789
    The same binary layout is used for objects and arrays, hence it must be
3790
    indicated with the argument @a is_array which one is expected
3791
    (true --> array, false --> object).
3792
3793
    @param[in] is_array Determines if the element list being read is to be
3794
                        treated as an object (@a is_array == false), or as an
3795
                        array (@a is_array == true).
3796
    @return whether a valid BSON-object/array was passed to the SAX parser
3797
    */
3798
    bool parse_bson_element_list(const bool is_array)
3799
    {
3800
        string_t key;
3801
        while (int element_type = get())
3802
        {
3803
            if (JSON_UNLIKELY(not unexpect_eof(input_format_t::bson, "element list")))
3804
            {
3805
                return false;
3806
            }
3807
3808
            const std::size_t element_type_parse_position = chars_read;
3809
            if (JSON_UNLIKELY(not get_bson_cstr(key)))
3810
            {
3811
                return false;
3812
            }
3813
3814
            if (not is_array and not sax->key(key))
3815
            {
3816
                return false;
3817
            }
3818
3819
            if (JSON_UNLIKELY(not parse_bson_element_internal(element_type, element_type_parse_position)))
3820
            {
3821
                return false;
3822
            }
3823
3824
            // get_bson_cstr only appends
3825
            key.clear();
3826
        }
3827
3828
        return true;
3829
    }
3830
3831
    /*!
3832
    @brief Reads an array from the BSON input and passes it to the SAX-parser.
3833
    @return whether a valid BSON-array was passed to the SAX parser
3834
    */
3835
    bool parse_bson_array()
3836
    {
3837
        std::int32_t document_size;
3838
        get_number<std::int32_t, true>(input_format_t::bson, document_size);
3839
3840
        if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
3841
        {
3842
            return false;
3843
        }
3844
3845
        if (JSON_UNLIKELY(not parse_bson_element_list(/*is_array*/true)))
3846
        {
3847
            return false;
3848
        }
3849
3850
        return sax->end_array();
3851
    }
3852
3853
    //////////
3854
    // CBOR //
3855
    //////////
3856
3857
    /*!
3858
    @param[in] get_char  whether a new character should be retrieved from the
3859
                         input (true, default) or whether the last read
3860
                         character should be considered instead
3861
3862
    @return whether a valid CBOR value was passed to the SAX parser
3863
    */
3864
    bool parse_cbor_internal(const bool get_char = true)
3865
    {
3866
        switch (get_char ? get() : current)
3867
        {
3868
            // EOF
3869
            case std::char_traits<char>::eof():
3870
                return unexpect_eof(input_format_t::cbor, "value");
3871
3872
            // Integer 0x00..0x17 (0..23)
3873
            case 0x00:
3874
            case 0x01:
3875
            case 0x02:
3876
            case 0x03:
3877
            case 0x04:
3878
            case 0x05:
3879
            case 0x06:
3880
            case 0x07:
3881
            case 0x08:
3882
            case 0x09:
3883
            case 0x0A:
3884
            case 0x0B:
3885
            case 0x0C:
3886
            case 0x0D:
3887
            case 0x0E:
3888
            case 0x0F:
3889
            case 0x10:
3890
            case 0x11:
3891
            case 0x12:
3892
            case 0x13:
3893
            case 0x14:
3894
            case 0x15:
3895
            case 0x16:
3896
            case 0x17:
3897
                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
3898
3899
            case 0x18: // Unsigned integer (one-byte uint8_t follows)
3900
            {
3901
                std::uint8_t number;
3902
                return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
3903
            }
3904
3905
            case 0x19: // Unsigned integer (two-byte uint16_t follows)
3906
            {
3907
                std::uint16_t number;
3908
                return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
3909
            }
3910
3911
            case 0x1A: // Unsigned integer (four-byte uint32_t follows)
3912
            {
3913
                std::uint32_t number;
3914
                return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
3915
            }
3916
3917
            case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
3918
            {
3919
                std::uint64_t number;
3920
                return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
3921
            }
3922
3923
            // Negative integer -1-0x00..-1-0x17 (-1..-24)
3924
            case 0x20:
3925
            case 0x21:
3926
            case 0x22:
3927
            case 0x23:
3928
            case 0x24:
3929
            case 0x25:
3930
            case 0x26:
3931
            case 0x27:
3932
            case 0x28:
3933
            case 0x29:
3934
            case 0x2A:
3935
            case 0x2B:
3936
            case 0x2C:
3937
            case 0x2D:
3938
            case 0x2E:
3939
            case 0x2F:
3940
            case 0x30:
3941
            case 0x31:
3942
            case 0x32:
3943
            case 0x33:
3944
            case 0x34:
3945
            case 0x35:
3946
            case 0x36:
3947
            case 0x37:
3948
                return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
3949
3950
            case 0x38: // Negative integer (one-byte uint8_t follows)
3951
            {
3952
                std::uint8_t number;
3953
                return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
3954
            }
3955
3956
            case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
3957
            {
3958
                std::uint16_t number;
3959
                return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
3960
            }
3961
3962
            case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
3963
            {
3964
                std::uint32_t number;
3965
                return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
3966
            }
3967
3968
            case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
3969
            {
3970
                std::uint64_t number;
3971
                return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1)
3972
                        - static_cast<number_integer_t>(number));
3973
            }
3974
3975
            // UTF-8 string (0x00..0x17 bytes follow)
3976
            case 0x60:
3977
            case 0x61:
3978
            case 0x62:
3979
            case 0x63:
3980
            case 0x64:
3981
            case 0x65:
3982
            case 0x66:
3983
            case 0x67:
3984
            case 0x68:
3985
            case 0x69:
3986
            case 0x6A:
3987
            case 0x6B:
3988
            case 0x6C:
3989
            case 0x6D:
3990
            case 0x6E:
3991
            case 0x6F:
3992
            case 0x70:
3993
            case 0x71:
3994
            case 0x72:
3995
            case 0x73:
3996
            case 0x74:
3997
            case 0x75:
3998
            case 0x76:
3999
            case 0x77:
4000
            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
4001
            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
4002
            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
4003
            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
4004
            case 0x7F: // UTF-8 string (indefinite length)
4005
            {
4006
                string_t s;
4007
                return get_cbor_string(s) and sax->string(s);
4008
            }
4009
4010
            // array (0x00..0x17 data items follow)
4011
            case 0x80:
4012
            case 0x81:
4013
            case 0x82:
4014
            case 0x83:
4015
            case 0x84:
4016
            case 0x85:
4017
            case 0x86:
4018
            case 0x87:
4019
            case 0x88:
4020
            case 0x89:
4021
            case 0x8A:
4022
            case 0x8B:
4023
            case 0x8C:
4024
            case 0x8D:
4025
            case 0x8E:
4026
            case 0x8F:
4027
            case 0x90:
4028
            case 0x91:
4029
            case 0x92:
4030
            case 0x93:
4031
            case 0x94:
4032
            case 0x95:
4033
            case 0x96:
4034
            case 0x97:
4035
                return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
4036
4037
            case 0x98: // array (one-byte uint8_t for n follows)
4038
            {
4039
                std::uint8_t len;
4040
                return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
4041
            }
4042
4043
            case 0x99: // array (two-byte uint16_t for n follow)
4044
            {
4045
                std::uint16_t len;
4046
                return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
4047
            }
4048
4049
            case 0x9A: // array (four-byte uint32_t for n follow)
4050
            {
4051
                std::uint32_t len;
4052
                return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
4053
            }
4054
4055
            case 0x9B: // array (eight-byte uint64_t for n follow)
4056
            {
4057
                std::uint64_t len;
4058
                return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
4059
            }
4060
4061
            case 0x9F: // array (indefinite length)
4062
                return get_cbor_array(std::size_t(-1));
4063
4064
            // map (0x00..0x17 pairs of data items follow)
4065
            case 0xA0:
4066
            case 0xA1:
4067
            case 0xA2:
4068
            case 0xA3:
4069
            case 0xA4:
4070
            case 0xA5:
4071
            case 0xA6:
4072
            case 0xA7:
4073
            case 0xA8:
4074
            case 0xA9:
4075
            case 0xAA:
4076
            case 0xAB:
4077
            case 0xAC:
4078
            case 0xAD:
4079
            case 0xAE:
4080
            case 0xAF:
4081
            case 0xB0:
4082
            case 0xB1:
4083
            case 0xB2:
4084
            case 0xB3:
4085
            case 0xB4:
4086
            case 0xB5:
4087
            case 0xB6:
4088
            case 0xB7:
4089
                return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
4090
4091
            case 0xB8: // map (one-byte uint8_t for n follows)
4092
            {
4093
                std::uint8_t len;
4094
                return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
4095
            }
4096
4097
            case 0xB9: // map (two-byte uint16_t for n follow)
4098
            {
4099
                std::uint16_t len;
4100
                return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
4101
            }
4102
4103
            case 0xBA: // map (four-byte uint32_t for n follow)
4104
            {
4105
                std::uint32_t len;
4106
                return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
4107
            }
4108
4109
            case 0xBB: // map (eight-byte uint64_t for n follow)
4110
            {
4111
                std::uint64_t len;
4112
                return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
4113
            }
4114
4115
            case 0xBF: // map (indefinite length)
4116
                return get_cbor_object(std::size_t(-1));
4117
4118
            case 0xF4: // false
4119
                return sax->boolean(false);
4120
4121
            case 0xF5: // true
4122
                return sax->boolean(true);
4123
4124
            case 0xF6: // null
4125
                return sax->null();
4126
4127
            case 0xF9: // Half-Precision Float (two-byte IEEE 754)
4128
            {
4129
                const int byte1_raw = get();
4130
                if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number")))
4131
                {
4132
                    return false;
4133
                }
4134
                const int byte2_raw = get();
4135
                if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number")))
4136
                {
4137
                    return false;
4138
                }
4139
4140
                const auto byte1 = static_cast<unsigned char>(byte1_raw);
4141
                const auto byte2 = static_cast<unsigned char>(byte2_raw);
4142
4143
                // code from RFC 7049, Appendix D, Figure 3:
4144
                // As half-precision floating-point numbers were only added
4145
                // to IEEE 754 in 2008, today's programming platforms often
4146
                // still only have limited support for them. It is very
4147
                // easy to include at least decoding support for them even
4148
                // without such support. An example of a small decoder for
4149
                // half-precision floating-point numbers in the C language
4150
                // is shown in Fig. 3.
4151
                const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
4152
                const double val = [&half]
4153
                {
4154
                    const int exp = (half >> 10u) & 0x1Fu;
4155
                    const unsigned int mant = half & 0x3FFu;
4156
                    assert(0 <= exp and exp <= 32);
4157
                    assert(0 <= mant and mant <= 1024);
4158
                    switch (exp)
4159
                    {
4160
                        case 0:
4161
                            return std::ldexp(mant, -24);
4162
                        case 31:
4163
                            return (mant == 0)
4164
                            ? std::numeric_limits<double>::infinity()
4165
                            : std::numeric_limits<double>::quiet_NaN();
4166
                        default:
4167
                            return std::ldexp(mant + 1024, exp - 25);
4168
                    }
4169
                }();
4170
                return sax->number_float((half & 0x8000u) != 0
4171
                                         ? static_cast<number_float_t>(-val)
4172
                                         : static_cast<number_float_t>(val), "");
4173
            }
4174
4175
            case 0xFA: // Single-Precision Float (four-byte IEEE 754)
4176
            {
4177
                float number;
4178
                return get_number(input_format_t::cbor, number) and sax->number_float(static_cast<number_float_t>(number), "");
4179
            }
4180
4181
            case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
4182
            {
4183
                double number;
4184
                return get_number(input_format_t::cbor, number) and sax->number_float(static_cast<number_float_t>(number), "");
4185
            }
4186
4187
            default: // anything else (0xFF is handled inside the other types)
4188
            {
4189
                auto last_token = get_token_string();
4190
                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")));
4191
            }
4192
        }
4193
    }
4194
4195
    /*!
4196
    @brief reads a CBOR string
4197
4198
    This function first reads starting bytes to determine the expected
4199
    string length and then copies this number of bytes into a string.
4200
    Additionally, CBOR's strings with indefinite lengths are supported.
4201
4202
    @param[out] result  created string
4203
4204
    @return whether string creation completed
4205
    */
4206
    bool get_cbor_string(string_t& result)
4207
    {
4208
        if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "string")))
4209
        {
4210
            return false;
4211
        }
4212
4213
        switch (current)
4214
        {
4215
            // UTF-8 string (0x00..0x17 bytes follow)
4216
            case 0x60:
4217
            case 0x61:
4218
            case 0x62:
4219
            case 0x63:
4220
            case 0x64:
4221
            case 0x65:
4222
            case 0x66:
4223
            case 0x67:
4224
            case 0x68:
4225
            case 0x69:
4226
            case 0x6A:
4227
            case 0x6B:
4228
            case 0x6C:
4229
            case 0x6D:
4230
            case 0x6E:
4231
            case 0x6F:
4232
            case 0x70:
4233
            case 0x71:
4234
            case 0x72:
4235
            case 0x73:
4236
            case 0x74:
4237
            case 0x75:
4238
            case 0x76:
4239
            case 0x77:
4240
            {
4241
                return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
4242
            }
4243
4244
            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
4245
            {
4246
                std::uint8_t len;
4247
                return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
4248
            }
4249
4250
            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
4251
            {
4252
                std::uint16_t len;
4253
                return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
4254
            }
4255
4256
            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
4257
            {
4258
                std::uint32_t len;
4259
                return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
4260
            }
4261
4262
            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
4263
            {
4264
                std::uint64_t len;
4265
                return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
4266
            }
4267
4268
            case 0x7F: // UTF-8 string (indefinite length)
4269
            {
4270
                while (get() != 0xFF)
4271
                {
4272
                    string_t chunk;
4273
                    if (not get_cbor_string(chunk))
4274
                    {
4275
                        return false;
4276
                    }
4277
                    result.append(chunk);
4278
                }
4279
                return true;
4280
            }
4281
4282
            default:
4283
            {
4284
                auto last_token = get_token_string();
4285
                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")));
4286
            }
4287
        }
4288
    }
4289
4290
    /*!
4291
    @param[in] len  the length of the array or std::size_t(-1) for an
4292
                    array of indefinite size
4293
    @return whether array creation completed
4294
    */
4295
    bool get_cbor_array(const std::size_t len)
4296
    {
4297
        if (JSON_UNLIKELY(not sax->start_array(len)))
4298
        {
4299
            return false;
4300
        }
4301
4302
        if (len != std::size_t(-1))
4303
        {
4304
            for (std::size_t i = 0; i < len; ++i)
4305
            {
4306
                if (JSON_UNLIKELY(not parse_cbor_internal()))
4307
                {
4308
                    return false;
4309
                }
4310
            }
4311
        }
4312
        else
4313
        {
4314
            while (get() != 0xFF)
4315
            {
4316
                if (JSON_UNLIKELY(not parse_cbor_internal(false)))
4317
                {
4318
                    return false;
4319
                }
4320
            }
4321
        }
4322
4323
        return sax->end_array();
4324
    }
4325
4326
    /*!
4327
    @param[in] len  the length of the object or std::size_t(-1) for an
4328
                    object of indefinite size
4329
    @return whether object creation completed
4330
    */
4331
    bool get_cbor_object(const std::size_t len)
4332
    {
4333
        if (JSON_UNLIKELY(not sax->start_object(len)))
4334
        {
4335
            return false;
4336
        }
4337
4338
        string_t key;
4339
        if (len != std::size_t(-1))
4340
        {
4341
            for (std::size_t i = 0; i < len; ++i)
4342
            {
4343
                get();
4344
                if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
4345
                {
4346
                    return false;
4347
                }
4348
4349
                if (JSON_UNLIKELY(not parse_cbor_internal()))
4350
                {
4351
                    return false;
4352
                }
4353
                key.clear();
4354
            }
4355
        }
4356
        else
4357
        {
4358
            while (get() != 0xFF)
4359
            {
4360
                if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
4361
                {
4362
                    return false;
4363
                }
4364
4365
                if (JSON_UNLIKELY(not parse_cbor_internal()))
4366
                {
4367
                    return false;
4368
                }
4369
                key.clear();
4370
            }
4371
        }
4372
4373
        return sax->end_object();
4374
    }
4375
4376
    /////////////
4377
    // MsgPack //
4378
    /////////////
4379
4380
    /*!
4381
    @return whether a valid MessagePack value was passed to the SAX parser
4382
    */
4383
    bool parse_msgpack_internal()
4384
    {
4385
        switch (get())
4386
        {
4387
            // EOF
4388
            case std::char_traits<char>::eof():
4389
                return unexpect_eof(input_format_t::msgpack, "value");
4390
4391
            // positive fixint
4392
            case 0x00:
4393
            case 0x01:
4394
            case 0x02:
4395
            case 0x03:
4396
            case 0x04:
4397
            case 0x05:
4398
            case 0x06:
4399
            case 0x07:
4400
            case 0x08:
4401
            case 0x09:
4402
            case 0x0A:
4403
            case 0x0B:
4404
            case 0x0C:
4405
            case 0x0D:
4406
            case 0x0E:
4407
            case 0x0F:
4408
            case 0x10:
4409
            case 0x11:
4410
            case 0x12:
4411
            case 0x13:
4412
            case 0x14:
4413
            case 0x15:
4414
            case 0x16:
4415
            case 0x17:
4416
            case 0x18:
4417
            case 0x19:
4418
            case 0x1A:
4419
            case 0x1B:
4420
            case 0x1C:
4421
            case 0x1D:
4422
            case 0x1E:
4423
            case 0x1F:
4424
            case 0x20:
4425
            case 0x21:
4426
            case 0x22:
4427
            case 0x23:
4428
            case 0x24:
4429
            case 0x25:
4430
            case 0x26:
4431
            case 0x27:
4432
            case 0x28:
4433
            case 0x29:
4434
            case 0x2A:
4435
            case 0x2B:
4436
            case 0x2C:
4437
            case 0x2D:
4438
            case 0x2E:
4439
            case 0x2F:
4440
            case 0x30:
4441
            case 0x31:
4442
            case 0x32:
4443
            case 0x33:
4444
            case 0x34:
4445
            case 0x35:
4446
            case 0x36:
4447
            case 0x37:
4448
            case 0x38:
4449
            case 0x39:
4450
            case 0x3A:
4451
            case 0x3B:
4452
            case 0x3C:
4453
            case 0x3D:
4454
            case 0x3E:
4455
            case 0x3F:
4456
            case 0x40:
4457
            case 0x41:
4458
            case 0x42:
4459
            case 0x43:
4460
            case 0x44:
4461
            case 0x45:
4462
            case 0x46:
4463
            case 0x47:
4464
            case 0x48:
4465
            case 0x49:
4466
            case 0x4A:
4467
            case 0x4B:
4468
            case 0x4C:
4469
            case 0x4D:
4470
            case 0x4E:
4471
            case 0x4F:
4472
            case 0x50:
4473
            case 0x51:
4474
            case 0x52:
4475
            case 0x53:
4476
            case 0x54:
4477
            case 0x55:
4478
            case 0x56:
4479
            case 0x57:
4480
            case 0x58:
4481
            case 0x59:
4482
            case 0x5A:
4483
            case 0x5B:
4484
            case 0x5C:
4485
            case 0x5D:
4486
            case 0x5E:
4487
            case 0x5F:
4488
            case 0x60:
4489
            case 0x61:
4490
            case 0x62:
4491
            case 0x63:
4492
            case 0x64:
4493
            case 0x65:
4494
            case 0x66:
4495
            case 0x67:
4496
            case 0x68:
4497
            case 0x69:
4498
            case 0x6A:
4499
            case 0x6B:
4500
            case 0x6C:
4501
            case 0x6D:
4502
            case 0x6E:
4503
            case 0x6F:
4504
            case 0x70:
4505
            case 0x71:
4506
            case 0x72:
4507
            case 0x73:
4508
            case 0x74:
4509
            case 0x75:
4510
            case 0x76:
4511
            case 0x77:
4512
            case 0x78:
4513
            case 0x79:
4514
            case 0x7A:
4515
            case 0x7B:
4516
            case 0x7C:
4517
            case 0x7D:
4518
            case 0x7E:
4519
            case 0x7F:
4520
                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
4521
4522
            // fixmap
4523
            case 0x80:
4524
            case 0x81:
4525
            case 0x82:
4526
            case 0x83:
4527
            case 0x84:
4528
            case 0x85:
4529
            case 0x86:
4530
            case 0x87:
4531
            case 0x88:
4532
            case 0x89:
4533
            case 0x8A:
4534
            case 0x8B:
4535
            case 0x8C:
4536
            case 0x8D:
4537
            case 0x8E:
4538
            case 0x8F:
4539
                return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
4540
4541
            // fixarray
4542
            case 0x90:
4543
            case 0x91:
4544
            case 0x92:
4545
            case 0x93:
4546
            case 0x94:
4547
            case 0x95:
4548
            case 0x96:
4549
            case 0x97:
4550
            case 0x98:
4551
            case 0x99:
4552
            case 0x9A:
4553
            case 0x9B:
4554
            case 0x9C:
4555
            case 0x9D:
4556
            case 0x9E:
4557
            case 0x9F:
4558
                return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
4559
4560
            // fixstr
4561
            case 0xA0:
4562
            case 0xA1:
4563
            case 0xA2:
4564
            case 0xA3:
4565
            case 0xA4:
4566
            case 0xA5:
4567
            case 0xA6:
4568
            case 0xA7:
4569
            case 0xA8:
4570
            case 0xA9:
4571
            case 0xAA:
4572
            case 0xAB:
4573
            case 0xAC:
4574
            case 0xAD:
4575
            case 0xAE:
4576
            case 0xAF:
4577
            case 0xB0:
4578
            case 0xB1:
4579
            case 0xB2:
4580
            case 0xB3:
4581
            case 0xB4:
4582
            case 0xB5:
4583
            case 0xB6:
4584
            case 0xB7:
4585
            case 0xB8:
4586
            case 0xB9:
4587
            case 0xBA:
4588
            case 0xBB:
4589
            case 0xBC:
4590
            case 0xBD:
4591
            case 0xBE:
4592
            case 0xBF:
4593
            {
4594
                string_t s;
4595
                return get_msgpack_string(s) and sax->string(s);
4596
            }
4597
4598
            case 0xC0: // nil
4599
                return sax->null();
4600
4601
            case 0xC2: // false
4602
                return sax->boolean(false);
4603
4604
            case 0xC3: // true
4605
                return sax->boolean(true);
4606
4607
            case 0xCA: // float 32
4608
            {
4609
                float number;
4610
                return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast<number_float_t>(number), "");
4611
            }
4612
4613
            case 0xCB: // float 64
4614
            {
4615
                double number;
4616
                return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast<number_float_t>(number), "");
4617
            }
4618
4619
            case 0xCC: // uint 8
4620
            {
4621
                std::uint8_t number;
4622
                return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
4623
            }
4624
4625
            case 0xCD: // uint 16
4626
            {
4627
                std::uint16_t number;
4628
                return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
4629
            }
4630
4631
            case 0xCE: // uint 32
4632
            {
4633
                std::uint32_t number;
4634
                return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
4635
            }
4636
4637
            case 0xCF: // uint 64
4638
            {
4639
                std::uint64_t number;
4640
                return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
4641
            }
4642
4643
            case 0xD0: // int 8
4644
            {
4645
                std::int8_t number;
4646
                return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
4647
            }
4648
4649
            case 0xD1: // int 16
4650
            {
4651
                std::int16_t number;
4652
                return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
4653
            }
4654
4655
            case 0xD2: // int 32
4656
            {
4657
                std::int32_t number;
4658
                return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
4659
            }
4660
4661
            case 0xD3: // int 64
4662
            {
4663
                std::int64_t number;
4664
                return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
4665
            }
4666
4667
            case 0xD9: // str 8
4668
            case 0xDA: // str 16
4669
            case 0xDB: // str 32
4670
            {
4671
                string_t s;
4672
                return get_msgpack_string(s) and sax->string(s);
4673
            }
4674
4675
            case 0xDC: // array 16
4676
            {
4677
                std::uint16_t len;
4678
                return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
4679
            }
4680
4681
            case 0xDD: // array 32
4682
            {
4683
                std::uint32_t len;
4684
                return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
4685
            }
4686
4687
            case 0xDE: // map 16
4688
            {
4689
                std::uint16_t len;
4690
                return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
4691
            }
4692
4693
            case 0xDF: // map 32
4694
            {
4695
                std::uint32_t len;
4696
                return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
4697
            }
4698
4699
            // negative fixint
4700
            case 0xE0:
4701
            case 0xE1:
4702
            case 0xE2:
4703
            case 0xE3:
4704
            case 0xE4:
4705
            case 0xE5:
4706
            case 0xE6:
4707
            case 0xE7:
4708
            case 0xE8:
4709
            case 0xE9:
4710
            case 0xEA:
4711
            case 0xEB:
4712
            case 0xEC:
4713
            case 0xED:
4714
            case 0xEE:
4715
            case 0xEF:
4716
            case 0xF0:
4717
            case 0xF1:
4718
            case 0xF2:
4719
            case 0xF3:
4720
            case 0xF4:
4721
            case 0xF5:
4722
            case 0xF6:
4723
            case 0xF7:
4724
            case 0xF8:
4725
            case 0xF9:
4726
            case 0xFA:
4727
            case 0xFB:
4728
            case 0xFC:
4729
            case 0xFD:
4730
            case 0xFE:
4731
            case 0xFF:
4732
                return sax->number_integer(static_cast<std::int8_t>(current));
4733
4734
            default: // anything else
4735
            {
4736
                auto last_token = get_token_string();
4737
                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")));
4738
            }
4739
        }
4740
    }
4741
4742
    /*!
4743
    @brief reads a MessagePack string
4744
4745
    This function first reads starting bytes to determine the expected
4746
    string length and then copies this number of bytes into a string.
4747
4748
    @param[out] result  created string
4749
4750
    @return whether string creation completed
4751
    */
4752
    bool get_msgpack_string(string_t& result)
4753
    {
4754
        if (JSON_UNLIKELY(not unexpect_eof(input_format_t::msgpack, "string")))
4755
        {
4756
            return false;
4757
        }
4758
4759
        switch (current)
4760
        {
4761
            // fixstr
4762
            case 0xA0:
4763
            case 0xA1:
4764
            case 0xA2:
4765
            case 0xA3:
4766
            case 0xA4:
4767
            case 0xA5:
4768
            case 0xA6:
4769
            case 0xA7:
4770
            case 0xA8:
4771
            case 0xA9:
4772
            case 0xAA:
4773
            case 0xAB:
4774
            case 0xAC:
4775
            case 0xAD:
4776
            case 0xAE:
4777
            case 0xAF:
4778
            case 0xB0:
4779
            case 0xB1:
4780
            case 0xB2:
4781
            case 0xB3:
4782
            case 0xB4:
4783
            case 0xB5:
4784
            case 0xB6:
4785
            case 0xB7:
4786
            case 0xB8:
4787
            case 0xB9:
4788
            case 0xBA:
4789
            case 0xBB:
4790
            case 0xBC:
4791
            case 0xBD:
4792
            case 0xBE:
4793
            case 0xBF:
4794
            {
4795
                return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
4796
            }
4797
4798
            case 0xD9: // str 8
4799
            {
4800
                std::uint8_t len;
4801
                return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
4802
            }
4803
4804
            case 0xDA: // str 16
4805
            {
4806
                std::uint16_t len;
4807
                return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
4808
            }
4809
4810
            case 0xDB: // str 32
4811
            {
4812
                std::uint32_t len;
4813
                return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
4814
            }
4815
4816
            default:
4817
            {
4818
                auto last_token = get_token_string();
4819
                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")));
4820
            }
4821
        }
4822
    }
4823
4824
    /*!
4825
    @param[in] len  the length of the array
4826
    @return whether array creation completed
4827
    */
4828
    bool get_msgpack_array(const std::size_t len)
4829
    {
4830
        if (JSON_UNLIKELY(not sax->start_array(len)))
4831
        {
4832
            return false;
4833
        }
4834
4835
        for (std::size_t i = 0; i < len; ++i)
4836
        {
4837
            if (JSON_UNLIKELY(not parse_msgpack_internal()))
4838
            {
4839
                return false;
4840
            }
4841
        }
4842
4843
        return sax->end_array();
4844
    }
4845
4846
    /*!
4847
    @param[in] len  the length of the object
4848
    @return whether object creation completed
4849
    */
4850
    bool get_msgpack_object(const std::size_t len)
4851
    {
4852
        if (JSON_UNLIKELY(not sax->start_object(len)))
4853
        {
4854
            return false;
4855
        }
4856
4857
        string_t key;
4858
        for (std::size_t i = 0; i < len; ++i)
4859
        {
4860
            get();
4861
            if (JSON_UNLIKELY(not get_msgpack_string(key) or not sax->key(key)))
4862
            {
4863
                return false;
4864
            }
4865
4866
            if (JSON_UNLIKELY(not parse_msgpack_internal()))
4867
            {
4868
                return false;
4869
            }
4870
            key.clear();
4871
        }
4872
4873
        return sax->end_object();
4874
    }
4875
4876
    ////////////
4877
    // UBJSON //
4878
    ////////////
4879
4880
    /*!
4881
    @param[in] get_char  whether a new character should be retrieved from the
4882
                         input (true, default) or whether the last read
4883
                         character should be considered instead
4884
4885
    @return whether a valid UBJSON value was passed to the SAX parser
4886
    */
4887
    bool parse_ubjson_internal(const bool get_char = true)
4888
    {
4889
        return get_ubjson_value(get_char ? get_ignore_noop() : current);
4890
    }
4891
4892
    /*!
4893
    @brief reads a UBJSON string
4894
4895
    This function is either called after reading the 'S' byte explicitly
4896
    indicating a string, or in case of an object key where the 'S' byte can be
4897
    left out.
4898
4899
    @param[out] result   created string
4900
    @param[in] get_char  whether a new character should be retrieved from the
4901
                         input (true, default) or whether the last read
4902
                         character should be considered instead
4903
4904
    @return whether string creation completed
4905
    */
4906
    bool get_ubjson_string(string_t& result, const bool get_char = true)
4907
    {
4908
        if (get_char)
4909
        {
4910
            get();  // TODO(niels): may we ignore N here?
4911
        }
4912
4913
        if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
4914
        {
4915
            return false;
4916
        }
4917
4918
        switch (current)
4919
        {
4920
            case 'U':
4921
            {
4922
                std::uint8_t len;
4923
                return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
4924
            }
4925
4926
            case 'i':
4927
            {
4928
                std::int8_t len;
4929
                return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
4930
            }
4931
4932
            case 'I':
4933
            {
4934
                std::int16_t len;
4935
                return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
4936
            }
4937
4938
            case 'l':
4939
            {
4940
                std::int32_t len;
4941
                return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
4942
            }
4943
4944
            case 'L':
4945
            {
4946
                std::int64_t len;
4947
                return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
4948
            }
4949
4950
            default:
4951
                auto last_token = get_token_string();
4952
                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")));
4953
        }
4954
    }
4955
4956
    /*!
4957
    @param[out] result  determined size
4958
    @return whether size determination completed
4959
    */
4960
    bool get_ubjson_size_value(std::size_t& result)
4961
    {
4962
        switch (get_ignore_noop())
4963
        {
4964
            case 'U':
4965
            {
4966
                std::uint8_t number;
4967
                if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
4968
                {
4969
                    return false;
4970
                }
4971
                result = static_cast<std::size_t>(number);
4972
                return true;
4973
            }
4974
4975
            case 'i':
4976
            {
4977
                std::int8_t number;
4978
                if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
4979
                {
4980
                    return false;
4981
                }
4982
                result = static_cast<std::size_t>(number);
4983
                return true;
4984
            }
4985
4986
            case 'I':
4987
            {
4988
                std::int16_t number;
4989
                if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
4990
                {
4991
                    return false;
4992
                }
4993
                result = static_cast<std::size_t>(number);
4994
                return true;
4995
            }
4996
4997
            case 'l':
4998
            {
4999
                std::int32_t number;
5000
                if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
5001
                {
5002
                    return false;
5003
                }
5004
                result = static_cast<std::size_t>(number);
5005
                return true;
5006
            }
5007
5008
            case 'L':
5009
            {
5010
                std::int64_t number;
5011
                if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
5012
                {
5013
                    return false;
5014
                }
5015
                result = static_cast<std::size_t>(number);
5016
                return true;
5017
            }
5018
5019
            default:
5020
            {
5021
                auto last_token = get_token_string();
5022
                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")));
5023
            }
5024
        }
5025
    }
5026
5027
    /*!
5028
    @brief determine the type and size for a container
5029
5030
    In the optimized UBJSON format, a type and a size can be provided to allow
5031
    for a more compact representation.
5032
5033
    @param[out] result  pair of the size and the type
5034
5035
    @return whether pair creation completed
5036
    */
5037
    bool get_ubjson_size_type(std::pair<std::size_t, int>& result)
5038
    {
5039
        result.first = string_t::npos; // size
5040
        result.second = 0; // type
5041
5042
        get_ignore_noop();
5043
5044
        if (current == '$')
5045
        {
5046
            result.second = get();  // must not ignore 'N', because 'N' maybe the type
5047
            if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "type")))
5048
            {
5049
                return false;
5050
            }
5051
5052
            get_ignore_noop();
5053
            if (JSON_UNLIKELY(current != '#'))
5054
            {
5055
                if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
5056
                {
5057
                    return false;
5058
                }
5059
                auto last_token = get_token_string();
5060
                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")));
5061
            }
5062
5063
            return get_ubjson_size_value(result.first);
5064
        }
5065
5066
        if (current == '#')
5067
        {
5068
            return get_ubjson_size_value(result.first);
5069
        }
5070
5071
        return true;
5072
    }
5073
5074
    /*!
5075
    @param prefix  the previously read or set type prefix
5076
    @return whether value creation completed
5077
    */
5078
    bool get_ubjson_value(const int prefix)
5079
    {
5080
        switch (prefix)
5081
        {
5082
            case std::char_traits<char>::eof():  // EOF
5083
                return unexpect_eof(input_format_t::ubjson, "value");
5084
5085
            case 'T':  // true
5086
                return sax->boolean(true);
5087
            case 'F':  // false
5088
                return sax->boolean(false);
5089
5090
            case 'Z':  // null
5091
                return sax->null();
5092
5093
            case 'U':
5094
            {
5095
                std::uint8_t number;
5096
                return get_number(input_format_t::ubjson, number) and sax->number_unsigned(number);
5097
            }
5098
5099
            case 'i':
5100
            {
5101
                std::int8_t number;
5102
                return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
5103
            }
5104
5105
            case 'I':
5106
            {
5107
                std::int16_t number;
5108
                return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
5109
            }
5110
5111
            case 'l':
5112
            {
5113
                std::int32_t number;
5114
                return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
5115
            }
5116
5117
            case 'L':
5118
            {
5119
                std::int64_t number;
5120
                return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
5121
            }
5122
5123
            case 'd':
5124
            {
5125
                float number;
5126
                return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast<number_float_t>(number), "");
5127
            }
5128
5129
            case 'D':
5130
            {
5131
                double number;
5132
                return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast<number_float_t>(number), "");
5133
            }
5134
5135
            case 'C':  // char
5136
            {
5137
                get();
5138
                if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "char")))
5139
                {
5140
                    return false;
5141
                }
5142
                if (JSON_UNLIKELY(current > 127))
5143
                {
5144
                    auto last_token = get_token_string();
5145
                    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")));
5146
                }
5147
                string_t s(1, static_cast<char>(current));
5148
                return sax->string(s);
5149
            }
5150
5151
            case 'S':  // string
5152
            {
5153
                string_t s;
5154
                return get_ubjson_string(s) and sax->string(s);
5155
            }
5156
5157
            case '[':  // array
5158
                return get_ubjson_array();
5159
5160
            case '{':  // object
5161
                return get_ubjson_object();
5162
5163
            default: // anything else
5164
            {
5165
                auto last_token = get_token_string();
5166
                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")));
5167
            }
5168
        }
5169
    }
5170
5171
    /*!
5172
    @return whether array creation completed
5173
    */
5174
    bool get_ubjson_array()
5175
    {
5176
        std::pair<std::size_t, int> size_and_type;
5177
        if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
5178
        {
5179
            return false;
5180
        }
5181
5182
        if (size_and_type.first != string_t::npos)
5183
        {
5184
            if (JSON_UNLIKELY(not sax->start_array(size_and_type.first)))
5185
            {
5186
                return false;
5187
            }
5188
5189
            if (size_and_type.second != 0)
5190
            {
5191
                if (size_and_type.second != 'N')
5192
                {
5193
                    for (std::size_t i = 0; i < size_and_type.first; ++i)
5194
                    {
5195
                        if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
5196
                        {
5197
                            return false;
5198
                        }
5199
                    }
5200
                }
5201
            }
5202
            else
5203
            {
5204
                for (std::size_t i = 0; i < size_and_type.first; ++i)
5205
                {
5206
                    if (JSON_UNLIKELY(not parse_ubjson_internal()))
5207
                    {
5208
                        return false;
5209
                    }
5210
                }
5211
            }
5212
        }
5213
        else
5214
        {
5215
            if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
5216
            {
5217
                return false;
5218
            }
5219
5220
            while (current != ']')
5221
            {
5222
                if (JSON_UNLIKELY(not parse_ubjson_internal(false)))
5223
                {
5224
                    return false;
5225
                }
5226
                get_ignore_noop();
5227
            }
5228
        }
5229
5230
        return sax->end_array();
5231
    }
5232
5233
    /*!
5234
    @return whether object creation completed
5235
    */
5236
    bool get_ubjson_object()
5237
    {
5238
        std::pair<std::size_t, int> size_and_type;
5239
        if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
5240
        {
5241
            return false;
5242
        }
5243
5244
        string_t key;
5245
        if (size_and_type.first != string_t::npos)
5246
        {
5247
            if (JSON_UNLIKELY(not sax->start_object(size_and_type.first)))
5248
            {
5249
                return false;
5250
            }
5251
5252
            if (size_and_type.second != 0)
5253
            {
5254
                for (std::size_t i = 0; i < size_and_type.first; ++i)
5255
                {
5256
                    if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
5257
                    {
5258
                        return false;
5259
                    }
5260
                    if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
5261
                    {
5262
                        return false;
5263
                    }
5264
                    key.clear();
5265
                }
5266
            }
5267
            else
5268
            {
5269
                for (std::size_t i = 0; i < size_and_type.first; ++i)
5270
                {
5271
                    if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
5272
                    {
5273
                        return false;
5274
                    }
5275
                    if (JSON_UNLIKELY(not parse_ubjson_internal()))
5276
                    {
5277
                        return false;
5278
                    }
5279
                    key.clear();
5280
                }
5281
            }
5282
        }
5283
        else
5284
        {
5285
            if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
5286
            {
5287
                return false;
5288
            }
5289
5290
            while (current != '}')
5291
            {
5292
                if (JSON_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key)))
5293
                {
5294
                    return false;
5295
                }
5296
                if (JSON_UNLIKELY(not parse_ubjson_internal()))
5297
                {
5298
                    return false;
5299
                }
5300
                get_ignore_noop();
5301
                key.clear();
5302
            }
5303
        }
5304
5305
        return sax->end_object();
5306
    }
5307
5308
    ///////////////////////
5309
    // Utility functions //
5310
    ///////////////////////
5311
5312
    /*!
5313
    @brief get next character from the input
5314
5315
    This function provides the interface to the used input adapter. It does
5316
    not throw in case the input reached EOF, but returns a -'ve valued
5317
    `std::char_traits<char>::eof()` in that case.
5318
5319
    @return character read from the input
5320
    */
5321
    int get()
5322
    {
5323
        ++chars_read;
5324
        return current = ia->get_character();
5325
    }
5326
5327
    /*!
5328
    @return character read from the input after ignoring all 'N' entries
5329
    */
5330
    int get_ignore_noop()
5331
    {
5332
        do
5333
        {
5334
            get();
5335
        }
5336
        while (current == 'N');
5337
5338
        return current;
5339
    }
5340
5341
    /*
5342
    @brief read a number from the input
5343
5344
    @tparam NumberType the type of the number
5345
    @param[in] format   the current format (for diagnostics)
5346
    @param[out] result  number of type @a NumberType
5347
5348
    @return whether conversion completed
5349
5350
    @note This function needs to respect the system's endianess, because
5351
          bytes in CBOR, MessagePack, and UBJSON are stored in network order
5352
          (big endian) and therefore need reordering on little endian systems.
5353
    */
5354
    template<typename NumberType, bool InputIsLittleEndian = false>
5355
    bool get_number(const input_format_t format, NumberType& result)
5356
    {
5357
        // step 1: read input into array with system's byte order
5358
        std::array<std::uint8_t, sizeof(NumberType)> vec;
5359
        for (std::size_t i = 0; i < sizeof(NumberType); ++i)